diff --git a/distributedcloud-client/dcmanagerclient/api/base.py b/distributedcloud-client/dcmanagerclient/api/base.py index 2e0f29e..7d1396a 100644 --- a/distributedcloud-client/dcmanagerclient/api/base.py +++ b/distributedcloud-client/dcmanagerclient/api/base.py @@ -1,5 +1,5 @@ # Copyright (c) 2016 Ericsson AB -# Copyright (c) 2017-2023 Wind River Systems, Inc. +# Copyright (c) 2017-2024 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. @@ -53,6 +53,8 @@ class Subcloud(Resource): 'backup-status': 'backup_status', 'backup-datetime': 'backup_datetime', 'prestage-software-version': 'prestage_software_version', + 'prestage-status': 'prestage_status', + 'prestage-versions': 'prestage_versions', 'region-name': 'region_name' } @@ -64,7 +66,8 @@ class Subcloud(Resource): group_id, sync_status="unknown", endpoint_sync_status=None, backup_status=None, backup_datetime=None, error_description=None, prestage_software_version=None, - peer_group_id=None, rehome_data=None, region_name=None): + peer_group_id=None, rehome_data=None, region_name=None, + prestage_status=None, prestage_versions=None): if endpoint_sync_status is None: endpoint_sync_status = {} self.manager = manager @@ -95,6 +98,8 @@ class Subcloud(Resource): self.backup_datetime = backup_datetime self.prestage_software_version = prestage_software_version self.region_name = region_name + self.prestage_status = prestage_status + self.prestage_versions = prestage_versions @classmethod def from_payload(cls, manager, payload): diff --git a/distributedcloud-client/dcmanagerclient/commands/v1/subcloud_manager.py b/distributedcloud-client/dcmanagerclient/commands/v1/subcloud_manager.py index 11b19a1..5717ea7 100644 --- a/distributedcloud-client/dcmanagerclient/commands/v1/subcloud_manager.py +++ b/distributedcloud-client/dcmanagerclient/commands/v1/subcloud_manager.py @@ -39,7 +39,7 @@ def format(subcloud=None): 'deploy status', 'sync', 'backup status', - 'backup datetime' + 'prestage status' ) if subcloud: @@ -51,7 +51,7 @@ def format(subcloud=None): subcloud.deploy_status, subcloud.sync_status, subcloud.backup_status, - subcloud.backup_datetime, + subcloud.prestage_status ) else: @@ -60,7 +60,7 @@ def format(subcloud=None): return columns, data -def detail_format(subcloud=None): +def basic_detail_format(subcloud=None): columns = ( 'id', 'name', @@ -80,7 +80,9 @@ def detail_format(subcloud=None): 'created_at', 'updated_at', 'backup_status', - 'backup_datetime' + 'backup_datetime', + 'prestage_status', + 'prestage_versions' ) if subcloud: @@ -103,9 +105,21 @@ def detail_format(subcloud=None): subcloud.created_at, subcloud.updated_at, subcloud.backup_status, - subcloud.backup_datetime + subcloud.backup_datetime, + subcloud.prestage_status, + subcloud.prestage_versions ) + else: + data = (tuple('' for _ in range(len(columns))),) + + return columns, data + + +def detail_format(subcloud=None): + columns, data = basic_detail_format(subcloud) + + if subcloud: for _listitem, sync_status in enumerate(subcloud.endpoint_sync_status): added_field = (sync_status['endpoint_type'] + "_sync_status",) @@ -117,10 +131,6 @@ def detail_format(subcloud=None): columns += ('oam_floating_ip',) data += (subcloud.oam_floating_ip,) - if subcloud.prestage_software_version: - columns += ('prestage_software_version',) - data += (subcloud.prestage_software_version,) - if subcloud.deploy_config_sync_status != "unknown": columns += ('deploy_config_sync_status',) data += (subcloud.deploy_config_sync_status,) @@ -128,6 +138,33 @@ def detail_format(subcloud=None): if subcloud.region_name is not None: columns += ('region_name',) data += (subcloud.region_name,) + + return columns, data + + +def detail_prestage_format(subcloud=None): + columns, data = detail_format(subcloud) + + if subcloud and subcloud.prestage_software_version: + columns += ('prestage_software_version',) + data += (subcloud.prestage_software_version,) + + return columns, data + + +def detail_list_format(subcloud=None): + columns, data = basic_detail_format(subcloud) + + # Find the index of 'deploy_status' in the tuple + deploy_status_index = columns.index('deploy_status') + + # Insert "sync" field after 'deploy_status' + columns = columns[:deploy_status_index + 1] + ("sync",) + \ + columns[deploy_status_index + 1:] + + if subcloud: + data = data[:deploy_status_index + 1] + (subcloud.sync_status,) + \ + data[deploy_status_index + 1:] else: data = (tuple('' for _ in range(len(columns))),) @@ -306,8 +343,18 @@ class AddSubcloud(base.DCManagerShowOne): class ListSubcloud(base.DCManagerLister): """List subclouds.""" + def __init__(self, app, app_args): + super(ListSubcloud, self).__init__(app, app_args) + # Set a flag to indicate displaying a basic column list or + # a list with customized or all columns + self.show_basic_list = True + + def _validate_parsed_args(self, parsed_args): + self.show_basic_list = \ + False if parsed_args.columns or parsed_args.detail else True + def _get_format_function(self): - return format + return format if self.show_basic_list else detail_list_format def get_parser(self, prog_name): parser = super(ListSubcloud, self).get_parser(prog_name) @@ -317,6 +364,12 @@ class ListSubcloud(base.DCManagerLister): action='store_true', help='List all subclouds include "secondary" state subclouds' ) + parser.add_argument( + '-d', '--detail', + required=False, + action='store_true', + help="List all columns of the subclouds" + ) return parser def _get_resources(self, parsed_args): @@ -894,7 +947,7 @@ class PrestageSubcloud(base.DCManagerShowOne): """Prestage a subcloud.""" def _get_format_function(self): - return detail_format + return detail_prestage_format def get_parser(self, prog_name): parser = super(PrestageSubcloud, self).get_parser(prog_name) diff --git a/distributedcloud-client/dcmanagerclient/tests/base.py b/distributedcloud-client/dcmanagerclient/tests/base.py index db8f56d..c1e27ce 100644 --- a/distributedcloud-client/dcmanagerclient/tests/base.py +++ b/distributedcloud-client/dcmanagerclient/tests/base.py @@ -1,6 +1,6 @@ # Copyright 2013 - Mirantis, Inc. # Copyright 2016 - Ericsson AB. -# Copyright (c) 2017-2021 Wind River Systems, Inc. +# Copyright (c) 2017-2024 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. @@ -56,6 +56,9 @@ SUBCLOUD_PEERGROUP_ID = None SUBCLOUD_REHOME_DATA = None BACKUP_STATUS = 'None' BACKUP_DATETIME = 'None' +PRESTAGE_STATUS = 'None' +PRESTAGE_VERSIONS = None +SYNC = None # Useful for subcloud name configuration NAME_SC2 = "subcloud2" @@ -84,7 +87,9 @@ SUBCLOUD_RESOURCE = api_base.Subcloud( updated_at=TIME_NOW, group_id=DEFAULT_SUBCLOUD_GROUP_ID, backup_status=BACKUP_STATUS, - backup_datetime=BACKUP_DATETIME) + backup_datetime=BACKUP_DATETIME, + prestage_status=PRESTAGE_STATUS, + prestage_versions=PRESTAGE_VERSIONS) # Subcloud CLI resource object with peerid rehome data SUBCLOUD_RESOURCE_WITH_PEERID = api_base.Subcloud( @@ -107,7 +112,35 @@ SUBCLOUD_RESOURCE_WITH_PEERID = api_base.Subcloud( created_at=TIME_NOW, updated_at=TIME_NOW, backup_status=BACKUP_STATUS, - backup_datetime=BACKUP_DATETIME) + backup_datetime=BACKUP_DATETIME, + prestage_status=PRESTAGE_STATUS, + prestage_versions=PRESTAGE_VERSIONS) + +# Subcloud CLI resource object with all list fields +SUBCLOUD_RESOURCE_WITH_ALL_LIST_FIELDS = 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, + sync_status=SYNC, + 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, + peer_group_id=SUBCLOUD_PEERGROUP_ID, + created_at=TIME_NOW, + updated_at=TIME_NOW, + backup_status=BACKUP_STATUS, + backup_datetime=BACKUP_DATETIME, + prestage_status=PRESTAGE_STATUS, + prestage_versions=PRESTAGE_VERSIONS) # Subcloud result values returned from various API calls (e.g. subcloud show) SUBCLOUD_FIELD_RESULT_LIST = ( @@ -151,13 +184,26 @@ SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID = ( TIME_NOW, TIME_NOW, BACKUP_STATUS, - BACKUP_DATETIME + BACKUP_DATETIME, + PRESTAGE_STATUS, + PRESTAGE_VERSIONS ) EMPTY_SUBCLOUD_FIELD_RESULT = (('',) * len(SUBCLOUD_FIELD_RESULT_LIST),) EMPTY_SUBCLOUD_FIELD_RESULT_WITH_PEERID_REHOME_DATA = \ (('',) * len(SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID),) +# Create subcloud all fields based on SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID +# and add an additional "sync" field +DEPLOY_STATUS_IDX = SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID.index(DEPLOY_STATUS) +SUBCLOUD_ALL_FIELDS_RESULT_LIST = \ + SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID[:DEPLOY_STATUS_IDX + 1] + \ + (SYNC,) + \ + SUBCLOUD_FIELD_RESULT_LIST_WITH_PEERID[DEPLOY_STATUS_IDX + 1:] + +EMPTY_SUBCLOUD_ALL_FIELDS_RESULT = \ + (('',) * len(SUBCLOUD_ALL_FIELDS_RESULT_LIST),) + # Subcloud result values returned from subcloud list command SUBCLOUD_LIST_RESULT = ( ID, @@ -167,7 +213,7 @@ SUBCLOUD_LIST_RESULT = ( DEPLOY_STATUS, SYNC_STATUS, BACKUP_STATUS, - BACKUP_DATETIME + PRESTAGE_STATUS ) EMPTY_SUBCLOUD_LIST_RESULT = (('',) * len(SUBCLOUD_LIST_RESULT),) @@ -187,7 +233,9 @@ FAKE_BOOTSTRAP_VALUES = { 'backup_status': BACKUP_STATUS, 'backup_datetime': BACKUP_DATETIME, 'backup_status': BACKUP_STATUS, - 'backup_datetime': BACKUP_DATETIME + 'backup_datetime': BACKUP_DATETIME, + 'prestage_status': PRESTAGE_STATUS, + 'prestage_versions': PRESTAGE_VERSIONS } FAKE_INSTALL_VALUES = { @@ -268,12 +316,13 @@ class BaseCommandTest(testtools.TestCase): super(BaseCommandTest, self).setUp() self.app = mock.Mock() self.client = self.app.client_manager.subcloud_manager + self.parsed_args = None def call(self, command, app_args=None, prog_name=''): if app_args is None: app_args = [] cmd = command(self.app, app_args) - parsed_args = cmd.get_parser(prog_name).parse_args(app_args) + self.parsed_args = cmd.get_parser(prog_name).parse_args(app_args) - return cmd.take_action(parsed_args) + return cmd.take_action(self.parsed_args) diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py index 7703112..bc752c2 100644 --- a/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_subcloud_manager.py @@ -40,6 +40,30 @@ class TestCLISubcloudManagerV1(base.BaseCommandTest): self.assertEqual(base.EMPTY_SUBCLOUD_LIST_RESULT, actual_call[1]) + def test_list_subclouds_with_all_fields(self): + self.client.subcloud_manager.list_subclouds.return_value = \ + [base.SUBCLOUD_RESOURCE_WITH_ALL_LIST_FIELDS] + actual_call = self.call(subcloud_cmd.ListSubcloud, app_args=['-d']) + self.assertEqual([base.SUBCLOUD_ALL_FIELDS_RESULT_LIST], + actual_call[1]) + + def test_list_subclouds_with_all_empty_fields(self): + self.client.subcloud_manager.list_subclouds.return_value = [] + actual_call = self.call(subcloud_cmd.ListSubcloud, + app_args=['--detail']) + self.assertEqual(base.EMPTY_SUBCLOUD_ALL_FIELDS_RESULT, + actual_call[1]) + + def test_list_subclouds_with_specified_columns(self): + self.client.subcloud_manager.list_subclouds.return_value = \ + [base.SUBCLOUD_RESOURCE_WITH_ALL_LIST_FIELDS] + self.call(subcloud_cmd.ListSubcloud, + app_args=['-c', 'name', + '-c', 'prestage_status', + '-c', 'prestage_versions']) + self.assertEqual(self.parsed_args.columns, + ['name', 'prestage_status', 'prestage_versions']) + def test_delete_subcloud_with_subcloud_id(self): self.call(subcloud_cmd.DeleteSubcloud, app_args=[base.ID]) self.client.subcloud_manager.delete_subcloud.\ diff --git a/distributedcloud-client/dcmanagerclient/utils.py b/distributedcloud-client/dcmanagerclient/utils.py index 9f5c3f6..6312238 100644 --- a/distributedcloud-client/dcmanagerclient/utils.py +++ b/distributedcloud-client/dcmanagerclient/utils.py @@ -1,7 +1,7 @@ # Copyright 2016 - Ericsson AB # Copyright 2015 - Huawei Technologies Co. Ltd # Copyright 2015 - StackStorm, Inc. -# Copyright (c) 2017-2023 Wind River Systems, Inc. +# Copyright (c) 2017-2024 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. @@ -124,7 +124,9 @@ def subcloud_detail_format(subcloud=None): 'created_at', 'updated_at', 'backup_status', - 'backup_datetime' + 'backup_datetime', + 'prestage_status', + 'prestage_versions' ) if subcloud: @@ -147,7 +149,9 @@ def subcloud_detail_format(subcloud=None): subcloud.created_at, subcloud.updated_at, subcloud.backup_status, - subcloud.backup_datetime + subcloud.backup_datetime, + subcloud.prestage_status, + subcloud.prestage_versions ) for _listitem, sync_status in enumerate(subcloud.endpoint_sync_status):