From d4f0215a1b5923645ad0bd0af6912afacbc1ea8f Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Mon, 18 May 2020 17:33:45 +0200 Subject: [PATCH] Change Ganesha to HA deploy This change also modifies the ganesha + manila-share services to run via pacemaker to enable them to be colocated with the VIP, a requirement to run manila and ganesha in a highly available configuration Change-Id: Idd0b594c24ef029f2415ee9ca13a8aca6d01d2a7 Closes-Bug: #1867358 --- src/lib/charm/openstack/manila_ganesha.py | 29 ++++++++++-- src/reactive/manila_ganesha.py | 44 +++++++++++++++++++ src/tests/bundles/bionic-rocky.yaml | 2 +- src/tests/bundles/bionic-stein.yaml | 2 +- src/tests/bundles/bionic-train.yaml | 2 +- .../overlays/local-charm-overlay.yaml.j2 | 11 +++++ ...test_lib_charm_openstack_manila_ganesha.py | 31 ++++++++++++- unit_tests/test_manila_ganesha_handlers.py | 5 +++ 8 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 src/tests/bundles/overlays/local-charm-overlay.yaml.j2 diff --git a/src/lib/charm/openstack/manila_ganesha.py b/src/lib/charm/openstack/manila_ganesha.py index 3d50a6b..37626d1 100644 --- a/src/lib/charm/openstack/manila_ganesha.py +++ b/src/lib/charm/openstack/manila_ganesha.py @@ -21,7 +21,11 @@ import charms_openstack.charm import charms_openstack.adapters import charms_openstack.plugins import charmhelpers.contrib.network.ip as ch_net_ip -from charmhelpers.core.hookenv import log +from charmhelpers.core.hookenv import ( + config, + log, +) +from charmhelpers.contrib.hahelpers.cluster import is_clustered from charmhelpers.contrib.storage.linux.ceph import ( CephBrokerRq, send_request_if_needed, @@ -56,6 +60,11 @@ def access_ip(config): return config.charm_instance.access_ip +@charms_openstack.adapters.config_property +def local_ip(_config): + return ch_net_ip.get_relation_ip('tenant-storage') + + @charms_openstack.adapters.config_property def use_memcache(config): """Do not enable memcache.""" @@ -152,8 +161,8 @@ class ManilaGaneshaCharm(charms_openstack.charm.HAOpenStackCharm, adapters_class = GaneshaCharmRelationAdapters # ceph_key_per_unit_name = True services = [ - 'nfs-ganesha', - 'manila-share', + # 'nfs-ganesha', + # 'manila-share', ] ha_resources = ['vips', 'dnsha'] release_pkg = 'manila-common' @@ -177,7 +186,19 @@ class ManilaGaneshaCharm(charms_openstack.charm.HAOpenStackCharm, @property def access_ip(self): - return ch_net_ip.get_relation_ip('tenant-storage') + vips = config().get('vip') + if vips: + vips = vips.split() + clustered = is_clustered() + net_addr = ch_net_ip.get_relation_ip('tenant-storage') + bound_cidr = ch_net_ip.resolve_network_cidr( + ch_net_ip.network_get_primary_address('tenant-storage') + ) + if clustered and vips: + for vip in vips: + if ch_net_ip.is_address_in_network(bound_cidr, vip): + return vip + return net_addr def enable_memcache(self, *args, **kwargs): return False diff --git a/src/reactive/manila_ganesha.py b/src/reactive/manila_ganesha.py index 3218f1d..4492f8f 100644 --- a/src/reactive/manila_ganesha.py +++ b/src/reactive/manila_ganesha.py @@ -16,6 +16,7 @@ charms_openstack.bus.discover() charm.use_defaults( 'charm.installed', 'amqp.connected', + 'cluster.available', 'shared-db.connected', 'config.changed', 'update-status', @@ -80,6 +81,15 @@ def render_things(*args): charm_instance.assess_status() +@reactive.when('config.rendered') +@reactive.when_not('ha.connected') +def enable_services_in_non_ha(): + with charm.provide_charm_instance() as charm_instance: + for service in charm_instance.services: + ch_core.host.service('enable', service) + ch_core.host.service('start', service) + + @reactive.when_all('config.rendered', 'ceph.pools.available') @reactive.when_not('ganesha-pool-configured') @@ -93,3 +103,37 @@ def configure_ganesha(*args): reactive.set_flag('ganesha-pool-configured') except subprocess.CalledProcessError: log("Failed to setup ganesha index object") + + +@reactive.when('ha.connected', 'ganesha-pool-configured', + 'config.rendered') +def cluster_connected(hacluster): + """Configure HA resources in corosync""" + with charm.provide_charm_instance() as this_charm: + this_charm.configure_ha_resources(hacluster) + for service in ['nfs-ganesha', 'manila-share']: + ch_core.host.service('disable', service) + ch_core.host.service('stop', service) + hacluster.add_systemd_service('nfs-ganesha', + 'nfs-ganesha', + clone=False) + hacluster.add_systemd_service('manila-share', + 'manila-share', + clone=False) + # This is a bit of a nasty hack to ensure that we can colocate the + # services to make manila + ganesha colocate. This can be tidied up + # once + # https://bugs.launchpad.net/charm-interface-hacluster/+bug/1880644 + # is resolved + import hooks.relations.hacluster.common as hacluster_common # noqa + crm = hacluster_common.CRM() + crm.colocation('ganesha_with_vip', + 'inf', + 'res_nfs_ganesha_nfs_ganesha', + 'grp_ganesha_vips') + crm.colocation('manila_with_vip', + 'inf', + 'res_manila_share_manila_share', + 'grp_ganesha_vips') + hacluster.manage_resources(crm) + this_charm.assess_status() diff --git a/src/tests/bundles/bionic-rocky.yaml b/src/tests/bundles/bionic-rocky.yaml index 18ebb7b..b819733 100644 --- a/src/tests/bundles/bionic-rocky.yaml +++ b/src/tests/bundles/bionic-rocky.yaml @@ -3,7 +3,7 @@ options: source: &source cloud:bionic-rocky services: manila-ganesha: - num_units: 1 + num_units: 3 series: bionic charm: ../../../manila-ganesha options: diff --git a/src/tests/bundles/bionic-stein.yaml b/src/tests/bundles/bionic-stein.yaml index 6aef92e..33d2bd4 100644 --- a/src/tests/bundles/bionic-stein.yaml +++ b/src/tests/bundles/bionic-stein.yaml @@ -3,7 +3,7 @@ options: source: &source cloud:bionic-stein services: manila-ganesha: - num_units: 1 + num_units: 3 series: bionic charm: ../../../manila-ganesha options: diff --git a/src/tests/bundles/bionic-train.yaml b/src/tests/bundles/bionic-train.yaml index df5dc11..47125c7 100644 --- a/src/tests/bundles/bionic-train.yaml +++ b/src/tests/bundles/bionic-train.yaml @@ -3,7 +3,7 @@ options: source: &source cloud:bionic-train services: manila-ganesha: - num_units: 1 + num_units: 3 series: bionic charm: ../../../manila-ganesha options: diff --git a/src/tests/bundles/overlays/local-charm-overlay.yaml.j2 b/src/tests/bundles/overlays/local-charm-overlay.yaml.j2 new file mode 100644 index 0000000..4d4934e --- /dev/null +++ b/src/tests/bundles/overlays/local-charm-overlay.yaml.j2 @@ -0,0 +1,11 @@ +# Add True HA +applications: + manila-ganesha: + options: + vip: '{{ OS_VIP00 }}' + hacluster: + charm: cs:~openstack-charmers-next/hacluster + num_units: 0 +relations: +- - manila-ganesha + - hacluster diff --git a/unit_tests/test_lib_charm_openstack_manila_ganesha.py b/unit_tests/test_lib_charm_openstack_manila_ganesha.py index d2fbe58..2158324 100644 --- a/unit_tests/test_lib_charm_openstack_manila_ganesha.py +++ b/unit_tests/test_lib_charm_openstack_manila_ganesha.py @@ -29,7 +29,7 @@ class Helper(test_utils.PatchHelper): self.patch_release(manila_ganesha.ManilaGaneshaCharm.release) -class TestOctaviaCharm(Helper): +class TestManilaGaneshaCharm(Helper): def test_request_ceph_permissions(self): self.patch_object(manila_ganesha, 'send_request_if_needed') @@ -39,3 +39,32 @@ class TestOctaviaCharm(Helper): c.request_ceph_permissions(ceph) ceph.set_local.assert_called_once() self.send_request_if_needed.assert_called_once() + + def test_access_ip_without_vip(self): + self.patch_object(manila_ganesha, 'is_clustered') + self.patch_object(manila_ganesha.ch_net_ip, 'get_relation_ip') + self.patch_object(manila_ganesha.ch_net_ip, 'is_address_in_network') + self.is_clustered.return_value = False + self.get_relation_ip.return_value = "10.0.0.1" + c = manila_ganesha.ManilaGaneshaCharm() + self.assertEqual(c.access_ip, "10.0.0.1") + self.is_clustered.assert_called_once() + self.get_relation_ip.assert_called_once_with('tenant-storage') + self.is_address_in_network.assert_not_called() + + def test_access_ip_with_vip(self): + self.patch_object(manila_ganesha, 'config') + self.patch_object(manila_ganesha, 'is_clustered') + self.patch_object(manila_ganesha.ch_net_ip, 'get_relation_ip') + self.patch_object(manila_ganesha.ch_net_ip, 'is_address_in_network') + self.patch_object(manila_ganesha.ch_net_ip, 'resolve_network_cidr') + self.config.return_value = {'vip': '10.0.0.10'} + self.is_clustered.return_value = True + self.get_relation_ip.return_value = "10.0.0.1" + self.resolve_network_cidr.return_value = '10.0.0.0/24' + c = manila_ganesha.ManilaGaneshaCharm() + self.assertEqual(c.access_ip, "10.0.0.10") + self.is_clustered.assert_called_once() + self.get_relation_ip.assert_called_once_with('tenant-storage') + self.is_address_in_network.assert_called_once_with( + '10.0.0.0/24', '10.0.0.10') diff --git a/unit_tests/test_manila_ganesha_handlers.py b/unit_tests/test_manila_ganesha_handlers.py index abf0102..86e2662 100644 --- a/unit_tests/test_manila_ganesha_handlers.py +++ b/unit_tests/test_manila_ganesha_handlers.py @@ -46,11 +46,16 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): 'manila-plugin.available', 'shared-db.available', 'identity-service.available'), + 'cluster_connected': ('ha.connected', + 'ganesha-pool-configured', + 'config.rendered',), + 'enable_services_in_non_ha': ('config.rendered',), }, 'when_not': { 'ceph_connected': ('ceph.available',), 'configure_ident_username': ('identity-service.available',), 'configure_ganesha': ('ganesha-pool-configured',), + 'enable_services_in_non_ha': ('ha.connected',), }, 'when_all': { 'configure_ganesha': ('config.rendered',