From 845b8beeb5d7b32fce66e6e9100d232970dcc595 Mon Sep 17 00:00:00 2001 From: "Juan J. Martinez" Date: Thu, 7 Nov 2013 11:36:55 +0000 Subject: [PATCH] Default region loading an old-style pickled ring This is to support upgrades from swift < 1.8 using old-style pickled rings to 1.10. Old-style pickled rings won't have region information. Change-Id: I18b2acba3d346e41def9d25d3d4dbd12705e5375 Closes-Bug: #1248919 --- swift/common/ring/ring.py | 5 ++- test/unit/common/ring/test_ring.py | 52 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/swift/common/ring/ring.py b/swift/common/ring/ring.py index 8f0d2835d1..31ebe60b9e 100644 --- a/swift/common/ring/ring.py +++ b/swift/common/ring/ring.py @@ -150,9 +150,12 @@ class Ring(object): # and replication_port are required for # replication process. An old replication # ring doesn't contain this parameters into - # device. + # device. Old-style pickled rings won't have + # region information. for dev in self._devs: if dev: + if 'region' not in dev: + dev.setdefault('region', 1) if 'ip' in dev: dev.setdefault('replication_ip', dev['ip']) if 'port' in dev: diff --git a/test/unit/common/ring/test_ring.py b/test/unit/common/ring/test_ring.py index 42852042e3..c423a946c1 100644 --- a/test/unit/common/ring/test_ring.py +++ b/test/unit/common/ring/test_ring.py @@ -263,6 +263,58 @@ class TestRing(unittest.TestCase): ring_name='without_replication') self.assertEquals(self.ring.devs, intended_devs) + def test_reload_old_style_pickled_ring(self): + devs = [{'id': 0, 'zone': 0, + 'weight': 1.0, 'ip': '10.1.1.1', + 'port': 6000}, + {'id': 1, 'zone': 0, + 'weight': 1.0, 'ip': '10.1.1.1', + 'port': 6000}, + None, + {'id': 3, 'zone': 2, + 'weight': 1.0, 'ip': '10.1.2.1', + 'port': 6000}, + {'id': 4, 'zone': 2, + 'weight': 1.0, 'ip': '10.1.2.2', + 'port': 6000}] + intended_devs = [{'id': 0, 'region': 1, 'zone': 0, 'weight': 1.0, + 'ip': '10.1.1.1', 'port': 6000, + 'replication_ip': '10.1.1.1', + 'replication_port': 6000}, + {'id': 1, 'region': 1, 'zone': 0, 'weight': 1.0, + 'ip': '10.1.1.1', 'port': 6000, + 'replication_ip': '10.1.1.1', + 'replication_port': 6000}, + None, + {'id': 3, 'region': 1, 'zone': 2, 'weight': 1.0, + 'ip': '10.1.2.1', 'port': 6000, + 'replication_ip': '10.1.2.1', + 'replication_port': 6000}, + {'id': 4, 'region': 1, 'zone': 2, 'weight': 1.0, + 'ip': '10.1.2.2', 'port': 6000, + 'replication_ip': '10.1.2.2', + 'replication_port': 6000}] + + # simulate an old-style pickled ring + testgz = os.path.join(self.testdir, + 'without_replication_or_region.ring.gz') + ring_data = ring.RingData(self.intended_replica2part2dev_id, + devs, + self.intended_part_shift) + # an old-style pickled ring won't have region data + for dev in ring_data.devs: + if dev: + del dev["region"] + gz_file = GzipFile(testgz, 'wb') + pickle.dump(ring_data, gz_file, protocol=2) + gz_file.close() + + self.ring = ring.Ring( + self.testdir, + reload_time=self.intended_reload_time, + ring_name='without_replication_or_region') + self.assertEquals(self.ring.devs, intended_devs) + def test_get_part(self): part1 = self.ring.get_part('a') nodes1 = self.ring.get_part_nodes(part1)