From dd4a7ac0fb422718584c801918fcd71327bd54cc Mon Sep 17 00:00:00 2001 From: Edward Hope-Morley <edward.hope-morley@canonical.com> Date: Tue, 24 Nov 2015 13:35:26 +0000 Subject: [PATCH] [hopem,r=] Add support for settting swift-storage unit rsyncd acls. Partially-Closes-Bug: 1427361 --- hooks/swift_hooks.py | 62 ++++++++++++++++++++++++++++------ hooks/upgrade-charm | 1 + unit_tests/test_swift_hooks.py | 36 +++++++++++++++++++- 3 files changed, 87 insertions(+), 12 deletions(-) create mode 120000 hooks/upgrade-charm diff --git a/hooks/swift_hooks.py b/hooks/swift_hooks.py index ec37af6..baf462f 100755 --- a/hooks/swift_hooks.py +++ b/hooks/swift_hooks.py @@ -2,6 +2,7 @@ import os import sys +import time from subprocess import ( check_call, @@ -192,6 +193,44 @@ def storage_joined(): mark_www_rings_deleted() +def get_host_ip(rid=None, unit=None): + addr = relation_get('private-address', rid=rid, unit=unit) + if config('prefer-ipv6'): + host_ip = format_ipv6_addr(addr) + if host_ip: + return host_ip + else: + msg = ("Did not get IPv6 address from storage relation " + "(got=%s)" % (addr)) + log(msg, level=WARNING) + + return openstack.get_host_ip(addr) + + +def update_rsync_acls(): + """Get Host IP of each storage unit and broadcast acl to all units.""" + hosts = [] + + if not is_elected_leader(SWIFT_HA_RES): + log("Skipping rsync acl update since not leader", level=DEBUG) + return + + # Get all unit addresses + for rid in relation_ids('swift-storage'): + for unit in related_units(rid): + hosts.append(get_host_ip(rid=rid, unit=unit)) + + rsync_hosts = ' '.join(hosts) + log("Broadcasting acl '%s' to all storage units" % (rsync_hosts), + level=DEBUG) + # We add a timestamp so that the storage units know which is the newest + settings = {'rsync_allowed_hosts': rsync_hosts, + 'timestamp': time.time()} + for rid in relation_ids('swift-storage'): + for unit in related_units(rid): + relation_set(unit=unit, relation_id=rid, **settings) + + @hooks.hook('swift-storage-relation-changed') @pause_aware_restart_on_change(restart_map()) def storage_changed(): @@ -206,17 +245,13 @@ def storage_changed(): return log("Leader established, updating ring builders", level=INFO) - addr = relation_get('private-address') - if config('prefer-ipv6'): - host_ip = format_ipv6_addr(addr) - if not host_ip: - msg = ("Did not get IPv6 address from storage relation " - "(got=%s)" % (addr)) - log(msg, level=WARNING) - host_ip = addr - return - else: - host_ip = openstack.get_host_ip(addr) + host_ip = get_host_ip() + if not host_ip: + log("No host ip found in storage relation - deferring storage " + "relation", level=WARNING) + return + + update_rsync_acls() zone = get_zone(config('zone-assignment')) node_settings = { @@ -540,6 +575,11 @@ def update_nrpe_config(): nrpe_setup.write() +@hooks.hook('upgrade-charm') +def upgrade_charm(): + update_rsync_acls() + + def main(): try: hooks.execute(sys.argv) diff --git a/hooks/upgrade-charm b/hooks/upgrade-charm new file mode 120000 index 0000000..8623fba --- /dev/null +++ b/hooks/upgrade-charm @@ -0,0 +1 @@ +swift_hooks.py \ No newline at end of file diff --git a/unit_tests/test_swift_hooks.py b/unit_tests/test_swift_hooks.py index 84bf0bf..e16061f 100644 --- a/unit_tests/test_swift_hooks.py +++ b/unit_tests/test_swift_hooks.py @@ -1,8 +1,12 @@ -from mock import patch import sys import unittest import uuid +from mock import ( + call, + patch, +) + sys.path.append("hooks") with patch('charmhelpers.core.hookenv.log'): with patch('lib.swift_utils.is_paused') as is_paused: @@ -129,3 +133,33 @@ class SwiftHooksTestCase(unittest.TestCase): requested_roles='Operator,Monitor', relation_id=None ) + + @patch.object(swift_hooks.time, 'time') + @patch.object(swift_hooks, 'get_host_ip') + @patch.object(swift_hooks, 'is_elected_leader') + @patch.object(swift_hooks, 'related_units') + @patch.object(swift_hooks, 'relation_ids') + @patch.object(swift_hooks, 'relation_set') + def test_update_rsync_acls(self, mock_rel_set, mock_rel_ids, + mock_rel_units, mock_is_leader, + mock_get_host_ip, mock_time): + mock_time.return_value = 1234 + mock_is_leader.return_value = True + mock_rel_ids.return_value = ['storage:1'] + mock_rel_units.return_value = ['unit/0', 'unit/1'] + + def fake_get_host_ip(rid, unit): + if unit == 'unit/0': + return '10.0.0.1' + elif unit == 'unit/1': + return '10.0.0.2' + + mock_get_host_ip.side_effect = fake_get_host_ip + swift_hooks.update_rsync_acls() + calls = [call(rsync_allowed_hosts='10.0.0.1 10.0.0.2', + relation_id='storage:1', + unit='unit/0', timestamp=1234), + call(rsync_allowed_hosts='10.0.0.1 10.0.0.2', + relation_id='storage:1', + unit='unit/1', timestamp=1234)] + mock_rel_set.assert_has_calls(calls)