From d661ff39cf2afb7b935533be6493d7d678020ada Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 12 Oct 2015 15:02:35 -0700 Subject: [PATCH] Create a node for each device. Fixes LP Bug#1479938 --- hooks/swift_hooks.py | 8 ++++++-- lib/swift_utils.py | 28 +++++++++++----------------- unit_tests/test_swift_utils.py | 11 ++++++++--- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/hooks/swift_hooks.py b/hooks/swift_hooks.py index ac67e11..cfffb40 100755 --- a/hooks/swift_hooks.py +++ b/hooks/swift_hooks.py @@ -228,11 +228,15 @@ def storage_changed(): # Allow for multiple devs per unit, passed along as a : separated list # Update and balance rings. + nodes = [] devs = relation_get('device') if devs: - node_settings['devices'] = devs.split(':') + for dev in devs.split(':'): + node = {k: v for k, v in node_settings.items()} + node['device'] = dev + nodes.append(node) - update_rings(node_settings) + update_rings(nodes) if not is_paused(): # Restart proxy here in case no config changes made (so # pause_aware_restart_on_change() ineffective). diff --git a/lib/swift_utils.py b/lib/swift_utils.py index 9385421..73fa5c6 100644 --- a/lib/swift_utils.py +++ b/lib/swift_utils.py @@ -402,18 +402,13 @@ def initialize_ring(path, part_power, replicas, min_hours): _write_ring(ring, path) -def exists_in_ring(ring_path, node, blockdev): +def exists_in_ring(ring_path, node): ring = _load_builder(ring_path).to_dict() node['port'] = ring_port(ring_path, node) - # Make a nodecopy dict, to add a 'device' key for the purpose - # of below comparison, as it doesn't have a single-valued 'device' - # but a list as e.g. 'devices': ['sdb', 'sdc', ...] - nodecopy = {k: v for k, v in node.items()} - nodecopy['device'] = blockdev for dev in ring['devs']: - d = [(i, dev[i]) for i in dev if i in nodecopy and i != 'zone'] - n = [(i, nodecopy[i]) for i in nodecopy if i in dev and i != 'zone'] + d = [(i, dev[i]) for i in dev if i in node and i != 'zone'] + n = [(i, node[i]) for i in node if i in dev and i != 'zone'] if sorted(d) == sorted(n): log('Node already exists in ring (%s).' % ring_path, level=INFO) @@ -422,7 +417,7 @@ def exists_in_ring(ring_path, node, blockdev): return False -def add_to_ring(ring_path, node, device): +def add_to_ring(ring_path, node): ring = _load_builder(ring_path) port = ring_port(ring_path, node) @@ -436,7 +431,7 @@ def add_to_ring(ring_path, node, device): 'zone': node['zone'], 'ip': node['ip'], 'port': port, - 'device': device, + 'device': node['device'], 'weight': 100, 'meta': '', } @@ -787,7 +782,7 @@ def sync_builders_and_rings_if_changed(f): @sync_builders_and_rings_if_changed -def update_rings(node_settings=None, min_part_hours=None): +def update_rings(nodes=[], min_part_hours=None): """Update builder with node settings and balance rings if necessary. Also update min_part_hours if provided. @@ -819,12 +814,11 @@ def update_rings(node_settings=None, min_part_hours=None): else: balance_required = True - if node_settings: - for blockdev in node_settings.get('devices', []): - for ring in SWIFT_RINGS.itervalues(): - if not exists_in_ring(ring, node_settings, blockdev): - add_to_ring(ring, node_settings, blockdev) - balance_required = True + for node in nodes: + for ring in SWIFT_RINGS.itervalues(): + if not exists_in_ring(ring, node): + add_to_ring(ring, node) + balance_required = True if balance_required: balance_rings() diff --git a/unit_tests/test_swift_utils.py b/unit_tests/test_swift_utils.py index ebdf9ee..15ecd1c 100644 --- a/unit_tests/test_swift_utils.py +++ b/unit_tests/test_swift_utils.py @@ -129,13 +129,18 @@ class SwiftUtilsTestCase(unittest.TestCase): 'account_port': 6002, 'zone': 1, 'ip': '1.2.3.4', - 'devices': devices } for path in swift_utils.SWIFT_RINGS.itervalues(): swift_utils.initialize_ring(path, 8, 3, 0) # verify all devices added to each ring - swift_utils.update_rings(node_settings) + nodes = [] + for dev in devices: + node = {k: v for k, v in node_settings.items()} + node['device'] = dev + nodes.append(node) + + swift_utils.update_rings(nodes) for path in swift_utils.SWIFT_RINGS.itervalues(): devs = swift_utils._load_builder(path).to_dict()['devs'] added_devices = [dev['device'] for dev in devs] @@ -143,7 +148,7 @@ class SwiftUtilsTestCase(unittest.TestCase): # try re-adding, assert add_to_ring was not called with mock.patch('swift_utils.add_to_ring') as mock_add_to_ring: - swift_utils.update_rings(node_settings) + swift_utils.update_rings(nodes) self.assertFalse(mock_add_to_ring.called) @mock.patch('lib.swift_utils.get_broker_token')