Skip to content

Instantly share code, notes, and snippets.

@alistairncoles
Created March 21, 2016 20:06
Show Gist options
  • Save alistairncoles/0dd102384c47bfe95787 to your computer and use it in GitHub Desktop.
Save alistairncoles/0dd102384c47bfe95787 to your computer and use it in GitHub Desktop.
container sync fixups
diff --git a/swift/container/sync.py b/swift/container/sync.py
index 95cd38a..cbf6a34 100644
--- a/swift/container/sync.py
+++ b/swift/container/sync.py
@@ -409,10 +409,10 @@ class ContainerSync(Daemon):
self.logger.exception(_('ERROR Syncing %s'),
broker if broker else path)
- def _update_sync_to_headers(self, sync_to, name, realm_key, user_key,
- realm, method, headers):
+ def _get_sync_headers(self, sync_to, name, realm_key, user_key, realm,
+ method, timestamp_str):
"""
- Updates container sync headers
+ Returns container sync headers
:param sync_to: The URL to the remote container.
:param name: The name of the object
@@ -424,24 +424,24 @@ class ContainerSync(Daemon):
:param realm: The realm from self.realms_conf, if there is one.
If None, fallback to using the older allowed_sync_hosts
way of syncing.
- :param method: HTTP method to create sig with
- :param headers: headers to update with container sync headers
-
- :returns: True if object already exists in remote
+ :param method: HTTP method to create signature with
+ :param timestamp_str: string representation of object x-timestamp
+ :returns: a dict containing appropriate container sync auth header
"""
+ headers = {'x-timestamp': timestamp_str}
if realm and realm_key:
nonce = uuid.uuid4().hex
path = urlparse(sync_to).path + '/' + quote(name)
sig = self.realms_conf.get_sig(method, path,
- headers.get('x-timestamp', 0),
+ timestamp_str,
nonce, realm_key,
user_key)
- headers['x-container-sync-auth'] = '%s %s %s' % (realm,
- nonce,
- sig)
+ headers['x-container-sync-auth'] = '%s %s %s' % (realm, nonce, sig)
else:
headers['x-container-sync-key'] = user_key
+ return headers
+
def _object_in_remote_container(self, name, timestamp, sync_to, user_key,
realm, realm_key):
"""
@@ -462,10 +462,9 @@ class ContainerSync(Daemon):
allowed_sync_hosts way of syncing.
:returns: True if object already exists in remote
"""
- headers = {}
- headers['x-timestamp'] = timestamp.internal
- self._update_sync_to_headers(sync_to, name, realm_key,
- user_key, realm, 'HEAD', headers)
+ headers = self._get_sync_headers(
+ sync_to, name, realm_key, user_key, realm, 'HEAD',
+ timestamp.internal)
try:
metadata, _ = head_object(sync_to, name=name,
headers=headers,
@@ -515,11 +514,10 @@ class ContainerSync(Daemon):
if row['deleted']:
# when sync'ing a deleted object, use ts_data - this is the
# timestamp of the source tombstone
+ headers = self._get_sync_headers(
+ sync_to, row['name'], realm_key, user_key, realm, 'DELETE',
+ ts_data.internal)
try:
- headers = {'x-timestamp': ts_data.internal}
- self._update_sync_to_headers(sync_to, row['name'],
- realm_key, user_key,
- realm, 'DELETE', headers)
delete_object(sync_to, name=row['name'], headers=headers,
proxy=self.select_http_proxy(),
logger=self.logger,
@@ -576,8 +574,9 @@ class ContainerSync(Daemon):
if 'content-type' in headers:
headers['content-type'] = clean_content_type(
headers['content-type'])
- self._update_sync_to_headers(sync_to, row['name'], realm_key,
- user_key, realm, 'PUT', headers)
+ headers.update(self._get_sync_headers(
+ sync_to, row['name'], realm_key, user_key, realm, 'PUT',
+ headers['x-timestamp']))
put_object(sync_to, name=row['name'], headers=headers,
contents=FileLikeIter(body),
proxy=self.select_http_proxy(), logger=self.logger,
diff --git a/test/unit/container/test_sync.py b/test/unit/container/test_sync.py
index 88122db..7a79127 100644
--- a/test/unit/container/test_sync.py
+++ b/test/unit/container/test_sync.py
@@ -1101,12 +1101,17 @@ class TestContainerSync(unittest.TestCase):
def fake_put_object(*args, **kwargs):
actual_puts.append((args, kwargs))
- def fake_head_object(*args, **kwargs):
- raise ClientException('test client exception', http_status=404)
+ def make_fake_head_object(exception=None):
+ def fake_head_object(*args, **kwargs):
+ if exception:
+ raise exception
+ return ({}, {})
+ return fake_head_object
cs._object_in_remote_container = orig_object_in_rcontainer
sync.put_object = fake_put_object
- sync.head_object = fake_head_object
+ sync.head_object = make_fake_head_object(
+ ClientException('test client exception', http_status=404))
self.assertTrue(cs.container_sync_row(
test_row, 'http://sync/to/path',
'key', FakeContainerBroker('broker'),
@@ -1116,10 +1121,8 @@ class TestContainerSync(unittest.TestCase):
# No additional errors
self.assertEqual(cs.container_failures, excepted_failure_count)
- def fake_head_object(*args, **kwargs):
- raise ClientException('test client exception', http_status=401)
-
- sync.head_object = fake_head_object
+ sync.head_object = make_fake_head_object(
+ ClientException('test client exception', http_status=401))
self.assertFalse(cs.container_sync_row(
test_row, 'http://sync/to/path',
'key', FakeContainerBroker('broker'),
@@ -1129,10 +1132,7 @@ class TestContainerSync(unittest.TestCase):
excepted_failure_count += 1
self.assertEqual(cs.container_failures, excepted_failure_count)
- def fake_head_object(*args, **kwargs):
- raise Exception()
-
- sync.head_object = fake_head_object
+ sync.head_object = make_fake_head_object(Exception())
self.assertFalse(cs.container_sync_row(
test_row,
'http://sync/to/path',
@@ -1143,10 +1143,7 @@ class TestContainerSync(unittest.TestCase):
excepted_failure_count += 1
self.assertEqual(cs.container_failures, excepted_failure_count)
- def fake_head_object(*args, **kwargs):
- return ({}, {})
-
- sync.head_object = fake_head_object
+ sync.head_object = make_fake_head_object()
self.assertTrue(cs.container_sync_row(
test_row, 'http://sync/to/path',
'key', FakeContainerBroker('broker'),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment