Add subcloud secondary status support and migration

Add "subcloud migrate" to rehome a 'secondary' state
subcloud.

Update "dcmanager subcloud add --secondary" command

Update "dcmanager subcloud update --bootstrap-address
--bootstrap-values"
to save data for day-2's rehome/migrate purpose.

Update "dcmanager list subcloud --all" include show
'secondary/secondary-failed' subclouds

Update result of "subcloud show",
add rehome_data section.

Usage:
dcmanager subcloud add --secondary
--bootstrap-address IP
--bootstrap-values [yaml file]

dcmanager subcloud update SUBCLOUD
--bootstrap-address IP
--bootstrap-values [yaml file]

dcmanager subcloud list --all

dcmanager subcloud show SUBCLOUD

dcmanager subcloud migrate SUBCLOUD
--sysadmin-password PASSWORD

Test Plan:
1. PASS - Verify that the dcmanager help subcloud migrate shows
          the correct help message;
2. PASS - Run 'dcmanager subcloud add --secondary' and verify that the
          correct API call is made;
3. PASS - Run 'dcmanager subcloud update --bootstrap-address
          --bootstrap-values' and verify that the
          correct API call is made;

4. PASS - Run 'dcmanager subcloud migrate' and verify that the
          correct API call is made;
5. PASS - Verify that the subcloud name/id parameter is required.

Story: 2010852
Task: 48489
Task: 48504
Depends-On: I9a308a4e2cc5057091ba195c4d05e9d1eb4a950c
Change-Id: Idd10267370dd2cd562c6eacc0d24c47cf68e9fd5
Signed-off-by: Wang Tao <tao.wang@windriver.com>
This commit is contained in:
twang4 2023-08-23 10:37:01 +08:00 committed by TaoWang
parent b6723b8f67
commit a8b8077983
9 changed files with 327 additions and 62 deletions

View File

@ -46,6 +46,7 @@ class Subcloud(Resource):
'created-at': 'created_at',
'updated-at': 'updated_at',
'group_id': 'group_id',
'rehome_data': 'rehome_data',
'sync_status': 'sync_status',
'endpoint_sync_status': 'endpoint_sync_status',
'backup-status': 'backup_status',
@ -60,7 +61,8 @@ class Subcloud(Resource):
systemcontroller_gateway_ip, created_at, updated_at,
group_id, sync_status="unknown", endpoint_sync_status=None,
backup_status=None, backup_datetime=None,
error_description=None, prestage_software_version=None):
error_description=None, prestage_software_version=None,
rehome_data=None):
if endpoint_sync_status is None:
endpoint_sync_status = {}
self.manager = manager
@ -83,6 +85,7 @@ class Subcloud(Resource):
self.created_at = created_at
self.updated_at = updated_at
self.group_id = group_id
self.rehome_data = rehome_data
self.sync_status = sync_status
self.endpoint_sync_status = endpoint_sync_status
self.backup_status = backup_status

View File

@ -105,6 +105,16 @@ class subcloud_manager(base.ResourceManager):
resource.append(self.json_to_resource(json_object))
return resource
def subcloud_migrate(self, url, data):
data = json.dumps(data)
resp = self.http_client.patch(url, data)
if resp.status_code != 200:
self._raise_api_exception(resp)
json_object = get_json(resp)
subcloud = self.resource_class.from_payload(self, json_object)
resource = [subcloud]
return resource
def _subcloud_prestage(self, url, data):
data = json.dumps(data)
resp = self.http_client.patch(url, data)
@ -190,3 +200,8 @@ class subcloud_manager(base.ResourceManager):
data = kwargs.get('data')
url = '/subclouds/%s/redeploy' % subcloud_ref
return self.subcloud_redeploy(url, files, data)
def migrate_subcloud(self, subcloud_ref, **kwargs):
data = kwargs.get('data')
url = '/subclouds/%s/migrate' % subcloud_ref
return self.subcloud_migrate(url, data)

View File

@ -71,6 +71,7 @@ def detail_format(subcloud=None):
'management_gateway_ip',
'systemcontroller_gateway_ip',
'group_id',
'rehome_data',
'created_at',
'updated_at',
'backup_status',
@ -93,6 +94,7 @@ def detail_format(subcloud=None):
subcloud.management_gateway_ip,
subcloud.systemcontroller_gateway_ip,
subcloud.group_id,
subcloud.rehome_data,
subcloud.created_at,
subcloud.updated_at,
subcloud.backup_status,
@ -194,6 +196,14 @@ class AddSubcloud(base.DCManagerShowOne):
'the subcloud with. If not specified, the current software '
'release of the system controller will be used.'
)
parser.add_argument(
'--secondary',
required=False,
action='store_true',
help='A flag indicating if this subcloud is a placeholder '
'for incoming subcloud rehoming.'
)
return parser
def _get_resources(self, parsed_args):
@ -223,20 +233,27 @@ class AddSubcloud(base.DCManagerShowOne):
error_msg = "migrate with deploy-config is not allowed"
raise exceptions.DCManagerClientException(error_msg)
if parsed_args.secondary:
error_msg = "secondary with deploy-config is not allowed"
raise exceptions.DCManagerClientException(error_msg)
if not os.path.isfile(parsed_args.deploy_config):
error_msg = "deploy-config does not exist: %s" % \
parsed_args.deploy_config
raise exceptions.DCManagerClientException(error_msg)
files['deploy_config'] = parsed_args.deploy_config
# Prompt the user for the subcloud's password if it isn't provided
if parsed_args.sysadmin_password is not None:
data['sysadmin_password'] = base64.b64encode(
parsed_args.sysadmin_password.encode("utf-8"))
else:
password = utils.prompt_for_password()
data["sysadmin_password"] = base64.b64encode(
password.encode("utf-8"))
# To add a secondary subcloud,
# do not need sysadmin_password
if not parsed_args.secondary:
# Prompt the user for the subcloud's password if it isn't provided
if parsed_args.sysadmin_password is not None:
data['sysadmin_password'] = base64.b64encode(
parsed_args.sysadmin_password.encode("utf-8"))
else:
password = utils.prompt_for_password()
data["sysadmin_password"] = base64.b64encode(
password.encode("utf-8"))
if parsed_args.install_values is not None:
if parsed_args.bmc_password is not None:
@ -256,6 +273,9 @@ class AddSubcloud(base.DCManagerShowOne):
if parsed_args.release is not None:
data['release'] = parsed_args.release
if parsed_args.secondary:
data['secondary'] = 'true'
return dcmanager_client.subcloud_manager.add_subcloud(files=files,
data=data)
@ -268,11 +288,26 @@ class ListSubcloud(base.DCManagerLister):
def get_parser(self, prog_name):
parser = super(ListSubcloud, self).get_parser(prog_name)
parser.add_argument(
'--all',
required=False,
action='store_true',
help='List all subclouds include "secondary" state subclouds'
)
return parser
def _get_resources(self, parsed_args):
dcmanager_client = self.app.client_manager.subcloud_manager
return dcmanager_client.subcloud_manager.list_subclouds()
subclouds = dcmanager_client.subcloud_manager.list_subclouds()
# for '--all' parameter, show all subclouds.
# for no parameter, hidden all 'secondary/secondary-failed'
# state subclouds.
if parsed_args.all:
return subclouds
filtered_subclouds = [s for s in subclouds if s.deploy_status not in
('secondary', 'secondary-failed')]
return filtered_subclouds
class ShowSubcloud(base.DCManagerShowOne):
@ -503,6 +538,12 @@ class UpdateSubcloud(base.DCManagerShowOne):
'provided you will be prompted. This parameter is only'
' valid if the --install-values are specified.'
)
parser.add_argument(
'--bootstrap-values',
required=False,
help='YAML file containing subcloud configuration settings. '
'Can be either a local file path or a URL.'
)
return parser
def _get_resources(self, parsed_args):
@ -535,6 +576,7 @@ class UpdateSubcloud(base.DCManagerShowOne):
data.get('management_end_ip'),
data.get('bootstrap_address')
]
# Semantic check if the required arguments for updating admin network
if all(value is not None for value in subcloud_network_values):
# Prompt the user for the subcloud's password if it isn't provided
@ -545,8 +587,14 @@ class UpdateSubcloud(base.DCManagerShowOne):
password = utils.prompt_for_password()
data["sysadmin_password"] = base64.b64encode(
password.encode("utf-8"))
# Not all network values exist
elif any(value is not None for value in subcloud_network_values):
# For subcloud network reconfiguration
# If any management_* presents, need all
# management_subnet/management_gateway_ip/
# management_start_ip/management_end_ip/bootstrap_address
# presents.
elif any(value is not None and value != parsed_args.bootstrap_address
for value in subcloud_network_values):
# Not all network values exist
error_msg = (
"For subcloud network reconfiguration request all the "
"following parameters are necessary: --management-subnet, "
@ -569,7 +617,15 @@ class UpdateSubcloud(base.DCManagerShowOne):
data["bmc_password"] = base64.b64encode(
password.encode("utf-8"))
if not data:
# Update the bootstrap values from yaml file
if parsed_args.bootstrap_values:
if not os.path.isfile(parsed_args.bootstrap_values):
error_msg = "bootstrap-values does not exist: %s" % \
parsed_args.bootstrap_values
raise exceptions.DCManagerClientException(error_msg)
files['bootstrap_values'] = parsed_args.bootstrap_values
if not (data or files):
error_msg = "Nothing to update"
raise exceptions.DCManagerClientException(error_msg)
@ -977,3 +1033,46 @@ class PrestageSubcloud(base.DCManagerShowOne):
print(e)
error_msg = "Unable to prestage subcloud %s" % (subcloud_ref)
raise exceptions.DCManagerClientException(error_msg)
class MigrateSubcloud(base.DCManagerShowOne):
"""Migrate a secondary status subcloud."""
def _get_format_function(self):
return detail_format
def get_parser(self, prog_name):
parser = super(MigrateSubcloud, self).get_parser(prog_name)
parser.add_argument(
'subcloud',
help='Name or ID of the subcloud to migrate.'
)
parser.add_argument(
'--sysadmin-password',
required=False,
help='sysadmin password of the subcloud to be configured, '
'if not provided you will be prompted.'
)
return parser
def _get_resources(self, parsed_args):
subcloud_ref = parsed_args.subcloud
dcmanager_client = self.app.client_manager.subcloud_manager
data = dict()
if parsed_args.sysadmin_password is not None:
data['sysadmin_password'] = base64.b64encode(
parsed_args.sysadmin_password.encode("utf-8")).decode("utf-8")
else:
password = utils.prompt_for_password()
data["sysadmin_password"] = base64.b64encode(
password.encode("utf-8")).decode("utf-8")
try:
return dcmanager_client.subcloud_manager.migrate_subcloud(
subcloud_ref=subcloud_ref, data=data)
except Exception as e:
print(e)
error_msg = "Unable to migrate subcloud %s" % (subcloud_ref)
raise exceptions.DCManagerClientException(error_msg)

View File

@ -536,6 +536,7 @@ class DCManagerShell(app.App):
'subcloud redeploy': sm.RedeploySubcloud,
'subcloud restore': sm.RestoreSubcloud,
'subcloud prestage': sm.PrestageSubcloud,
'subcloud migrate': sm.MigrateSubcloud,
'subcloud-backup create': sbm.CreateSubcloudBackup,
'subcloud-backup delete': sbm.DeleteSubcloudBackup,
'subcloud-backup restore': sbm.RestoreSubcloudBackup,

View File

@ -51,6 +51,7 @@ EXTERNAL_OAM_GATEWAY_ADDRESS = "10.10.10.1"
EXTERNAL_OAM_FLOATING_ADDRESS = "10.10.10.12"
DEFAULT_SUBCLOUD_GROUP_ID = '1'
DEPLOY_CONFIG_SYNC_STATUS = 'Deployment: configurations up-to-date'
SUBCLOUD_REHOME_DATA = None
BACKUP_STATUS = 'None'
BACKUP_DATETIME = 'None'
@ -77,6 +78,29 @@ SUBCLOUD_RESOURCE = api_base.Subcloud(
backup_status=BACKUP_STATUS,
backup_datetime=BACKUP_DATETIME)
# Subcloud CLI resource object with peerid rehome data
SUBCLOUD_RESOURCE_WITH_PEERID_REHOME_DATA = api_base.Subcloud(
mock,
subcloud_id=ID,
name=NAME,
description=DESCRIPTION,
location=LOCATION,
software_version=SOFTWARE_VERSION,
management_state=MANAGEMENT_STATE,
availability_status=AVAILABILITY_STATUS,
deploy_status=DEPLOY_STATUS,
management_subnet=MANAGEMENT_SUBNET,
management_start_ip=MANAGEMENT_START_IP,
management_end_ip=MANAGEMENT_END_IP,
management_gateway_ip=MANAGEMENT_GATEWAY_IP,
systemcontroller_gateway_ip=SYSTEMCONTROLLER_GATEWAY_IP,
group_id=DEFAULT_SUBCLOUD_GROUP_ID,
rehome_data=SUBCLOUD_REHOME_DATA,
created_at=TIME_NOW,
updated_at=TIME_NOW,
backup_status=BACKUP_STATUS,
backup_datetime=BACKUP_DATETIME)
# Subcloud result values returned from various API calls (e.g. subcloud show)
SUBCLOUD_FIELD_RESULT_LIST = (
ID,
@ -99,7 +123,31 @@ SUBCLOUD_FIELD_RESULT_LIST = (
BACKUP_DATETIME
)
# Subcloud result values returned from various API calls (e.g. subcloud show)
SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA = (
ID,
NAME,
DESCRIPTION,
LOCATION,
SOFTWARE_VERSION,
MANAGEMENT_STATE,
AVAILABILITY_STATUS,
DEPLOY_STATUS,
MANAGEMENT_SUBNET,
MANAGEMENT_START_IP,
MANAGEMENT_END_IP,
MANAGEMENT_GATEWAY_IP,
SYSTEMCONTROLLER_GATEWAY_IP,
DEFAULT_SUBCLOUD_GROUP_ID,
SUBCLOUD_REHOME_DATA,
TIME_NOW,
TIME_NOW,
BACKUP_STATUS,
BACKUP_DATETIME
)
EMPTY_SUBCLOUD_FIELD_RESULT = (('<none>',) * len(SUBCLOUD_FIELD_RESULT_LIST),)
EMPTY_SUBCLOUD_FIELD_RESULT_WITH_PEERID_REHOME_DATA = \
(('<none>',) * len(SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA),)
# Subcloud result values returned from subcloud list command
SUBCLOUD_LIST_RESULT = (

View File

@ -44,7 +44,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
'--deploy-config', config_file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_subcloud_deploy_bootstrap(self):
self.client.subcloud_deploy_bootstrap.return_value = [
@ -59,7 +61,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
'--bootstrap-address', base.BOOTSTRAP_ADDRESS,
'--bootstrap-values', bootstrap_file_path,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_install_subcloud(self):
self.client.subcloud_deploy_install.return_value = [
@ -72,7 +76,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
cmd.InstallPhasedSubcloudDeploy, app_args=[
base.NAME, '--install-values', file_path,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_install_subcloud_with_release(self):
self.client.subcloud_deploy_install.return_value = [
@ -87,7 +93,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
'--install-values', file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_install_subcloud_without_install_values(self):
self.client.subcloud_deploy_install.return_value = [
@ -96,7 +104,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
actual_call = self.call(
cmd.InstallPhasedSubcloudDeploy, app_args=[base.NAME])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_install_file_does_not_exist(self):
self.client.subcloud_deploy_install.return_value = [
@ -122,7 +132,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
actual_call = self.call(
cmd.ConfigPhasedSubcloudDeploy,
app_args=[base.NAME, '--deploy-config', file_path])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_configure_file_does_not_exist(self):
self.client.subcloud_deploy_config.return_value = [
@ -144,7 +156,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
actual_call = self.call(
cmd.CompletePhasedSubcloudDeploy,
app_args=[base.NAME])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_abort_subcloud(self):
self.client.subcloud_deploy_abort.return_value = [
@ -152,7 +166,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
actual_call = self.call(
cmd.AbortPhasedSubcloudDeploy,
app_args=[base.NAME])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_subcloud_deploy_resume_all_parameters(self):
self.client.subcloud_deploy_resume.return_value = [
@ -175,7 +191,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
'--deploy-config', config_file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_subcloud_deploy_resume_missing_files(self):
self.client.subcloud_deploy_resume.return_value = [
@ -225,7 +243,9 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
actual_call = self.call(
cmd.PhasedSubcloudDeployResume,
app_args=[base.NAME])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_subcloud_deploy_resume_no_files_only_release(self):
self.client.subcloud_deploy_resume.return_value = [
@ -236,4 +256,6 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
base.NAME,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])

View File

@ -84,8 +84,9 @@ class TestCLISubcloudGroupManagerV1(base.BaseCommandTest):
app_args=[ID])
self.client.subcloud_group_manager.subcloud_group_list_subclouds.\
assert_called_once_with(ID)
self.assertEqual([base.SUBCLOUD_FIELD_RESULT_LIST],
actual_call[1])
self.assertEqual([
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA],
actual_call[1])
def test_delete_subcloud_group_by_id(self):
self.call(subcloud_group_cmd.DeleteSubcloudGroup, app_args=[ID])

View File

@ -53,8 +53,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
self.client.subcloud_manager.subcloud_detail.\
return_value = [base.SUBCLOUD_RESOURCE]
actual_call = self.call(subcloud_cmd.ShowSubcloud, app_args=[base.ID])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST,
actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_show_subcloud_with_additional_detail(self):
SUBCLOUD_WITH_ADDITIONAL_DETAIL = copy.copy(base.SUBCLOUD_RESOURCE)
@ -66,16 +67,18 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
return_value = [SUBCLOUD_WITH_ADDITIONAL_DETAIL]
actual_call = self.call(subcloud_cmd.ShowSubcloud,
app_args=[base.ID, '--detail'])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST +
(base.EXTERNAL_OAM_FLOATING_ADDRESS,
base.DEPLOY_CONFIG_SYNC_STATUS),
actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA +
(base.EXTERNAL_OAM_FLOATING_ADDRESS,
base.DEPLOY_CONFIG_SYNC_STATUS),
actual_call[1])
def test_show_subcloud_negative(self):
self.client.subcloud_manager.subcloud_detail.return_value = []
actual_call = self.call(subcloud_cmd.ShowSubcloud, app_args=[base.ID])
self.assertEqual(base.EMPTY_SUBCLOUD_FIELD_RESULT,
actual_call[1])
self.assertEqual(
base.EMPTY_SUBCLOUD_FIELD_RESULT_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
def test_add_subcloud(self, getpass):
@ -98,8 +101,12 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
'--bootstrap-values', file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call1[1])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call2[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call1[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call2[1])
@mock.patch('getpass.getpass', return_value='testpassword')
def test_add_migrate_subcloud(self, getpass):
@ -115,7 +122,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
'--bootstrap-values', file_path,
'--migrate',
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
def test_add_migrate_subcloud_with_deploy_config(self, getpass):
@ -142,7 +151,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
return_value = [base.SUBCLOUD_RESOURCE]
actual_call = self.call(
subcloud_cmd.UnmanageSubcloud, app_args=[base.ID])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_unmanage_subcloud_without_subcloud_id(self):
self.assertRaises(SystemExit, self.call,
@ -153,7 +164,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
return_value = [base.SUBCLOUD_RESOURCE]
actual_call = self.call(
subcloud_cmd.ManageSubcloud, app_args=[base.ID])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
def test_manage_subcloud_without_subcloud_id(self):
self.assertRaises(SystemExit, self.call,
@ -162,18 +175,24 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
def test_update_subcloud(self):
self.client.subcloud_manager.update_subcloud.\
return_value = [base.SUBCLOUD_RESOURCE]
actual_call = self.call(
subcloud_cmd.UpdateSubcloud,
app_args=[base.ID,
'--description', 'subcloud description',
'--location', 'subcloud location',
'--sysadmin-password', 'testpassword',
'--management-subnet', 'subcloud network subnet',
'--management-gateway-ip', 'subcloud network gateway ip',
'--management-start-ip', 'sc network start ip',
'--management-end-ip', 'subcloud network end ip',
'--bootstrap-address', 'subcloud bootstrap address'])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
with tempfile.NamedTemporaryFile(mode='w') as f_bootstrap:
bootstrap_file_path = os.path.abspath(f_bootstrap.name)
actual_call = self.call(
subcloud_cmd.UpdateSubcloud,
app_args=[
base.ID,
'--description', 'subcloud description',
'--location', 'subcloud location',
'--sysadmin-password', 'testpassword',
'--management-subnet', 'subcloud network subnet',
'--management-gateway-ip', 'subcloud network gateway ip',
'--management-start-ip', 'sc network start ip',
'--management-end-ip', 'subcloud network end ip',
'--bootstrap-address', 'subcloud bootstrap address',
'--bootstrap-values', bootstrap_file_path])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
def test_success_reconfigure_subcloud(self, getpass):
@ -189,7 +208,8 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
app_args=[base.ID,
'--deploy-config', file_path])
expected_result = list(base.SUBCLOUD_FIELD_RESULT_LIST)
expected_result = list(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA)
expected_result[7] = base.DEPLOY_STATE_PRE_DEPLOY
self.assertEqual(tuple(expected_result), actual_call[1])
@ -221,7 +241,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
actual_call = self.call(
subcloud_cmd.ReinstallSubcloud,
app_args=[base.ID, '--bootstrap-values', file_path])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
@mock.patch('six.moves.input', return_value='reinstall')
@ -245,8 +267,12 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
'--bootstrap-values', file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call1[1])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call2[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call1[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call2[1])
@mock.patch('getpass.getpass', return_value='testpassword')
@mock.patch('six.moves.input', return_value='reinstall')
@ -288,7 +314,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
'--deploy-config', config_file_path,
'--release', base.SOFTWARE_VERSION,
])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
@mock.patch('six.moves.input', return_value='redeploy')
@ -298,7 +326,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
actual_call = self.call(
subcloud_cmd.RedeploySubcloud,
app_args=[base.ID])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
@mock.patch('getpass.getpass', return_value='testpassword')
@mock.patch('six.moves.input', return_value='redeploy')
@ -355,8 +385,9 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
app_args=[base.ID,
'--sysadmin-password', 'testpassword',
'--force'])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST,
actual_call_without_release[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call_without_release[1])
def test_prestage_without_subcloudID(self):
self.assertRaises(SystemExit, self.call,
@ -374,6 +405,49 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest):
'--sysadmin-password', 'testpassword',
'--force',
'--release', base.SOFTWARE_VERSION])
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST +
(base.SOFTWARE_VERSION,),
actual_call_with_release[1])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA +
(base.SOFTWARE_VERSION,),
actual_call_with_release[1])
def test_migrate_subcloud(self):
self.client.subcloud_manager.migrate_subcloud. \
return_value = [base.SUBCLOUD_RESOURCE]
actual_call_without_release = self.call(
subcloud_cmd.MigrateSubcloud,
app_args=[base.ID,
'--sysadmin-password', 'testpassword'])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call_without_release[1])
self.assertRaises(SystemExit, self.call,
subcloud_cmd.MigrateSubcloud, app_args=[])
def test_add_secondary_subcloud(self):
self.client.subcloud_manager.add_subcloud.\
return_value = [base.SUBCLOUD_RESOURCE]
with tempfile.NamedTemporaryFile(mode='w') as f_bootstrap:
bootstrap_file_path = os.path.abspath(f_bootstrap.name)
actual_call = self.call(
subcloud_cmd.AddSubcloud,
app_args=[
'--bootstrap-address', base.BOOTSTRAP_ADDRESS,
'--bootstrap-values', bootstrap_file_path,
'--sysadmin-password', 'testpassword',
'--secondary',
])
self.assertEqual(
base.SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID_REHOME_DATA,
actual_call[1])
with tempfile.NamedTemporaryFile() as f_config:
config_file_path = os.path.abspath(f_config.name)
self.assertRaises(
DCManagerClientException, self.call,
subcloud_cmd.AddSubcloud, app_args=[
'--bootstrap-address', base.BOOTSTRAP_ADDRESS,
'--bootstrap-values', bootstrap_file_path,
'--sysadmin-password', 'testpassword',
'--deploy-config', config_file_path,
'--secondary'
])

View File

@ -120,6 +120,7 @@ def subcloud_detail_format(subcloud=None):
'management_gateway_ip',
'systemcontroller_gateway_ip',
'group_id',
'rehome_data',
'created_at',
'updated_at',
'backup_status',
@ -142,6 +143,7 @@ def subcloud_detail_format(subcloud=None):
subcloud.management_gateway_ip,
subcloud.systemcontroller_gateway_ip,
subcloud.group_id,
subcloud.rehome_data,
subcloud.created_at,
subcloud.updated_at,
subcloud.backup_status,