Add probe test for reconciler with object versioning

Verify that the reconciler is able to move objects to a container that
has, or will have, versioning enabled, and versions of the moved object
can subsequently be created.

Change-Id: I019447614ebadbb9e2cc8a18c0369bc16a89c0d9
This commit is contained in:
Alistair Coles 2024-11-26 12:55:19 +00:00
parent fa889358ac
commit e751ccfb27
2 changed files with 86 additions and 13 deletions

View File

@ -140,7 +140,7 @@ class BaseBrain(object):
tuple(self.servers.stop(number=n) for n in self.handoff_numbers) tuple(self.servers.stop(number=n) for n in self.handoff_numbers)
@command @command
def put_container(self, policy_index=None): def put_container(self, policy_index=None, extra_headers=None):
""" """
put container with next storage policy put container with next storage policy
""" """
@ -155,6 +155,8 @@ class BaseBrain(object):
policy = self.policy policy = self.policy
headers = {'X-Storage-Policy': policy.name} headers = {'X-Storage-Policy': policy.name}
if extra_headers:
headers.update(extra_headers)
self.client.put_container(self.container_name, headers=headers) self.client.put_container(self.container_name, headers=headers)
@command @command
@ -201,6 +203,10 @@ class PublicBrainClient(object):
return client.post_container(self.url, self.token, container_name, return client.post_container(self.url, self.token, container_name,
headers) headers)
def get_container(self, container_name, headers=None, query_string=None):
return client.get_container(self.url, self.token, container_name,
headers=headers, query_string=query_string)
def delete_container(self, container_name): def delete_container(self, container_name):
return client.delete_container(self.url, self.token, container_name) return client.delete_container(self.url, self.token, container_name)

View File

@ -34,11 +34,11 @@ from swiftclient import ClientException
TIMEOUT = 60 TIMEOUT = 60
class TestContainerMergePolicyIndex(ReplProbeTest): class BaseTestContainerMergePolicyIndex(ReplProbeTest):
@unittest.skipIf(len(ENABLED_POLICIES) < 2, "Need more than one policy") @unittest.skipIf(len(ENABLED_POLICIES) < 2, "Need more than one policy")
def setUp(self): def setUp(self):
super(TestContainerMergePolicyIndex, self).setUp() super(BaseTestContainerMergePolicyIndex, self).setUp()
self.container_name = 'container-%s' % uuid.uuid4() self.container_name = 'container-%s' % uuid.uuid4()
self.object_name = 'object-%s' % uuid.uuid4() self.object_name = 'object-%s' % uuid.uuid4()
self.brain = BrainSplitter(self.url, self.token, self.container_name, self.brain = BrainSplitter(self.url, self.token, self.container_name,
@ -60,16 +60,7 @@ class TestContainerMergePolicyIndex(ReplProbeTest):
self.account, self.container_name, self.object_name, self.account, self.container_name, self.object_name,
int(policy_index), TIMEOUT)) int(policy_index), TIMEOUT))
def test_merge_storage_policy_index(self): def _do_test_merge_storage_policy_index(self):
# generic split brain
self.brain.stop_primary_half()
self.brain.put_container()
self.brain.start_primary_half()
self.brain.stop_handoff_half()
self.brain.put_container()
self.brain.put_object(headers={'x-object-meta-test': 'custom-meta'},
contents=b'VERIFY')
self.brain.start_handoff_half()
# make sure we have some manner of split brain # make sure we have some manner of split brain
container_part, container_nodes = self.container_ring.get_nodes( container_part, container_nodes = self.container_ring.get_nodes(
self.account, self.container_name) self.account, self.container_name)
@ -147,6 +138,20 @@ class TestContainerMergePolicyIndex(ReplProbeTest):
self.assertEqual(b'VERIFY', data) self.assertEqual(b'VERIFY', data)
self.assertEqual('custom-meta', headers['x-object-meta-test']) self.assertEqual('custom-meta', headers['x-object-meta-test'])
class TestContainerMergePolicyIndex(BaseTestContainerMergePolicyIndex):
def test_merge_storage_policy_index(self):
# generic split brain
self.brain.stop_primary_half()
self.brain.put_container()
self.brain.start_primary_half()
self.brain.stop_handoff_half()
self.brain.put_container()
self.brain.put_object(headers={'x-object-meta-test': 'custom-meta'},
contents=b'VERIFY')
self.brain.start_handoff_half()
self._do_test_merge_storage_policy_index()
def test_reconcile_delete(self): def test_reconcile_delete(self):
# generic split brain # generic split brain
self.brain.stop_primary_half() self.brain.stop_primary_half()
@ -578,5 +583,67 @@ class TestReservedNamespaceMergePolicyIndex(TestContainerMergePolicyIndex):
'SLO does not allow parts in the reserved namespace') 'SLO does not allow parts in the reserved namespace')
class TestVersioningMergePolicyIndex(BaseTestContainerMergePolicyIndex):
def test_merge_storage_policy_index_before_versioning_enabled(self):
# reconcile split brain container...
self.brain.stop_primary_half()
self.brain.put_container()
self.brain.start_primary_half()
self.brain.stop_handoff_half()
self.brain.put_container()
self.brain.put_object(headers={'x-object-meta-test': 'custom-meta'},
contents=b'VERIFY')
self.brain.start_handoff_half()
self._do_test_merge_storage_policy_index()
# .. then enable versioning and overwrite the moved object
self.brain.client.post_container(
self.container_name, headers={'X-Versions-Enabled': 'True'})
self.brain.client.put_object(
self.container_name, self.object_name, {}, b'MODIFIED')
# check both versions...
hdrs, listing = self.brain.client.get_container(
self.container_name, query_string='format=json&versions=true')
self.assertEqual(2, len(listing), listing)
hdrs, content = self.brain.client.get_object(
self.container_name,
listing[0]['name'],
query_string='version-id=%s' % listing[0]['version_id'])
self.assertEqual(b'MODIFIED', content)
hdrs, content = self.brain.client.get_object(
self.container_name,
listing[1]['name'],
query_string='version-id=%s' % listing[1]['version_id'])
self.assertEqual(b'VERIFY', content)
def test_merge_storage_policy_index_after_versioning_enabled(self):
# reconcile split brain versioning container...
self.brain.stop_primary_half()
self.brain.put_container(extra_headers={'X-Versions-Enabled': 'True'})
self.brain.start_primary_half()
self.brain.stop_handoff_half()
self.brain.put_container(extra_headers={'X-Versions-Enabled': 'True'})
self.brain.put_object(headers={'x-object-meta-test': 'custom-meta'},
contents=b'VERIFY')
self.brain.start_handoff_half()
self._do_test_merge_storage_policy_index()
# .. then overwrite the moved object
self.brain.client.put_object(
self.container_name, self.object_name, {}, b'MODIFIED')
# check both versions...
hdrs, listing = self.brain.client.get_container(
self.container_name, query_string='format=json&versions=true')
self.assertEqual(2, len(listing), listing)
hdrs, content = self.brain.client.get_object(
self.container_name,
listing[0]['name'],
query_string='version-id=%s' % listing[0]['version_id'])
self.assertEqual(b'MODIFIED', content)
hdrs, content = self.brain.client.get_object(
self.container_name,
listing[1]['name'],
query_string='version-id=%s' % listing[1]['version_id'])
self.assertEqual(b'VERIFY', content)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()