From 367a2aedcbe5da5559ab116f11ce775b857d7465 Mon Sep 17 00:00:00 2001 From: utkarshbhatthere Date: Thu, 22 Sep 2022 11:39:37 +0000 Subject: [PATCH] Adds primary/secondary multisite relation A new relation with primary/secondary nomenclature is added and the old master/slave relation is marked as *Deprecated*. In future, master/slave relation would be completely removed. Change-Id: I9cda48b74a20aaa9a41baedc79332bfaf13951d3 func-test-pr: https://github.com/openstack-charmers/zaza-openstack-tests/pull/926 --- hooks/hooks.py | 57 +++++++++++++--- ...ation-broken => primary-relation-departed} | 0 ...lation-changed => primary-relation-joined} | 0 ...tion-broken => secondary-relation-changed} | 0 ...ion-joined => secondary-relation-departed} | 0 hooks/utils.py | 20 +++--- metadata.yaml | 4 ++ unit_tests/test_hooks.py | 68 +++++++++---------- 8 files changed, 96 insertions(+), 53 deletions(-) rename hooks/{master-relation-broken => primary-relation-departed} (100%) rename hooks/{master-relation-changed => primary-relation-joined} (100%) rename hooks/{slave-relation-broken => secondary-relation-changed} (100%) rename hooks/{slave-relation-joined => secondary-relation-departed} (100%) diff --git a/hooks/hooks.py b/hooks/hooks.py index 7c5e9cd0..f7abed61 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -340,7 +340,7 @@ def mon_relation(rid=None, unit=None): # NOTE(jamespage): # Multi-site deployments need to defer restart as the - # zone is not created until the master relation is + # zone is not created until the primary relation is # joined; restarting here will cause a restart burst # in systemd and stop the process restarting once # zone configuration is complete. @@ -690,8 +690,8 @@ def radosgw_user_changed(relation_id=None): 'daemon-id': socket.gethostname()}) -@hooks.hook('master-relation-joined') -def master_relation_joined(relation_id=None): +@hooks.hook('primary-relation-joined') +def primary_relation_joined(relation_id=None): if not ready_for_service(legacy=False): log('unit not ready, deferring multisite configuration') return @@ -742,9 +742,9 @@ def master_relation_joined(relation_id=None): multisite.create_realm(realm, default=True) mutation = True - # Migration if master site has buckets configured. + # Migration if primary site has buckets configured. # Migration involves renaming existing zone/zongroups such that existing - # buckets and their objects can be preserved on the master site. + # buckets and their objects can be preserved on the primary site. if multisite.check_cluster_has_buckets() is True: log('Migrating to multisite with zone ({}) and zonegroup ({})' .format(zone, zonegroup), level=DEBUG) @@ -821,8 +821,8 @@ def master_relation_joined(relation_id=None): secret=secret) -@hooks.hook('master-relation-departed') -@hooks.hook('slave-relation-departed') +@hooks.hook('primary-relation-departed') +@hooks.hook('secondary-relation-departed') def multisite_relation_departed(): if not is_leader(): log('Cannot remove multisite relation, this unit is not the leader') @@ -868,8 +868,8 @@ def multisite_relation_departed(): raise RuntimeError("Residual multisite config at local site.") -@hooks.hook('slave-relation-changed') -def slave_relation_changed(relation_id=None, unit=None): +@hooks.hook('secondary-relation-changed') +def secondary_relation_changed(relation_id=None, unit=None): if not is_leader(): log('Cannot setup multisite configuration, this unit is not the ' 'leader') @@ -884,7 +884,7 @@ def slave_relation_changed(relation_id=None, unit=None): master_data.get('access_key'), master_data.get('secret'), master_data.get('url'))): - log("Defer processing until master RGW has provided required data") + log("Defer processing until primary RGW has provided required data") return public_url = '{}:{}'.format( @@ -933,6 +933,9 @@ def slave_relation_changed(relation_id=None, unit=None): if zone not in multisite.list_zones(): log('zone {} not found, creating now'.format(zone)) + multisite.pull_period(url=master_data['url'], + access_key=master_data['access_key'], + secret=master_data['secret']) multisite.create_zone(zone, endpoints=endpoints, default=False, master=False, @@ -953,6 +956,27 @@ def slave_relation_changed(relation_id=None, unit=None): log('No mutation detected.', 'INFO') +@hooks.hook('master-relation-departed') +@hooks.hook('slave-relation-departed') +def master_slave_relation_departed(): + log("departed relation is deprecated", "WARN") + multisite_relation_departed() + + +@hooks.hook('master-relation-joined') +def master_relation_joined(relation_id=None): + log("This relation is deprecated, use primary-secondary relation instead", + "WARN") + primary_relation_joined(relation_id) + + +@hooks.hook('slave-relation-changed') +def slave_relation_changed(relation_id=None, unit=None): + log("This relation is deprecated, use primary-secondary relation instead", + "WARN") + secondary_relation_changed(relation_id, unit) + + @hooks.hook('leader-settings-changed') def leader_settings_changed(): # NOTE: leader unit will only ever set leader storage @@ -962,19 +986,30 @@ def leader_settings_changed(): if restart_nonce_changed(leader_get('restart_nonce')): service_restart(service_name()) if not is_leader(): + # Deprecated Master/Slave relation for r_id in relation_ids('master'): master_relation_joined(r_id) + # Primary/Secondary relation + for r_id in relation_ids('primary'): + primary_relation_joined(r_id) for r_id in relation_ids('radosgw-user'): radosgw_user_changed(r_id) def process_multisite_relations(): - """Re-trigger any pending master/slave relations""" + """Re-trigger any pending multisite relations""" + # Deprecated Master/Slave relation for r_id in relation_ids('master'): master_relation_joined(r_id) for r_id in relation_ids('slave'): for unit in related_units(r_id): slave_relation_changed(r_id, unit) + # Primary/Secondary relation + for r_id in relation_ids('primary'): + primary_relation_joined(r_id) + for r_id in relation_ids('secondary'): + for unit in related_units(r_id): + secondary_relation_changed(r_id, unit) if __name__ == '__main__': diff --git a/hooks/master-relation-broken b/hooks/primary-relation-departed similarity index 100% rename from hooks/master-relation-broken rename to hooks/primary-relation-departed diff --git a/hooks/master-relation-changed b/hooks/primary-relation-joined similarity index 100% rename from hooks/master-relation-changed rename to hooks/primary-relation-joined diff --git a/hooks/slave-relation-broken b/hooks/secondary-relation-changed similarity index 100% rename from hooks/slave-relation-broken rename to hooks/secondary-relation-changed diff --git a/hooks/slave-relation-joined b/hooks/secondary-relation-departed similarity index 100% rename from hooks/slave-relation-joined rename to hooks/secondary-relation-departed diff --git a/hooks/utils.py b/hooks/utils.py index 80da68fc..97d71d9f 100644 --- a/hooks/utils.py +++ b/hooks/utils.py @@ -218,10 +218,14 @@ def check_optional_config_and_relations(configs): leader_get('secret'), leader_get('restart_nonce')) + # An operator may have deployed both relations + primary_rids = relation_ids('master') + relation_ids('primary') + secondary_rids = relation_ids('slave') + relation_ids('secondary') + multisite_rids = primary_rids + secondary_rids + # Any realm or zonegroup config is present, multisite checks can be done. # zone config can't be used because it's used by default. - if config('realm') or config('zonegroup') or relation_ids('master') \ - or relation_ids('slave'): + if config('realm') or config('zonegroup') or multisite_rids: # All of Realm, zonegroup, and zone must be configured. if not all(multisite_config): return ('blocked', @@ -229,14 +233,14 @@ def check_optional_config_and_relations(configs): '(realm={realm}, zonegroup={zonegroup}' ', zone={zone})'.format(**config())) - # Master/Slave Relation should be configured. - if not (relation_ids('master') or relation_ids('slave')): + # Primary/Secondary Relation should be configured. + if not multisite_rids: return ('blocked', - 'multi-site configuration but master/slave ' + 'multi-site configuration but primary/secondary ' 'relation missing') # Primary site status check - if relation_ids('master'): + if primary_rids: # Migration: The system is not multisite already. if not multisite.is_multisite_configured(config('zone'), config('zonegroup')): @@ -261,7 +265,7 @@ def check_optional_config_and_relations(configs): 'waiting for configuration of master zone') # Secondary site status check - if relation_ids('slave'): + if secondary_rids: # Migration: The system is not multisite already. if not multisite.is_multisite_configured(config('zone'), config('zonegroup')): @@ -270,7 +274,7 @@ def check_optional_config_and_relations(configs): "Non-Pristine RGW site can't be used as secondary") multisite_ready = False - for rid in relation_ids('slave'): + for rid in secondary_rids: for unit in related_units(rid): if relation_get('url', unit=unit, rid=rid): multisite_ready = True diff --git a/metadata.yaml b/metadata.yaml index c89cd043..a0f590d3 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -30,6 +30,8 @@ requires: interface: tls-certificates slave: interface: radosgw-multisite + secondary: + interface: radosgw-multisite provides: nrpe-external-master: interface: nrpe-external-master @@ -38,6 +40,8 @@ provides: interface: http master: interface: radosgw-multisite + primary: + interface: radosgw-multisite object-store: interface: swift-proxy radosgw-user: diff --git a/unit_tests/test_hooks.py b/unit_tests/test_hooks.py index cec082cf..e0fed1aa 100644 --- a/unit_tests/test_hooks.py +++ b/unit_tests/test_hooks.py @@ -609,21 +609,21 @@ class MiscMultisiteTests(CharmTestCase): 'related_units', 'leader_get', 'is_leader', - 'master_relation_joined', - 'slave_relation_changed', + 'primary_relation_joined', + 'secondary_relation_changed', 'service_restart', 'service_name', 'multisite' ] _relation_ids = { - 'master': ['master:1'], - 'slave': ['slave:1'], + 'primary': ['primary:1'], + 'secondary': ['secondary:1'], } _related_units = { - 'master:1': ['rgw/0', 'rgw/1'], - 'slave:1': ['rgw-s/0', 'rgw-s/1'], + 'primary:1': ['rgw/0', 'rgw/1'], + 'secondary:1': ['rgw-s/0', 'rgw-s/1'], } def setUp(self): @@ -642,14 +642,14 @@ class MiscMultisiteTests(CharmTestCase): self.is_leader.return_value = False ceph_hooks.leader_settings_changed() self.service_restart.assert_called_once_with('rgw@hostname') - self.master_relation_joined.assert_called_once_with('master:1') + self.primary_relation_joined.assert_called_once_with('primary:1') def test_process_multisite_relations(self): ceph_hooks.process_multisite_relations() - self.master_relation_joined.assert_called_once_with('master:1') - self.slave_relation_changed.assert_has_calls([ - call('slave:1', 'rgw-s/0'), - call('slave:1', 'rgw-s/1'), + self.primary_relation_joined.assert_called_once_with('primary:1') + self.secondary_relation_changed.assert_has_calls([ + call('secondary:1', 'rgw-s/0'), + call('secondary:1', 'rgw-s/1'), ]) @@ -684,7 +684,7 @@ class CephRadosMultisiteTests(CharmTestCase): self.systemd_based_radosgw.return_value = True -class MasterMultisiteTests(CephRadosMultisiteTests): +class PrimaryMultisiteTests(CephRadosMultisiteTests): _complete_config = { 'realm': 'testrealm', @@ -703,8 +703,8 @@ class MasterMultisiteTests(CephRadosMultisiteTests): 'restart_nonce': 'foobar', } - def test_master_relation_joined_missing_config(self): - ceph_hooks.master_relation_joined('master:1') + def test_primary_relation_joined_missing_config(self): + ceph_hooks.primary_relation_joined('primary:1') self.config.assert_has_calls([ call('realm'), call('zonegroup'), @@ -712,7 +712,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests): ]) self.relation_set.assert_not_called() - def test_master_relation_joined_create_everything(self): + def test_primary_relation_joined_create_everything(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.listen_port.return_value = 80 @@ -725,7 +725,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests): self.multisite.create_system_user.return_value = ( 'mykey', 'mysecret', ) - ceph_hooks.master_relation_joined('master:1') + ceph_hooks.primary_relation_joined('primary:1') self.config.assert_has_calls([ call('realm'), call('zonegroup'), @@ -768,12 +768,12 @@ class MasterMultisiteTests(CephRadosMultisiteTests): call(restart_nonce=ANY), ]) self.relation_set.assert_called_with( - relation_id='master:1', + relation_id='primary:1', access_key='mykey', secret='mysecret', ) - def test_master_relation_joined_create_nothing(self): + def test_primary_relation_joined_create_nothing(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.is_leader.return_value = True @@ -786,7 +786,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests): self.multisite.list_users.return_value = [ ceph_hooks.MULTISITE_SYSTEM_USER ] - ceph_hooks.master_relation_joined('master:1') + ceph_hooks.primary_relation_joined('primary:1') self.multisite.create_realm.assert_not_called() self.multisite.create_zonegroup.assert_not_called() self.multisite.create_zone.assert_not_called() @@ -795,15 +795,15 @@ class MasterMultisiteTests(CephRadosMultisiteTests): self.service_restart.assert_not_called() self.leader_set.assert_not_called() - def test_master_relation_joined_not_leader(self): + def test_primary_relation_joined_not_leader(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.listen_port.return_value = 80 self.is_leader.return_value = False self.leader_get.side_effect = lambda attr: self._leader_data.get(attr) - ceph_hooks.master_relation_joined('master:1') + ceph_hooks.primary_relation_joined('primary:1') self.relation_set.assert_called_once_with( - relation_id='master:1', + relation_id='primary:1', realm='testrealm', zonegroup='testzonegroup', url='http://rgw:80', @@ -833,7 +833,7 @@ class MasterMultisiteTests(CephRadosMultisiteTests): ) -class SlaveMultisiteTests(CephRadosMultisiteTests): +class SecondaryMultisiteTests(CephRadosMultisiteTests): _complete_config = { 'realm': 'testrealm', @@ -846,7 +846,7 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): 'zonegroup': 'testzonegroup', 'access_key': 'anotherkey', 'secret': 'anothersecret', - 'url': 'http://master:80' + 'url': 'http://primary:80' } _test_bad_relation = { @@ -854,10 +854,10 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): 'zonegroup': 'anotherzg', 'access_key': 'anotherkey', 'secret': 'anothersecret', - 'url': 'http://master:80' + 'url': 'http://primary:80' } - def test_slave_relation_changed(self): + def test_secondary_relation_changed(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.is_leader.return_value = True @@ -867,7 +867,7 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): self.multisite.list_realms.return_value = [] self.multisite.list_zones.return_value = [] self.multisite.check_cluster_has_buckets.return_value = False - ceph_hooks.slave_relation_changed('slave:1', 'rgw/0') + ceph_hooks.secondary_relation_changed('secondary:1', 'rgw/0') self.config.assert_has_calls([ call('realm'), call('zonegroup'), @@ -878,7 +878,7 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): access_key=self._test_relation['access_key'], secret=self._test_relation['secret'], ) - self.multisite.pull_period.assert_called_once_with( + self.multisite.pull_period.assert_called_with( url=self._test_relation['url'], access_key=self._test_relation['access_key'], secret=self._test_relation['secret'], @@ -902,20 +902,20 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): self.service_restart.assert_called_once() self.leader_set.assert_called_once_with(restart_nonce=ANY) - def test_slave_relation_changed_incomplete_relation(self): + def test_secondary_relation_changed_incomplete_relation(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.is_leader.return_value = True self.relation_get.return_value = {} - ceph_hooks.slave_relation_changed('slave:1', 'rgw/0') + ceph_hooks.secondary_relation_changed('secondary:1', 'rgw/0') self.config.assert_not_called() - def test_slave_relation_changed_mismatching_config(self): + def test_secondary_relation_changed_mismatching_config(self): for k, v in self._complete_config.items(): self.test_config.set(k, v) self.is_leader.return_value = True self.relation_get.return_value = self._test_bad_relation - ceph_hooks.slave_relation_changed('slave:1', 'rgw/0') + ceph_hooks.secondary_relation_changed('secondary:1', 'rgw/0') self.config.assert_has_calls([ call('realm'), call('zonegroup'), @@ -923,9 +923,9 @@ class SlaveMultisiteTests(CephRadosMultisiteTests): ]) self.multisite.list_realms.assert_not_called() - def test_slave_relation_changed_not_leader(self): + def test_secondary_relation_changed_not_leader(self): self.is_leader.return_value = False - ceph_hooks.slave_relation_changed('slave:1', 'rgw/0') + ceph_hooks.secondary_relation_changed('secondary:1', 'rgw/0') self.relation_get.assert_not_called() @patch.object(ceph_hooks, 'apt_install')