|
| 1 | +import pytest |
| 2 | +from ducktape.utils.util import wait_until |
| 3 | +from requests import HTTPError |
| 4 | + |
| 5 | +from rptest.services.admin import Admin |
| 6 | +from rptest.services.cluster import cluster |
| 7 | +from rptest.services.redpanda import SISettings |
| 8 | +from rptest.tests.redpanda_test import RedpandaTest |
| 9 | + |
| 10 | + |
| 11 | +class CloudStorageCacheAdminApisNoCacheTest(RedpandaTest): |
| 12 | + """ |
| 13 | + Test the Cloud Storage Cache Admin APIs when tiered storage is not configured. |
| 14 | + """ |
| 15 | + def __init__(self, test_context): |
| 16 | + super().__init__(test_context, num_brokers=1) |
| 17 | + self.admin = Admin(self.redpanda) |
| 18 | + |
| 19 | + @cluster(num_nodes=1) |
| 20 | + def test_admin_apis(self): |
| 21 | + for node in self.redpanda.nodes: |
| 22 | + with pytest.raises(HTTPError) as excinfo: |
| 23 | + self.admin.cloud_storage_trim(byte_limit=None, |
| 24 | + object_limit=None, |
| 25 | + node=node) |
| 26 | + |
| 27 | + assert "Cloud Storage Cache is not available. Is cloud storage enabled?" == excinfo.value.response.json( |
| 28 | + )['message'] |
| 29 | + |
| 30 | + |
| 31 | +class CloudStorageCacheAdminApisTest(RedpandaTest): |
| 32 | + """ |
| 33 | + Test the Cloud Storage Cache Admin APIs when tiered storage is configured. |
| 34 | + """ |
| 35 | + def __init__(self, test_context): |
| 36 | + super().__init__(test_context, |
| 37 | + num_brokers=1, |
| 38 | + si_settings=SISettings(test_context)) |
| 39 | + self.admin = Admin(self.redpanda) |
| 40 | + |
| 41 | + def setUp(self): |
| 42 | + pass |
| 43 | + |
| 44 | + @cluster(num_nodes=1, |
| 45 | + log_allow_list=["Free space information is not available"]) |
| 46 | + def test_admin_apis(self): |
| 47 | + num_objects = 100 |
| 48 | + object_size = 4096 |
| 49 | + |
| 50 | + for node in self.redpanda.nodes: |
| 51 | + node.account.ssh( |
| 52 | + f"mkdir -p {self.redpanda.cache_dir} ; " |
| 53 | + f"for n in `seq 1 {num_objects}`; do " |
| 54 | + f"dd if=/dev/urandom bs={object_size} count=1 of={self.redpanda.cache_dir}/garbage_$n.bin ; done", |
| 55 | + ) |
| 56 | + |
| 57 | + self.redpanda.start(clean_nodes=False) |
| 58 | + |
| 59 | + # Assert initial conditions. |
| 60 | + usage = self.admin.get_local_storage_usage(node) |
| 61 | + assert usage['cloud_storage_cache_objects'] == num_objects, usage |
| 62 | + |
| 63 | + # Trim with default settings. Nothing should be trimmed as we are well |
| 64 | + # below reasonable limits. |
| 65 | + # Wrapped with wait_until as it will fail until a background fiber |
| 66 | + # updates information about free disk space. |
| 67 | + wait_until(lambda: self.admin.cloud_storage_trim( |
| 68 | + byte_limit=None, object_limit=None, node=node), |
| 69 | + timeout_sec=30, |
| 70 | + backoff_sec=1, |
| 71 | + retry_on_exc=True) |
| 72 | + |
| 73 | + usage = self.admin.get_local_storage_usage(node) |
| 74 | + assert usage['cloud_storage_cache_objects'] == num_objects, usage |
| 75 | + |
| 76 | + # Trim with byte limit. We should trim half of objects. |
| 77 | + self.admin.cloud_storage_trim(byte_limit=object_size * 50, |
| 78 | + object_limit=None, |
| 79 | + node=node) |
| 80 | + usage = self.admin.get_local_storage_usage(node) |
| 81 | + |
| 82 | + # Although we set the limit to size of 50 objects, the value |
| 83 | + # gets multiplied by 0.8 internally so we end up with 40 objects left. |
| 84 | + assert usage['cloud_storage_cache_objects'] == 40, usage |
| 85 | + |
| 86 | + # Trim with object limit. We should trim 20 objects. |
| 87 | + self.admin.cloud_storage_trim(byte_limit=None, |
| 88 | + object_limit=20, |
| 89 | + node=node) |
| 90 | + usage = self.admin.get_local_storage_usage(node) |
| 91 | + |
| 92 | + # Although we set the limit to 20 objects, the value |
| 93 | + # gets multiplied by 0.8 internally so we end up with 16 objects left. |
| 94 | + assert usage['cloud_storage_cache_objects'] == 16, usage |
0 commit comments