Update subcloud admin parameters in db
The current restrictions for network reconfiguration post-install is problematic for correcting or updating network configuration for Subcloud deployments or supporting Subcloud rehoming procedures. The proposed solution is to decouple the Distributed Cloud networking operations from the management network by introducing a new admin network type that will be used for the addressing and routing between the central System Controller and the Subcloud. Currently, network parameters are not able to be modified via the dcmanager subcloud update CLI. This commit allows a subcloud to modify the current network parameters via the dcmanager subcloud update CLI and have that be reflected in the dcmanager DB (subcloud entity). Test-plan: Debian dcmanager subcloud update --admin-subnet --admin-gateway-ip --admin-node-0-address --admin-node-1-address dcmanager subcloud show Negative Testing : 1. Test dcmanager subcloud update command with invalid admin-subnet . Example: dcmanager subcloud update --admin-subnet 254.254.254.2 --admin-gateway-ip 192.168.101.1 --admin-node-0-address 192.168.101.5 --admin-node-1-address 192.168.101.49 subcloud1 dcmanager subcloud show subcloud1 Result: dcmanager subcloud update should not update invalid admin-subnet IP . 2. Test dcmanager subcloud update command with invalid admin-gateway-ip , admin-node-0-address & admin-node-1-address . It should not allow subcloud update with invalid admin IP. 3. Test dcmanager subcloud update --description without updating admin parameters in a subcloud . Example: dcmanager subcloud update --description mks subcloud1 dcmanager subcloud show Expected result : It should not update any admin parameters (admin-subnet, admin-gateway-ip , admin-node-0-address & admin-node-1-address) in a subcloud . It should only update subcloud description. Story: 2010319 Task: 46962 Signed-off-by: rsujay <ramkrishna.sujay@windriver.com> Change-Id: I4cbaab5add873eb4264182645042bff1ee7f2456
This commit is contained in:
parent
fd05375f84
commit
8ca98d3ee1
@ -572,6 +572,17 @@ class SubcloudsController(object):
|
||||
LOG.exception(e)
|
||||
pecan.abort(400, _("admin_gateway_address invalid: %s") % e)
|
||||
|
||||
subcloud_admin_address_start = IPAddress(admin_start_address_str)
|
||||
subcloud_admin_address_end = IPAddress(admin_end_address_str)
|
||||
subcloud_admin_gw_ip = IPAddress(admin_gateway_address_str)
|
||||
if ((subcloud_admin_gw_ip >= subcloud_admin_address_start) and
|
||||
(subcloud_admin_gw_ip <= subcloud_admin_address_end)):
|
||||
pecan.abort(400, _("admin_gateway_address invalid, "
|
||||
"is within admin pool: %(start)s - "
|
||||
"%(end)s") %
|
||||
{'start': subcloud_admin_address_start,
|
||||
'end': subcloud_admin_address_end})
|
||||
|
||||
def _format_ip_address(self, payload):
|
||||
"""Format IP addresses in 'bootstrap_values' and 'install_values'.
|
||||
|
||||
@ -1174,6 +1185,29 @@ class SubcloudsController(object):
|
||||
location = payload.get('location')
|
||||
group_id = payload.get('group_id')
|
||||
|
||||
admin_subnet_str = payload.get('admin_subnet')
|
||||
admin_start_ip_str = payload.get('admin_node_0_address')
|
||||
admin_end_ip_str = payload.get('admin_node_1_address')
|
||||
admin_gateway_ip_str = payload.get('admin_gateway_ip')
|
||||
admin_address_configured = False
|
||||
|
||||
# Syntax checking
|
||||
|
||||
if (admin_subnet_str and admin_gateway_ip_str and
|
||||
admin_start_ip_str and admin_end_ip_str):
|
||||
# Parse/validate the admin subnet
|
||||
subcloud_subnets = []
|
||||
subclouds = db_api.subcloud_get_all(context)
|
||||
for subcloud in subclouds:
|
||||
subcloud_subnets.append(IPNetwork(subcloud.management_subnet))
|
||||
|
||||
admin_address_configured = True
|
||||
self._validate_admin_network_config(admin_subnet_str,
|
||||
admin_start_ip_str,
|
||||
admin_end_ip_str,
|
||||
admin_gateway_ip_str,
|
||||
subcloud_subnets)
|
||||
|
||||
# Syntax checking
|
||||
if management_state and \
|
||||
management_state not in [dccommon_consts.MANAGEMENT_UNMANAGED,
|
||||
@ -1211,10 +1245,22 @@ class SubcloudsController(object):
|
||||
try:
|
||||
# Inform dcmanager that subcloud has been updated.
|
||||
# It will do all the real work...
|
||||
subcloud = self.dcmanager_rpc_client.update_subcloud(
|
||||
context, subcloud_id, management_state=management_state,
|
||||
description=description, location=location, group_id=group_id,
|
||||
data_install=data_install, force=force_flag)
|
||||
if admin_address_configured:
|
||||
subcloud = self.dcmanager_rpc_client.update_subcloud(
|
||||
context, subcloud_id, management_state=management_state,
|
||||
description=description, management_subnet=payload.get('admin_subnet'),
|
||||
management_gateway_ip=payload.get('admin_gateway_ip'),
|
||||
management_start_ip=payload.get('admin_node_0_address'),
|
||||
management_end_ip=payload.get('admin_node_1_address'),
|
||||
location=location, group_id=group_id,
|
||||
data_install=data_install, force=force_flag)
|
||||
else:
|
||||
subcloud = self.dcmanager_rpc_client.update_subcloud(
|
||||
context, subcloud_id, management_state=management_state,
|
||||
description=description, location=location,
|
||||
group_id=group_id, data_install=data_install,
|
||||
force=force_flag)
|
||||
|
||||
return subcloud
|
||||
except RemoteError as e:
|
||||
pecan.abort(422, e.value)
|
||||
|
@ -168,7 +168,9 @@ def subcloud_get_all_with_status(context):
|
||||
|
||||
def subcloud_update(context, subcloud_id, management_state=None,
|
||||
availability_status=None, software_version=None,
|
||||
description=None, location=None, audit_fail_count=None,
|
||||
description=None, management_subnet=None, management_gateway_ip=None,
|
||||
management_start_ip=None, management_end_ip=None,
|
||||
location=None, audit_fail_count=None,
|
||||
deploy_status=None, backup_status=None,
|
||||
backup_datetime=None, error_description=None,
|
||||
openstack_installed=None, group_id=None,
|
||||
@ -176,9 +178,10 @@ def subcloud_update(context, subcloud_id, management_state=None,
|
||||
"""Update a subcloud or raise if it does not exist."""
|
||||
return IMPL.subcloud_update(context, subcloud_id, management_state,
|
||||
availability_status, software_version,
|
||||
description, location, audit_fail_count,
|
||||
deploy_status, backup_status, backup_datetime,
|
||||
error_description, openstack_installed,
|
||||
description, management_subnet, management_gateway_ip,
|
||||
management_start_ip, management_end_ip, location,
|
||||
audit_fail_count, deploy_status, backup_status,
|
||||
backup_datetime, error_description, openstack_installed,
|
||||
group_id, data_install, data_upgrade)
|
||||
|
||||
|
||||
|
@ -374,7 +374,9 @@ def subcloud_create(context, name, description, location, software_version,
|
||||
@require_admin_context
|
||||
def subcloud_update(context, subcloud_id, management_state=None,
|
||||
availability_status=None, software_version=None,
|
||||
description=None, location=None, audit_fail_count=None,
|
||||
description=None, management_subnet=None,
|
||||
management_gateway_ip=None, management_start_ip=None,
|
||||
management_end_ip=None, location=None, audit_fail_count=None,
|
||||
deploy_status=None, backup_status=None,
|
||||
backup_datetime=None, error_description=None,
|
||||
openstack_installed=None,
|
||||
@ -391,6 +393,14 @@ def subcloud_update(context, subcloud_id, management_state=None,
|
||||
subcloud_ref.software_version = software_version
|
||||
if description is not None:
|
||||
subcloud_ref.description = description
|
||||
if management_subnet is not None:
|
||||
subcloud_ref.management_subnet = management_subnet
|
||||
if management_gateway_ip is not None:
|
||||
subcloud_ref.management_gateway_ip = management_gateway_ip
|
||||
if management_start_ip is not None:
|
||||
subcloud_ref.management_start_ip = management_start_ip
|
||||
if management_end_ip is not None:
|
||||
subcloud_ref.management_end_ip = management_end_ip
|
||||
if location is not None:
|
||||
subcloud_ref.location = location
|
||||
if audit_fail_count is not None:
|
||||
|
@ -107,13 +107,19 @@ class DCManagerService(service.Service):
|
||||
|
||||
@request_context
|
||||
def update_subcloud(self, context, subcloud_id, management_state=None,
|
||||
description=None, location=None, group_id=None,
|
||||
data_install=None, force=None):
|
||||
description=None, management_subnet=None,
|
||||
management_gateway_ip=None, management_start_ip=None,
|
||||
management_end_ip=None, location=None,
|
||||
group_id=None, data_install=None, force=None):
|
||||
# Updates a subcloud
|
||||
LOG.info("Handling update_subcloud request for: %s" % subcloud_id)
|
||||
subcloud = self.subcloud_manager.update_subcloud(context, subcloud_id,
|
||||
management_state,
|
||||
description,
|
||||
management_subnet,
|
||||
management_gateway_ip,
|
||||
management_start_ip,
|
||||
management_end_ip,
|
||||
location,
|
||||
group_id,
|
||||
data_install,
|
||||
|
@ -1584,6 +1584,10 @@ class SubcloudManager(manager.Manager):
|
||||
subcloud_id,
|
||||
management_state=None,
|
||||
description=None,
|
||||
management_subnet=None,
|
||||
management_gateway_ip=None,
|
||||
management_start_ip=None,
|
||||
management_end_ip=None,
|
||||
location=None,
|
||||
group_id=None,
|
||||
data_install=None,
|
||||
@ -1641,6 +1645,10 @@ class SubcloudManager(manager.Manager):
|
||||
subcloud_id,
|
||||
management_state=management_state,
|
||||
description=description,
|
||||
management_subnet=management_subnet,
|
||||
management_gateway_ip=management_gateway_ip,
|
||||
management_start_ip=management_start_ip,
|
||||
management_end_ip=management_end_ip,
|
||||
location=location,
|
||||
group_id=group_id,
|
||||
data_install=data_install)
|
||||
|
@ -129,12 +129,18 @@ class ManagerClient(RPCClient):
|
||||
subcloud_id=subcloud_id))
|
||||
|
||||
def update_subcloud(self, ctxt, subcloud_id, management_state=None,
|
||||
description=None, location=None, group_id=None,
|
||||
description=None, management_subnet=None,
|
||||
management_gateway_ip=None, management_start_ip=None,
|
||||
management_end_ip=None, location=None, group_id=None,
|
||||
data_install=None, force=None):
|
||||
return self.call(ctxt, self.make_msg('update_subcloud',
|
||||
subcloud_id=subcloud_id,
|
||||
management_state=management_state,
|
||||
description=description,
|
||||
management_subnet=management_subnet,
|
||||
management_gateway_ip=management_gateway_ip,
|
||||
management_start_ip=management_start_ip,
|
||||
management_end_ip=management_end_ip,
|
||||
location=location,
|
||||
group_id=group_id,
|
||||
data_install=data_install,
|
||||
|
@ -1041,6 +1041,40 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
||||
force=None)
|
||||
self.assertEqual(response.status_int, 200)
|
||||
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
@mock.patch.object(subclouds.SubcloudsController, '_validate_admin_network_config')
|
||||
@mock.patch.object(subclouds.SubcloudsController, '_get_patch_data')
|
||||
def test_patch_subcloud_admin_values(self, mock_get_patch_data,
|
||||
mock_validate_admin_network_config,
|
||||
mock_rpc_client):
|
||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
|
||||
data = {'admin_subnet': "192.168.102.0/24",
|
||||
'admin_node_0_address': "192.168.102.5",
|
||||
'admin_node_1_address': "192.168.102.49",
|
||||
'admin_gateway_ip': "192.168.102.1"}
|
||||
|
||||
mock_rpc_client().update_subcloud.return_value = True
|
||||
mock_get_patch_data.return_value = data
|
||||
response = self.app.patch_json(FAKE_URL + '/' + str(subcloud.id),
|
||||
headers=FAKE_HEADERS,
|
||||
params=data)
|
||||
self.assertEqual(response.status_int, 200)
|
||||
mock_validate_admin_network_config.assert_called_once()
|
||||
mock_rpc_client().update_subcloud.assert_called_once_with(
|
||||
mock.ANY,
|
||||
subcloud.id,
|
||||
management_state=None,
|
||||
description=None,
|
||||
management_subnet=data['admin_subnet'],
|
||||
management_gateway_ip=data['admin_gateway_ip'],
|
||||
management_start_ip=data['admin_node_0_address'],
|
||||
management_end_ip=data['admin_node_1_address'],
|
||||
location=None,
|
||||
group_id=None,
|
||||
data_install=None,
|
||||
force=None)
|
||||
self.assertEqual(response.status_int, 200)
|
||||
|
||||
@mock.patch.object(rpc_client, 'ManagerClient')
|
||||
@mock.patch.object(subclouds.SubcloudsController, '_get_patch_data')
|
||||
def test_patch_subcloud_install_values(self, mock_get_patch_data,
|
||||
|
@ -178,15 +178,27 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
|
||||
management_state = 'testmanagementstate'
|
||||
availability_status = 'testavailabilitystatus'
|
||||
software_version = 'testversion'
|
||||
admin_subnet = '192.168.102.0/24'
|
||||
admin_start_ip = '192.168.102.5'
|
||||
admin_end_ip = '192.168.102.49'
|
||||
admin_gateway_ip = '192.168.102.1'
|
||||
updated = db_api.subcloud_update(
|
||||
self.ctx, subcloud.id,
|
||||
management_state=management_state,
|
||||
availability_status=availability_status,
|
||||
software_version=software_version)
|
||||
software_version=software_version,
|
||||
management_subnet=admin_subnet,
|
||||
management_start_ip=admin_start_ip,
|
||||
management_end_ip=admin_end_ip,
|
||||
management_gateway_ip=admin_gateway_ip)
|
||||
self.assertIsNotNone(updated)
|
||||
self.assertEqual(management_state, updated.management_state)
|
||||
self.assertEqual(availability_status, updated.availability_status)
|
||||
self.assertEqual(software_version, updated.software_version)
|
||||
self.assertEqual(admin_subnet, updated.management_subnet)
|
||||
self.assertEqual(admin_start_ip, updated.management_start_ip)
|
||||
self.assertEqual(admin_end_ip, updated.management_end_ip)
|
||||
self.assertEqual(admin_gateway_ip, updated.management_gateway_ip)
|
||||
|
||||
updated_subcloud = db_api.subcloud_get(self.ctx, subcloud.id)
|
||||
self.assertEqual(management_state,
|
||||
@ -195,6 +207,14 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
|
||||
updated_subcloud.availability_status)
|
||||
self.assertEqual(software_version,
|
||||
updated_subcloud.software_version)
|
||||
self.assertEqual(admin_subnet,
|
||||
updated_subcloud.management_subnet)
|
||||
self.assertEqual(admin_start_ip,
|
||||
updated_subcloud.management_start_ip)
|
||||
self.assertEqual(admin_end_ip,
|
||||
updated_subcloud.management_end_ip)
|
||||
self.assertEqual(admin_gateway_ip,
|
||||
updated_subcloud.management_gateway_ip)
|
||||
|
||||
def test_delete_subcloud(self):
|
||||
fake_subcloud = utils.create_subcloud_dict(base.SUBCLOUD_SAMPLE_DATA_0)
|
||||
|
@ -97,6 +97,8 @@ class TestDCManagerService(base.DCManagerTestCase):
|
||||
self.context, subcloud_id=1, management_state='testmgmtstatus')
|
||||
mock_subcloud_manager().update_subcloud.\
|
||||
assert_called_once_with(self.context, mock.ANY,
|
||||
mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY,
|
||||
mock.ANY, mock.ANY)
|
||||
|
@ -647,6 +647,62 @@ class TestSubcloudManager(base.DCManagerTestCase):
|
||||
self.assertEqual("subcloud new location",
|
||||
updated_subcloud.location)
|
||||
|
||||
def test_update_subcloud_with_admin_values(self):
|
||||
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)
|
||||
|
||||
data = {'admin_subnet': "192.168.102.0/24",
|
||||
'admin_node_0_address': "192.168.102.5",
|
||||
'admin_node_1_address': "192.168.102.49",
|
||||
'admin_gateway_ip': "192.168.102.1"}
|
||||
|
||||
fake_dcmanager_notification = FakeDCManagerNotifications()
|
||||
|
||||
p = mock.patch('dcmanager.rpc.client.DCManagerNotifications')
|
||||
mock_dcmanager_api = p.start()
|
||||
mock_dcmanager_api.return_value = fake_dcmanager_notification
|
||||
|
||||
sm = subcloud_manager.SubcloudManager()
|
||||
sm.update_subcloud(self.ctx,
|
||||
subcloud.id,
|
||||
management_state=dccommon_consts.MANAGEMENT_MANAGED,
|
||||
description="subcloud new description",
|
||||
location="subcloud new location",
|
||||
management_subnet=data['admin_subnet'],
|
||||
management_gateway_ip=data['admin_gateway_ip'],
|
||||
management_start_ip=data['admin_node_0_address'],
|
||||
management_end_ip=data['admin_node_1_address'])
|
||||
|
||||
fake_dcmanager_notification.subcloud_managed.assert_called_once_with(
|
||||
self.ctx, subcloud.name)
|
||||
|
||||
exclude_endpoints = [dccommon_consts.ENDPOINT_TYPE_PATCHING,
|
||||
dccommon_consts.ENDPOINT_TYPE_LOAD]
|
||||
self.fake_dcmanager_audit_api.trigger_subcloud_audits.\
|
||||
assert_called_once_with(self.ctx, subcloud.id, exclude_endpoints)
|
||||
|
||||
# Verify subcloud was updated with correct values
|
||||
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
|
||||
self.assertEqual(dccommon_consts.MANAGEMENT_MANAGED,
|
||||
updated_subcloud.management_state)
|
||||
self.assertEqual("subcloud new description",
|
||||
updated_subcloud.description)
|
||||
self.assertEqual("subcloud new location",
|
||||
updated_subcloud.location)
|
||||
self.assertEqual(data['admin_subnet'],
|
||||
updated_subcloud.management_subnet)
|
||||
self.assertEqual(data['admin_gateway_ip'],
|
||||
updated_subcloud.management_gateway_ip)
|
||||
self.assertEqual(data['admin_node_0_address'],
|
||||
updated_subcloud.management_start_ip)
|
||||
self.assertEqual(data['admin_node_1_address'],
|
||||
updated_subcloud.management_end_ip)
|
||||
|
||||
def test_update_subcloud_with_install_values(self):
|
||||
subcloud = self.create_subcloud_static(
|
||||
self.ctx,
|
||||
|
Loading…
Reference in New Issue
Block a user