Generalize subcloud network reconfiguration
This commit refactors the subcloud network reconfiguration, allowing for a more flexible and generalized approach, adding the option to fallback to the management network as well. Test Plan: PASS: Run dcmanager subcloud update with network paramaters (dcmanager subcloud update --sysadmin-password <password> --management-subnet <network-subnet> --management-gateway-ip <network-gateway-ip> --management-start-ip <network-start-ip> --management-end-ip <network-end-ip> --bootstrap-address <bootstrap-address> <subcloud_name>) - The update_playbook will be called and update the subcloud (subcloud route to systemcontroller and admin endpoints) - A new route to the subcloud is created on the system controller. - Subcloud service endpoint URLs are updated in keystone (openstack endpoint list|grep <subcloud-name>) on the system controller. PASS: verify successful deployment of a new subcloud PASS: verify successful reconfiguration of a subcloud from mgmt to admin network Depends-On: https://review.opendev.org/c/starlingx/ansible-playbooks/+/878504 Story: 2010319 Task: 47706 Signed-off-by: Hugo Brito <hugo.brito@windriver.com> Change-Id: I1df57a206e21fa2444bd645c456c4d5d1b539066
This commit is contained in:
parent
ad1f05ac5f
commit
3d7cb75e22
|
@ -319,13 +319,13 @@ The attributes of a subcloud which are modifiable:
|
|||
|
||||
- group_id
|
||||
|
||||
- admin-subnet
|
||||
- management-subnet
|
||||
|
||||
- admin-gateway-ip
|
||||
- management-gateway-ip
|
||||
|
||||
- admin-node-0-address
|
||||
- management-start-ip
|
||||
|
||||
- admin-node-1-address
|
||||
- management-end-ip
|
||||
|
||||
**Normal response codes**
|
||||
|
||||
|
@ -346,10 +346,12 @@ serviceUnavailable (503)
|
|||
- location: subcloud_location
|
||||
- management-state: subcloud_management_state
|
||||
- group_id: subcloud_group_id
|
||||
- admin-subnet: subcloud_admin_subnet
|
||||
- admin-gateway-ip: subcloud_admin_gateway_ip
|
||||
- admin-node-0-address: subcloud_admin_node_0_address
|
||||
- admin-node-1-address: subcloud_admin_node_1_address
|
||||
- management-subnet: subcloud_management_subnet
|
||||
- management-gateway-ip: subcloud_management_gateway_ip
|
||||
- management-start-ip: subcloud_management_start_ip
|
||||
- management-end-ip: subcloud_management_end_ip
|
||||
- bootstrap-address: bootstrap_address
|
||||
- sysadmin-password: sysadmin_password
|
||||
|
||||
Request Example
|
||||
----------------
|
||||
|
|
|
@ -398,30 +398,6 @@ strategy_steps:
|
|||
in: body
|
||||
required: false
|
||||
type: array
|
||||
subcloud_admin_gateway_ip:
|
||||
description: |
|
||||
The admin gateway ip of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_admin_node_0_address:
|
||||
description: |
|
||||
The admin node-0 address of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_admin_node_1_address:
|
||||
description: |
|
||||
The admin node-1 address of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_admin_subnet:
|
||||
description: |
|
||||
The admin subnet of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_apply_type:
|
||||
description: |
|
||||
The apply type for the update. `serial` or `parallel`.
|
||||
|
@ -555,12 +531,36 @@ subcloud_location:
|
|||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_management_end_ip:
|
||||
description: |
|
||||
The management end ip of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_management_gateway_ip:
|
||||
description: |
|
||||
The management gateway ip of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_management_start_ip:
|
||||
description: |
|
||||
The management start ip of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_management_state:
|
||||
description: |
|
||||
Management state of the subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_management_subnet:
|
||||
description: |
|
||||
The management subnet of a subcloud.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
subcloud_name:
|
||||
description: |
|
||||
The name of a subcloud.
|
||||
|
|
|
@ -96,6 +96,11 @@ INSTALL_VALUES_ADDRESSES = [
|
|||
'network_address'
|
||||
]
|
||||
|
||||
SUBCLOUD_MANDATORY_NETWORK_PARAMS = [
|
||||
'management_subnet', 'management_gateway_ip',
|
||||
'management_start_ip', 'management_end_ip'
|
||||
]
|
||||
|
||||
ANSIBLE_BOOTSTRAP_VALIDATE_CONFIG_VARS = \
|
||||
consts.ANSIBLE_CURRENT_VERSION_BASE_PATH + \
|
||||
'/roles/bootstrap/validate-config/vars/main.yml'
|
||||
|
@ -452,7 +457,7 @@ class SubcloudsController(object):
|
|||
|
||||
# Ensure systemcontroller gateway is in the management subnet
|
||||
# for the systemcontroller region.
|
||||
management_address_pool = self._get_management_address_pool(context)
|
||||
management_address_pool = self._get_network_address_pool()
|
||||
systemcontroller_subnet_str = "%s/%d" % (
|
||||
management_address_pool.network,
|
||||
management_address_pool.prefix)
|
||||
|
@ -592,6 +597,39 @@ class SubcloudsController(object):
|
|||
{'start': subcloud_admin_address_start,
|
||||
'end': subcloud_admin_address_end})
|
||||
|
||||
# TODO(nicodemos): Check if subcloud is online and network already exist in the
|
||||
# subcloud when the lock/unlock is not required for network reconfiguration
|
||||
def _validate_network_reconfiguration(self, payload, subcloud):
|
||||
if payload.get('management-state'):
|
||||
pecan.abort(422, _("Management state and network reconfiguration must "
|
||||
"be updated separately"))
|
||||
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED:
|
||||
pecan.abort(422, _("A subcloud must be unmanaged to perform network "
|
||||
"reconfiguration"))
|
||||
if not payload.get('bootstrap_address'):
|
||||
pecan.abort(422, _("The bootstrap_address parameter is required for "
|
||||
"network reconfiguration"))
|
||||
# Check if all parameters exist
|
||||
if not all(payload.get(value) is not None for value in (
|
||||
SUBCLOUD_MANDATORY_NETWORK_PARAMS)):
|
||||
mandatory_params = ', '.join('--{}'.format(param.replace(
|
||||
'_', '-')) for param in SUBCLOUD_MANDATORY_NETWORK_PARAMS)
|
||||
abort_msg = (
|
||||
"The following parameters are necessary for "
|
||||
"subcloud network reconfiguration: {}".format(mandatory_params)
|
||||
)
|
||||
pecan.abort(422, _(abort_msg))
|
||||
|
||||
# Check if any network values are already in use
|
||||
for param in SUBCLOUD_MANDATORY_NETWORK_PARAMS:
|
||||
if payload.get(param) == getattr(subcloud, param):
|
||||
pecan.abort(422, _("%s already in use by the subcloud.") % param)
|
||||
|
||||
# Check if password is valid
|
||||
valid, msg = utils.is_password_valid(payload)
|
||||
if not valid:
|
||||
pecan.abort(400, _(msg))
|
||||
|
||||
def _format_ip_address(self, payload):
|
||||
"""Format IP addresses in 'bootstrap_values' and 'install_values'.
|
||||
|
||||
|
@ -857,13 +895,17 @@ class SubcloudsController(object):
|
|||
if patches[patch_id]['patchstate'] in [patching_v1.PATCH_STATE_PARTIAL_APPLY, patching_v1.PATCH_STATE_PARTIAL_REMOVE]:
|
||||
pecan.abort(422, _('Subcloud add is not allowed while system controller patching is still in progress.'))
|
||||
|
||||
def _get_management_address_pool(self, context):
|
||||
"""Get the system controller's management address pool"""
|
||||
ks_client = self.get_ks_client()
|
||||
def _get_network_address_pool(
|
||||
self, network='management',
|
||||
region_name=dccommon_consts.DEFAULT_REGION_NAME):
|
||||
"""Get the region network address pool"""
|
||||
ks_client = self.get_ks_client(region_name)
|
||||
endpoint = ks_client.endpoint_cache.get_endpoint('sysinv')
|
||||
sysinv_client = SysinvClient(dccommon_consts.DEFAULT_REGION_NAME,
|
||||
sysinv_client = SysinvClient(region_name,
|
||||
ks_client.session,
|
||||
endpoint=endpoint)
|
||||
if network == 'admin':
|
||||
return sysinv_client.get_admin_address_pool()
|
||||
return sysinv_client.get_management_address_pool()
|
||||
|
||||
# TODO(gsilvatr): refactor to use implementation from common/utils and test
|
||||
|
@ -1260,7 +1302,6 @@ class SubcloudsController(object):
|
|||
subcloud_ref)
|
||||
except exceptions.SubcloudNameNotFound:
|
||||
pecan.abort(404, _('Subcloud not found'))
|
||||
|
||||
subcloud_id = subcloud.id
|
||||
|
||||
if verb is None:
|
||||
|
@ -1269,39 +1310,26 @@ class SubcloudsController(object):
|
|||
if not payload:
|
||||
pecan.abort(400, _('Body required'))
|
||||
|
||||
# Check if exist any network reconfiguration parameters
|
||||
reconfigure_network = any(payload.get(value) is not None for value in (
|
||||
SUBCLOUD_MANDATORY_NETWORK_PARAMS))
|
||||
|
||||
if reconfigure_network:
|
||||
system_controller_mgmt_pool = self._get_network_address_pool()
|
||||
# Required parameters
|
||||
payload['name'] = subcloud.name
|
||||
payload['system_controller_network'] = (
|
||||
system_controller_mgmt_pool.network)
|
||||
payload['system_controller_network_prefix'] = (
|
||||
system_controller_mgmt_pool.prefix
|
||||
)
|
||||
# Validation
|
||||
self._validate_network_reconfiguration(payload, subcloud)
|
||||
|
||||
management_state = payload.get('management-state')
|
||||
group_id = payload.get('group_id')
|
||||
description = payload.get('description')
|
||||
location = payload.get('location')
|
||||
admin_subnet_str = payload.get('admin_subnet')
|
||||
admin_start_ip_str = payload.get('admin_start_address')
|
||||
admin_end_ip_str = payload.get('admin_end_address')
|
||||
admin_gateway_ip_str = payload.get('admin_gateway_ip')
|
||||
|
||||
# Syntax checking
|
||||
|
||||
if (admin_subnet_str and admin_gateway_ip_str and
|
||||
admin_start_ip_str and admin_end_ip_str):
|
||||
# Required parameters
|
||||
payload['name'] = subcloud.name
|
||||
payload['systemcontroller_gateway_ip'] = (
|
||||
subcloud.systemcontroller_gateway_ip)
|
||||
|
||||
# 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))
|
||||
|
||||
self._validate_admin_network_config(admin_subnet_str,
|
||||
admin_start_ip_str,
|
||||
admin_end_ip_str,
|
||||
admin_gateway_ip_str,
|
||||
subcloud_subnets)
|
||||
# Password only required when update admin network
|
||||
valid, msg = utils.is_password_valid(payload)
|
||||
if not valid:
|
||||
pecan.abort(400, _(msg))
|
||||
|
||||
# Syntax checking
|
||||
if management_state and \
|
||||
|
@ -1335,27 +1363,16 @@ class SubcloudsController(object):
|
|||
if self._validate_install_values(payload, subcloud):
|
||||
payload['data_install'] = json.dumps(payload[INSTALL_VALUES])
|
||||
try:
|
||||
# Inform dcmanager that subcloud has been updated.
|
||||
# It will do all the real work...
|
||||
if payload.get('admin_subnet'):
|
||||
if payload.get('management-state'):
|
||||
pecan.abort(422, _('Management state and network configuration must be updated separately'))
|
||||
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED:
|
||||
pecan.abort(422, _("Subcloud must be unmanaged to update admin network"))
|
||||
|
||||
subcloud = db_api.subcloud_update(
|
||||
context, subcloud_id,
|
||||
deploy_status=consts.DEPLOY_STATE_RECONFIGURING_NETWORK)
|
||||
if reconfigure_network:
|
||||
self.dcmanager_rpc_client.update_subcloud_with_network_reconfig(
|
||||
context, subcloud_id, payload)
|
||||
return db_api.subcloud_db_model_to_dict(subcloud)
|
||||
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=payload.get('data_install'),
|
||||
force=force_flag)
|
||||
return subcloud
|
||||
subcloud = self.dcmanager_rpc_client.update_subcloud(
|
||||
context, subcloud_id, management_state=management_state,
|
||||
description=description, location=location,
|
||||
group_id=group_id, data_install=payload.get('data_install'),
|
||||
force=force_flag)
|
||||
return subcloud
|
||||
except RemoteError as e:
|
||||
pecan.abort(422, e.value)
|
||||
except Exception as e:
|
||||
|
|
|
@ -26,6 +26,7 @@ import shutil
|
|||
import threading
|
||||
import time
|
||||
|
||||
from cgtsclient.exc import HTTPConflict
|
||||
from eventlet import greenpool
|
||||
from fm_api import constants as fm_const
|
||||
from fm_api import fm_api
|
||||
|
@ -1741,6 +1742,11 @@ class SubcloudManager(manager.Manager):
|
|||
return db_api.subcloud_db_model_to_dict(subcloud)
|
||||
|
||||
def update_subcloud_with_network_reconfig(self, context, subcloud_id, payload):
|
||||
subcloud = db_api.subcloud_get(context, subcloud_id)
|
||||
subcloud = db_api.subcloud_update(
|
||||
context, subcloud.id,
|
||||
deploy_status=consts.DEPLOY_STATE_RECONFIGURING_NETWORK
|
||||
)
|
||||
subcloud_name = payload['name']
|
||||
try:
|
||||
self._create_intermediate_ca_cert(payload)
|
||||
|
@ -1754,22 +1760,25 @@ class SubcloudManager(manager.Manager):
|
|||
update_command = self.compose_update_command(
|
||||
subcloud_name, subcloud_inventory_file)
|
||||
except Exception:
|
||||
LOG.exception("Failed to prepare subcloud %s for update."
|
||||
% subcloud_name)
|
||||
LOG.exception(
|
||||
"Failed to prepare subcloud %s for update." % subcloud_name)
|
||||
return
|
||||
try:
|
||||
apply_thread = threading.Thread(
|
||||
target=self._run_admin_network_update_playbook,
|
||||
args=(subcloud_name, update_command, overrides_file, payload, context, subcloud_id))
|
||||
target=self._run_network_reconfig_playbook,
|
||||
args=(subcloud_name, update_command, overrides_file,
|
||||
payload, context, subcloud))
|
||||
apply_thread.start()
|
||||
except Exception:
|
||||
LOG.exception("Failed to update subcloud %s" % subcloud_name)
|
||||
|
||||
def _run_admin_network_update_playbook(
|
||||
self, subcloud_name, update_command, overrides_file, payload, context, subcloud_id):
|
||||
def _run_network_reconfig_playbook(
|
||||
self, subcloud_name, update_command, overrides_file,
|
||||
payload, context, subcloud
|
||||
):
|
||||
log_file = (os.path.join(consts.DC_ANSIBLE_LOG_DIR, subcloud_name) +
|
||||
'_playbook_output.log')
|
||||
subcloud = db_api.subcloud_get(context, subcloud_id)
|
||||
subcloud_id = subcloud.id
|
||||
try:
|
||||
run_playbook(log_file, update_command)
|
||||
utils.delete_subcloud_inventory(overrides_file)
|
||||
|
@ -1787,9 +1796,14 @@ class SubcloudManager(manager.Manager):
|
|||
m_ks_client = OpenStackDriver(
|
||||
region_name=dccommon_consts.DEFAULT_REGION_NAME,
|
||||
region_clients=None).keystone_client
|
||||
self._create_subcloud_admin_route(payload, m_ks_client)
|
||||
self._create_subcloud_route(payload, m_ks_client, subcloud)
|
||||
except HTTPConflict:
|
||||
# The route already exists
|
||||
LOG.warning(
|
||||
"Failed to create route to subcloud %s" % subcloud_name)
|
||||
except Exception:
|
||||
LOG.exception("Failed to create route to admin")
|
||||
LOG.exception(
|
||||
"Failed to create route to subcloud %s." % subcloud_name)
|
||||
db_api.subcloud_update(
|
||||
context, subcloud_id,
|
||||
deploy_status=consts.DEPLOY_STATE_RECONFIGURING_NETWORK_FAILED,
|
||||
|
@ -1797,7 +1811,8 @@ class SubcloudManager(manager.Manager):
|
|||
)
|
||||
return
|
||||
try:
|
||||
self._update_services_endpoint(context, payload, m_ks_client)
|
||||
self._update_services_endpoint(
|
||||
context, payload, subcloud_name, m_ks_client)
|
||||
except Exception:
|
||||
LOG.exception("Failed to update subcloud %s endpoints" % subcloud_name)
|
||||
db_api.subcloud_update(
|
||||
|
@ -1810,45 +1825,46 @@ class SubcloudManager(manager.Manager):
|
|||
self._delete_subcloud_routes(m_ks_client, subcloud)
|
||||
|
||||
db_api.subcloud_update(
|
||||
context, subcloud_id,
|
||||
deploy_status=consts.DEPLOY_STATE_DONE
|
||||
context, subcloud_id, deploy_status=consts.DEPLOY_STATE_DONE
|
||||
)
|
||||
|
||||
subcloud = db_api.subcloud_update(
|
||||
context,
|
||||
subcloud_id,
|
||||
description=payload.get('description', subcloud.description),
|
||||
management_subnet=payload.get('admin_subnet'),
|
||||
management_gateway_ip=payload.get('admin_gateway_ip'),
|
||||
management_start_ip=payload.get('admin_start_address'),
|
||||
management_end_ip=payload.get('admin_end_address'),
|
||||
management_subnet=payload.get('management_subnet'),
|
||||
management_gateway_ip=payload.get('management_gateway_ip'),
|
||||
management_start_ip=payload.get('management_start_ip'),
|
||||
management_end_ip=payload.get('management_end_ip'),
|
||||
location=payload.get('location', subcloud.location),
|
||||
group_id=payload.get('group_id', subcloud.group_id),
|
||||
data_install=payload.get('data_install', subcloud.data_install)
|
||||
)
|
||||
|
||||
def _create_subcloud_admin_route(self, payload, keystone_client):
|
||||
subcloud_subnet = netaddr.IPNetwork(utils.get_management_subnet(payload))
|
||||
# Regenerate the addn_hosts_dc file
|
||||
self._create_addn_hosts_dc(context)
|
||||
|
||||
def _create_subcloud_route(self, payload, keystone_client, subcloud):
|
||||
subcloud_subnet = netaddr.IPNetwork(payload.get('management_subnet'))
|
||||
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
|
||||
sysinv_client = SysinvClient(dccommon_consts.DEFAULT_REGION_NAME,
|
||||
keystone_client.session,
|
||||
endpoint=endpoint)
|
||||
systemcontroller_gateway_ip = payload.get('systemcontroller_gateway_ip')
|
||||
# TODO(nicodemos) delete old route
|
||||
cached_regionone_data = self._get_cached_regionone_data(
|
||||
keystone_client, sysinv_client)
|
||||
for mgmt_if_uuid in cached_regionone_data['mgmt_interface_uuids']:
|
||||
sysinv_client.create_route(mgmt_if_uuid,
|
||||
str(subcloud_subnet.ip),
|
||||
subcloud_subnet.prefixlen,
|
||||
systemcontroller_gateway_ip,
|
||||
subcloud.systemcontroller_gateway_ip,
|
||||
1)
|
||||
|
||||
def _update_services_endpoint(self, context, payload, m_ks_client):
|
||||
endpoint_ip = str(ipaddress.ip_network(payload.get('admin_subnet'))[2])
|
||||
subcloud_name = payload.get('name')
|
||||
def _update_services_endpoint(
|
||||
self, context, payload, subcloud_name, m_ks_client):
|
||||
endpoint_ip = str(ipaddress.ip_network(
|
||||
payload.get('management_subnet'))[2])
|
||||
if netaddr.IPAddress(endpoint_ip).version == 6:
|
||||
endpoint_ip = '[' + endpoint_ip + ']'
|
||||
endpoint_ip = f"[{endpoint_ip}]"
|
||||
|
||||
services_endpoints = {
|
||||
"keystone": "https://{}:5001/v3".format(endpoint_ip),
|
||||
|
@ -1911,14 +1927,17 @@ class SubcloudManager(manager.Manager):
|
|||
payload['sysadmin_password'])
|
||||
payload['override_values']['ansible_become_pass'] = (
|
||||
payload['sysadmin_password'])
|
||||
payload['override_values']['admin_gateway_address'] = (
|
||||
payload['admin_gateway_ip'])
|
||||
payload['override_values']['admin_floating_address'] = (
|
||||
payload['admin_start_address']
|
||||
)
|
||||
payload['override_values']['admin_subnet'] = (
|
||||
payload['admin_subnet']
|
||||
)
|
||||
|
||||
payload['override_values']['sc_gateway_address'] = (
|
||||
payload['management_gateway_ip'])
|
||||
payload['override_values']['sc_floating_address'] = (
|
||||
payload['management_start_ip'])
|
||||
payload['override_values']['system_controller_network'] = (
|
||||
payload['system_controller_network'])
|
||||
payload['override_values']['system_controller_network_prefix'] = (
|
||||
payload['system_controller_network_prefix'])
|
||||
payload['override_values']['sc_subnet'] = payload['management_subnet']
|
||||
|
||||
payload['override_values']['dc_root_ca_cert'] = payload['dc_root_ca_cert']
|
||||
payload['override_values']['sc_ca_cert'] = payload['sc_ca_cert']
|
||||
payload['override_values']['sc_ca_key'] = payload['sc_ca_key']
|
||||
|
|
|
@ -278,9 +278,9 @@ class TestSubcloudPost(testroot.DCManagerApiTest,
|
|||
'192.168.204.100')
|
||||
|
||||
p = mock.patch.object(subclouds.SubcloudsController,
|
||||
'_get_management_address_pool')
|
||||
self.mock_get_management_address_pool = p.start()
|
||||
self.mock_get_management_address_pool.return_value = \
|
||||
'_get_network_address_pool')
|
||||
self.mock_get_network_address_pool = p.start()
|
||||
self.mock_get_network_address_pool.return_value = \
|
||||
self.management_address_pool
|
||||
self.addCleanup(p.stop)
|
||||
|
||||
|
@ -1234,21 +1234,30 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
|||
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_network_address_pool')
|
||||
@mock.patch.object(subclouds.SubcloudsController,
|
||||
'_validate_network_reconfiguration')
|
||||
@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):
|
||||
def test_patch_subcloud_network_values(
|
||||
self, mock_get_patch_data, mock_validate_network_reconfiguration,
|
||||
mock_mgmt_address_pool, mock_rpc_client):
|
||||
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
|
||||
db_api.subcloud_update(self.ctx, subcloud.id,
|
||||
availability_status=dccommon_consts.AVAILABILITY_ONLINE)
|
||||
db_api.subcloud_update(
|
||||
self.ctx, subcloud.id,
|
||||
availability_status=dccommon_consts.AVAILABILITY_ONLINE)
|
||||
fake_password = (
|
||||
base64.b64encode('testpass'.encode("utf-8"))).decode('ascii')
|
||||
payload = {'sysadmin_password': fake_password,
|
||||
'admin_subnet': "192.168.102.0/24",
|
||||
'admin_start_address': "192.168.102.5",
|
||||
'admin_end_address': "192.168.102.49",
|
||||
'admin_gateway_ip': "192.168.102.1"}
|
||||
'bootstrap_address': "192.168.102.2",
|
||||
'management_subnet': "192.168.102.0/24",
|
||||
'management_start_ip': "192.168.102.5",
|
||||
'management_end_ip': "192.168.102.49",
|
||||
'management_gateway_ip': "192.168.102.1"}
|
||||
|
||||
fake_management_address_pool = FakeAddressPool('192.168.204.0', 24,
|
||||
'192.168.204.2',
|
||||
'192.168.204.100')
|
||||
mock_mgmt_address_pool.return_value = fake_management_address_pool
|
||||
|
||||
mock_rpc_client().update_subcloud_with_network_reconfig.return_value = True
|
||||
mock_get_patch_data.return_value = payload
|
||||
|
@ -1256,7 +1265,7 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
|
|||
headers=FAKE_HEADERS,
|
||||
params=payload)
|
||||
self.assertEqual(response.status_int, 200)
|
||||
mock_validate_admin_network_config.assert_called_once()
|
||||
mock_validate_network_reconfiguration.assert_called_once()
|
||||
mock_rpc_client().update_subcloud_with_network_reconfig.assert_called_once_with(
|
||||
mock.ANY,
|
||||
subcloud.id,
|
||||
|
|
|
@ -661,17 +661,19 @@ class TestSubcloudManager(base.DCManagerTestCase):
|
|||
self.assertEqual("subcloud new location",
|
||||
updated_subcloud.location)
|
||||
|
||||
@mock.patch.object(subcloud_manager.SubcloudManager,
|
||||
'_create_addn_hosts_dc')
|
||||
@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_admin_route')
|
||||
'_create_subcloud_route')
|
||||
@mock.patch.object(subcloud_manager, 'OpenStackDriver')
|
||||
@mock.patch.object(subcloud_manager, 'run_playbook')
|
||||
def test_update_subcloud_with_admin_values(
|
||||
def test_update_subcloud_network_reconfiguration(
|
||||
self, mock_run_playbook, mock_keystone_client, mock_create_route,
|
||||
mock_update_endpoints, mock_delete_route):
|
||||
mock_update_endpoints, mock_delete_route, mock_addn_hosts_dc):
|
||||
subcloud = self.create_subcloud_static(
|
||||
self.ctx,
|
||||
name='subcloud1',
|
||||
|
@ -683,10 +685,10 @@ class TestSubcloudManager(base.DCManagerTestCase):
|
|||
payload = {'name': subcloud.name,
|
||||
'description': "subcloud description",
|
||||
'location': "subcloud location",
|
||||
'admin_subnet': "192.168.102.0/24",
|
||||
'admin_start_address': "192.168.102.5",
|
||||
'admin_end_address': "192.168.102.49",
|
||||
'admin_gateway_ip': "192.168.102.1"}
|
||||
'management_subnet': "192.168.102.0/24",
|
||||
'management_start_ip': "192.168.102.5",
|
||||
'management_end_ip': "192.168.102.49",
|
||||
'management_gateway_ip': "192.168.102.1"}
|
||||
|
||||
fake_dcmanager_notification = FakeDCManagerNotifications()
|
||||
|
||||
|
@ -695,14 +697,15 @@ class TestSubcloudManager(base.DCManagerTestCase):
|
|||
mock_dcmanager_api.return_value = fake_dcmanager_notification
|
||||
|
||||
sm = subcloud_manager.SubcloudManager()
|
||||
sm._run_admin_network_update_playbook(
|
||||
subcloud.name, mock.ANY, None, payload, self.ctx, subcloud.id)
|
||||
sm._run_network_reconfig_playbook(
|
||||
subcloud.name, mock.ANY, None, payload, self.ctx, subcloud)
|
||||
|
||||
mock_run_playbook.assert_called_once()
|
||||
mock_keystone_client.assert_called_once()
|
||||
mock_create_route.assert_called_once()
|
||||
mock_update_endpoints.assert_called_once()
|
||||
mock_delete_route.assert_called_once()
|
||||
mock_addn_hosts_dc.assert_called_once()
|
||||
|
||||
# Verify subcloud was updated with correct values
|
||||
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
|
||||
|
@ -710,13 +713,13 @@ class TestSubcloudManager(base.DCManagerTestCase):
|
|||
updated_subcloud.description)
|
||||
self.assertEqual(payload['location'],
|
||||
updated_subcloud.location)
|
||||
self.assertEqual(payload['admin_subnet'],
|
||||
self.assertEqual(payload['management_subnet'],
|
||||
updated_subcloud.management_subnet)
|
||||
self.assertEqual(payload['admin_gateway_ip'],
|
||||
self.assertEqual(payload['management_gateway_ip'],
|
||||
updated_subcloud.management_gateway_ip)
|
||||
self.assertEqual(payload['admin_start_address'],
|
||||
self.assertEqual(payload['management_start_ip'],
|
||||
updated_subcloud.management_start_ip)
|
||||
self.assertEqual(payload['admin_end_address'],
|
||||
self.assertEqual(payload['management_end_ip'],
|
||||
updated_subcloud.management_end_ip)
|
||||
|
||||
def test_update_subcloud_with_install_values(self):
|
||||
|
|
Loading…
Reference in New Issue