diff --git a/distributedcloud/dcmanager/common/utils.py b/distributedcloud/dcmanager/common/utils.py index 9f82c7e20..b118acfd9 100644 --- a/distributedcloud/dcmanager/common/utils.py +++ b/distributedcloud/dcmanager/common/utils.py @@ -933,6 +933,27 @@ def get_management_gateway_address(payload): return payload.get('management_gateway_address', '') +def has_network_reconfig(payload, subcloud): + """Check if network reconfiguration is needed + + :param payload: subcloud configuration + :param subcloud: subcloud object + """ + management_subnet = get_management_subnet(payload) + start_address = get_management_start_address(payload) + end_address = get_management_end_address(payload) + gateway_address = get_management_gateway_address(payload) + + has_network_reconfig = any([ + management_subnet != subcloud.management_subnet, + start_address != subcloud.management_start_ip, + end_address != subcloud.management_end_ip, + gateway_address != subcloud.management_gateway_ip + ]) + + return has_network_reconfig + + def set_open_file_limit(new_soft_limit: int): """Adjust the maximum number of open files for this process (soft limit)""" try: diff --git a/distributedcloud/dcmanager/manager/subcloud_manager.py b/distributedcloud/dcmanager/manager/subcloud_manager.py index 8c6f34228..3c7d6f3a3 100644 --- a/distributedcloud/dcmanager/manager/subcloud_manager.py +++ b/distributedcloud/dcmanager/manager/subcloud_manager.py @@ -30,7 +30,6 @@ from cgtsclient.exc import HTTPConflict from eventlet import greenpool from fm_api import constants as fm_const from fm_api import fm_api -import ipaddress import keyring import netaddr from oslo_log import log as logging @@ -626,8 +625,7 @@ class SubcloudManager(manager.Manager): subcloud.name, ansible_subcloud_inventory_file, payload['software_version']) - management_subnet = utils.get_management_subnet(payload) - network_reconfig = management_subnet != subcloud.management_subnet + network_reconfig = utils.has_network_reconfig(payload, subcloud) apply_thread = threading.Thread( target=self.run_deploy_thread, args=(subcloud, payload, context, @@ -2381,6 +2379,7 @@ class SubcloudManager(manager.Manager): def _configure_system_controller_network(self, context, payload, subcloud): subcloud_name = subcloud.name subcloud_id = subcloud.id + try: m_ks_client = OpenStackDriver( region_name=dccommon_consts.DEFAULT_REGION_NAME, @@ -2389,8 +2388,7 @@ class SubcloudManager(manager.Manager): subcloud.systemcontroller_gateway_ip) except HTTPConflict: # The route already exists - LOG.warning( - "Failed to create route to subcloud %s" % subcloud_name) + LOG.warning("Failed to create route to subcloud %s" % subcloud_name) except Exception: LOG.exception( "Failed to create route to subcloud %s." % subcloud_name) @@ -2413,7 +2411,8 @@ class SubcloudManager(manager.Manager): return # Delete old routes - self._delete_subcloud_routes(m_ks_client, subcloud) + if utils.get_management_subnet(payload) != subcloud.management_subnet: + self._delete_subcloud_routes(m_ks_client, subcloud) def _create_subcloud_route(self, payload, keystone_client, systemcontroller_gateway_ip): @@ -2433,8 +2432,7 @@ class SubcloudManager(manager.Manager): def _update_services_endpoint( self, context, payload, subcloud_name, m_ks_client): - endpoint_ip = str(ipaddress.ip_network( - utils.get_management_subnet(payload))[2]) + endpoint_ip = utils.get_management_start_address(payload) if netaddr.IPAddress(endpoint_ip).version == 6: endpoint_ip = f"[{endpoint_ip}]" @@ -2464,6 +2462,9 @@ class SubcloudManager(manager.Manager): LOG.exception("Endpoint Type Error: %s" % service_type) m_ks_client.keystone_client.endpoints.update( endpoint, url=admin_endpoint_url) + + LOG.info("Update services endpoint to %s in subcloud %s" % ( + endpoint_ip, subcloud_name)) # Update service URLs in subcloud endpoint cache self.audit_rpc_client.trigger_subcloud_endpoints_update( context, subcloud_name, services_endpoints) diff --git a/distributedcloud/dcmanager/tests/unit/manager/test_subcloud_manager.py b/distributedcloud/dcmanager/tests/unit/manager/test_subcloud_manager.py index 4e03f549a..63f3b4466 100644 --- a/distributedcloud/dcmanager/tests/unit/manager/test_subcloud_manager.py +++ b/distributedcloud/dcmanager/tests/unit/manager/test_subcloud_manager.py @@ -982,6 +982,40 @@ class TestSubcloudManager(base.DCManagerTestCase): self.assertEqual(payload['management_end_ip'], updated_subcloud.management_end_ip) + @mock.patch.object(subcloud_manager.SubcloudManager, + '_delete_subcloud_routes') + @mock.patch.object(subcloud_manager.SubcloudManager, + '_update_services_endpoint') + @mock.patch.object(subcloud_manager.SubcloudManager, + '_create_subcloud_route') + @mock.patch.object(subcloud_manager, 'OpenStackDriver') + def test_network_reconf_same_subnet( + self, mock_keystone_client, mock_create_route, + mock_update_endpoints, mock_delete_route): + subcloud = self.create_subcloud_static( + self.ctx, + name='subcloud1', + deploy_status=consts.DEPLOY_STATE_DONE) + db_api.subcloud_update( + self.ctx, subcloud.id, + availability_status=dccommon_consts.AVAILABILITY_ONLINE) + + payload = {'name': "subcloud1", + 'description': "subcloud description", + 'location': "subcloud location", + 'management_subnet': "192.168.101.0/24", + 'management_start_ip': "192.168.101.3", + 'management_end_ip': "192.168.101.49", + 'management_gateway_ip': "192.168.101.1"} + + sm = subcloud_manager.SubcloudManager() + sm._configure_system_controller_network(self.ctx, payload, subcloud) + + mock_keystone_client.assert_called_once() + mock_create_route.assert_called_once() + mock_update_endpoints.assert_called_once() + self.assertFalse(mock_delete_route.called) + def test_update_subcloud_with_install_values(self): subcloud = self.create_subcloud_static( self.ctx, diff --git a/distributedcloud/dcmanager/tests/unit/manager/test_utils.py b/distributedcloud/dcmanager/tests/unit/manager/test_utils.py new file mode 100644 index 000000000..46d7907c1 --- /dev/null +++ b/distributedcloud/dcmanager/tests/unit/manager/test_utils.py @@ -0,0 +1,53 @@ +# Copyright (c) 2023 Wind River Systems, Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +from dcmanager.common import utils +from dcmanager.tests import base +from dcmanager.tests.unit.common import fake_subcloud +from dcmanager.tests import utils as test_utils + + +class TestUtils(base.DCManagerTestCase): + def setUp(self): + super(TestUtils, self).setUp() + self.ctx = test_utils.dummy_context() + + def test_has_network_reconfig_same_values(self): + subcloud = fake_subcloud.create_fake_subcloud(self.ctx) + payload = {"management_subnet": "192.168.101.0/24", + "management_gateway_address": "192.168.101.1", + "management_start_address": "192.168.101.2", + "management_end_address": "192.168.101.50"} + result = utils.has_network_reconfig(payload, subcloud) + self.assertFalse(result) + + def test_has_network_reconfig_different_subnet(self): + subcloud = fake_subcloud.create_fake_subcloud(self.ctx) + payload = {"management_subnet": "192.168.102.0/24", + "management_gateway_address": "192.168.102.1", + "management_start_address": "192.168.102.2", + "management_end_address": "192.168.102.50"} + result = utils.has_network_reconfig(payload, subcloud) + self.assertTrue(result) + + def test_has_network_reconfig_different_start_address(self): + subcloud = fake_subcloud.create_fake_subcloud(self.ctx) + payload = {"management_subnet": "192.168.101.0/24", + "management_gateway_address": "192.168.101.5", + "management_start_address": "192.168.101.7", + "management_end_address": "192.168.101.50"} + result = utils.has_network_reconfig(payload, subcloud) + self.assertTrue(result) diff --git a/distributedcloud/dcmanager/tests/unit/utils/__init__.py b/distributedcloud/dcmanager/tests/unit/utils/__init__.py new file mode 100644 index 000000000..e69de29bb