Merge "Subcloud Name Reconfiguration"

This commit is contained in:
Zuul 2023-09-07 14:02:21 +00:00 committed by Gerrit Code Review
commit a0dfc1adc3
73 changed files with 1167 additions and 377 deletions

View File

@ -78,6 +78,7 @@ Response
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -173,6 +174,7 @@ Request Example
- management-gateway-ip: management_gateway_ip
- management-start-ip: management_start_ip
- management-end-ip: management_end_ip
- region-name: region_name
Response Example
----------------
@ -283,6 +285,7 @@ This operation does not accept a request body.
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -314,6 +317,8 @@ Modifies a specific subcloud
The attributes of a subcloud which are modifiable:
- name
- description
- location
@ -349,6 +354,7 @@ serviceUnavailable (503)
.. rest_parameters:: parameters.yaml
- subcloud: subcloud_uri
- name: subcloud_name
- description: subcloud_description
- location: subcloud_location
- management-state: subcloud_management_state
@ -382,6 +388,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -526,6 +533,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -857,6 +865,7 @@ This operation does not accept a request body.
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -1025,6 +1034,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -1136,6 +1146,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -1830,6 +1841,7 @@ Request Example
- backup-status: backup_status
- backup-datetime: backup_datetime
- error-description: error_description
- region-name: region_name
- management-subnet: management_subnet
- management-start-ip: management_start_ip
- management-end-ip: management_end_ip
@ -1897,6 +1909,7 @@ Request Example
- backup-status: backup_status
- backup-datetime: backup_datetime
- error-description: error_description
- region-name: region_name
- management-subnet: management_subnet
- management-start-ip: management_start_ip
- management-end-ip: management_end_ip
@ -1963,6 +1976,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -2036,6 +2050,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -2103,6 +2118,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -2170,6 +2186,7 @@ Request Example
- deploy-status: deploy_status
- backup-status: backup_status
- backup-datetime: backup_datetime
- region-name: region_name
- openstack-installed: openstack_installed
- management-state: management_state
- systemcontroller-gateway-ip: systemcontroller_gateway_ip
@ -2246,6 +2263,7 @@ Request Example
- backup-status: backup_status
- backup-datetime: backup_datetime
- error-description: error_description
- region-name: region_name
- management-subnet: management_subnet
- management-start-ip: management_start_ip
- management-end-ip: management_end_ip

View File

@ -9,6 +9,7 @@
"deploy-status": "aborting-install",
"backup-status": null,
"backup-datetime": null,
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -9,6 +9,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2023-05-02 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -9,6 +9,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2023-05-02 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -10,6 +10,7 @@
"backup-status": null,
"backup-datetime": null,
"error-description": "No errors present",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"management-subnet": "192.168.102.0/24",
"management-start-ip": "192.168.102.2",
"management-end-ip": "192.168.102.50",

View File

@ -9,6 +9,7 @@
"deploy-status": "pre-install",
"backup-status": null,
"backup-datetime": null,
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -10,6 +10,7 @@
"backup-status": null,
"backup-datetime": null,
"error-description": "No errors present",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"management-subnet": "192.168.102.0/24",
"management-start-ip": "192.168.102.2",
"management-end-ip": "192.168.102.50",

View File

@ -14,6 +14,7 @@
"error-description": "",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -14,6 +14,7 @@
"error-description": "",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -12,6 +12,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"openstack-installed": false,
"management-state": "managed",
"systemcontroller-gateway-ip": "192.168.204.101",

View File

@ -21,7 +21,8 @@
"data_install": null,
"data_upgrade": null,
"oam_floating_ip": "192.168.101.2",
"deploy_config_sync_status": "Deployment: configurations up-to-date"
"deploy_config_sync_status": "Deployment: configurations up-to-date",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"endpoint_sync_status": [
{
"sync_status": "in-sync",

View File

@ -11,6 +11,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -9,6 +9,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"description": "Ottawa Site",
"group_id": 1,
"location": "YOW",

View File

@ -12,6 +12,7 @@
"deploy-status": "complete",
"backup-status": "complete",
"backup-datetime": "2022-07-08 11:23:58.132134",
"region-name": "bbadb3e8e2ab473792c80ef09c5a12a4",
"openstack-installed": false,
"management-state": "managed",
"systemcontroller-gateway-ip": "192.168.204.101",

View File

@ -13,5 +13,6 @@
"management-gateway-ip": "192.168.205.1",
"management-end-ip": "192.168.205.160",
"id": 4,
"name": "subcloud7"
"name": "subcloud7",
"region-name": "b098933127ed408e9ad7f6e81c587edb"
}

View File

@ -171,6 +171,8 @@ class PhasedSubcloudDeployController(object):
payload = get_create_payload(request)
psd_common.subcloud_region_create(payload, context)
psd_common.pre_deploy_create(payload, context, request)
try:

View File

@ -201,7 +201,7 @@ class SubcloudBackupController(object):
and request_entity.type == 'subcloud'):
# Check the system health only if the command was issued
# to a single subcloud to avoid huge delays.
if not utils.is_subcloud_healthy(subcloud.name):
if not utils.is_subcloud_healthy(subcloud.region_name):
msg = _('Subcloud %s must be in good health for '
'subcloud-backup create.' % subcloud.name)
pecan.abort(400, msg)

View File

@ -404,6 +404,10 @@ class SubcloudsController(object):
first_time = False
for s in subcloud_list:
# This is to reduce changes on cert-mon
# Overwrites the name value with region
if utils.is_req_from_cert_mon_agent(request):
s['name'] = s['region-name']
result['subclouds'].append(s)
return result
@ -421,11 +425,19 @@ class SubcloudsController(object):
except exceptions.SubcloudNotFound:
pecan.abort(404, _('Subcloud not found'))
else:
# Look up subcloud by name
try:
subcloud = db_api.subcloud_get_by_name(context,
subcloud_ref)
except exceptions.SubcloudNameNotFound:
# This method replaces subcloud_get_by_name, since it
# allows to lookup the subcloud either by region name
# or subcloud name.
# When the request comes from the cert-monitor, it is
# based on the region name (which is UUID format).
# Whereas, if the request comes from a client other
# than cert-monitor, it will do the lookup based on
# the subcloud name.
subcloud = db_api.subcloud_get_by_name_or_region_name(
context,
subcloud_ref)
except exceptions.SubcloudNameOrRegionNameNotFound:
pecan.abort(404, _('Subcloud not found'))
subcloud_id = subcloud.id
@ -448,6 +460,8 @@ class SubcloudsController(object):
self._append_static_err_content(subcloud_dict)
subcloud_region = subcloud.region_name
subcloud_dict.pop('region-name')
if detail is not None:
oam_floating_ip = "unavailable"
deploy_config_sync_status = "unknown"
@ -455,19 +469,20 @@ class SubcloudsController(object):
# Get the keystone client that will be used
# for _get_deploy_config_sync_status and _get_oam_addresses
sc_ks_client = psd_common.get_ks_client(subcloud.name)
sc_ks_client = psd_common.get_ks_client(subcloud_region)
oam_addresses = self._get_oam_addresses(context,
subcloud.name, sc_ks_client)
subcloud_region, sc_ks_client)
if oam_addresses is not None:
oam_floating_ip = oam_addresses.oam_floating_ip
deploy_config_state = self._get_deploy_config_sync_status(
context, subcloud.name, sc_ks_client)
context, subcloud_region, sc_ks_client)
if deploy_config_state is not None:
deploy_config_sync_status = deploy_config_state
extra_details = {"oam_floating_ip": oam_floating_ip,
"deploy_config_sync_status": deploy_config_sync_status}
"deploy_config_sync_status": deploy_config_sync_status,
"region_name": subcloud_region}
subcloud_dict.update(extra_details)
return subcloud_dict
@ -481,6 +496,8 @@ class SubcloudsController(object):
restcomm.extract_credentials_for_policy())
context = restcomm.extract_context_from_environ()
bootstrap_sc_name = psd_common.get_bootstrap_subcloud_name(request)
payload = psd_common.get_request_data(request, None,
SUBCLOUD_ADD_GET_FILE_CONTENTS)
@ -488,10 +505,19 @@ class SubcloudsController(object):
psd_common.validate_secondary_parameter(payload, request)
# Compares to match both supplied and bootstrap name param
# of the subcloud if migrate is on
if payload.get('migrate') == 'true' and bootstrap_sc_name is not None:
if bootstrap_sc_name != payload.get('name'):
pecan.abort(400, _('subcloud name does not match the '
'name defined in bootstrap file'))
# No need sysadmin_password when add a secondary subcloud
if 'secondary' not in payload:
psd_common.validate_sysadmin_password(payload)
psd_common.subcloud_region_create(payload, context)
psd_common.pre_deploy_create(payload, context, request)
try:
@ -537,12 +563,21 @@ class SubcloudsController(object):
except exceptions.SubcloudNotFound:
pecan.abort(404, _('Subcloud not found'))
else:
# Look up subcloud by name
try:
subcloud = db_api.subcloud_get_by_name(context,
subcloud_ref)
except exceptions.SubcloudNameNotFound:
pecan.abort(404, _('Subcloud not found'))
# This method replaces subcloud_get_by_name, since it
# allows to lookup the subcloud either by region name
# or subcloud name.
# When the request comes from the cert-monitor, it is
# based on the region name (which is UUID format).
# Whereas, if the request comes from a client other
# than cert-monitor, it will do the lookup based on
# the subcloud name.
subcloud = db_api.subcloud_get_by_name_or_region_name(
context,
subcloud_ref)
except exceptions.SubcloudNameOrRegionNameNotFound:
pecan.abort(404, _('Subcloud not found'))
subcloud_id = subcloud.id
if verb is None:
@ -551,6 +586,43 @@ class SubcloudsController(object):
if not payload:
pecan.abort(400, _('Body required'))
# Rename the subcloud
new_subcloud_name = payload.get('name')
if new_subcloud_name is not None:
# To be renamed the subcloud must be in unmanaged and valid deploy state
if subcloud.management_state != dccommon_consts.MANAGEMENT_UNMANAGED \
or subcloud.deploy_status not in consts.STATES_FOR_SUBCLOUD_RENAME:
msg = ('Subcloud %s must be unmanaged and in a valid deploy state '
'for the subcloud rename operation.' % subcloud.name)
# Validates new name
if not utils.is_subcloud_name_format_valid(new_subcloud_name):
pecan.abort(400, _("new name must contain alphabetic characters"))
# Checks if new subcloud name is the same as the current subcloud
if new_subcloud_name == subcloud.name:
pecan.abort(400, _('Provided subcloud name %s is the same as the '
'current subcloud %s. A different name is '
'required to rename the subcloud' %
(new_subcloud_name, subcloud.name)))
error_msg = ('Unable to rename subcloud %s with their region %s to %s' %
(subcloud.name, subcloud.region_name, new_subcloud_name))
try:
LOG.info("Renaming subcloud %s to: %s\n" % (subcloud.name,
new_subcloud_name))
sc = self.dcmanager_rpc_client.rename_subcloud(context,
subcloud_id,
subcloud.name,
new_subcloud_name)
subcloud.name = sc['name']
except RemoteError as e:
LOG.error(error_msg)
pecan.abort(422, e.value)
except Exception:
LOG.error(error_msg)
pecan.abort(500, _('Unable to rename subcloud'))
# Check if exist any network reconfiguration parameters
reconfigure_network = any(payload.get(value) is not None for value in (
SUBCLOUD_MANDATORY_NETWORK_PARAMS))
@ -562,6 +634,7 @@ class SubcloudsController(object):
system_controller_mgmt_pool = psd_common.get_network_address_pool()
# Required parameters
payload['name'] = subcloud.name
payload['region_name'] = subcloud.region_name
payload['system_controller_network'] = (
system_controller_mgmt_pool.network)
payload['system_controller_network_prefix'] = (
@ -715,7 +788,7 @@ class SubcloudsController(object):
'Please use /v1.0/subclouds/{subcloud}/redeploy'))
elif verb == 'update_status':
res = self.updatestatus(subcloud.name)
res = self.updatestatus(subcloud.name, subcloud.region_name)
return res
elif verb == 'prestage':
if utils.subcloud_is_secondary_state(subcloud.deploy_status):
@ -816,10 +889,11 @@ class SubcloudsController(object):
LOG.exception(e)
pecan.abort(500, _('Unable to delete subcloud'))
def updatestatus(self, subcloud_name):
def updatestatus(self, subcloud_name, subcloud_region):
"""Update subcloud sync status
:param subcloud_name: name of the subcloud
:param subcloud_region: name of the subcloud region
:return: json result object for the operation on success
"""
@ -848,7 +922,7 @@ class SubcloudsController(object):
LOG.info('update %s set %s=%s' % (subcloud_name, endpoint, status))
context = restcomm.extract_context_from_environ()
self.dcmanager_state_rpc_client.update_subcloud_endpoint_status(
context, subcloud_name, endpoint, status)
context, subcloud_name, subcloud_region, endpoint, status)
result = {'result': 'OK'}
return result

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2021-2022 Wind River Systems, Inc.
# Copyright (c) 2021-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -20,21 +20,22 @@ class Auditor(object):
self.state_rpc_client = dcmanager_state_rpc_client
self.endpoint_type = endpoint_type
def _set_subcloud_sync_status(self, sc_name, sc_sync_status):
def _set_subcloud_sync_status(self, sc_name, sc_region, sc_sync_status):
"""Update the sync status for endpoint."""
self.state_rpc_client.update_subcloud_endpoint_status(
self.context,
subcloud_name=sc_name,
subcloud_region=sc_region,
endpoint_type=self.endpoint_type,
sync_status=sc_sync_status)
def set_subcloud_endpoint_in_sync(self, sc_name):
def set_subcloud_endpoint_in_sync(self, sc_name, sc_region):
"""Set the endpoint sync status of this subcloud to be in sync"""
self._set_subcloud_sync_status(sc_name, dccommon_consts.SYNC_STATUS_IN_SYNC)
self._set_subcloud_sync_status(sc_name, sc_region, dccommon_consts.SYNC_STATUS_IN_SYNC)
def set_subcloud_endpoint_out_of_sync(self, sc_name):
def set_subcloud_endpoint_out_of_sync(self, sc_name, sc_region):
"""Set the endpoint sync status of this subcloud to be out of sync"""
self._set_subcloud_sync_status(sc_name,
self._set_subcloud_sync_status(sc_name, sc_region,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
@abc.abstractmethod

View File

@ -1,5 +1,5 @@
# Copyright 2017 Ericsson AB.
# Copyright (c) 2017-2022 Wind River Systems, Inc.
# Copyright (c) 2017-2023 Wind River Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -75,11 +75,12 @@ class FirmwareAudit(object):
self.state_rpc_client = dcmanager_state_rpc_client
self.audit_count = 0
def _update_subcloud_sync_status(self, sc_name, sc_endpoint_type,
def _update_subcloud_sync_status(self, sc_name, sc_region, sc_endpoint_type,
sc_status):
self.state_rpc_client.update_subcloud_endpoint_status(
self.context,
subcloud_name=sc_name,
subcloud_region=sc_region,
endpoint_type=sc_endpoint_type,
sync_status=sc_status)
@ -225,19 +226,20 @@ class FirmwareAudit(object):
return False
return True
def subcloud_firmware_audit(self, subcloud_name, audit_data):
def subcloud_firmware_audit(self, subcloud_name, subcloud_region, audit_data):
LOG.info('Triggered firmware audit for: %s.' % subcloud_name)
if not audit_data:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
dccommon_consts.SYNC_STATUS_IN_SYNC)
LOG.debug('No images to audit, exiting firmware audit')
return
try:
sc_os_client = OpenStackDriver(region_name=subcloud_name,
sc_os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None).keystone_client
endpoint = sc_os_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name, sc_os_client.session,
sysinv_client = SysinvClient(subcloud_region, sc_os_client.session,
endpoint=endpoint)
except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure,
@ -267,7 +269,8 @@ class FirmwareAudit(object):
LOG.info("No enabled devices on the subcloud %s,"
"exiting firmware audit" % subcloud_name)
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
dccommon_consts.SYNC_STATUS_IN_SYNC)
return
@ -312,10 +315,12 @@ class FirmwareAudit(object):
if out_of_sync:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
else:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
dccommon_consts.SYNC_STATUS_IN_SYNC)
LOG.info('Firmware audit completed for: %s.' % subcloud_name)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2021-2022 Wind River Systems, Inc.
# Copyright (c) 2021-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -46,20 +46,21 @@ class KubeRootcaUpdateAudit(Auditor):
"""
return []
def subcloud_audit(self, subcloud_name, region_one_audit_data):
def subcloud_audit(self, subcloud_name, subcloud_region, region_one_audit_data):
"""Perform an audit of kube root CA update info in a subcloud.
:param subcloud_name: the name of the subcloud
:param subcloud_region: the region of the subcloud
:param region_one_audit_data: ignored. Always an empty list
"""
LOG.info("Triggered %s audit for: %s" % (self.audit_type,
subcloud_name))
# check for a particular alarm in the subcloud
try:
sc_os_client = OpenStackDriver(region_name=subcloud_name,
sc_os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None)
session = sc_os_client.keystone_client.session
fm_client = FmClient(subcloud_name, session)
fm_client = FmClient(subcloud_region, session)
except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure,
keystone_exceptions.ConnectTimeout,
@ -75,8 +76,8 @@ class KubeRootcaUpdateAudit(Auditor):
out_of_sync = True
break
if out_of_sync:
self.set_subcloud_endpoint_out_of_sync(subcloud_name)
self.set_subcloud_endpoint_out_of_sync(subcloud_name, subcloud_region)
else:
self.set_subcloud_endpoint_in_sync(subcloud_name)
self.set_subcloud_endpoint_in_sync(subcloud_name, subcloud_region)
LOG.info("%s audit completed for: %s" % (self.audit_type,
subcloud_name))

View File

@ -1,5 +1,5 @@
# Copyright 2017 Ericsson AB.
# Copyright (c) 2017-2022 Wind River Systems, Inc.
# Copyright (c) 2017-2023 Wind River Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -55,11 +55,12 @@ class KubernetesAudit(object):
self.state_rpc_client = dcmanager_state_rpc_client
self.audit_count = 0
def _update_subcloud_sync_status(self, sc_name, sc_endpoint_type,
def _update_subcloud_sync_status(self, sc_name, sc_region, sc_endpoint_type,
sc_status):
self.state_rpc_client.update_subcloud_endpoint_status(
self.context,
subcloud_name=sc_name,
subcloud_region=sc_region,
endpoint_type=sc_endpoint_type,
sync_status=sc_status)
@ -90,19 +91,20 @@ class KubernetesAudit(object):
LOG.debug("RegionOne kubernetes versions: %s" % region_one_data)
return region_one_data
def subcloud_kubernetes_audit(self, subcloud_name, audit_data):
def subcloud_kubernetes_audit(self, subcloud_name, subcloud_region, audit_data):
LOG.info('Triggered kubernetes audit for: %s' % subcloud_name)
if not audit_data:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
dccommon_consts.SYNC_STATUS_IN_SYNC)
LOG.debug('No region one audit data, exiting kubernetes audit')
return
try:
sc_os_client = OpenStackDriver(region_name=subcloud_name,
sc_os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None).keystone_client
endpoint = sc_os_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name, sc_os_client.session,
sysinv_client = SysinvClient(subcloud_region, sc_os_client.session,
endpoint=endpoint)
except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure,
@ -152,10 +154,12 @@ class KubernetesAudit(object):
if out_of_sync:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
else:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
dccommon_consts.SYNC_STATUS_IN_SYNC)
LOG.info('Kubernetes audit completed for: %s' % subcloud_name)

View File

@ -1,5 +1,5 @@
# Copyright 2017 Ericsson AB.
# Copyright (c) 2017-2022 Wind River Systems, Inc.
# Copyright (c) 2017-2023 Wind River Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -62,11 +62,12 @@ class PatchAudit(object):
self.state_rpc_client = dcmanager_state_rpc_client
self.audit_count = 0
def _update_subcloud_sync_status(self, sc_name, sc_endpoint_type,
def _update_subcloud_sync_status(self, sc_name, sc_region, sc_endpoint_type,
sc_status):
self.state_rpc_client.update_subcloud_endpoint_status(
self.context,
subcloud_name=sc_name,
subcloud_region=sc_region,
endpoint_type=sc_endpoint_type,
sync_status=sc_status)
@ -132,19 +133,19 @@ class PatchAudit(object):
return PatchAuditData(regionone_patches, applied_patch_ids,
committed_patch_ids, regionone_software_version)
def subcloud_patch_audit(self, subcloud_name, audit_data, do_load_audit):
def subcloud_patch_audit(self, subcloud_name, subcloud_region, audit_data, do_load_audit):
LOG.info('Triggered patch audit for: %s.' % subcloud_name)
try:
sc_os_client = OpenStackDriver(region_name=subcloud_name,
sc_os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None).keystone_client
session = sc_os_client.session
patching_endpoint = sc_os_client.endpoint_cache.get_endpoint('patching')
sysinv_endpoint = sc_os_client.endpoint_cache.get_endpoint('sysinv')
patching_client = PatchingClient(
subcloud_name, session,
subcloud_region, session,
endpoint=patching_endpoint)
sysinv_client = SysinvClient(
subcloud_name, session,
subcloud_region, session,
endpoint=sysinv_endpoint)
except (keystone_exceptions.EndpointNotFound,
keystone_exceptions.ConnectFailure,
@ -227,11 +228,13 @@ class PatchAudit(object):
if out_of_sync:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_PATCHING,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_PATCHING,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
else:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_PATCHING,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_PATCHING,
dccommon_consts.SYNC_STATUS_IN_SYNC)
# Check subcloud software version every other audit cycle
@ -251,16 +254,19 @@ class PatchAudit(object):
if subcloud_software_version == audit_data.software_version:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_LOAD,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_LOAD,
dccommon_consts.SYNC_STATUS_IN_SYNC)
else:
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_LOAD,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_LOAD,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
else:
# As upgrade is still in progress, set the subcloud load
# status as out-of-sync.
self._update_subcloud_sync_status(
subcloud_name, dccommon_consts.ENDPOINT_TYPE_LOAD,
subcloud_name,
subcloud_region, dccommon_consts.ENDPOINT_TYPE_LOAD,
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
LOG.info('Patch audit completed for: %s.' % subcloud_name)

View File

@ -153,7 +153,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
# Create a new greenthread for each subcloud to allow the audits
# to be done in parallel. If there are not enough greenthreads
# in the pool, this will block until one becomes available.
self.subcloud_workers[subcloud.name] = \
self.subcloud_workers[subcloud.region_name] = \
self.thread_group_manager.start(self._do_audit_subcloud,
subcloud,
update_subcloud_state,
@ -204,12 +204,13 @@ class SubcloudAuditWorkerManager(manager.Manager):
'audit_fail_count for subcloud: %s' % subcloud.name)
def _update_subcloud_availability(self, subcloud_name,
subcloud_region,
availability_status=None,
update_state_only=False,
audit_fail_count=None):
try:
self.state_rpc_client.update_subcloud_availability(
self.context, subcloud_name, availability_status,
self.context, subcloud_name, subcloud_region, availability_status,
update_state_only, audit_fail_count)
LOG.info('Notifying dcmanager-state, subcloud:%s, availability:%s' %
(subcloud_name,
@ -339,7 +340,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
db_api.subcloud_audits_end_audit(self.context,
subcloud.id, audits_done)
# Remove the worker for this subcloud
self.subcloud_workers.pop(subcloud.name, None)
self.subcloud_workers.pop(subcloud.region_name, None)
LOG.debug("PID: %s, done auditing subcloud: %s." %
(self.pid, subcloud.name))
@ -361,6 +362,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
avail_status_current = subcloud.availability_status
audit_fail_count = subcloud.audit_fail_count
subcloud_name = subcloud.name
subcloud_region = subcloud.region_name
audits_done = list()
failures = list()
@ -371,7 +373,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
fm_client = None
avail_to_set = dccommon_consts.AVAILABILITY_OFFLINE
try:
os_client = OpenStackDriver(region_name=subcloud_name,
os_client = OpenStackDriver(region_name=subcloud_region,
thread_name='subcloud-audit',
region_clients=['fm', 'sysinv'])
sysinv_client = os_client.sysinv_client
@ -452,6 +454,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
(avail_to_set, subcloud_name))
self._update_subcloud_availability(
subcloud_name,
subcloud_region,
availability_status=avail_to_set,
audit_fail_count=audit_fail_count)
@ -470,6 +473,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
% subcloud_name)
self._update_subcloud_availability(
subcloud_name,
subcloud_region,
availability_status=avail_status_current,
update_state_only=True)
@ -488,6 +492,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
if do_patch_audit and patch_audit_data:
try:
self.patch_audit.subcloud_patch_audit(subcloud_name,
subcloud_region,
patch_audit_data,
do_load_audit)
audits_done.append('patch')
@ -504,6 +509,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
if do_firmware_audit:
try:
self.firmware_audit.subcloud_firmware_audit(subcloud_name,
subcloud_region,
firmware_audit_data)
audits_done.append('firmware')
except Exception:
@ -514,6 +520,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
try:
self.kubernetes_audit.subcloud_kubernetes_audit(
subcloud_name,
subcloud_region,
kubernetes_audit_data)
audits_done.append('kubernetes')
except Exception:
@ -524,6 +531,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
try:
self.kube_rootca_update_audit.subcloud_audit(
subcloud_name,
subcloud_region,
kube_rootca_update_audit_data)
audits_done.append('kube-rootca-update')
except Exception:
@ -536,7 +544,7 @@ class SubcloudAuditWorkerManager(manager.Manager):
# audits_done to be empty:
try:
self._audit_subcloud_openstack_app(
subcloud_name, sysinv_client, subcloud.openstack_installed)
subcloud_region, sysinv_client, subcloud.openstack_installed)
except Exception:
LOG.exception(failmsg % (subcloud.name, 'openstack'))
failures.append('openstack')

View File

@ -419,3 +419,9 @@ ALTERNATE_DEPLOY_PLAYBOOK_DIR = ALTERNATE_DEPLOY_FILES_DIR + '/playbooks'
DEPLOY_PLAYBOOK_POSTFIX = 'deployment-manager.yaml'
SUPPORTED_UPGRADES_METADATA_FILE_PATH = '/usr/rootdirs/opt/upgrades/metadata.xml'
# Required for subcloud name configuration
CERT_MON_HTTP_AGENT = 'cert-mon/1.0'
OS_REGION_NAME = "OS_REGION_NAME"
STATES_FOR_SUBCLOUD_RENAME = [DEPLOY_STATE_DONE,
PRESTAGE_STATE_COMPLETE]

View File

@ -115,6 +115,18 @@ class SubcloudNameNotFound(NotFound):
message = _("Subcloud with name %(name)s doesn't exist.")
class SubcloudRegionNameNotFound(NotFound):
message = _("Subcloud with region name %(region_name)s doesn't exist.")
class SubcloudNameOrRegionNameNotFound(NotFound):
message = _("Subcloud with name or region name %(name)s doesn't exist.")
class SubcloudOrRegionNameAlreadyExists(Conflict):
message = _("Subcloud with name or region name %(name)s already exist.")
class SubcloudNotOnline(DCManagerException):
message = _("Subcloud is not online.")

View File

@ -11,6 +11,7 @@ import typing
import netaddr
from oslo_log import log as logging
from oslo_utils import uuidutils
import pecan
import tsconfig.tsconfig as tsc
import yaml
@ -730,7 +731,18 @@ def upload_deploy_config_file(request, payload):
pecan.abort(400, _("No %s file uploaded" % consts.DEPLOY_CONFIG))
file_item.file.seek(0, os.SEEK_SET)
contents = file_item.file.read()
file_lines = file_item.file.readlines()
# Updates the OS_REGION_NAME param which is required for deployment
contents = ""
for line in file_lines:
dec_line = line.decode('utf8')
if consts.OS_REGION_NAME in dec_line:
os_reg_item = dec_line.split(":")
dec_line = os_reg_item[0] + ": " + payload['region_name'] + "\n"
contents = contents + dec_line
contents = contents.encode()
# the deploy config needs to upload to the override location
fn = get_config_file_path(payload['name'], consts.DEPLOY_CONFIG)
upload_config_file(contents, fn, consts.DEPLOY_CONFIG)
@ -844,6 +856,9 @@ def add_subcloud_to_database(context, payload):
if 'install_values' in payload:
data_install = json.dumps(payload['install_values'])
LOG.info("Creating subcloud %s with region: %s", payload.get('name'),
payload.get('region_name'))
subcloud = db_api.subcloud_create(
context,
payload['name'],
@ -857,6 +872,7 @@ def add_subcloud_to_database(context, payload):
payload['systemcontroller_gateway_address'],
consts.DEPLOY_STATE_NONE,
consts.ERROR_DESC_EMPTY,
payload['region_name'],
False,
group_id,
data_install=data_install)
@ -1023,3 +1039,118 @@ def pre_deploy_bootstrap(context: RequestContext, payload: dict,
# again:
validate_system_controller_patch_status("bootstrap")
validate_k8s_version(payload)
def get_bootstrap_subcloud_name(request: pecan.Request):
bootstrap_values = request.POST.get(consts.BOOTSTRAP_VALUES)
bootstrap_sc_name = None
if bootstrap_values is not None:
bootstrap_values.file.seek(0, os.SEEK_SET)
contents = bootstrap_values.file.read()
data = yaml.safe_load(contents.decode('utf8'))
bootstrap_sc_name = data.get('name')
return bootstrap_sc_name
def get_region_value_from_subcloud(payload: dict):
subcloud_region = None
# It connects to the subcloud via the bootstrap-address IP and tries
# to get the region from it
if payload['bootstrap-address'] is not None:
try:
subcloud_region = utils.\
get_region_from_subcloud_address(payload)
LOG.info("Retrieved region value from subcloud to be migrated: %s"
% subcloud_region)
if subcloud_region is None:
msg = ("Cannot find subcloud's region name from address: %s"
% payload['bootstrap-address'])
LOG.error(msg)
raise exceptions.InvalidParameterValue(err=msg)
except Exception:
LOG.error("Unable to retrieve the region value from subcloud "
"address %s" % payload['bootstrap-address'])
raise
return subcloud_region
def is_migrate_scenario(payload: dict):
migrate = False
migrate_str = payload.get('migrate')
if migrate_str is not None:
if migrate_str == "true":
migrate = True
return migrate
def generate_subcloud_unique_region(context: RequestContext, payload: dict):
LOG.debug("Begin generate subcloud unique region for subcloud %s"
% payload['name'])
is_migrate = is_migrate_scenario(payload)
migrate_sc_region = None
# If migration flag is present, tries to connect to subcloud to
# get the region value
if is_migrate:
LOG.debug("The scenario matches that of the subcloud migration, "
"therefore it will try to obtain the value of the "
"region from subcloud %s..." % payload['name'])
migrate_sc_region = get_region_value_from_subcloud(payload)
else:
LOG.debug("The scenario matches that of creating a new subcloud, "
"so a region will be generated randomly for "
"subcloud %s..." % payload['name'])
while True:
# If migrate flag is not present, creates a random region value
if not is_migrate:
subcloud_region = uuidutils.generate_uuid().replace("-", "")
else:
# In the migration/rehome scenario uses the region value
# returned by queried subcloud
subcloud_region = migrate_sc_region
# Lookup region to check if exists
try:
db_api.subcloud_get_by_region_name(context,
subcloud_region)
LOG.info("Subcloud region: %s already exists. "
"Generating new one..." % (subcloud_region))
# In the migration scenario, it is intended to use the
# same region that the current subcloud has, therefore
# another region value cannot be generated.
if is_migrate:
LOG.error("Subcloud region to migrate: %s already exists "
"and it is not allowed to generate a new region "
"for a subcloud migration" % (subcloud_region))
raise exceptions.SubcloudAlreadyExists(
region_name=subcloud_region)
except exceptions.SubcloudRegionNameNotFound:
break
except Exception:
message = "Unable to generate subcloud region"
LOG.error(message)
raise
if not is_migrate:
LOG.info("Generated region for new subcloud %s: %s"
% (payload.get('name'), subcloud_region))
else:
LOG.info("Region for subcloud %s to be migrated: %s"
% (payload.get('name'), subcloud_region))
return subcloud_region
def subcloud_region_create(payload: dict, context: RequestContext):
try:
# Generates a unique region value
payload['region_name'] = generate_subcloud_unique_region(context,
payload)
except Exception:
# For logging purpose only
msg = "Unable to generate or retrieve region value"
if not is_migrate_scenario(payload):
msg = "Unable to generate region value to update deploy \
config for subcloud %s" % payload.get('name')
LOG.exception(msg)
pecan.abort(400, _(msg))

View File

@ -188,7 +188,7 @@ def validate_prestage(subcloud, payload):
initial_subcloud_validate(subcloud, installed_loads, software_version)
subcloud_type, system_health, oam_floating_ip = \
_get_prestage_subcloud_info(subcloud.name)
_get_prestage_subcloud_info(subcloud)
if subcloud_type != consts.SYSTEM_MODE_SIMPLEX:
raise exceptions.PrestagePreCheckFailedException(
@ -287,18 +287,18 @@ def _prestage_standalone_thread(context, subcloud, payload):
raise
def _get_prestage_subcloud_info(subcloud_name):
def _get_prestage_subcloud_info(subcloud):
"""Retrieve prestage data from the subcloud.
Pull all required data here in order to minimize keystone/sysinv client
interactions.
"""
try:
os_client = OpenStackDriver(region_name=subcloud_name,
os_client = OpenStackDriver(region_name=subcloud.region_name,
region_clients=None)
keystone_client = os_client.keystone_client
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name,
sysinv_client = SysinvClient(subcloud.region_name,
keystone_client.session,
endpoint=endpoint)
mode = sysinv_client.get_system().system_mode
@ -309,7 +309,7 @@ def _get_prestage_subcloud_info(subcloud_name):
except Exception as e:
LOG.exception(e)
raise exceptions.PrestagePreCheckFailedException(
subcloud=subcloud_name,
subcloud=subcloud.name,
details="Failed to retrieve subcloud system mode and system health.")

View File

@ -55,6 +55,7 @@ DC_MANAGER_GRPNAME = "root"
# Max lines output msg from logs
MAX_LINES_MSG = 10
REGION_VALUE_CMD = "grep " + consts.OS_REGION_NAME + " /etc/platform/openrc"
ABORT_UPDATE_STATUS = {
consts.DEPLOY_STATE_INSTALLING: consts.DEPLOY_STATE_ABORTING_INSTALL,
@ -552,23 +553,23 @@ def subcloud_db_list_to_dict(subclouds):
for subcloud in subclouds]}
def get_oam_addresses(subcloud_name, sc_ks_client):
def get_oam_addresses(subcloud, sc_ks_client):
"""Get the subclouds oam addresses"""
# First need to retrieve the Subcloud's Keystone session
try:
endpoint = sc_ks_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name,
sysinv_client = SysinvClient(subcloud.region_name,
sc_ks_client.session,
endpoint=endpoint)
return sysinv_client.get_oam_addresses()
except (keystone_exceptions.EndpointNotFound, IndexError) as e:
message = ("Identity endpoint for subcloud: %s not found. %s" %
(subcloud_name, e))
(subcloud.name, e))
LOG.error(message)
except dccommon_exceptions.OAMAddressesNotFound:
message = ("OAM addresses for subcloud: %s not found." %
subcloud_name)
subcloud.name)
LOG.error(message)
return None
@ -596,6 +597,65 @@ def pre_check_management_affected_alarm(system_health):
return True
def is_subcloud_name_format_valid(name):
"""Validates subcloud name format
Regex based on RFC 1123 subdomain validation
param: name = Subcloud name
returns True if name is valid, otherwise it returns false.
"""
rex = r"[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*"
pat = re.compile(rex)
if re.fullmatch(pat, name):
return True
return False
def get_region_from_subcloud_address(payload):
"""Retrieves the current region from the subcloud being migrated
param: payload = Subcloud payload
returns the OS_REGION_NAME value from subcloud
"""
cmd = [
"sshpass",
"-p",
str(payload['sysadmin_password']),
"ssh",
"-q",
"sysadmin@" + str(payload['bootstrap-address']),
REGION_VALUE_CMD,
]
try:
LOG.info("Getting region value from subcloud %s" % payload['name'])
task = subprocess.check_output(
cmd,
stderr=subprocess.STDOUT).decode('utf-8')
if len(task) < 1:
return None
subcloud_region = str(task.split("=")[1]).strip()
except Exception:
LOG.error("Unable to get region value from subcloud %s"
% payload['name'])
raise
system_regions = [dccommon_consts.DEFAULT_REGION_NAME,
dccommon_consts.SYSTEM_CONTROLLER_NAME]
if subcloud_region in system_regions:
LOG.error("Invalid region value: %s" % subcloud_region)
raise exceptions.InvalidParameterValue(
err="Invalid region value: %s" % subcloud_region)
# Returns the region value from result:
# Current systems: export OS_REGION_NAME=subcloudX
# New systems: export OS_REGION_NAME=abcdefghhijlkmnopqrstuvqxyz12342
return subcloud_region
def find_ansible_error_msg(subcloud_name, log_file, stage=None):
"""Find errors into ansible logs.
@ -817,15 +877,15 @@ def get_matching_iso(software_version=None):
return None, str(e)
def is_subcloud_healthy(subcloud_name):
def is_subcloud_healthy(subcloud_region):
system_health = ""
try:
os_client = OpenStackDriver(region_name=subcloud_name,
os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None)
keystone_client = os_client.keystone_client
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name,
sysinv_client = SysinvClient(subcloud_region,
keystone_client.session,
endpoint=endpoint)
system_health = sysinv_client.get_system_health()
@ -1083,19 +1143,19 @@ def decode_and_normalize_passwd(input_passwd):
return passwd
def get_failure_msg(subcloud_name):
def get_failure_msg(subcloud_region):
try:
os_client = OpenStackDriver(region_name=subcloud_name,
os_client = OpenStackDriver(region_name=subcloud_region,
region_clients=None)
keystone_client = os_client.keystone_client
endpoint = keystone_client.endpoint_cache.get_endpoint('sysinv')
sysinv_client = SysinvClient(subcloud_name,
sysinv_client = SysinvClient(subcloud_region,
keystone_client.session,
endpoint=endpoint)
msg = sysinv_client.get_error_msg()
return msg
except Exception as e:
LOG.exception("{}: {}".format(subcloud_name, e))
LOG.exception("{}: {}".format(subcloud_region, e))
return consts.ERROR_DESC_FAILED
@ -1181,3 +1241,19 @@ def get_current_supported_upgrade_versions():
supported_versions.append(version.strip())
return supported_versions
# Feature: Subcloud Name Reconfiguration
# This method is useful to determine the origin of the request
# towards the api. The goal was to avoid any code changes in
# the cert-monitor module, since it only needs the region reference.
# When this method is called, the condition is applied to replace the
# value of the "name" field with the value of the "region_name" field
# in the response. In this way, the cert-monitor does not lose the
# region reference in subcloud rename operation.
def is_req_from_cert_mon_agent(request):
ua = request.headers.get("User-Agent")
if ua == consts.CERT_MON_HTTP_AGENT:
return True
else:
return False

View File

@ -112,6 +112,7 @@ def subcloud_db_model_to_dict(subcloud):
"backup-status": subcloud.backup_status,
"backup-datetime": subcloud.backup_datetime,
"error-description": subcloud.error_description,
'region-name': subcloud.region_name,
"management-subnet": subcloud.management_subnet,
"management-start-ip": subcloud.management_start_ip,
"management-end-ip": subcloud.management_end_ip,
@ -132,14 +133,14 @@ def subcloud_create(context, name, description, location, software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status, error_description,
openstack_installed, group_id, data_install=None):
region_name, openstack_installed, group_id, data_install=None):
"""Create a subcloud."""
return IMPL.subcloud_create(context, name, description, location,
software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status,
error_description, openstack_installed, group_id,
error_description, region_name, openstack_installed, group_id,
data_install)
@ -158,6 +159,16 @@ def subcloud_get_by_name(context, name) -> models.Subcloud:
return IMPL.subcloud_get_by_name(context, name)
def subcloud_get_by_region_name(context, region_name):
"""Retrieve a subcloud by region name or raise if it does not exist."""
return IMPL.subcloud_get_by_region_name(context, region_name)
def subcloud_get_by_name_or_region_name(context, name):
"""Retrieve a subcloud by name or region name or raise if it does not exist."""
return IMPL.subcloud_get_by_name_or_region_name(context, name)
def subcloud_get_all(context):
"""Retrieve all subclouds."""
return IMPL.subcloud_get_all(context)
@ -174,7 +185,7 @@ def subcloud_get_all_with_status(context):
def subcloud_update(context, subcloud_id, management_state=None,
availability_status=None, software_version=None,
availability_status=None, software_version=None, name=None,
description=None, management_subnet=None, management_gateway_ip=None,
management_start_ip=None, management_end_ip=None,
location=None, audit_fail_count=None,
@ -187,7 +198,7 @@ def subcloud_update(context, subcloud_id, management_state=None,
rehome_data=None):
"""Update a subcloud or raise if it does not exist."""
return IMPL.subcloud_update(context, subcloud_id, management_state,
availability_status, software_version,
availability_status, software_version, name,
description, management_subnet, management_gateway_ip,
management_start_ip, management_end_ip, location,
audit_fail_count, deploy_status, backup_status,
@ -677,3 +688,7 @@ def subcloud_alarms_update(context, name, values):
def subcloud_alarms_delete(context, name):
return IMPL.subcloud_alarms_delete(context, name)
def subcloud_rename_alarms(context, subcloud_name, new_name):
return IMPL.subcloud_rename_alarms(context, subcloud_name, new_name)

View File

@ -32,6 +32,7 @@ from oslo_utils import strutils
from oslo_utils import uuidutils
from sqlalchemy import desc
from sqlalchemy import or_
from sqlalchemy.orm.exc import MultipleResultsFound
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm import joinedload_all
@ -317,6 +318,32 @@ def subcloud_get_by_name(context, name):
return result
@require_context
def subcloud_get_by_region_name(context, region_name):
result = model_query(context, models.Subcloud). \
filter_by(deleted=0). \
filter_by(region_name=region_name). \
first()
if not result:
raise exception.SubcloudRegionNameNotFound(region_name=region_name)
return result
@require_context
def subcloud_get_by_name_or_region_name(context, name):
result = model_query(context, models.Subcloud). \
filter_by(deleted=0). \
filter(or_(models.Subcloud.name == name, models.Subcloud.region_name == name)). \
first()
if not result:
raise exception.SubcloudNameOrRegionNameNotFound(name=name)
return result
@require_context
def subcloud_get_all(context):
return model_query(context, models.Subcloud). \
@ -349,7 +376,7 @@ def subcloud_create(context, name, description, location, software_version,
management_subnet, management_gateway_ip,
management_start_ip, management_end_ip,
systemcontroller_gateway_ip, deploy_status, error_description,
openstack_installed, group_id,
region_name, openstack_installed, group_id,
data_install=None):
with write_session() as session:
subcloud_ref = models.Subcloud()
@ -366,6 +393,7 @@ def subcloud_create(context, name, description, location, software_version,
subcloud_ref.systemcontroller_gateway_ip = systemcontroller_gateway_ip
subcloud_ref.deploy_status = deploy_status
subcloud_ref.error_description = error_description
subcloud_ref.region_name = region_name
subcloud_ref.audit_fail_count = 0
subcloud_ref.openstack_installed = openstack_installed
subcloud_ref.group_id = group_id
@ -381,7 +409,7 @@ 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, management_subnet=None,
name=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,
@ -401,6 +429,8 @@ def subcloud_update(context, subcloud_id, management_state=None,
subcloud_ref.availability_status = availability_status
if software_version is not None:
subcloud_ref.software_version = software_version
if name is not None:
subcloud_ref.name = name
if description is not None:
subcloud_ref.description = description
if management_subnet is not None:
@ -1221,3 +1251,12 @@ def subcloud_alarms_delete(context, name):
with write_session() as session:
session.query(models.SubcloudAlarmSummary).\
filter_by(name=name).delete()
@require_admin_context
def subcloud_rename_alarms(context, subcloud_name, new_name):
with write_session() as session:
result = _subcloud_alarms_get(context, subcloud_name)
result.name = new_name
result.save(session)
return result

View File

@ -0,0 +1,37 @@
# Copyright (c) 2023 Wind River Systems, Inc.
# 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 sqlalchemy import Column, MetaData, String, Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
subclouds = Table('subclouds', meta, autoload=True)
# Add the 'region_name' column to the subclouds table.
subclouds.create_column(Column('region_name',
String(255)))
# populates region_name with name field value for existing subclouds
if migrate_engine.name == 'postgresql':
with migrate_engine.begin() as conn:
conn.execute("UPDATE subclouds SET region_name = name")
return True
def downgrade(migrate_engine):
raise NotImplementedError('Database downgrade is unsupported.')

View File

@ -148,6 +148,7 @@ class Subcloud(BASE, DCManagerBase):
backup_status = Column(String(255))
backup_datetime = Column(DateTime(timezone=False))
error_description = Column(String(2048))
region_name = Column(String(255), unique=True)
data_upgrade = Column(String())
management_subnet = Column(String(255))
management_gateway_ip = Column(String(255))

View File

@ -110,6 +110,27 @@ class DCManagerService(service.Service):
LOG.info("Handling delete_subcloud request for: %s" % subcloud_id)
return self.subcloud_manager.delete_subcloud(context, subcloud_id)
@request_context
def rename_subcloud(self, context, subcloud_id, curr_subcloud_name,
new_subcloud_name=None):
# Rename a subcloud
LOG.info("Handling rename_subcloud request for: %s" %
curr_subcloud_name)
subcloud = self.subcloud_manager.rename_subcloud(context,
subcloud_id,
curr_subcloud_name,
new_subcloud_name)
return subcloud
@request_context
def get_subcloud_name_by_region_name(self, context, subcloud_region):
# get subcloud by region name
LOG.debug("Handling get_subcloud_name_by_region_name request for "
"region: %s" % subcloud_region)
subcloud = self.subcloud_manager.get_subcloud_name_by_region_name(context,
subcloud_region)
return subcloud
@request_context
def update_subcloud(self, context, subcloud_id, management_state=None,
description=None, location=None,

View File

@ -179,10 +179,10 @@ class SubcloudManager(manager.Manager):
@staticmethod
def _create_intermediate_ca_cert(payload):
subcloud_name = payload["name"]
cert_name = SubcloudManager._get_subcloud_cert_name(subcloud_name)
subcloud_region = payload["region_name"]
cert_name = SubcloudManager._get_subcloud_cert_name(subcloud_region)
secret_name = SubcloudManager._get_subcloud_cert_secret_name(
subcloud_name)
subcloud_region)
cert = {
"apiVersion": "%s/%s" % (kubeoperator.CERT_MANAGER_GROUP,
@ -255,6 +255,7 @@ class SubcloudManager(manager.Manager):
return install_command
def compose_bootstrap_command(self, subcloud_name,
subcloud_region,
ansible_subcloud_inventory_file,
software_version=None):
bootstrap_command = [
@ -268,7 +269,7 @@ class SubcloudManager(manager.Manager):
# which overrides to load
bootstrap_command += [
"-e", str("override_files_dir='%s' region_name=%s") % (
dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_name),
dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_region),
"-e", "install_release_version=%s" %
software_version if software_version else SW_VERSION]
return bootstrap_command
@ -324,7 +325,7 @@ class SubcloudManager(manager.Manager):
subcloud_name + "_update_values.yml"]
return subcloud_update_command
def compose_rehome_command(self, subcloud_name,
def compose_rehome_command(self, subcloud_name, subcloud_region,
ansible_subcloud_inventory_file,
software_version):
rehome_command = [
@ -335,7 +336,7 @@ class SubcloudManager(manager.Manager):
"--limit", subcloud_name,
"--timeout", REHOME_PLAYBOOK_TIMEOUT,
"-e", str("override_files_dir='%s' region_name=%s") % (
dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_name)]
dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_region)]
return rehome_command
def migrate_subcloud(self, context, subcloud_ref, payload):
@ -394,6 +395,7 @@ class SubcloudManager(manager.Manager):
rehome_command = self.compose_rehome_command(
subcloud.name,
subcloud.region_name,
ansible_subcloud_inventory_file,
subcloud.software_version)
@ -407,7 +409,7 @@ class SubcloudManager(manager.Manager):
:param subcloud_id: id of the subcloud
:param payload: subcloud configuration
"""
LOG.info(f"Adding subcloud {payload['name']}.")
LOG.info(f"Adding subcloud {payload['name']} with region {payload['region_name']}.")
rehoming = payload.get('migrate', '').lower() == "true"
secondary = (payload.get('secondary', '').lower() == "true")
@ -653,6 +655,7 @@ class SubcloudManager(manager.Manager):
bootstrap_command = self.compose_bootstrap_command(
subcloud.name,
subcloud.region_name,
ansible_subcloud_inventory_file,
subcloud.software_version)
return bootstrap_command
@ -923,7 +926,7 @@ class SubcloudManager(manager.Manager):
endpoint["id"],
endpoint['admin_endpoint_url'],
interface=dccommon_consts.KS_ENDPOINT_ADMIN,
region=subcloud.name)
region=subcloud.region_name)
except Exception as e:
# Keystone service must be temporarily busy, retry
LOG.error(str(e))
@ -931,11 +934,11 @@ class SubcloudManager(manager.Manager):
endpoint["id"],
endpoint['admin_endpoint_url'],
interface=dccommon_consts.KS_ENDPOINT_ADMIN,
region=subcloud.name)
region=subcloud.region_name)
# Inform orchestrator that subcloud has been added
self.dcorch_rpc_client.add_subcloud(
context, subcloud.name, subcloud.software_version)
context, subcloud.region_name, subcloud.software_version)
# create entry into alarm summary table, will get real values later
alarm_updates = {'critical_alarms': -1,
@ -1282,7 +1285,7 @@ class SubcloudManager(manager.Manager):
def _backup_subcloud(self, context, payload, subcloud):
try:
# Health check validation
if not utils.is_subcloud_healthy(subcloud.name):
if not utils.is_subcloud_healthy(subcloud.region_name):
db_api.subcloud_update(
context,
subcloud.id,
@ -1442,9 +1445,9 @@ class SubcloudManager(manager.Manager):
else:
# Use subcloud floating IP for host reachability
keystone_client = OpenStackDriver(
region_name=subcloud.name,
region_name=subcloud.region_name,
region_clients=None).keystone_client
oam_fip = utils.get_oam_addresses(subcloud.name, keystone_client)\
oam_fip = utils.get_oam_addresses(subcloud, keystone_client)\
.oam_floating_ip
# Add parameters used to generate inventory
@ -2042,10 +2045,10 @@ class SubcloudManager(manager.Manager):
1)
@staticmethod
def _delete_subcloud_cert(subcloud_name):
cert_name = SubcloudManager._get_subcloud_cert_name(subcloud_name)
def _delete_subcloud_cert(subcloud_region):
cert_name = SubcloudManager._get_subcloud_cert_name(subcloud_region)
secret_name = SubcloudManager._get_subcloud_cert_secret_name(
subcloud_name)
subcloud_region)
kube = kubeoperator.KubeOperator()
kube.delete_cert_manager_certificate(CERT_NAMESPACE, cert_name)
@ -2059,7 +2062,7 @@ class SubcloudManager(manager.Manager):
"""Remove subcloud details from database and inform orchestrators"""
# Inform orchestrators that subcloud has been deleted
try:
self.dcorch_rpc_client.del_subcloud(context, subcloud.name)
self.dcorch_rpc_client.del_subcloud(context, subcloud.region_name)
except RemoteError as e:
# TODO(kmacleod): this should be caught as explicit remote exception
# Fix when centos/python2 is no longer supported
@ -2083,8 +2086,8 @@ class SubcloudManager(manager.Manager):
region_clients=None).keystone_client
# Delete keystone endpoints for subcloud
keystone_client.delete_endpoints(subcloud.name)
keystone_client.delete_region(subcloud.name)
keystone_client.delete_endpoints(subcloud.region_name)
keystone_client.delete_region(subcloud.region_name)
# Delete the routes to this subcloud
self._delete_subcloud_routes(keystone_client, subcloud)
@ -2100,7 +2103,7 @@ class SubcloudManager(manager.Manager):
utils.delete_subcloud_inventory(ansible_subcloud_inventory_file)
# Delete the subcloud intermediate certificate
SubcloudManager._delete_subcloud_cert(subcloud.name)
SubcloudManager._delete_subcloud_cert(subcloud.region_name)
# Delete the subcloud backup path
self._delete_subcloud_backup_data(subcloud.name)
@ -2142,6 +2145,42 @@ class SubcloudManager(manager.Manager):
if os.path.exists(install_path):
shutil.rmtree(install_path)
def _rename_subcloud_ansible_files(self, cur_sc_name, new_sc_name):
"""Renames the ansible and logs files from the given subcloud"""
ansible_path = dccommon_consts.ANSIBLE_OVERRIDES_PATH
log_path = consts.DC_ANSIBLE_LOG_DIR
ansible_file_list = os.listdir(ansible_path)
log_file_list = os.listdir(log_path)
ansible_file_list = [ansible_path + '/' + x for x in ansible_file_list]
log_file_list = [log_path + '/' + x for x in log_file_list]
for cur_file in ansible_file_list + log_file_list:
new_file = cur_file.replace(cur_sc_name, new_sc_name)
if os.path.exists(cur_file) and new_sc_name in new_file:
os.rename(cur_file, new_file)
# Gets new ansible inventory file
ansible_inv_file = self._get_ansible_filename(new_sc_name,
INVENTORY_FILE_POSTFIX)
# Updates inventory host param with the new subcloud name
with open(ansible_inv_file, 'r') as f:
data = yaml.safe_load(f)
mkey = list(data.keys())[0]
if mkey in data and 'hosts' in data[mkey] and \
cur_sc_name in data[mkey]['hosts']:
data[mkey]['hosts'][new_sc_name] = \
data[mkey]['hosts'].pop(cur_sc_name)
with open(ansible_inv_file, 'w') as f:
yaml.dump(data, f, sort_keys=False)
@staticmethod
def _delete_subcloud_backup_data(subcloud_name):
try:
@ -2208,6 +2247,62 @@ class SubcloudManager(manager.Manager):
(subcloud.name, alarm_id))
LOG.exception(e)
def rename_subcloud(self,
context,
subcloud_id,
curr_subcloud_name,
new_subcloud_name=None):
"""Rename subcloud.
:param context: request context object.
:param subcloud_id: id of subcloud to rename
:param curr_subcloud_name: current subcloud name
:param new_subcloud_name: new subcloud name
"""
try:
subcloud = db_api.\
subcloud_get_by_name_or_region_name(context,
new_subcloud_name)
except exceptions.SubcloudNameOrRegionNameNotFound:
pass
else:
# If the found subcloud id is not the same as the received
# subcloud id, it indicates that the name change does not
# correspond to the current subcloud.
# Therefore it is not allowed to change the name.
if subcloud_id != subcloud.id:
raise exceptions.SubcloudOrRegionNameAlreadyExists(
name=new_subcloud_name)
# updates subcloud name
subcloud = db_api.subcloud_update(context, subcloud_id,
name=new_subcloud_name)
# updates subcloud names on alarms
db_api.subcloud_rename_alarms(context, curr_subcloud_name,
new_subcloud_name)
# Deletes subcloud alarms
entity_instance_id = "subcloud=%s" % curr_subcloud_name
self.fm_api.clear_all(entity_instance_id)
# Regenerate the dnsmasq host entry
self._create_addn_hosts_dc(context)
# Rename related subcloud files
self._rename_subcloud_ansible_files(curr_subcloud_name,
new_subcloud_name)
return subcloud
def get_subcloud_name_by_region_name(self,
context,
subcloud_region):
subcloud_name = None
if subcloud_region is not None:
sc = db_api.subcloud_get_by_region_name(context, subcloud_region)
subcloud_name = sc.get("name")
return subcloud_name
def update_subcloud(self,
context,
subcloud_id,
@ -2363,7 +2458,7 @@ class SubcloudManager(manager.Manager):
# Inform orchestrator of state change
self.dcorch_rpc_client.update_subcloud_states(
context,
subcloud.name,
subcloud.region_name,
management_state,
subcloud.availability_status)
@ -2391,6 +2486,7 @@ class SubcloudManager(manager.Manager):
self.state_rpc_client.update_subcloud_endpoint_status_sync(
context,
subcloud_name=subcloud.name,
subcloud_region=subcloud.region_name,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_UNKNOWN,
ignore_endpoints=[dccommon_consts.ENDPOINT_TYPE_DC_CERT])
@ -2399,7 +2495,7 @@ class SubcloudManager(manager.Manager):
# Tell cert-mon to audit endpoint certificate
LOG.info('Request certmon audit for %s' % subcloud.name)
dc_notification = dcmanager_rpc_client.DCManagerNotifications()
dc_notification.subcloud_managed(context, subcloud.name)
dc_notification.subcloud_managed(context, subcloud.region_name)
return db_api.subcloud_db_model_to_dict(subcloud)
@ -2487,6 +2583,7 @@ class SubcloudManager(manager.Manager):
:param update_db: whether it should update the db on success/failure
"""
subcloud_name = subcloud.name
subcloud_region = subcloud.region_name
subcloud_id = subcloud.id
sys_controller_gw_ip = payload.get("systemcontroller_gateway_address",
subcloud.systemcontroller_gateway_ip)
@ -2509,7 +2606,7 @@ class SubcloudManager(manager.Manager):
return
try:
self._update_services_endpoint(
context, payload, subcloud_name, m_ks_client)
context, payload, subcloud_region, m_ks_client)
except Exception:
LOG.exception("Failed to update subcloud %s endpoints" % subcloud_name)
if update_db:
@ -2541,7 +2638,7 @@ class SubcloudManager(manager.Manager):
1)
def _update_services_endpoint(
self, context, payload, subcloud_name, m_ks_client):
self, context, payload, subcloud_region, m_ks_client):
endpoint_ip = utils.get_management_start_address(payload)
if netaddr.IPAddress(endpoint_ip).version == 6:
endpoint_ip = f"[{endpoint_ip}]"
@ -2556,7 +2653,7 @@ class SubcloudManager(manager.Manager):
}
for endpoint in m_ks_client.keystone_client.endpoints.list(
region=subcloud_name):
region=subcloud_region):
service_type = m_ks_client.keystone_client.services.get(
endpoint.service_id).type
if service_type == dccommon_consts.ENDPOINT_TYPE_PLATFORM:
@ -2576,17 +2673,17 @@ class SubcloudManager(manager.Manager):
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))
LOG.info("Update services endpoint to %s in subcloud region %s" % (
endpoint_ip, subcloud_region))
# Update service URLs in subcloud endpoint cache
self.audit_rpc_client.trigger_subcloud_endpoints_update(
context, subcloud_name, services_endpoints)
context, subcloud_region, services_endpoints)
self.dcorch_rpc_client.update_subcloud_endpoints(
context, subcloud_name, services_endpoints)
context, subcloud_region, services_endpoints)
# Update sysinv URL in cert-mon cache
dc_notification = dcmanager_rpc_client.DCManagerNotifications()
dc_notification.subcloud_sysinv_endpoint_update(
context, subcloud_name, services_endpoints.get("sysinv"))
context, subcloud_region, services_endpoints.get("sysinv"))
def _create_subcloud_update_overrides_file(
self, payload, subcloud_name, filename_suffix):
@ -2630,7 +2727,7 @@ class SubcloudManager(manager.Manager):
payload['override_values']['sc_ca_key'] = payload['sc_ca_key']
def update_subcloud_sync_endpoint_type(self, context,
subcloud_name,
subcloud_region,
endpoint_type_list,
openstack_installed):
operation = 'add' if openstack_installed else 'remove'
@ -2646,17 +2743,17 @@ class SubcloudManager(manager.Manager):
}
try:
subcloud = db_api.subcloud_get_by_name(context, subcloud_name)
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
except Exception:
LOG.exception("Failed to get subcloud by name: %s" % subcloud_name)
LOG.exception("Failed to get subcloud by region name: %s" % subcloud_region)
raise
try:
# Notify dcorch to add/remove sync endpoint type list
func_switcher[operation][0](self.context, subcloud_name,
func_switcher[operation][0](self.context, subcloud_region,
endpoint_type_list)
LOG.info('Notifying dcorch, subcloud: %s new sync endpoint: %s' %
(subcloud_name, endpoint_type_list))
(subcloud.name, endpoint_type_list))
# Update subcloud status table by adding/removing openstack sync
# endpoint types
@ -2668,7 +2765,7 @@ class SubcloudManager(manager.Manager):
openstack_installed=openstack_installed)
except Exception:
LOG.exception('Problem informing dcorch of subcloud sync endpoint'
' type change, subcloud: %s' % subcloud_name)
' type change, subcloud region: %s' % subcloud_region)
def handle_subcloud_operations_in_progress(self):
"""Identify subclouds in transitory stages and update subcloud

View File

@ -156,6 +156,14 @@ class OrchThread(threading.Thread):
@staticmethod
def get_region_name(strategy_step):
"""Get the region name for a strategy step"""
if strategy_step.subcloud_id is None:
# This is the SystemController.
return dccommon_consts.DEFAULT_REGION_NAME
return strategy_step.subcloud.region_name
@staticmethod
def get_subcloud_name(strategy_step):
"""Get the subcloud name for a strategy step"""
if strategy_step.subcloud_id is None:
# This is the SystemController.
return dccommon_consts.DEFAULT_REGION_NAME
@ -263,18 +271,18 @@ class OrchThread(threading.Thread):
for strategy_step in strategy_steps:
if strategy_step.state == consts.STRATEGY_STATE_COMPLETE:
# This step is complete
self._delete_subcloud_worker(strategy_step.subcloud.name,
self._delete_subcloud_worker(strategy_step.subcloud.region_name,
strategy_step.subcloud_id)
continue
elif strategy_step.state == consts.STRATEGY_STATE_ABORTED:
# This step was aborted
self._delete_subcloud_worker(strategy_step.subcloud.name,
self._delete_subcloud_worker(strategy_step.subcloud.region_name,
strategy_step.subcloud_id)
abort_detected = True
continue
elif strategy_step.state == consts.STRATEGY_STATE_FAILED:
failure_detected = True
self._delete_subcloud_worker(strategy_step.subcloud.name,
self._delete_subcloud_worker(strategy_step.subcloud.region_name,
strategy_step.subcloud_id)
# This step has failed and needs no further action
if strategy_step.subcloud_id is None:
@ -572,7 +580,7 @@ class OrchThread(threading.Thread):
% (self.update_type,
strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step)))
self.get_subcloud_name(strategy_step)))
# Instantiate the state operator and perform the state actions
state_operator = self.determine_state_operator(strategy_step)
state_operator.registerStopEvent(self._stop)
@ -585,7 +593,7 @@ class OrchThread(threading.Thread):
% (self.update_type,
strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step)))
strategy_step.subcloud.name))
# Transition immediately to complete. Update the details to show
# that this subcloud has been skipped
details = self.format_update_details(None, str(ex))
@ -598,7 +606,7 @@ class OrchThread(threading.Thread):
% (self.update_type,
strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step)))
strategy_step.subcloud.name))
details = self.format_update_details(strategy_step.state, str(ex))
self.strategy_step_update(strategy_step.subcloud_id,
state=consts.STRATEGY_STATE_FAILED,

View File

@ -55,39 +55,47 @@ class BaseState(object):
LOG.debug("Stage: %s, State: %s, Subcloud: %s, Details: %s"
% (strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step),
self.get_subcloud_name(strategy_step),
details))
def info_log(self, strategy_step, details):
LOG.info("Stage: %s, State: %s, Subcloud: %s, Details: %s"
% (strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step),
self.get_subcloud_name(strategy_step),
details))
def warn_log(self, strategy_step, details):
LOG.warn("Stage: %s, State: %s, Subcloud: %s, Details: %s"
% (strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step),
self.get_subcloud_name(strategy_step),
details))
def error_log(self, strategy_step, details):
LOG.error("Stage: %s, State: %s, Subcloud: %s, Details: %s"
% (strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step),
self.get_subcloud_name(strategy_step),
details))
def exception_log(self, strategy_step, details):
LOG.exception("Stage: %s, State: %s, Subcloud: %s, Details: %s"
% (strategy_step.stage,
strategy_step.state,
self.get_region_name(strategy_step),
self.get_subcloud_name(strategy_step),
details))
@staticmethod
def get_region_name(strategy_step):
"""Get the region name for a strategy step"""
if strategy_step.subcloud_id is None:
# This is the SystemController.
return dccommon_consts.DEFAULT_REGION_NAME
return strategy_step.subcloud.region_name
@staticmethod
def get_subcloud_name(strategy_step):
"""Get the region name for a strategy step"""
if strategy_step.subcloud_id is None:
# This is the SystemController.

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2022 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -33,10 +33,11 @@ class FinishingFwUpdateState(BaseState):
% (dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
dccommon_consts.SYNC_STATUS_IN_SYNC))
dcmanager_state_rpc_client = dcmanager_rpc_client.SubcloudStateClient()
# The subcloud name is the same as the region in the strategy_step
# The subcloud name may differ from the region name in the strategy_step
dcmanager_state_rpc_client.update_subcloud_endpoint_status(
self.context,
subcloud_name=self.get_region_name(strategy_step),
subcloud_name=self.get_subcloud_name(strategy_step),
subcloud_region=self.get_region_name(strategy_step),
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2021 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -33,7 +33,7 @@ class LockHostState(BaseState):
"""
# Create a sysinv client on the subcloud
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.name)
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
host = sysinv_client.get_host(self.target_hostname)
@ -58,7 +58,7 @@ class LockHostState(BaseState):
raise StrategyStoppedException()
# query the administrative state to see if it is the new state.
host = self.get_sysinv_client(
strategy_step.subcloud.name).get_host(self.target_hostname)
strategy_step.subcloud.region_name).get_host(self.target_hostname)
if host.administrative == consts.ADMIN_LOCKED:
msg = "Host: %s is now: %s" % (self.target_hostname,
host.administrative)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2021 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -61,7 +61,7 @@ class UnlockHostState(BaseState):
"""
# Retrieve host from sysinv client on the subcloud
host = self._get_host_with_retry(strategy_step.subcloud.name)
host = self._get_host_with_retry(strategy_step.subcloud.region_name)
# if the host is already in the desired state, no need for action
if self.check_host_ready(host):
@ -85,7 +85,7 @@ class UnlockHostState(BaseState):
while True:
try:
response = self.get_sysinv_client(
strategy_step.subcloud.name).unlock_host(host.id)
strategy_step.subcloud.region_name).unlock_host(host.id)
if (response.ihost_action != 'unlock' or
response.task != 'Unlocking'):
raise Exception("Unable to unlock host %s"
@ -113,7 +113,7 @@ class UnlockHostState(BaseState):
try:
# query the administrative state to see if it is the new state.
host = self.get_sysinv_client(
strategy_step.subcloud.name).get_host(self.target_hostname)
strategy_step.subcloud.region_name).get_host(self.target_hostname)
if self.check_host_ready(host):
# Success. Break out of the loop.
msg = "Host: %s is now: %s %s %s" % (self.target_hostname,

View File

@ -38,7 +38,7 @@ class ActivatingUpgradeState(BaseState):
def get_upgrade_state(self, strategy_step):
try:
upgrades = self.get_sysinv_client(
strategy_step.subcloud.name).get_upgrades()
strategy_step.subcloud.region_name).get_upgrades()
except Exception as exception:
self.warn_log(strategy_step,
@ -86,7 +86,7 @@ class ActivatingUpgradeState(BaseState):
# if max retries have occurred, fail the state
if activate_retry_counter >= self.max_failed_retries:
error_msg = utils.get_failure_msg(strategy_step.subcloud.name)
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
db_api.subcloud_update(
self.context, strategy_step.subcloud_id,
error_description=error_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
@ -104,7 +104,7 @@ class ActivatingUpgradeState(BaseState):
# (no upgrade found, bad host state, auth)
try:
self.get_sysinv_client(
strategy_step.subcloud.name).upgrade_activate()
strategy_step.subcloud.region_name).upgrade_activate()
first_activate = False # clear first activation flag
activate_retry_counter = 0 # reset activation retries
except Exception as exception:
@ -129,7 +129,7 @@ class ActivatingUpgradeState(BaseState):
% upgrade_state)
try:
self.get_sysinv_client(
strategy_step.subcloud.name).upgrade_activate()
strategy_step.subcloud.region_name).upgrade_activate()
except Exception as exception:
self.warn_log(strategy_step,
"Encountered exception: %s, "
@ -147,7 +147,7 @@ class ActivatingUpgradeState(BaseState):
break
audit_counter += 1
if audit_counter >= self.max_queries:
error_msg = utils.get_failure_msg(strategy_step.subcloud.name)
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
db_api.subcloud_update(
self.context, strategy_step.subcloud_id,
error_description=error_msg[0:consts.ERROR_DESCRIPTION_LENGTH])

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -32,7 +32,7 @@ class DeletingLoadState(BaseState):
Any exceptions raised by this method set the strategy to FAILED.
"""
# get the sysinv client for the subcloud
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.name)
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
current_loads = sysinv_client.get_loads()
load_id = None

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2022 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -56,7 +56,7 @@ class FinishingPatchStrategyState(BaseState):
"RegionOne committed_patch_ids: %s" % committed_patch_ids)
subcloud_patches = self.get_patching_client(
strategy_step.subcloud.name).query()
strategy_step.subcloud.region_name).query()
self.debug_log(strategy_step,
"Patches for subcloud: %s" % subcloud_patches)
@ -93,6 +93,6 @@ class FinishingPatchStrategyState(BaseState):
self.info_log(strategy_step,
"Committing patches %s in subcloud" % patches_to_commit)
self.get_patching_client(
strategy_step.subcloud.name).commit(patches_to_commit)
strategy_step.subcloud.region_name).commit(patches_to_commit)
return self.next_state

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020-2022 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -49,13 +49,13 @@ class ImportingLoadState(BaseState):
self.info_log(strategy_step, "Retrieving load list from subcloud...")
# success when only one load, the active load, remains
if len(self.get_sysinv_client(
strategy_step.subcloud.name).get_loads()) == 1:
strategy_step.subcloud.region_name).get_loads()) == 1:
msg = "Load: %s has been removed." % load_version
self.info_log(strategy_step, msg)
return True
else:
load = self.get_sysinv_client(
strategy_step.subcloud.name).get_load(load_id)
strategy_step.subcloud.region_name).get_load(load_id)
if load.state == consts.IMPORTED_LOAD_STATE:
# success when load is imported
msg = "Load: %s is now: %s" % (load_version,
@ -102,7 +102,7 @@ class ImportingLoadState(BaseState):
load_info = {}
# Check if the load is already imported by checking the version
current_loads = self.get_sysinv_client(
strategy_step.subcloud.name).get_loads()
strategy_step.subcloud.region_name).get_loads()
for load in current_loads:
if load.software_version == target_version:
@ -140,12 +140,12 @@ class ImportingLoadState(BaseState):
self.info_log(strategy_step,
"Deleting load %s..." % load_id_to_be_deleted)
self.get_sysinv_client(
strategy_step.subcloud.name).delete_load(load_id_to_be_deleted)
strategy_step.subcloud.region_name).delete_load(load_id_to_be_deleted)
req_info['type'] = LOAD_DELETE_REQUEST_TYPE
self._wait_for_request_to_complete(strategy_step, req_info)
subcloud_type = self.get_sysinv_client(
strategy_step.subcloud.name).get_system().system_mode
strategy_step.subcloud.region_name).get_system().system_mode
load_import_retry_counter = 0
load = None
if subcloud_type == consts.SYSTEM_MODE_SIMPLEX:
@ -158,7 +158,7 @@ class ImportingLoadState(BaseState):
target_load = {key: target_load[key] for key in creation_keys}
try:
load = self.get_sysinv_client(
strategy_step.subcloud.name).import_load_metadata(target_load)
strategy_step.subcloud.region_name).import_load_metadata(target_load)
self.info_log(strategy_step,
"Load: %s is now: %s" % (
load.software_version, load.state))
@ -190,7 +190,7 @@ class ImportingLoadState(BaseState):
# Call the API. import_load blocks until the load state is 'importing'
self.info_log(strategy_step, "Sending load import request...")
load = self.get_sysinv_client(
strategy_step.subcloud.name).import_load(iso_path, sig_path)
strategy_step.subcloud.region_name).import_load(iso_path, sig_path)
break
except VaultLoadMissingError:

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020, 2022 Wind River Systems, Inc.
# Copyright (c) 2020-2023 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -64,7 +64,7 @@ class InstallingLicenseState(BaseState):
# retrieve the keystone session for the subcloud and query its license
subcloud_sysinv_client = \
self.get_sysinv_client(strategy_step.subcloud.name)
self.get_sysinv_client(strategy_step.subcloud.region_name)
subcloud_license_response = subcloud_sysinv_client.get_license()
subcloud_license = subcloud_license_response.get('content')
subcloud_error = subcloud_license_response.get('error')

View File

@ -72,7 +72,7 @@ class MigratingDataState(BaseState):
try:
# query the administrative state to see if it is the new state.
host = self.get_sysinv_client(
strategy_step.subcloud.name).get_host(target_hostname)
strategy_step.subcloud.region_name).get_host(target_hostname)
if (host.administrative == consts.ADMIN_UNLOCKED and
host.operational == consts.OPERATIONAL_ENABLED):
# Success. Break out of the loop.
@ -156,7 +156,7 @@ class MigratingDataState(BaseState):
msg_subcloud = utils.find_ansible_error_msg(
strategy_step.subcloud.name, log_file, consts.DEPLOY_STATE_MIGRATING_DATA)
# Get script output in case it is available
error_msg = utils.get_failure_msg(strategy_step.subcloud.name)
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
failure = ('%s \n%s' % (error_msg, msg_subcloud))
db_api.subcloud_update(
self.context, strategy_step.subcloud_id,

View File

@ -204,8 +204,8 @@ class PreCheckState(BaseState):
if subcloud.availability_status == dccommon_consts.AVAILABILITY_ONLINE:
subcloud_sysinv_client = None
try:
subcloud_sysinv_client = self.get_sysinv_client(strategy_step.subcloud.name)
subcloud_fm_client = self.get_fm_client(strategy_step.subcloud.name)
subcloud_sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
subcloud_fm_client = self.get_fm_client(strategy_step.subcloud.region_name)
except Exception:
# if getting the token times out, the orchestrator may have
# restarted and subcloud may be offline; so will attempt
@ -220,7 +220,7 @@ class PreCheckState(BaseState):
host = subcloud_sysinv_client.get_host("controller-0")
subcloud_type = self.get_sysinv_client(
strategy_step.subcloud.name).get_system().system_mode
strategy_step.subcloud.region_name).get_system().system_mode
upgrades = subcloud_sysinv_client.get_upgrades()
if subcloud_type == consts.SYSTEM_MODE_SIMPLEX:
@ -324,7 +324,7 @@ class PreCheckState(BaseState):
all_hosts_upgraded = True
subcloud_hosts = self.get_sysinv_client(
strategy_step.subcloud.name).get_hosts()
strategy_step.subcloud.region_name).get_hosts()
for subcloud_host in subcloud_hosts:
if(subcloud_host.software_load != target_version or
subcloud_host.administrative == consts.ADMIN_LOCKED or

View File

@ -36,7 +36,7 @@ class StartingUpgradeState(BaseState):
def get_upgrade_state(self, strategy_step):
try:
upgrades = self.get_sysinv_client(
strategy_step.subcloud.name).get_upgrades()
strategy_step.subcloud.region_name).get_upgrades()
except Exception as exception:
self.warn_log(strategy_step,
"Encountered exception: %s, "
@ -58,7 +58,7 @@ class StartingUpgradeState(BaseState):
# Check if an existing upgrade is already in progress.
# The list of upgrades will never contain more than one entry.
upgrades = self.get_sysinv_client(
strategy_step.subcloud.name).get_upgrades()
strategy_step.subcloud.region_name).get_upgrades()
if upgrades is not None and len(upgrades) > 0:
for upgrade in upgrades:
# If a previous upgrade exists (even one that failed) skip
@ -79,7 +79,7 @@ class StartingUpgradeState(BaseState):
# This call is asynchronous and throws an exception on failure.
self.get_sysinv_client(
strategy_step.subcloud.name).upgrade_start(force=force_flag)
strategy_step.subcloud.region_name).upgrade_start(force=force_flag)
# Do not move to the next state until the upgrade state is correct
counter = 0
@ -96,7 +96,7 @@ class StartingUpgradeState(BaseState):
if upgrade_state in UPGRADE_RETRY_STATES:
retry_counter += 1
if retry_counter >= self.max_failed_retries:
error_msg = utils.get_failure_msg(strategy_step.subcloud.name)
error_msg = utils.get_failure_msg(strategy_step.subcloud.region_name)
db_api.subcloud_update(
self.context, strategy_step.subcloud_id,
error_description=error_msg[0:consts.ERROR_DESCRIPTION_LENGTH])
@ -110,7 +110,7 @@ class StartingUpgradeState(BaseState):
% upgrade_state)
try:
self.get_sysinv_client(
strategy_step.subcloud.name).upgrade_start(force=force_flag)
strategy_step.subcloud.region_name).upgrade_start(force=force_flag)
except Exception as exception:
self.warn_log(strategy_step,
"Encountered exception: %s, "

View File

@ -48,7 +48,7 @@ class TransferCACertificateState(BaseState):
retry_counter = 0
while True:
try:
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.name)
sysinv_client = self.get_sysinv_client(strategy_step.subcloud.region_name)
data = {'mode': 'openldap_ca'}
ldap_ca_cert, ldap_ca_key = utils.get_certificate_from_secret(

View File

@ -38,9 +38,9 @@ class UpgradingSimplexState(BaseState):
subcloud_barbican_client = None
try:
subcloud_sysinv_client = self.get_sysinv_client(
strategy_step.subcloud.name)
strategy_step.subcloud.region_name)
subcloud_barbican_client = self.get_barbican_client(
strategy_step.subcloud.name)
strategy_step.subcloud.region_name)
except Exception:
# if getting the token times out, the orchestrator may have
# restarted and subcloud may be offline; so will attempt

View File

@ -69,6 +69,7 @@ class SubcloudStateClient(RPCClient):
def update_subcloud_availability(self, ctxt,
subcloud_name,
subcloud_region,
availability_status,
update_state_only=False,
audit_fail_count=None):
@ -77,11 +78,13 @@ class SubcloudStateClient(RPCClient):
ctxt,
self.make_msg('update_subcloud_availability',
subcloud_name=subcloud_name,
subcloud_region=subcloud_region,
availability_status=availability_status,
update_state_only=update_state_only,
audit_fail_count=audit_fail_count))
def update_subcloud_endpoint_status(self, ctxt, subcloud_name=None,
subcloud_region=None,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
ignore_endpoints=None,
@ -90,12 +93,14 @@ class SubcloudStateClient(RPCClient):
# See below for synchronous method call
return self.cast(ctxt, self.make_msg('update_subcloud_endpoint_status',
subcloud_name=subcloud_name,
subcloud_region=subcloud_region,
endpoint_type=endpoint_type,
sync_status=sync_status,
ignore_endpoints=ignore_endpoints,
alarmable=alarmable))
def update_subcloud_endpoint_status_sync(self, ctxt, subcloud_name=None,
subcloud_region=None,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
ignore_endpoints=None,
@ -103,6 +108,7 @@ class SubcloudStateClient(RPCClient):
# Note: synchronous
return self.call(ctxt, self.make_msg('update_subcloud_endpoint_status',
subcloud_name=subcloud_name,
subcloud_region=subcloud_region,
endpoint_type=endpoint_type,
sync_status=sync_status,
ignore_endpoints=ignore_endpoints,
@ -133,6 +139,12 @@ class ManagerClient(RPCClient):
return self.call(ctxt, self.make_msg('delete_subcloud',
subcloud_id=subcloud_id))
def rename_subcloud(self, ctxt, subcloud_id, curr_subcloud_name, new_subcloud_name=None):
return self.call(ctxt, self.make_msg('rename_subcloud',
subcloud_id=subcloud_id,
curr_subcloud_name=curr_subcloud_name,
new_subcloud_name=new_subcloud_name))
def update_subcloud(self, ctxt, subcloud_id, management_state=None,
description=None, location=None, group_id=None,
data_install=None, force=None,
@ -173,13 +185,13 @@ class ManagerClient(RPCClient):
payload=payload))
def update_subcloud_sync_endpoint_type(self, ctxt,
subcloud_name,
subcloud_region,
endpoint_type_list,
openstack_installed):
return self.cast(
ctxt,
self.make_msg('update_subcloud_sync_endpoint_type',
subcloud_name=subcloud_name,
subcloud_region=subcloud_region,
endpoint_type_list=endpoint_type_list,
openstack_installed=openstack_installed))
@ -229,6 +241,10 @@ class ManagerClient(RPCClient):
subcloud_ref=subcloud_ref,
payload=payload))
def get_subcloud_name_by_region_name(self, ctxt, subcloud_region):
return self.call(ctxt, self.make_msg('get_subcloud_name_by_region_name',
subcloud_region=subcloud_region))
class DCManagerNotifications(RPCClient):
"""DC Manager Notification interface to broadcast subcloud state changed

View File

@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2017-2022 Wind River Systems, Inc.
# Copyright (c) 2017-2023 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
@ -113,6 +113,7 @@ class DCManagerStateService(service.Service):
@request_context
def update_subcloud_endpoint_status(self, context, subcloud_name=None,
subcloud_region=None,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
alarmable=True,
@ -124,7 +125,7 @@ class DCManagerStateService(service.Service):
self.subcloud_state_manager. \
update_subcloud_endpoint_status(context,
subcloud_name,
subcloud_region,
endpoint_type,
sync_status,
alarmable,
@ -153,6 +154,7 @@ class DCManagerStateService(service.Service):
@request_context
def update_subcloud_availability(self, context,
subcloud_name,
subcloud_region,
availability_status,
update_state_only=False,
audit_fail_count=None):
@ -161,7 +163,7 @@ class DCManagerStateService(service.Service):
subcloud_name)
self.subcloud_state_manager.update_subcloud_availability(
context,
subcloud_name,
subcloud_region,
availability_status,
update_state_only,
audit_fail_count)

View File

@ -42,9 +42,9 @@ def sync_update_subcloud_endpoint_status(func):
"""Synchronized lock decorator for _update_subcloud_endpoint_status. """
def _get_lock_and_call(*args, **kwargs):
"""Get a single fair lock per subcloud based on subcloud name. """
"""Get a single fair lock per subcloud based on subcloud region. """
# subcloud name is the 3rd argument to
# subcloud region is the 3rd argument to
# _update_subcloud_endpoint_status()
@utils.synchronized(args[2], external=True, fair=True)
def _call_func(*args, **kwargs):
@ -262,7 +262,7 @@ class SubcloudStateManager(manager.Manager):
@sync_update_subcloud_endpoint_status
def _update_subcloud_endpoint_status(
self, context,
subcloud_name,
subcloud_region,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
alarmable=True,
@ -270,7 +270,7 @@ class SubcloudStateManager(manager.Manager):
"""Update subcloud endpoint status
:param context: request context object
:param subcloud_name: name of subcloud to update
:param subcloud_region: name of subcloud region to update
:param endpoint_type: endpoint type to update
:param sync_status: sync status to set
:param alarmable: controls raising an alarm if applicable
@ -281,13 +281,13 @@ class SubcloudStateManager(manager.Manager):
if ignore_endpoints is None:
ignore_endpoints = []
if not subcloud_name:
if not subcloud_region:
raise exceptions.BadRequest(
resource='subcloud',
msg='Subcloud name not provided')
msg='Subcloud region not provided')
try:
subcloud = db_api.subcloud_get_by_name(context, subcloud_name)
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
except Exception as e:
LOG.exception(e)
raise e
@ -327,12 +327,12 @@ class SubcloudStateManager(manager.Manager):
else:
LOG.info("Ignoring subcloud sync_status update for subcloud:%s "
"availability:%s management:%s endpoint:%s sync:%s" %
(subcloud_name, subcloud.availability_status,
(subcloud.name, subcloud.availability_status,
subcloud.management_state, endpoint_type, sync_status))
def update_subcloud_endpoint_status(
self, context,
subcloud_name=None,
subcloud_region=None,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
alarmable=True,
@ -340,7 +340,7 @@ class SubcloudStateManager(manager.Manager):
"""Update subcloud endpoint status
:param context: request context object
:param subcloud_name: name of subcloud to update
:param subcloud_region: region of subcloud to update
:param endpoint_type: endpoint type to update
:param sync_status: sync status to set
:param alarmable: controls raising an alarm if applicable
@ -351,18 +351,18 @@ class SubcloudStateManager(manager.Manager):
if ignore_endpoints is None:
ignore_endpoints = []
if subcloud_name:
if subcloud_region:
self._update_subcloud_endpoint_status(
context, subcloud_name, endpoint_type, sync_status, alarmable,
context, subcloud_region, endpoint_type, sync_status, alarmable,
ignore_endpoints)
else:
# update all subclouds
for subcloud in db_api.subcloud_get_all(context):
self._update_subcloud_endpoint_status(
context, subcloud.name, endpoint_type, sync_status,
context, subcloud.region_name, endpoint_type, sync_status,
alarmable, ignore_endpoints)
def _update_subcloud_state(self, context, subcloud_name,
def _update_subcloud_state(self, context, subcloud_name, subcloud_region,
management_state, availability_status):
try:
LOG.info('Notifying dcorch, subcloud:%s management: %s, '
@ -372,7 +372,7 @@ class SubcloudStateManager(manager.Manager):
availability_status))
self.dcorch_rpc_client.update_subcloud_states(
context, subcloud_name, management_state, availability_status)
context, subcloud_region, management_state, availability_status)
except Exception:
LOG.exception('Problem informing dcorch of subcloud state change,'
@ -418,20 +418,21 @@ class SubcloudStateManager(manager.Manager):
LOG.exception("Failed to raise offline alarm for subcloud: %s",
subcloud_name)
def update_subcloud_availability(self, context, subcloud_name,
def update_subcloud_availability(self, context, subcloud_region,
availability_status,
update_state_only=False,
audit_fail_count=None):
try:
subcloud = db_api.subcloud_get_by_name(context, subcloud_name)
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
except Exception:
LOG.exception("Failed to get subcloud by name: %s" % subcloud_name)
LOG.exception("Failed to get subcloud by region name %s" % subcloud_region)
raise
if update_state_only:
# Nothing has changed, but we want to send a state update for this
# subcloud as an audit. Get the most up-to-date data.
self._update_subcloud_state(context, subcloud_name,
self._update_subcloud_state(context, subcloud.name,
subcloud.region_name,
subcloud.management_state,
availability_status)
elif availability_status is None:
@ -443,17 +444,17 @@ class SubcloudStateManager(manager.Manager):
# slim possibility subcloud could have been deleted since
# we found it in db, ignore this benign error.
LOG.info('Ignoring SubcloudNotFound when attempting '
'audit_fail_count update: %s' % subcloud_name)
'audit_fail_count update: %s' % subcloud.name)
return
else:
self._raise_or_clear_subcloud_status_alarm(subcloud_name,
self._raise_or_clear_subcloud_status_alarm(subcloud.name,
availability_status)
if availability_status == dccommon_consts.AVAILABILITY_OFFLINE:
# Subcloud is going offline, set all endpoint statuses to
# unknown.
self._update_subcloud_endpoint_status(
context, subcloud_name, endpoint_type=None,
context, subcloud.region_name, endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_UNKNOWN)
try:
@ -466,27 +467,28 @@ class SubcloudStateManager(manager.Manager):
# slim possibility subcloud could have been deleted since
# we found it in db, ignore this benign error.
LOG.info('Ignoring SubcloudNotFound when attempting state'
' update: %s' % subcloud_name)
' update: %s' % subcloud.name)
return
if availability_status == dccommon_consts.AVAILABILITY_ONLINE:
# Subcloud is going online
# Tell cert-mon to audit endpoint certificate.
LOG.info('Request for online audit for %s' % subcloud_name)
LOG.info('Request for online audit for %s' % subcloud.name)
dc_notification = rpc_client.DCManagerNotifications()
dc_notification.subcloud_online(context, subcloud_name)
dc_notification.subcloud_online(context, subcloud.region_name)
# Trigger all the audits for the subcloud so it can update the
# sync status ASAP.
self.audit_rpc_client.trigger_subcloud_audits(context,
subcloud.id)
# Send dcorch a state update
self._update_subcloud_state(context, subcloud_name,
self._update_subcloud_state(context, subcloud.name,
subcloud.region_name,
updated_subcloud.management_state,
availability_status)
def update_subcloud_sync_endpoint_type(self, context,
subcloud_name,
subcloud_region,
endpoint_type_list,
openstack_installed):
operation = 'add' if openstack_installed else 'remove'
@ -502,17 +504,17 @@ class SubcloudStateManager(manager.Manager):
}
try:
subcloud = db_api.subcloud_get_by_name(context, subcloud_name)
subcloud = db_api.subcloud_get_by_region_name(context, subcloud_region)
except Exception:
LOG.exception("Failed to get subcloud by name: %s" % subcloud_name)
LOG.exception("Failed to get subcloud by region name: %s" % subcloud_region)
raise
try:
# Notify dcorch to add/remove sync endpoint type list
func_switcher[operation][0](self.context, subcloud_name,
func_switcher[operation][0](self.context, subcloud_region,
endpoint_type_list)
LOG.info('Notifying dcorch, subcloud: %s new sync endpoint: %s' %
(subcloud_name, endpoint_type_list))
(subcloud.name, endpoint_type_list))
# Update subcloud status table by adding/removing openstack sync
# endpoint types
@ -524,4 +526,4 @@ class SubcloudStateManager(manager.Manager):
openstack_installed=openstack_installed)
except Exception:
LOG.exception('Problem informing dcorch of subcloud sync endpoint'
' type change, subcloud: %s' % subcloud_name)
' type change, subcloud: %s' % subcloud.name)

View File

@ -36,6 +36,29 @@ get_engine = api.get_engine
from sqlalchemy.engine import Engine
from sqlalchemy import event
SUBCLOUD_1 = {'name': 'subcloud1',
'region_name': '2ec93dfb654846909efe61d1b39dd2ce'}
SUBCLOUD_2 = {'name': 'subcloud2',
'region_name': 'ca2761ee7aa34cbe8415ec9a3c86854f'}
SUBCLOUD_3 = {'name': 'subcloud3',
'region_name': '659e12e5f7ad411abfcd83f5cedca0bf'}
SUBCLOUD_4 = {'name': 'subcloud4',
'region_name': 'c25f3b0553384104b664789bd93a2ba8'}
SUBCLOUD_5 = {'name': 'subcloud5',
'region_name': '809581dc2d154e008480bac1f43b7aff'}
SUBCLOUD_6 = {'name': 'subcloud6',
'region_name': '8c60b99f3e1245b7bc5a049802ade8d2'}
SUBCLOUD_7 = {'name': 'subcloud7',
'region_name': '9fde6dca22fa422bb1e8cf03bedc18e4'}
SUBCLOUD_8 = {'name': 'subcloud8',
'region_name': 'f3cb0b109c4543fda3ed50ed5783279d'}
SUBCLOUD_9 = {'name': 'subcloud9',
'region_name': '1cfab1df7b444bb3bd562894d684f352'}
SUBCLOUD_10 = {'name': 'subcloud10',
'region_name': '6d0040199b4f4a9fb4a1f2ed4d498159'}
SUBCLOUD_11 = {'name': 'subcloud11',
'region_name': '169e6fc231e94959ad6ff0a66fbcb753'}
SUBCLOUD_SAMPLE_DATA_0 = [
6, # id
"subcloud-4", # name
@ -63,6 +86,7 @@ SUBCLOUD_SAMPLE_DATA_0 = [
1, # group_id
consts.DEPLOY_STATE_DONE, # deploy_status
consts.ERROR_DESC_EMPTY, # error_description
SUBCLOUD_4['region_name'], # region_name
json.dumps({'data_install': 'test data install values'}), # data_install
]

View File

@ -17,6 +17,7 @@ from dcmanager.common import consts
from dcmanager.db.sqlalchemy import api as db_api
from dcmanager.rpc import client as rpc_client
from dcmanager.tests import base
from dcmanager.tests.unit.api import test_root_controller as testroot
from dcmanager.tests.unit.common import fake_subcloud
from dcmanager.tests import utils
@ -1059,7 +1060,9 @@ class TestSubcloudRestore(testroot.DCManagerApiTest):
test_group_id = 1
subcloud = fake_subcloud.create_fake_subcloud(self.ctx, group_id=test_group_id)
subcloud2 = fake_subcloud.create_fake_subcloud(self.ctx, group_id=test_group_id, name='subcloud2')
subcloud2 = fake_subcloud.create_fake_subcloud(self.ctx, group_id=test_group_id,
name=base.SUBCLOUD_2['name'],
region_name=base.SUBCLOUD_2['region_name'])
# Valid subcloud, management state is 'unmanaged'
db_api.subcloud_update(self.ctx,
subcloud.id,

View File

@ -239,6 +239,7 @@ class TestSubcloudGroupGet(testroot.DCManagerApiTest,
FAKE_SUBCLOUD_DATA.get('systemcontroller_gateway_ip'),
'deploy_status': FAKE_SUBCLOUD_DATA.get('deploy_status'),
'error_description': FAKE_SUBCLOUD_DATA.get('error_description'),
'region_name': FAKE_SUBCLOUD_DATA.get('region_name'),
'openstack_installed':
FAKE_SUBCLOUD_DATA.get('openstack_installed'),
'group_id': FAKE_SUBCLOUD_DATA.get('group_id', 1)

View File

@ -1429,7 +1429,8 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
data, headers=FAKE_HEADERS)
self.mock_rpc_state_client().update_subcloud_endpoint_status.\
assert_called_once_with(mock.ANY, subcloud.name, 'dc-cert', 'in-sync')
assert_called_once_with(mock.ANY, subcloud.name, subcloud.region_name,
'dc-cert', 'in-sync')
self.assertEqual(response.status_int, 200)

View File

@ -28,7 +28,6 @@ from dcmanager.audit import subcloud_audit_manager
from dcmanager.tests import base
from dcmanager.tests import utils
CONF = cfg.CONF
@ -462,11 +461,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -494,11 +496,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -525,11 +530,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -556,11 +564,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -587,11 +598,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -618,11 +632,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -649,11 +666,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -680,11 +700,14 @@ class TestFirmwareAudit(base.DCManagerTestCase):
am.firmware_audit = fm
firmware_audit_data = self.get_fw_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
fm.subcloud_firmware_audit(name, firmware_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
fm.subcloud_firmware_audit(name, region, firmware_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_FIRMWARE,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \

View File

@ -24,7 +24,6 @@ from dcmanager.audit import subcloud_audit_manager
from dcmanager.tests import base
from dcmanager.tests import utils
PREVIOUS_KUBE_VERSION = 'v1.2.3'
UPGRADED_KUBE_VERSION = 'v1.2.3-a'
@ -166,11 +165,14 @@ class TestKubernetesAudit(base.DCManagerTestCase):
am.kubernetes_audit = audit
kubernetes_audit_data = self.get_kube_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
audit.subcloud_kubernetes_audit(name, kubernetes_audit_data)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
audit.subcloud_kubernetes_audit(name, region, kubernetes_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -190,15 +192,18 @@ class TestKubernetesAudit(base.DCManagerTestCase):
]
kubernetes_audit_data = self.get_kube_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
# return different kube versions in the subclouds
self.kube_sysinv_client.get_kube_versions.return_value = [
FakeKubeVersion(version=PREVIOUS_KUBE_VERSION),
]
audit.subcloud_kubernetes_audit(name, kubernetes_audit_data)
audit.subcloud_kubernetes_audit(name, region, kubernetes_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -218,15 +223,18 @@ class TestKubernetesAudit(base.DCManagerTestCase):
]
kubernetes_audit_data = self.get_kube_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
# return different kube versions in the subclouds
self.kube_sysinv_client.get_kube_versions.return_value = [
FakeKubeVersion(version=UPGRADED_KUBE_VERSION),
]
audit.subcloud_kubernetes_audit(name, kubernetes_audit_data)
audit.subcloud_kubernetes_audit(name, region, kubernetes_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -247,15 +255,18 @@ class TestKubernetesAudit(base.DCManagerTestCase):
]
kubernetes_audit_data = self.get_kube_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
# return same kube versions in the subclouds
self.kube_sysinv_client.get_kube_versions.return_value = [
FakeKubeVersion(version=UPGRADED_KUBE_VERSION),
]
audit.subcloud_kubernetes_audit(name, kubernetes_audit_data)
audit.subcloud_kubernetes_audit(name, region, kubernetes_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -282,15 +293,18 @@ class TestKubernetesAudit(base.DCManagerTestCase):
]
kubernetes_audit_data = self.get_kube_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
# return same kube versions in the subclouds
self.kube_sysinv_client.get_kube_versions.return_value = [
FakeKubeVersion(version=UPGRADED_KUBE_VERSION),
]
audit.subcloud_kubernetes_audit(name, kubernetes_audit_data)
audit.subcloud_kubernetes_audit(name, region, kubernetes_audit_data)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_KUBERNETES,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \

View File

@ -1,4 +1,4 @@
# Copyright (c) 2017-2022 Wind River Systems, Inc.
# Copyright (c) 2017-2023 Wind River Systems, Inc.
# 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
@ -27,7 +27,6 @@ from dcmanager.audit import subcloud_audit_manager
from dcmanager.tests import base
from dcmanager.tests import utils
CONF = cfg.CONF
@ -85,7 +84,8 @@ class FakePatchingClientInSync(object):
'repostate': 'Applied',
'patchstate': 'Applied'},
}
elif self.region in ['subcloud1', 'subcloud2']:
elif self.region in [base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['region_name']]:
return {'DC.1': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'},
@ -117,25 +117,25 @@ class FakePatchingClientOutOfSync(object):
'DC.2': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'}}
elif self.region == 'subcloud1':
elif self.region == base.SUBCLOUD_1['region_name']:
return {'DC.1': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'},
'DC.2': {'sw_version': '17.07',
'repostate': 'Available',
'patchstate': 'Available'}}
elif self.region == 'subcloud2':
elif self.region == base.SUBCLOUD_2['region_name']:
return {'DC.1': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'}}
elif self.region == 'subcloud3':
elif self.region == base.SUBCLOUD_3['region_name']:
return {'DC.1': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'},
'DC.2': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'}}
elif self.region == 'subcloud4':
elif self.region == base.SUBCLOUD_4['region_name']:
return {'DC.1': {'sw_version': '17.07',
'repostate': 'Applied',
'patchstate': 'Applied'},
@ -219,7 +219,7 @@ class FakeSysinvClientOneLoadUnmatchedSoftwareVersion(object):
return self.upgrades
def get_system(self):
if self.region == 'subcloud2':
if self.region == base.SUBCLOUD_2['region_name']:
return System('17.06')
else:
return self.system
@ -238,7 +238,7 @@ class FakeSysinvClientOneLoadUpgradeInProgress(object):
return self.loads
def get_upgrades(self):
if self.region == 'subcloud2':
if self.region == base.SUBCLOUD_2['region_name']:
return [Upgrade('started')]
else:
return self.upgrades
@ -302,15 +302,19 @@ class TestPatchAudit(base.DCManagerTestCase):
do_load_audit = True
patch_audit_data = self.get_patch_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
pm.subcloud_patch_audit(name, patch_audit_data, do_load_audit)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
pm.subcloud_patch_audit(name, region, patch_audit_data, do_load_audit)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status. \
@ -336,40 +340,52 @@ class TestPatchAudit(base.DCManagerTestCase):
do_load_audit = True
patch_audit_data = self.get_patch_audit_data(am)
for name in ['subcloud1', 'subcloud2', 'subcloud3', 'subcloud4']:
pm.subcloud_patch_audit(name, patch_audit_data, do_load_audit)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name'],
base.SUBCLOUD_3['name']: base.SUBCLOUD_3['region_name'],
base.SUBCLOUD_4['name']: base.SUBCLOUD_4['region_name']}
for name, region in subclouds.items():
pm.subcloud_patch_audit(name, region, patch_audit_data, do_load_audit)
expected_calls = [
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud3',
subcloud_name=base.SUBCLOUD_3['name'],
subcloud_region=base.SUBCLOUD_3['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud3',
subcloud_name=base.SUBCLOUD_3['name'],
subcloud_region=base.SUBCLOUD_3['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud4',
subcloud_name=base.SUBCLOUD_4['name'],
subcloud_region=base.SUBCLOUD_4['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud4',
subcloud_name=base.SUBCLOUD_4['name'],
subcloud_region=base.SUBCLOUD_4['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
]
@ -397,15 +413,19 @@ class TestPatchAudit(base.DCManagerTestCase):
do_load_audit = True
patch_audit_data = self.get_patch_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
pm.subcloud_patch_audit(name, patch_audit_data, do_load_audit)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
pm.subcloud_patch_audit(name, region, patch_audit_data, do_load_audit)
expected_calls = [
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
mock.call(mock.ANY,
subcloud_name=name,
subcloud_region=region,
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)]
self.fake_dcmanager_state_api.update_subcloud_endpoint_status.\
@ -431,24 +451,30 @@ class TestPatchAudit(base.DCManagerTestCase):
do_load_audit = True
patch_audit_data = self.get_patch_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
pm.subcloud_patch_audit(name, patch_audit_data, do_load_audit)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
pm.subcloud_patch_audit(name, region, patch_audit_data, do_load_audit)
expected_calls = [
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
]
@ -475,24 +501,30 @@ class TestPatchAudit(base.DCManagerTestCase):
do_load_audit = True
patch_audit_data = self.get_patch_audit_data(am)
for name in ['subcloud1', 'subcloud2']:
pm.subcloud_patch_audit(name, patch_audit_data, do_load_audit)
subclouds = {base.SUBCLOUD_1['name']: base.SUBCLOUD_1['region_name'],
base.SUBCLOUD_2['name']: base.SUBCLOUD_2['region_name']}
for name, region in subclouds.items():
pm.subcloud_patch_audit(name, region, patch_audit_data, do_load_audit)
expected_calls = [
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud1',
subcloud_name=base.SUBCLOUD_1['name'],
subcloud_region=base.SUBCLOUD_1['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_PATCHING,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC),
mock.call(mock.ANY,
subcloud_name='subcloud2',
subcloud_name=base.SUBCLOUD_2['name'],
subcloud_region=base.SUBCLOUD_2['region_name'],
endpoint_type=dccommon_consts.ENDPOINT_TYPE_LOAD,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC),
]

View File

@ -276,6 +276,7 @@ class TestAuditManager(base.DCManagerTestCase):
'systemcontroller_gateway_ip': "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': base.SUBCLOUD_1['region_name'],
'openstack_installed': False,
'group_id': 1,
}

View File

@ -370,6 +370,7 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
'systemcontroller_gateway_ip': "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': base.SUBCLOUD_1['region_name'],
'openstack_installed': False,
'group_id': 1,
}
@ -429,8 +430,8 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the subcloud was set to online
self.fake_dcmanager_state_api.update_subcloud_availability.assert_called_with(
mock.ANY, subcloud.name, dccommon_consts.AVAILABILITY_ONLINE,
False, 0)
mock.ANY, subcloud.name, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE, False, 0)
# Verify the _update_subcloud_audit_fail_count is not called
with mock.patch.object(wm, '_update_subcloud_audit_fail_count') as \
@ -447,19 +448,19 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify patch audit is called
self.fake_patch_audit.subcloud_patch_audit.assert_called_with(
subcloud.name, patch_audit_data, do_load_audit)
subcloud.name, subcloud.region_name, patch_audit_data, do_load_audit)
# Verify firmware audit is called
self.fake_firmware_audit.subcloud_firmware_audit.assert_called_with(
subcloud.name, firmware_audit_data)
subcloud.name, subcloud.region_name, firmware_audit_data)
# Verify kubernetes audit is called
self.fake_kubernetes_audit.subcloud_kubernetes_audit.assert_called_with(
subcloud.name, kubernetes_audit_data)
subcloud.name, subcloud.region_name, kubernetes_audit_data)
# Verify kube rootca update audit is called
self.fake_kube_rootca_update_audit.subcloud_audit.assert_called_with(
subcloud.name, kube_rootca_update_audit_data)
subcloud.name, subcloud.region_name, kube_rootca_update_audit_data)
def test_audit_subcloud_online_first_identity_sync_not_complete(self):
@ -506,8 +507,8 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the subcloud was set to online
self.fake_dcmanager_state_api.update_subcloud_availability.assert_called_with(
mock.ANY, subcloud.name, dccommon_consts.AVAILABILITY_ONLINE,
False, 0)
mock.ANY, subcloud.name, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE, False, 0)
# Verify the _update_subcloud_audit_fail_count is not called
with mock.patch.object(wm, '_update_subcloud_audit_fail_count') as \
@ -573,8 +574,8 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the subcloud was set to online
self.fake_dcmanager_state_api.update_subcloud_availability.assert_called_with(
mock.ANY, subcloud.name, dccommon_consts.AVAILABILITY_ONLINE,
False, 0)
mock.ANY, subcloud.name, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE, False, 0)
# Verify the _update_subcloud_audit_fail_count is not called
with mock.patch.object(wm, '_update_subcloud_audit_fail_count') as \
@ -669,8 +670,8 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the subcloud state was updated even though no change
self.fake_dcmanager_state_api.update_subcloud_availability.assert_called_with(
mock.ANY, subcloud.name, dccommon_consts.AVAILABILITY_ONLINE,
True, None)
mock.ANY, subcloud.name, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE, True, None)
# Verify the _update_subcloud_audit_fail_count is not called
with mock.patch.object(wm, '_update_subcloud_audit_fail_count') as \
@ -785,19 +786,19 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify patch audit is called only once
self.fake_patch_audit.subcloud_patch_audit.assert_called_once_with(
subcloud.name, mock.ANY, True)
subcloud.name, subcloud.region_name, mock.ANY, True)
# Verify firmware audit is only called once
self.fake_firmware_audit.subcloud_firmware_audit.assert_called_once_with(
subcloud.name, mock.ANY)
subcloud.name, subcloud.region_name, mock.ANY)
# Verify kubernetes audit is only called once
self.fake_kubernetes_audit.subcloud_kubernetes_audit.assert_called_once_with(
subcloud.name, mock.ANY)
subcloud.name, subcloud.region_name, mock.ANY)
# Verify kube rootca update audit is only called once
self.fake_kube_rootca_update_audit.subcloud_audit.assert_called_once_with(
subcloud.name, mock.ANY)
subcloud.name, subcloud.region_name, mock.ANY)
def test_audit_subcloud_offline_no_change(self):
subcloud = self.create_subcloud_static(self.ctx, name='subcloud1')
@ -1060,12 +1061,12 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the openstack endpoints were removed
self.fake_dcmanager_api.update_subcloud_sync_endpoint_type.\
assert_called_with(mock.ANY, 'subcloud1',
assert_called_with(mock.ANY, subcloud.region_name,
dccommon_consts.ENDPOINT_TYPES_LIST_OS, False)
# Verify alarm update is called
self.fake_alarm_aggr.update_alarm_summary.assert_called_once_with(
'subcloud1', self.fake_openstack_client.fm_client)
subcloud.name, self.fake_openstack_client.fm_client)
# Verify patch audit is not called
self.fake_patch_audit.subcloud_patch_audit.assert_not_called()
@ -1122,7 +1123,7 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify the openstack endpoints were removed
self.fake_dcmanager_api.update_subcloud_sync_endpoint_type.\
assert_called_with(mock.ANY, 'subcloud1',
assert_called_with(mock.ANY, subcloud.region_name,
dccommon_consts.ENDPOINT_TYPES_LIST_OS, False)
# Verify alarm update is called
@ -1195,7 +1196,7 @@ class TestAuditWorkerManager(base.DCManagerTestCase):
# Verify patch audit is called
self.fake_patch_audit.subcloud_patch_audit.assert_called_with(
subcloud.name, patch_audit_data, do_load_audit)
subcloud.name, subcloud.region_name, patch_audit_data, do_load_audit)
# Verify the _update_subcloud_audit_fail_count is not called
with mock.patch.object(wm, '_update_subcloud_audit_fail_count') as \

View File

@ -9,6 +9,7 @@ import base64
from dcmanager.common import consts
from dcmanager.db.sqlalchemy import api as db_api
from dcmanager.tests import base
from dcmanager.tests import utils
FAKE_TENANT = utils.UUID1
@ -33,6 +34,7 @@ FAKE_SUBCLOUD_DATA = {"id": FAKE_ID,
"systemcontroller_gateway_address": "192.168.204.101",
"deploy_status": consts.DEPLOY_STATE_DONE,
'error_description': consts.ERROR_DESC_EMPTY,
'region_name': base.SUBCLOUD_1['region_name'],
"external_oam_subnet": "10.10.10.0/24",
"external_oam_gateway_address": "10.10.10.1",
"external_oam_floating_address": "10.10.10.12",
@ -128,6 +130,7 @@ def create_fake_subcloud(ctxt, **kwargs):
"systemcontroller_gateway_ip": "192.168.204.101",
'deploy_status': consts.DEPLOY_STATE_DONE,
'error_description': consts.ERROR_DESC_EMPTY,
'region_name': base.SUBCLOUD_1['region_name'],
'openstack_installed': False,
'group_id': 1,
'data_install': 'data from install',

View File

@ -15,6 +15,7 @@
import datetime
from oslo_db import exception as db_exception
from oslo_utils import uuidutils
from dcmanager.common import exceptions as exception
from dcmanager.db import api as api
@ -40,6 +41,7 @@ class DBAPISubcloudAuditsTest(base.DCManagerTestCase):
'systemcontroller_gateway_ip': "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': uuidutils.generate_uuid().replace("-", ""),
'openstack_installed': False,
'group_id': 1,
}

View File

@ -57,6 +57,7 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
'systemcontroller_gateway_ip': "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': base.SUBCLOUD_1['region_name'],
'openstack_installed': False,
'group_id': 1,
}
@ -78,6 +79,7 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
'systemcontroller_gateway_address'],
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': data['region_name'],
'openstack_installed': False,
'group_id': 1,
}
@ -143,19 +145,26 @@ class DBAPISubcloudTest(base.DCManagerTestCase):
def test_create_multiple_subclouds(self):
name1 = 'testname1'
region1 = base.SUBCLOUD_1['region_name']
name2 = 'testname2'
region2 = base.SUBCLOUD_2['region_name']
name3 = 'testname3'
subcloud = self.create_subcloud_static(self.ctx, name=name1)
region3 = base.SUBCLOUD_3['region_name']
subcloud = self.create_subcloud_static(self.ctx,
name=name1,
region_name=region1)
self.assertIsNotNone(subcloud)
subcloud2 = self.create_subcloud_static(self.ctx,
name=name2,
region_name=region2,
management_start_ip="2.3.4.6",
management_end_ip="2.3.4.7")
self.assertIsNotNone(subcloud2)
subcloud3 = self.create_subcloud_static(self.ctx,
name=name3,
region_name=region3,
management_start_ip="3.3.4.6",
management_end_ip="3.3.4.7")
self.assertIsNotNone(subcloud3)

View File

@ -22,6 +22,7 @@ from dcmanager.manager import service
from dcmanager.tests import base
from dcmanager.tests import utils
from oslo_config import cfg
from oslo_utils import uuidutils
CONF = cfg.CONF
FAKE_USER = utils.UUID1
@ -76,9 +77,11 @@ class TestDCManagerService(base.DCManagerTestCase):
@mock.patch.object(service, 'SubcloudManager')
def test_add_subcloud(self, mock_subcloud_manager):
payload = {'name': 'testname',
'region_name': uuidutils.generate_uuid().replace("-", "")}
self.service_obj.init_managers()
self.service_obj.add_subcloud(
self.context, subcloud_id=1, payload={'name': 'testname'})
self.context, subcloud_id=1, payload=payload)
mock_subcloud_manager().add_subcloud.\
assert_called_once_with(self.context, 1, mock.ANY)

View File

@ -423,6 +423,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
"systemcontroller_gateway_ip": "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': "No errors present",
'region_name': base.SUBCLOUD_1['region_name'],
'openstack_installed': False,
'group_id': 1,
'data_install': 'data from install',
@ -501,7 +502,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
values['deploy_status'] = consts.DEPLOY_STATE_NONE
# dcmanager add_subcloud queries the data from the db
subcloud = self.create_subcloud_static(self.ctx, name=values['name'])
subcloud = self.create_subcloud_static(self.ctx, name=values['name'],
region_name=values['region_name'])
values['id'] = subcloud.id
mock_keystone_client().keystone_client = FakeKeystoneClient()
@ -535,7 +537,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
values['deploy_status'] = consts.DEPLOY_STATE_NONE
# dcmanager add_subcloud queries the data from the db
subcloud = self.create_subcloud_static(self.ctx, name=values['name'])
subcloud = self.create_subcloud_static(self.ctx, name=values['name'],
region_name=values['region_name'])
values['id'] = subcloud.id
mock_keystone_client.side_effect = FakeException('boom')
@ -731,6 +734,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Create subcloud in DB
subcloud = self.create_subcloud_static(self.ctx, name=payload['name'])
payload['region_name'] = subcloud.region_name
# Mock return values
mock_get_playbook_for_software_version.return_value = SW_VERSION
@ -790,7 +794,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
sysadmin_password = values['sysadmin_password']
# dcmanager add_subcloud queries the data from the db
subcloud = self.create_subcloud_static(self.ctx, name=values['name'])
subcloud = self.create_subcloud_static(self.ctx, name=values['name'],
region_name=values['region_name'])
mock_keystone_client().keystone_client = FakeKeystoneClient()
mock_keyring.get_password.return_value = sysadmin_password
@ -809,6 +814,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
mock_run_playbook.assert_called_once()
mock_compose_rehome_command.assert_called_once_with(
values['name'],
values['region_name'],
sm._get_ansible_filename(values['name'], consts.INVENTORY_FILE_POSTFIX),
subcloud['software_version'])
@ -836,7 +842,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
services = FAKE_SERVICES
# dcmanager add_subcloud queries the data from the db
subcloud = self.create_subcloud_static(self.ctx, name=values['name'])
subcloud = self.create_subcloud_static(self.ctx, name=values['name'],
region_name=values['region_name'])
self.fake_dcorch_api.add_subcloud.side_effect = FakeException('boom')
mock_get_cached_regionone_data.return_value = FAKE_CACHED_REGIONONE_DATA
@ -865,7 +872,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
services = FAKE_SERVICES
# dcmanager add_subcloud queries the data from the db
subcloud = self.create_subcloud_static(self.ctx, name=values['name'])
subcloud = self.create_subcloud_static(self.ctx, name=values['name'],
region_name=values['region_name'])
self.fake_dcorch_api.add_subcloud.side_effect = FakeException('boom')
mock_get_cached_regionone_data.return_value = FAKE_CACHED_REGIONONE_DATA
@ -933,7 +941,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
location="subcloud new location")
fake_dcmanager_notification.subcloud_managed.assert_called_once_with(
self.ctx, subcloud.name)
self.ctx, subcloud.region_name)
# Verify subcloud was updated with correct values
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
@ -1063,7 +1071,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
data_install="install values")
fake_dcmanager_cermon_api.subcloud_managed.assert_called_once_with(
self.ctx, subcloud.name)
self.ctx, subcloud.region_name)
# Verify subcloud was updated with correct values
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
@ -1190,7 +1198,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
group_id=2)
fake_dcmanager_cermon_api.subcloud_managed.assert_called_once_with(
self.ctx, subcloud.name)
self.ctx, subcloud.region_name)
# Verify subcloud was updated with correct values
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
@ -1234,7 +1242,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.ENDPOINT_TYPE_DC_CERT]:
# Update
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint)
# Verify
@ -1253,7 +1261,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.ENDPOINT_TYPE_NFV,
dccommon_consts.ENDPOINT_TYPE_DC_CERT]:
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)
@ -1267,7 +1275,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Attempt to update each status to be unknown for an offline/unmanaged
# subcloud. This is allowed.
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_UNKNOWN)
@ -1286,7 +1294,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Attempt to update each status to be out-of-sync for an
# offline/unmanaged subcloud. Exclude one endpoint. This is allowed.
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=None,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
ignore_endpoints=[dccommon_consts.ENDPOINT_TYPE_DC_CERT])
@ -1328,7 +1336,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.ENDPOINT_TYPE_FM,
dccommon_consts.ENDPOINT_TYPE_NFV]:
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)
@ -1343,7 +1351,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# online/unmanaged subcloud. This is allowed. Verify the change.
endpoint = dccommon_consts.ENDPOINT_TYPE_DC_CERT
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)
@ -1373,7 +1381,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.ENDPOINT_TYPE_NFV,
dccommon_consts.ENDPOINT_TYPE_DC_CERT]:
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)
@ -1393,11 +1401,11 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.ENDPOINT_TYPE_NFV,
dccommon_consts.ENDPOINT_TYPE_DC_CERT]:
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_OUT_OF_SYNC)
# Verify lock was called
mock_lock.assert_called_with(subcloud.name)
mock_lock.assert_called_with(subcloud.region_name)
# Verify status was updated
updated_subcloud_status = db_api.subcloud_status_get(
@ -1436,7 +1444,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
self.assertIsNotNone(status)
self.assertEqual(status.sync_status, dccommon_consts.SYNC_STATUS_UNKNOWN)
ssm.update_subcloud_availability(self.ctx, subcloud.name,
ssm.update_subcloud_availability(self.ctx, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE)
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, 'subcloud1')
@ -1445,13 +1453,14 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.AVAILABILITY_ONLINE)
# Verify notifying dcorch
self.fake_dcorch_api.update_subcloud_states.assert_called_once_with(
self.ctx, subcloud.name, updated_subcloud.management_state,
self.ctx, subcloud.region_name, updated_subcloud.management_state,
dccommon_consts.AVAILABILITY_ONLINE)
# Verify triggering audits
self.fake_dcmanager_audit_api.trigger_subcloud_audits.\
assert_called_once_with(self.ctx, subcloud.id)
fake_dcmanager_cermon_api.subcloud_online.assert_called_once_with(self.ctx, subcloud.name)
fake_dcmanager_cermon_api.subcloud_online.\
assert_called_once_with(self.ctx, subcloud.region_name)
def test_update_subcloud_availability_go_online_unmanaged(self):
# create a subcloud
@ -1483,7 +1492,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
self.assertIsNotNone(status)
self.assertEqual(status.sync_status, dccommon_consts.SYNC_STATUS_UNKNOWN)
ssm.update_subcloud_availability(self.ctx, subcloud.name,
ssm.update_subcloud_availability(self.ctx, subcloud.region_name,
dccommon_consts.AVAILABILITY_ONLINE)
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, 'subcloud1')
@ -1492,13 +1501,14 @@ class TestSubcloudManager(base.DCManagerTestCase):
dccommon_consts.AVAILABILITY_ONLINE)
# Verify notifying dcorch
self.fake_dcorch_api.update_subcloud_states.assert_called_once_with(
self.ctx, subcloud.name, updated_subcloud.management_state,
self.ctx, subcloud.region_name, updated_subcloud.management_state,
dccommon_consts.AVAILABILITY_ONLINE)
# Verify triggering audits
self.fake_dcmanager_audit_api.trigger_subcloud_audits.\
assert_called_once_with(self.ctx, subcloud.id)
fake_dcmanager_cermon_api.subcloud_online.assert_called_once_with(self.ctx, subcloud.name)
fake_dcmanager_cermon_api.subcloud_online.\
assert_called_once_with(self.ctx, subcloud.region_name)
def test_update_subcloud_availability_go_offline(self):
subcloud = self.create_subcloud_static(self.ctx, name='subcloud1')
@ -1520,7 +1530,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
db_api.subcloud_status_create(
self.ctx, subcloud.id, endpoint)
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=dccommon_consts.SYNC_STATUS_IN_SYNC)
@ -1531,7 +1541,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Audit fails once
audit_fail_count = 1
ssm.update_subcloud_availability(self.ctx, subcloud.name,
ssm.update_subcloud_availability(self.ctx, subcloud.region_name,
availability_status=None,
audit_fail_count=audit_fail_count)
# Verify the subcloud availability was not updated
@ -1546,7 +1556,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Audit fails again
audit_fail_count = audit_fail_count + 1
ssm.update_subcloud_availability(self.ctx, subcloud.name,
ssm.update_subcloud_availability(self.ctx, subcloud.region_name,
dccommon_consts.AVAILABILITY_OFFLINE,
audit_fail_count=audit_fail_count)
@ -1557,7 +1567,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Verify notifying dcorch
self.fake_dcorch_api.update_subcloud_states.assert_called_once_with(
self.ctx, subcloud.name, updated_subcloud.management_state,
self.ctx, subcloud.region_name, updated_subcloud.management_state,
dccommon_consts.AVAILABILITY_OFFLINE)
# Verify all endpoint statuses set to unknown
@ -1597,7 +1607,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Update identity to the original status
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=original_sync_status)
@ -1607,7 +1617,7 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Update identity to new status and get the count of the trigger again
ssm.update_subcloud_endpoint_status(
self.ctx, subcloud_name=subcloud.name,
self.ctx, subcloud_region=subcloud.region_name,
endpoint_type=endpoint,
sync_status=new_sync_status)
new_trigger_subcloud_audits = \
@ -1634,13 +1644,13 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Test openstack app installed
openstack_installed = True
sm.update_subcloud_sync_endpoint_type(self.ctx, subcloud.name,
sm.update_subcloud_sync_endpoint_type(self.ctx, subcloud.region_name,
endpoint_type_list,
openstack_installed)
# Verify notifying dcorch to add subcloud sync endpoint type
self.fake_dcorch_api.add_subcloud_sync_endpoint_type.\
assert_called_once_with(self.ctx, subcloud.name,
assert_called_once_with(self.ctx, subcloud.region_name,
endpoint_type_list)
# Verify the subcloud status created for os endpoints
@ -1657,12 +1667,12 @@ class TestSubcloudManager(base.DCManagerTestCase):
# Test openstack app removed
openstack_installed = False
sm.update_subcloud_sync_endpoint_type(self.ctx, subcloud.name,
sm.update_subcloud_sync_endpoint_type(self.ctx, subcloud.region_name,
endpoint_type_list,
openstack_installed)
# Verify notifying dcorch to remove subcloud sync endpoint type
self.fake_dcorch_api.remove_subcloud_sync_endpoint_type.\
assert_called_once_with(self.ctx, subcloud.name,
assert_called_once_with(self.ctx, subcloud.region_name,
endpoint_type_list)
# Verify the subcloud status is deleted for os endpoints
@ -1703,8 +1713,11 @@ class TestSubcloudManager(base.DCManagerTestCase):
def test_compose_bootstrap_command(self, mock_isfile):
mock_isfile.return_value = True
sm = subcloud_manager.SubcloudManager()
subcloud_name = base.SUBCLOUD_1['name']
subcloud_region = base.SUBCLOUD_1['region_name']
bootstrap_command = sm.compose_bootstrap_command(
'subcloud1',
subcloud_name,
subcloud_region,
f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_inventory.yml',
FAKE_PREVIOUS_SW_VERSION)
self.assertEqual(
@ -1715,8 +1728,9 @@ class TestSubcloudManager(base.DCManagerTestCase):
subcloud_manager.ANSIBLE_SUBCLOUD_PLAYBOOK,
FAKE_PREVIOUS_SW_VERSION),
'-i', f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_inventory.yml',
'--limit', 'subcloud1', '-e',
f"override_files_dir='{dccommon_consts.ANSIBLE_OVERRIDES_PATH}' region_name=subcloud1",
'--limit', '%s' % subcloud_name, '-e',
str("override_files_dir='%s' region_name=%s") %
(dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_region),
'-e', "install_release_version=%s" % FAKE_PREVIOUS_SW_VERSION
]
)
@ -1746,8 +1760,12 @@ class TestSubcloudManager(base.DCManagerTestCase):
def test_compose_rehome_command(self, mock_isfile):
mock_isfile.return_value = True
sm = subcloud_manager.SubcloudManager()
subcloud_name = base.SUBCLOUD_1['name']
subcloud_region = base.SUBCLOUD_1['region_name']
rehome_command = sm.compose_rehome_command(
'subcloud1',
subcloud_name,
subcloud_region,
f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_inventory.yml',
FAKE_PREVIOUS_SW_VERSION)
self.assertEqual(
@ -1758,10 +1776,10 @@ class TestSubcloudManager(base.DCManagerTestCase):
subcloud_manager.ANSIBLE_SUBCLOUD_REHOME_PLAYBOOK,
FAKE_PREVIOUS_SW_VERSION),
'-i', f'{dccommon_consts.ANSIBLE_OVERRIDES_PATH}/subcloud1_inventory.yml',
'--limit', 'subcloud1',
'--limit', subcloud_name,
'--timeout', subcloud_manager.REHOME_PLAYBOOK_TIMEOUT,
'-e',
f"override_files_dir='{dccommon_consts.ANSIBLE_OVERRIDES_PATH}' region_name=subcloud1"
'-e', str("override_files_dir='%s' region_name=%s") %
(dccommon_consts.ANSIBLE_OVERRIDES_PATH, subcloud_region)
]
)
@ -1823,39 +1841,48 @@ class TestSubcloudManager(base.DCManagerTestCase):
def test_handle_subcloud_operations_in_progress(self):
subcloud1 = self.create_subcloud_static(
self.ctx,
name='subcloud1',
name=base.SUBCLOUD_1['name'],
region_name=base.SUBCLOUD_1['region_name'],
deploy_status=consts.DEPLOY_STATE_PRE_DEPLOY)
subcloud2 = self.create_subcloud_static(
self.ctx,
name='subcloud2',
name=base.SUBCLOUD_2['name'],
region_name=base.SUBCLOUD_2['region_name'],
deploy_status=consts.DEPLOY_STATE_PRE_INSTALL)
subcloud3 = self.create_subcloud_static(
self.ctx,
name='subcloud3',
name=base.SUBCLOUD_3['name'],
region_name=base.SUBCLOUD_3['region_name'],
deploy_status=consts.DEPLOY_STATE_INSTALLING)
subcloud4 = self.create_subcloud_static(
self.ctx,
name='subcloud4',
name=base.SUBCLOUD_4['name'],
region_name=base.SUBCLOUD_4['region_name'],
deploy_status=consts.DEPLOY_STATE_BOOTSTRAPPING)
subcloud5 = self.create_subcloud_static(
self.ctx,
name='subcloud5',
name=base.SUBCLOUD_5['name'],
region_name=base.SUBCLOUD_5['region_name'],
deploy_status=consts.DEPLOY_STATE_DEPLOYING)
subcloud6 = self.create_subcloud_static(
self.ctx,
name='subcloud6',
name=base.SUBCLOUD_6['name'],
region_name=base.SUBCLOUD_6['region_name'],
deploy_status=consts.DEPLOY_STATE_MIGRATING_DATA)
subcloud7 = self.create_subcloud_static(
self.ctx,
name='subcloud7',
name=base.SUBCLOUD_7['name'],
region_name=base.SUBCLOUD_7['region_name'],
deploy_status=consts.DEPLOY_STATE_PRE_RESTORE)
subcloud8 = self.create_subcloud_static(
self.ctx,
name='subcloud8',
name=base.SUBCLOUD_8['name'],
region_name=base.SUBCLOUD_8['region_name'],
deploy_status=consts.DEPLOY_STATE_RESTORING)
subcloud9 = self.create_subcloud_static(
self.ctx,
name='subcloud9',
name=base.SUBCLOUD_9['name'],
region_name=base.SUBCLOUD_9['region_name'],
deploy_status=consts.DEPLOY_STATE_NONE)
subcloud10 = self.create_subcloud_static(
self.ctx,
@ -1940,47 +1967,58 @@ class TestSubcloudManager(base.DCManagerTestCase):
def test_handle_completed_subcloud_operations(self):
subcloud1 = self.create_subcloud_static(
self.ctx,
name='subcloud1',
name=base.SUBCLOUD_1['name'],
region_name=base.SUBCLOUD_1['region_name'],
deploy_status=consts.DEPLOY_STATE_CREATE_FAILED)
subcloud2 = self.create_subcloud_static(
self.ctx,
name='subcloud2',
name=base.SUBCLOUD_2['name'],
region_name=base.SUBCLOUD_2['region_name'],
deploy_status=consts.DEPLOY_STATE_PRE_INSTALL_FAILED)
subcloud3 = self.create_subcloud_static(
self.ctx,
name='subcloud3',
name=base.SUBCLOUD_3['name'],
region_name=base.SUBCLOUD_3['region_name'],
deploy_status=consts.DEPLOY_STATE_INSTALL_FAILED)
subcloud4 = self.create_subcloud_static(
self.ctx,
name='subcloud4',
name=base.SUBCLOUD_4['name'],
region_name=base.SUBCLOUD_4['region_name'],
deploy_status=consts.DEPLOY_STATE_INSTALLED)
subcloud5 = self.create_subcloud_static(
self.ctx,
name='subcloud5',
name=base.SUBCLOUD_5['name'],
region_name=base.SUBCLOUD_5['region_name'],
deploy_status=consts.DEPLOY_STATE_BOOTSTRAP_FAILED)
subcloud6 = self.create_subcloud_static(
self.ctx,
name='subcloud6',
name=base.SUBCLOUD_6['name'],
region_name=base.SUBCLOUD_6['region_name'],
deploy_status=consts.DEPLOY_STATE_CONFIG_FAILED)
subcloud7 = self.create_subcloud_static(
self.ctx,
name='subcloud7',
name=base.SUBCLOUD_7['name'],
region_name=base.SUBCLOUD_7['region_name'],
deploy_status=consts.DEPLOY_STATE_DATA_MIGRATION_FAILED)
subcloud8 = self.create_subcloud_static(
self.ctx,
name='subcloud8',
name=base.SUBCLOUD_8['name'],
region_name=base.SUBCLOUD_8['region_name'],
deploy_status=consts.DEPLOY_STATE_MIGRATED)
subcloud9 = self.create_subcloud_static(
self.ctx,
name='subcloud9',
name=base.SUBCLOUD_9['name'],
region_name=base.SUBCLOUD_9['region_name'],
deploy_status=consts.DEPLOY_STATE_RESTORE_PREP_FAILED)
subcloud10 = self.create_subcloud_static(
self.ctx,
name='subcloud10',
name=base.SUBCLOUD_10['name'],
region_name=base.SUBCLOUD_10['region_name'],
deploy_status=consts.DEPLOY_STATE_RESTORE_FAILED)
subcloud11 = self.create_subcloud_static(
self.ctx,
name='subcloud11',
name=base.SUBCLOUD_11['name'],
region_name=base.SUBCLOUD_11['region_name'],
deploy_status=consts.DEPLOY_STATE_DONE)
subcloud12 = self.create_subcloud_static(
self.ctx,
@ -2792,7 +2830,8 @@ class TestSubcloudManager(base.DCManagerTestCase):
values = {
'name': 'TestSubcloud',
'sysadmin_password': '123',
'secondary': 'true'
'secondary': 'true',
'region_name': '2ec93dfb654846909efe61d1b39dd2ce'
}
# Create an instance of SubcloudManager

View File

@ -8,6 +8,7 @@ import mock
from dccommon import consts as dccommon_consts
from dcmanager.common import consts
from dcmanager.db.sqlalchemy import api as db_api
from dcmanager.tests import base
from dcmanager.tests.unit.common import fake_strategy
from dcmanager.tests.unit.common import fake_subcloud
from dcmanager.tests.unit.orchestrator.states.fakes import FakeAlarm
@ -520,7 +521,8 @@ class TestSwUpgradePreCheckSimplexStage(TestSwUpgradePreCheckStage):
# and no data install values
self.subcloud = fake_subcloud.create_fake_subcloud(
self.ctx,
name="subcloud2",
name=base.SUBCLOUD_2['name'],
region_name=base.SUBCLOUD_2['region_name'],
data_install=None
)
@ -604,7 +606,8 @@ class TestSwUpgradePreCheckSimplexStage(TestSwUpgradePreCheckStage):
# availability status as "offline" and no data install values
self.subcloud = fake_subcloud.create_fake_subcloud(
self.ctx,
name="subcloud2",
name=base.SUBCLOUD_2['name'],
region_name=base.SUBCLOUD_2['region_name'],
data_install=None,
deploy_status=consts.DEPLOY_STATE_INSTALL_FAILED
)

View File

@ -4,6 +4,7 @@
# SPDX-License-Identifier: Apache-2.0
#
import mock
from oslo_utils import uuidutils
from dccommon import consts as dccommon_consts
from dccommon.drivers.openstack import vim
@ -39,6 +40,7 @@ class TestFwOrchThread(TestSwUpdate):
"systemcontroller_gateway_ip": "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': uuidutils.generate_uuid().replace("-", ""),
'openstack_installed': False,
'group_id': group_id,
'data_install': 'data from install',

View File

@ -17,6 +17,7 @@ import copy
import mock
from oslo_config import cfg
from oslo_utils import uuidutils
from dccommon import consts as dccommon_consts
from dcmanager.common import consts
@ -117,6 +118,7 @@ class TestSwUpdateManager(base.DCManagerTestCase):
"systemcontroller_gateway_ip": "192.168.204.101",
'deploy_status': "not-deployed",
'error_description': 'No errors present',
'region_name': uuidutils.generate_uuid().replace("-", ""),
'openstack_installed': False,
'group_id': group_id,
'data_install': 'data from install',

View File

@ -93,4 +93,5 @@ def create_subcloud_dict(data_list):
'group_id': data_list[23],
'deploy_status': data_list[24],
'error_description': data_list[25],
'data_install': data_list[26]}
'region_name': data_list[26],
'data_install': data_list[27]}

View File

@ -377,12 +377,12 @@ def add_identity_filter(query, value,
:return: Modified query.
"""
if strutils.is_int_like(value):
if use_region_name:
return query.filter_by(region_name=value)
elif strutils.is_int_like(value):
return query.filter_by(id=value)
elif uuidutils.is_uuid_like(value):
return query.filter_by(uuid=value)
elif use_region_name:
return query.filter_by(region_name=value)
elif use_resource_type:
return query.filter_by(resource_type=value)
else:

View File

@ -87,6 +87,7 @@ class SyncThread(object):
self.log_extra = {
"instance": self.subcloud_name + ": "}
self.dcmanager_state_rpc_client = dcmanager_rpc_client.SubcloudStateClient()
self.dcmanager_rpc_client = dcmanager_rpc_client.ManagerClient()
self.sc_admin_session = None
self.admin_session = None
@ -298,15 +299,35 @@ class SyncThread(object):
self.subcloud_name, sync_status, alarmable),
extra=self.log_extra)
self.dcmanager_state_rpc_client.update_subcloud_endpoint_status(
self.ctxt, self.subcloud_name,
self.endpoint_type, sync_status,
alarmable=alarmable)
try:
# This block is required to get the real subcloud name
# dcorch uses the subcloud name as the region name.
# The region name cannot be changed, so at this point it
# is necessary to query the subcloud name as it is required
# for logging purposes.
db_api.subcloud_sync_update(
self.ctxt, self.subcloud_name, self.endpoint_type,
values={'sync_status_reported': sync_status,
'sync_status_report_time': timeutils.utcnow()})
# Save current subcloud name (region name from dcorch DB)
dcorch_subcloud_region = self.subcloud_name
# Get the subcloud name from dcmanager database supplying
# the dcorch region name
subcloud_name = self.dcmanager_rpc_client \
.get_subcloud_name_by_region_name(self.ctxt,
dcorch_subcloud_region)
# Updates the endpoint status supplying the subcloud name and
# the region name
self.dcmanager_state_rpc_client.update_subcloud_endpoint_status(
self.ctxt, subcloud_name, dcorch_subcloud_region,
self.endpoint_type, sync_status,
alarmable=alarmable)
db_api.subcloud_sync_update(
self.ctxt, dcorch_subcloud_region, self.endpoint_type,
values={'sync_status_reported': sync_status,
'sync_status_report_time': timeutils.utcnow()})
except Exception:
raise
def sync(self, engine_id):
LOG.debug("{}: starting sync routine".format(self.subcloud_name),