Fix potential missing key error in container_info
If upgrading from a non-storage policy enabled version of swift to a storage policy enabled version its possible that memcached will have an info structure that does not contain the 'storage_policy" key resulting in an unhandled exception during the lookup. The fix is to simply make sure we never return the dict without a storage_policy key defined; if it doesn't exist its safe to make it '0' as this means you're in the update scenario and there's xno other possibility. Change-Id: If8e8f66d32819c5bfb2d1308e14643f3600ea6e9
This commit is contained in:
parent
7fcbbebbeb
commit
0800668557
@ -296,6 +296,7 @@ def get_container_info(env, app, swift_source=None):
|
||||
swift_source=swift_source)
|
||||
if not info:
|
||||
info = headers_to_container_info({}, 0)
|
||||
info.setdefault('storage_policy', '0')
|
||||
return info
|
||||
|
||||
|
||||
@ -988,6 +989,7 @@ class Controller(object):
|
||||
else:
|
||||
info['partition'] = part
|
||||
info['nodes'] = nodes
|
||||
info.setdefault('storage_policy', '0')
|
||||
return info
|
||||
|
||||
def _make_request(self, nodes, part, method, path, headers, query,
|
||||
|
@ -315,6 +315,7 @@ class TestFuncs(unittest.TestCase):
|
||||
req = Request.blank("/v1/AUTH_account/cont",
|
||||
environ={'swift.cache': FakeCache({})})
|
||||
resp = get_container_info(req.environ, FakeApp())
|
||||
self.assertEquals(resp['storage_policy'], '0')
|
||||
self.assertEquals(resp['bytes'], 6666)
|
||||
self.assertEquals(resp['object_count'], 1000)
|
||||
|
||||
@ -342,6 +343,7 @@ class TestFuncs(unittest.TestCase):
|
||||
req = Request.blank("/v1/account/cont",
|
||||
environ={'swift.cache': FakeCache(cache_stub)})
|
||||
resp = get_container_info(req.environ, FakeApp())
|
||||
self.assertEquals(resp['storage_policy'], '0')
|
||||
self.assertEquals(resp['bytes'], 3333)
|
||||
self.assertEquals(resp['object_count'], 10)
|
||||
self.assertEquals(resp['status'], 404)
|
||||
|
@ -119,6 +119,20 @@ class TestObjControllerWriteAffinity(unittest.TestCase):
|
||||
StoragePolicy(2, 'two'),
|
||||
])
|
||||
class TestObjController(unittest.TestCase):
|
||||
container_info = {
|
||||
'partition': 1,
|
||||
'nodes': [
|
||||
{'ip': '127.0.0.1', 'port': '1', 'device': 'sda'},
|
||||
{'ip': '127.0.0.1', 'port': '2', 'device': 'sda'},
|
||||
{'ip': '127.0.0.1', 'port': '3', 'device': 'sda'},
|
||||
],
|
||||
'write_acl': None,
|
||||
'read_acl': None,
|
||||
'storage_policy': None,
|
||||
'sync_key': None,
|
||||
'versions': None,
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
# setup fake rings with handoffs
|
||||
self.obj_ring = FakeRing(max_more_nodes=3)
|
||||
@ -132,21 +146,15 @@ class TestObjController(unittest.TestCase):
|
||||
container_ring=FakeRing(), logger=logger)
|
||||
|
||||
class FakeContainerInfoObjController(proxy_server.ObjectController):
|
||||
pass
|
||||
self.controller = FakeContainerInfoObjController
|
||||
self.controller.container_info = mock.MagicMock(return_value={
|
||||
'partition': 1,
|
||||
'nodes': [
|
||||
{'ip': '127.0.0.1', 'port': '1', 'device': 'sda'},
|
||||
{'ip': '127.0.0.1', 'port': '2', 'device': 'sda'},
|
||||
{'ip': '127.0.0.1', 'port': '3', 'device': 'sda'},
|
||||
],
|
||||
'write_acl': None,
|
||||
'read_acl': None,
|
||||
'storage_policy': None,
|
||||
'sync_key': None,
|
||||
'versions': None})
|
||||
self.app.object_controller = self.controller
|
||||
|
||||
def container_info(controller, *args, **kwargs):
|
||||
patch_path = 'swift.proxy.controllers.base.get_info'
|
||||
with mock.patch(patch_path) as mock_get_info:
|
||||
mock_get_info.return_value = dict(self.container_info)
|
||||
return super(FakeContainerInfoObjController,
|
||||
controller).container_info(*args, **kwargs)
|
||||
|
||||
self.app.object_controller = FakeContainerInfoObjController
|
||||
|
||||
def test_PUT_simple(self):
|
||||
req = swift.common.swob.Request.blank('/v1/a/c/o', method='PUT')
|
||||
@ -244,8 +252,7 @@ class TestObjController(unittest.TestCase):
|
||||
def test_container_sync_put_x_timestamp_not_found(self):
|
||||
test_indexes = [None] + [int(p) for p in POLICIES]
|
||||
for policy_index in test_indexes:
|
||||
self.controller.container_info.return_value['storage_policy'] = \
|
||||
policy_index
|
||||
self.container_info['storage_policy'] = policy_index
|
||||
put_timestamp = utils.Timestamp(time.time()).normal
|
||||
req = swob.Request.blank(
|
||||
'/v1/a/c/o', method='PUT', headers={
|
||||
@ -263,8 +270,7 @@ class TestObjController(unittest.TestCase):
|
||||
def test_container_sync_put_x_timestamp_match(self):
|
||||
test_indexes = [None] + [int(p) for p in POLICIES]
|
||||
for policy_index in test_indexes:
|
||||
self.controller.container_info.return_value['storage_policy'] = \
|
||||
policy_index
|
||||
self.container_info['storage_policy'] = policy_index
|
||||
put_timestamp = utils.Timestamp(time.time()).normal
|
||||
req = swob.Request.blank(
|
||||
'/v1/a/c/o', method='PUT', headers={
|
||||
@ -282,8 +288,7 @@ class TestObjController(unittest.TestCase):
|
||||
ts = (utils.Timestamp(t) for t in itertools.count(int(time.time())))
|
||||
test_indexes = [None] + [int(p) for p in POLICIES]
|
||||
for policy_index in test_indexes:
|
||||
self.controller.container_info.return_value['storage_policy'] = \
|
||||
policy_index
|
||||
self.container_info['storage_policy'] = policy_index
|
||||
req = swob.Request.blank(
|
||||
'/v1/a/c/o', method='PUT', headers={
|
||||
'Content-Length': 0,
|
||||
@ -392,5 +397,25 @@ class TestObjController(unittest.TestCase):
|
||||
self.assertEquals(req.environ.get('swift.log_info'), None)
|
||||
|
||||
|
||||
@patch_policies([
|
||||
StoragePolicy(0, 'zero', True),
|
||||
StoragePolicy(1, 'one'),
|
||||
StoragePolicy(2, 'two'),
|
||||
])
|
||||
class TestObjControllerLegacyCache(TestObjController):
|
||||
"""
|
||||
This test pretends like memcache returned a stored value that should
|
||||
resemble whatever "old" format. It catches KeyErrors you'd get if your
|
||||
code was expecting some new format during a rolling upgrade.
|
||||
"""
|
||||
|
||||
container_info = {
|
||||
'read_acl': None,
|
||||
'write_acl': None,
|
||||
'sync_key': None,
|
||||
'versions': None,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user