From b9130523851ef8f8f2f300d4b583c76c012c51d4 Mon Sep 17 00:00:00 2001 From: Yuxing Jiang Date: Tue, 20 Apr 2021 10:37:47 -0400 Subject: [PATCH] Add RPCAPI calls to apply LDAP client and DNS runtime manifest This commit adds RPCAPI calls to invoke runtime manifest of LDAP client and DNS after adding system controller network and system controller OAM network in a subcloud after the initial network configuration completed. Tested: Delete the system controller network and system controller OAM network in a subcloud and add them with different values. The related configuration and Hieradata are updated. Depends-On: https://review.opendev.org/c/starlingx/stx-puppet/+/787750 Depends-On: https://review.opendev.org/c/starlingx/stx-puppet/+/785977 Story: 2008774 Task: 42307 Change-Id: I4ddf88efa16299c9415f4bf156f2be57e8cc826e Signed-off-by: Yuxing Jiang --- .../sysinv/api/controllers/v1/network.py | 18 +++++++++ .../sysinv/sysinv/sysinv/conductor/manager.py | 20 ++++++++++ .../sysinv/sysinv/sysinv/conductor/rpcapi.py | 22 ++++++++++ .../sysinv/sysinv/tests/api/test_network.py | 40 +++++++++++++++++++ .../sysinv/tests/conductor/test_manager.py | 38 ++++++++++++++++++ .../sysinv/tests/conductor/test_rpcapi.py | 6 +++ sysinv/sysinv/sysinv/sysinv/tests/db/base.py | 20 ++++++++++ 7 files changed, 164 insertions(+) diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network.py index 5af4336b26..4c002d3d1e 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/network.py @@ -345,8 +345,26 @@ class NetworkController(rest.RestController): pecan.request.rpcapi.reconfigure_service_endpoints( pecan.request.context, chosts[0]) + # After the initial configration completed, we can still delete/add + # the system controller networks in a subcloud's controller to + # re-home a subcloud to a new central cloud. In this case, we want + # to update the related services configurations in runtime. + if cutils.is_initial_config_complete() and \ + network['type'] in [constants.NETWORK_TYPE_SYSTEM_CONTROLLER, + constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM]: + self._update_system_controller_network_config(network['type']) return Network.convert_with_links(result) + def _update_system_controller_network_config(self, type): + """ Update related services configurations after updating system + controller networks""" + if type == constants.NETWORK_TYPE_SYSTEM_CONTROLLER: + pecan.request.rpcapi.update_ldap_client_config( + pecan.request.context) + elif type == constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM: + pecan.request.rpcapi.update_dnsmasq_config( + pecan.request.context) + @wsme_pecan.wsexpose(NetworkCollection, types.uuid, int, wtypes.text, wtypes.text) def get_all(self, marker=None, limit=None, sort_key='id', sort_dir='asc'): diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index 84297cdeb0..1aa5da21f6 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -10733,6 +10733,26 @@ class ConductorManager(service.PeriodicService): } self._config_apply_runtime_manifest(context, config_uuid, config_dict) + def update_dnsmasq_config(self, context): + """Update the dnsmasq configuration""" + personalities = [constants.CONTROLLER] + config_uuid = self._config_update_hosts(context, personalities) + config_dict = { + "personalities": personalities, + "classes": ['platform::dns::dnsmasq::runtime'], + } + self._config_apply_runtime_manifest(context, config_uuid, config_dict) + + def update_ldap_client_config(self, context): + """Update the LDAP client configuration""" + personalities = [constants.CONTROLLER] + config_uuid = self._config_update_hosts(context, personalities) + config_dict = { + "personalities": personalities, + "classes": ['platform::ldap::client::runtime'], + } + self._config_apply_runtime_manifest(context, config_uuid, config_dict) + def get_ceph_pools_config(self, context): return self._ceph.get_pools_config() diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py index 3b07e3a680..a3412185f2 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py @@ -2186,3 +2186,25 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy): :param context: request context. """ return self.call(context, self.make_msg('get_restore_state')) + + def update_ldap_client_config(self, context): + """Synchronously, have a conductor configure LDAP client configureation + + Does the following tasks: + - Update puppet hiera configuration file and apply run time manifest. + + :param context: request context. + """ + return self.call(context, + self.make_msg('update_ldap_client_config')) + + def update_dnsmasq_config(self, context): + """Synchronously, have a conductor configure the DNS configuration + + Does the following tasks: + - Update puppet hiera configuration file and apply run time manifest. + + :param context: request context. + """ + return self.call(context, + self.make_msg('update_dnsmasq_config')) diff --git a/sysinv/sysinv/sysinv/sysinv/tests/api/test_network.py b/sysinv/sysinv/sysinv/sysinv/tests/api/test_network.py index 2c4b262ad9..6798a014cb 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/api/test_network.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/api/test_network.py @@ -120,6 +120,14 @@ class NetworkTestCase(base.FunctionalTest, dbbase.BaseHostTestCase): hostnames, self.storage_subnet, constants.NETWORK_TYPE_STORAGE) + self._create_test_addresses( + hostnames, self.system_controller_subnet, + constants.NETWORK_TYPE_SYSTEM_CONTROLLER) + + self._create_test_addresses( + hostnames, self.system_controller_oam_subnet, + constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM) + class TestPostMixin(NetworkTestCase): @@ -175,6 +183,38 @@ class TestPostMixin(NetworkTestCase): self.assertIn("Network of type %s already exists." % network_type, response.json['error_message']) + def test_create_success_system_controller_oam(self): + self._create_test_host(constants.CONTROLLER) + m = mock.Mock() + update_dnsmasq_config = "sysinv.conductor.rpcapi." \ + "ConductorAPI." \ + "update_dnsmasq_config" + with mock.patch('sysinv.common.utils.is_initial_config_complete', + lambda: True), \ + mock.patch(update_dnsmasq_config, + m.update_dnsmasq_config): + self._test_create_network_success( + 'system-controller-oam', + constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM, + self.system_controller_oam_subnet) + m.update_dnsmasq_config.assert_called_once() + + def test_create_success_system_controller(self): + self._create_test_host(constants.CONTROLLER) + m = mock.Mock() + update_ldap_client_config = "sysinv.conductor.rpcapi." \ + "ConductorAPI." \ + "update_ldap_client_config" + with mock.patch('sysinv.common.utils.is_initial_config_complete', + lambda: True), \ + mock.patch(update_ldap_client_config, + m.update_ldap_client_config): + self._test_create_network_success( + 'system-controller', + constants.NETWORK_TYPE_SYSTEM_CONTROLLER, + self.system_controller_subnet) + m.update_ldap_client_config.assert_called_once() + def test_create_success_pxeboot(self): self._test_create_network_success( 'pxeboot', diff --git a/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_manager.py b/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_manager.py index 6c47c1882d..4ed5c4b4ab 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_manager.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_manager.py @@ -1901,6 +1901,44 @@ class ManagerTestCase(base.DbTestCase): ihost = self.dbapi.ihost_get(host_id) self.assertEqual(ihost.reboot_needed, True) + def test_update_dnsmasq_config(self): + mock_config_update_hosts = mock.MagicMock() + mock_config_apply_runtime_manifest = mock.MagicMock() + p = mock.patch('sysinv.conductor.manager.ConductorManager._config_update_hosts', + mock_config_update_hosts) + p.start().return_value = '1234' + self.addCleanup(p.stop) + p2 = mock.patch('sysinv.conductor.manager.ConductorManager._config_apply_runtime_manifest', + mock_config_apply_runtime_manifest) + p2.start() + self.addCleanup(p2.stop) + self.service.update_dnsmasq_config(self.context) + personalities = [constants.CONTROLLER] + config_dict = { + "personalities": personalities, + "classes": ['platform::dns::dnsmasq::runtime'], + } + mock_config_apply_runtime_manifest.assert_called_with(mock.ANY, '1234', config_dict) + + def test_update_ldap_client_config(self): + mock_config_update_hosts = mock.MagicMock() + mock_config_apply_runtime_manifest = mock.MagicMock() + p = mock.patch('sysinv.conductor.manager.ConductorManager._config_update_hosts', + mock_config_update_hosts) + p.start().return_value = '1234' + self.addCleanup(p.stop) + p2 = mock.patch('sysinv.conductor.manager.ConductorManager._config_apply_runtime_manifest', + mock_config_apply_runtime_manifest) + p2.start() + self.addCleanup(p2.stop) + self.service.update_ldap_client_config(self.context) + personalities = [constants.CONTROLLER] + config_dict = { + "personalities": personalities, + "classes": ['platform::ldap::client::runtime'], + } + mock_config_apply_runtime_manifest.assert_called_with(mock.ANY, '1234', config_dict) + class ManagerTestCaseInternal(base.BaseHostTestCase): diff --git a/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_rpcapi.py b/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_rpcapi.py index 7983d8bda0..18f6062255 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/conductor/test_rpcapi.py @@ -95,3 +95,9 @@ class RPCAPITestCase(base.DbTestCase): 'call', host=self.fake_ihost, do_worker_apply=False) + + def test_update_ldap_client_config(self): + self._test_rpcapi('update_ldap_client_config', 'call') + + def test_update_dnsmasq_config(self): + self._test_rpcapi('update_dnsmasq_config', 'call') diff --git a/sysinv/sysinv/sysinv/sysinv/tests/db/base.py b/sysinv/sysinv/sysinv/sysinv/tests/db/base.py index af2c89e3d6..225d886791 100644 --- a/sysinv/sysinv/sysinv/sysinv/tests/db/base.py +++ b/sysinv/sysinv/sysinv/sysinv/tests/db/base.py @@ -48,6 +48,8 @@ class BaseIPv4Mixin(object): cluster_service_subnet = netaddr.IPNetwork('10.96.0.0/12') multicast_subnet = netaddr.IPNetwork('239.1.1.0/28') storage_subnet = netaddr.IPNetwork('10.10.20.0/24') + system_controller_subnet = netaddr.IPNetwork('192.168.104.0/24') + system_controller_oam_subnet = netaddr.IPNetwork('10.10.50.0/24') nameservers = ['8.8.8.8', '8.8.4.4'] @@ -65,6 +67,8 @@ class BaseIPv6Mixin(object): cluster_service_subnet = netaddr.IPNetwork('fd04::/112') multicast_subnet = netaddr.IPNetwork('ff08::1:1:0/124') storage_subnet = netaddr.IPNetwork('fd05::/64') + system_controller_subnet = netaddr.IPNetwork('fd07::/64') + system_controller_oam_subnet = netaddr.IPNetwork('fd06::/64') nameservers = ['2001:4860:4860::8888', '2001:4860:4860::8844'] @@ -240,6 +244,14 @@ class BaseSystemTestCase(BaseIPv4Mixin, DbTestCase): constants.NETWORK_TYPE_STORAGE, self.storage_subnet) + self._create_test_network('system-controller', + constants.NETWORK_TYPE_SYSTEM_CONTROLLER, + self.system_controller_subnet) + + self._create_test_network('system-controller-oam', + constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM, + self.system_controller_oam_subnet) + def _create_test_addresses(self, hostnames, subnet, network_type, start=1, stop=None): ips = itertools.islice(subnet, start, stop) @@ -286,6 +298,14 @@ class BaseSystemTestCase(BaseIPv4Mixin, DbTestCase): hostnames, self.storage_subnet, constants.NETWORK_TYPE_STORAGE) + self._create_test_addresses( + hostnames, self.system_controller_subnet, + constants.NETWORK_TYPE_SYSTEM_CONTROLLER) + + self._create_test_addresses( + hostnames, self.system_controller_oam_subnet, + constants.NETWORK_TYPE_SYSTEM_CONTROLLER_OAM) + def _create_test_oam(self): self.oam = dbutils.create_test_oam()