From 8122ea75d02991bcf9b0119d5bba472c83ba688a Mon Sep 17 00:00:00 2001 From: "Zhang Rong(Jon)" Date: Thu, 3 Aug 2023 22:49:12 +0800 Subject: [PATCH] Add system peer management API support Add dcmanager system-peer management api. Test Plan: 1. PASS - Verify that cloud manage system-peer through api successfully. 2. PASS - Run the add command without providing the password and verify that the CLI asks for it. 3. PASS - Run the add with every possible parameter and verify all of them were successfully passed to the backend. 4. PASS - Verify dcmanager help output the correct help messages for each command. CLI example: dcmanager system-peer add --peer-uuid 800503ca-21c1-40b2-9425-88319185fe61 --peer-name dc-0 --manager-endpoint http://128.128.128.1:5000/v3 --peer-controller-gateway-address 192.168.205.1 (peer's uuid from the peer site `system show` command) dcmanager system-peer list dcmanager system-peer update --administrative-state enabled 1 dcmanager system-peer show 1 dcmanager system-peer delete 1 Story: 2010852 Task: 48487 Depends-On: I349cd24bccc732eb8ed56df9346185cfce7b2570 Change-Id: I7ea22991d8ea879af7401e10b058e7ee44cd6a8d Signed-off-by: Zhang Rong(Jon) --- .../dcmanagerclient/api/v1/client.py | 2 + .../api/v1/system_peer_manager.py | 131 ++++++ .../commands/v1/system_peer_manager.py | 419 ++++++++++++++++++ .../dcmanagerclient/shell.py | 7 + .../tests/v1/test_system_peer_manager.py | 190 ++++++++ .../dcmanagerclient/utils.py | 6 +- 6 files changed, 752 insertions(+), 3 deletions(-) create mode 100644 distributedcloud-client/dcmanagerclient/api/v1/system_peer_manager.py create mode 100644 distributedcloud-client/dcmanagerclient/commands/v1/system_peer_manager.py create mode 100644 distributedcloud-client/dcmanagerclient/tests/v1/test_system_peer_manager.py diff --git a/distributedcloud-client/dcmanagerclient/api/v1/client.py b/distributedcloud-client/dcmanagerclient/api/v1/client.py index 99b57de..4903d73 100644 --- a/distributedcloud-client/dcmanagerclient/api/v1/client.py +++ b/distributedcloud-client/dcmanagerclient/api/v1/client.py @@ -37,6 +37,7 @@ from dcmanagerclient.api.v1 import sw_prestage_manager as spr from dcmanagerclient.api.v1 import sw_strategy_manager as sstm from dcmanagerclient.api.v1 import sw_update_options_manager as suom from dcmanagerclient.api.v1 import sw_upgrade_manager as supm +from dcmanagerclient.api.v1 import system_peer_manager as sp _DEFAULT_DCMANAGER_URL = "http://localhost:8119/v1.0" @@ -103,6 +104,7 @@ class Client(object): self.http_client) self.subcloud_deploy_manager = sdm.subcloud_deploy_manager( self.http_client) + self.system_peer_manager = sp.system_peer_manager(self.http_client) self.alarm_manager = am.alarm_manager(self.http_client) self.fw_update_manager = fum.fw_update_manager(self.http_client) self.kube_rootca_update_manager = \ diff --git a/distributedcloud-client/dcmanagerclient/api/v1/system_peer_manager.py b/distributedcloud-client/dcmanagerclient/api/v1/system_peer_manager.py new file mode 100644 index 0000000..ee6c4f2 --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/api/v1/system_peer_manager.py @@ -0,0 +1,131 @@ +# Copyright (c) 2023 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import json + +from dcmanagerclient.api import base +from dcmanagerclient.api.base import get_json + +BASE_URL = '/system-peers/' + + +class SystemPeer(base.Resource): + resource_name = 'system_peer' + + def __init__(self, + manager, + peer_id, + peer_uuid, + peer_name, + manager_endpoint, + manager_username, + peer_controller_gateway_address, + administrative_state, + heartbeat_interval, + heartbeat_failure_threshold, + heartbeat_failure_policy, + heartbeat_maintenance_timeout, + created_at, + updated_at): + self.manager = manager + self.peer_id = peer_id + self.peer_uuid = peer_uuid + self.peer_name = peer_name + self.manager_endpoint = manager_endpoint + self.manager_username = manager_username + self.gateway_address = peer_controller_gateway_address + self.administrative_state = administrative_state + self.heartbeat_interval = heartbeat_interval + self.heartbeat_failure_threshold = heartbeat_failure_threshold + self.heartbeat_failure_policy = heartbeat_failure_policy + self.heartbeat_maintenance_timeout = heartbeat_maintenance_timeout + self.created_at = created_at + self.updated_at = updated_at + + +class system_peer_manager(base.ResourceManager): + resource_class = SystemPeer + + def _json_to_resource(self, json_object): + return self.resource_class( + self, + peer_id=json_object['id'], + peer_uuid=json_object['peer-uuid'], + peer_name=json_object['peer-name'], + manager_endpoint=json_object['manager-endpoint'], + manager_username=json_object['manager-username'], + peer_controller_gateway_address=json_object[ + 'peer-controller-gateway-address'], + administrative_state=json_object['administrative-state'], + heartbeat_interval=json_object['heartbeat-interval'], + heartbeat_failure_threshold=json_object[ + 'heartbeat-failure-threshold'], + heartbeat_failure_policy=json_object['heartbeat-failure-policy'], + heartbeat_maintenance_timeout=json_object[ + 'heartbeat-maintenance-timeout'], + created_at=json_object['created-at'], + updated_at=json_object['updated-at']) + + def system_peer_create(self, url, data): + data = json.dumps(data) + resp = self.http_client.post(url, data) + if resp.status_code != 200: + self._raise_api_exception(resp) + json_object = get_json(resp) + resource = list() + resource.append(self._json_to_resource(json_object)) + return resource + + def system_peer_update(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) + resource = list() + resource.append(self._json_to_resource(json_object)) + return resource + + def system_peer_list(self, url): + resp = self.http_client.get(url) + if resp.status_code != 200: + self._raise_api_exception(resp) + json_response_key = get_json(resp) + json_objects = json_response_key['system_peers'] + resource = list() + for json_object in json_objects: + resource.append(self._json_to_resource(json_object)) + return resource + + def _system_peer_detail(self, url): + resp = self.http_client.get(url) + if resp.status_code != 200: + self._raise_api_exception(resp) + json_object = get_json(resp) + resource = list() + resource.append(self._json_to_resource(json_object)) + return resource + + def add_system_peer(self, **kwargs): + data = kwargs + url = BASE_URL + return self.system_peer_create(url, data) + + def list_system_peers(self): + url = BASE_URL + return self.system_peer_list(url) + + def system_peer_detail(self, system_peer_ref): + url = BASE_URL + system_peer_ref + return self._system_peer_detail(url) + + def delete_system_peer(self, system_peer_ref): + url = BASE_URL + system_peer_ref + return self._delete(url) + + def update_system_peer(self, system_peer_ref, **kwargs): + data = kwargs + url = BASE_URL + system_peer_ref + return self.system_peer_update(url, data) diff --git a/distributedcloud-client/dcmanagerclient/commands/v1/system_peer_manager.py b/distributedcloud-client/dcmanagerclient/commands/v1/system_peer_manager.py new file mode 100644 index 0000000..8514545 --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/commands/v1/system_peer_manager.py @@ -0,0 +1,419 @@ +# Copyright (c) 2023 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import base64 +from osc_lib.command import command + +from dcmanagerclient.commands.v1 import base +from dcmanagerclient import exceptions +from dcmanagerclient import utils + + +def peer_format(system_peer=None): + columns = ( + 'id', + 'peer uuid', + 'peer name', + 'manager endpoint', + 'controller gateway address' + ) + + if system_peer: + data = ( + system_peer.peer_id, + system_peer.peer_uuid, + system_peer.peer_name, + system_peer.manager_endpoint, + system_peer.gateway_address + ) + + else: + data = (tuple('' for _ in range(len(columns))),) + + return columns, data + + +def detail_peer_format(system_peer=None): + # Include all the fields in peer_format + # plus some additional fields + columns = ( + 'id', + 'peer uuid', + 'peer name', + 'manager endpoint', + 'manager username', + 'controller gateway address', + 'administrative state', + 'heartbeat interval', + 'heartbeat failure threshold', + 'heartbeat failure policy', + 'heartbeat maintenance timeout', + 'created_at', + 'updated_at', + ) + + if system_peer: + data = ( + system_peer.peer_id, + system_peer.peer_uuid, + system_peer.peer_name, + system_peer.manager_endpoint, + system_peer.manager_username, + system_peer.gateway_address, + system_peer.administrative_state, + system_peer.heartbeat_interval, + system_peer.heartbeat_failure_threshold, + system_peer.heartbeat_failure_policy, + system_peer.heartbeat_maintenance_timeout, + system_peer.created_at, + system_peer.updated_at, + ) + else: + data = (tuple('' for _ in range(len(columns))),) + + return columns, data + + +class AddSystemPeer(base.DCManagerShowOne): + """Add a new system peer.""" + + def _get_format_function(self): + return detail_peer_format + + def get_parser(self, prog_name): + parser = super(AddSystemPeer, self).get_parser(prog_name) + + parser.add_argument( + '--peer-uuid', + required=True, + help='UUID of the new system peer.' + ) + + parser.add_argument( + '--peer-name', + required=True, + help='Name for the new system peer.' + ) + + parser.add_argument( + '--manager-endpoint', + required=True, + help='URI of DC manager of peer System Controller.' + ) + + parser.add_argument( + '--peer-controller-gateway-address', + required=True, + help='Gateway address of peer site controller node.' + ) + + parser.add_argument( + '--manager-username', + required=False, + default='admin', + help='Administrative username (default admin).' + ) + + parser.add_argument( + '--manager-password', + required=False, + help='Admin user password for authenticating into the DC manager.' + ) + + parser.add_argument( + '--administrative-state', + required=False, + default='enabled', + help='Administrative control of peer state (enabled | disabled) \ + (default enabled).' + ) + + parser.add_argument( + '--heartbeat-interval', + required=False, + default=60, + help='Interval between heartbeat messages (in seconds) (default \ + 60).' + ) + + parser.add_argument( + '--heartbeat-failure-threshold', + required=False, + default=3, + help='Consecutive heartbeat failures before failure declared \ + (default 3).' + ) + + parser.add_argument( + '--heartbeat-failure-policy', + required=False, + default='alarm', + help='Action to take with failure detection \ + (alarm | rehome | delegate) (default alarm).' + ) + + parser.add_argument( + '--heartbeat-maintenance-timeout', + required=False, + default=600, + help='Overall failure timeout during maintenance state (in \ + seconds) (default 600).' + ) + return parser + + def _get_resources(self, parsed_args): + dcmanager_client = self.app.client_manager.system_peer_manager + kwargs = dict() + + if parsed_args.peer_uuid is not None: + kwargs['peer_uuid'] = parsed_args.peer_uuid + + if parsed_args.peer_name is not None: + kwargs['peer_name'] = parsed_args.peer_name + + if parsed_args.manager_endpoint is not None: + kwargs['manager_endpoint'] = parsed_args.manager_endpoint + + if parsed_args.manager_username is not None: + kwargs['manager_username'] = parsed_args.manager_username + + # Prompt the user for the peer's password if it isn't provided + if parsed_args.manager_password is not None: + kwargs['manager_password'] = base64.b64encode( + parsed_args.manager_password.encode("utf-8")).decode("utf-8") + else: + password = utils.prompt_for_password( + password_type=parsed_args.manager_username, + item_type='system peer') + kwargs["manager_password"] = base64.b64encode( + password.encode("utf-8")).decode("utf-8") + + if parsed_args.peer_controller_gateway_address is not None: + kwargs['peer_controller_gateway_address'] = \ + parsed_args.peer_controller_gateway_address + + if parsed_args.administrative_state is not None: + kwargs['administrative_state'] = parsed_args.administrative_state + + if parsed_args.heartbeat_interval is not None: + kwargs['heartbeat_interval'] = parsed_args.heartbeat_interval + + if parsed_args.heartbeat_failure_threshold is not None: + kwargs['heartbeat_failure_threshold'] = \ + parsed_args.heartbeat_failure_threshold + + if parsed_args.heartbeat_failure_policy is not None: + kwargs['heartbeat_failure_policy'] = \ + parsed_args.heartbeat_failure_policy + + if parsed_args.heartbeat_maintenance_timeout is not None: + kwargs['heartbeat_maintenance_timeout'] = \ + parsed_args.heartbeat_maintenance_timeout + return dcmanager_client.system_peer_manager.add_system_peer( + **kwargs) + + +class ListSystemPeer(base.DCManagerLister): + """List system peers.""" + + def _get_format_function(self): + return peer_format + + def get_parser(self, prog_name): + parser = super(ListSystemPeer, self).get_parser(prog_name) + return parser + + def _get_resources(self, parsed_args): + dcmanager_client = self.app.client_manager.system_peer_manager + return dcmanager_client.system_peer_manager.list_system_peers() + + +class ShowSystemPeer(base.DCManagerShowOne): + """Show the details of a system peer.""" + + def _get_format_function(self): + return detail_peer_format + + def get_parser(self, prog_name): + parser = super(ShowSystemPeer, self).get_parser(prog_name) + + parser.add_argument( + 'peer', + help='UUID or ID of system peer to view the details.' + ) + + return parser + + def _get_resources(self, parsed_args): + system_peer_ref = parsed_args.peer + dcmanager_client = self.app.client_manager.system_peer_manager + return dcmanager_client.system_peer_manager.\ + system_peer_detail(system_peer_ref) + + +class DeleteSystemPeer(command.Command): + """Delete system peer details from the database.""" + + def get_parser(self, prog_name): + parser = super(DeleteSystemPeer, self).get_parser(prog_name) + + parser.add_argument( + 'peer', + help='UUID or ID of the system peer to delete.' + ) + return parser + + def take_action(self, parsed_args): + system_peer_ref = parsed_args.peer + dcmanager_client = self.app.client_manager.system_peer_manager + try: + dcmanager_client.system_peer_manager.\ + delete_system_peer(system_peer_ref) + except Exception as e: + print(e) + msg = "Unable to delete system peer %s" % (system_peer_ref) + raise exceptions.DCManagerClientException(msg) + + +class UpdateSystemPeer(base.DCManagerShowOne): + """Update attributes of a system peer.""" + + def _get_format_function(self): + return detail_peer_format + + def get_parser(self, prog_name): + parser = super(UpdateSystemPeer, self).get_parser(prog_name) + + parser.add_argument( + 'peer', + help='UUID or ID of the system peer to update.' + ) + + parser.add_argument( + '--peer-uuid', + required=False, + help='UUID of the new system peer.' + ) + + parser.add_argument( + '--peer-name', + required=False, + help='Name for the new system peer.' + ) + + parser.add_argument( + '--manager-endpoint', + required=False, + help='URI of DC manager of peer System Controller.' + ) + + parser.add_argument( + '--manager-username', + required=False, + help='Administrative username (default admin).' + ) + + parser.add_argument( + '--manager-password', + required=False, + nargs='?', + const=True, + help='Admin user password for authenticating into the DC manager' + ) + + parser.add_argument( + '--peer-controller-gateway-address', + required=False, + help='Gateway address of peer site controller node.' + ) + + parser.add_argument( + '--administrative-state', + required=False, + help='Administrative control of peer state (enabled | disabled) \ + (default enabled).' + ) + + parser.add_argument( + '--heartbeat-interval', + required=False, + help='Interval between heartbeat messages (in seconds) (default \ + 60).' + ) + + parser.add_argument( + '--heartbeat-failure-threshold', + required=False, + help='Consecutive heartbeat failures before failure declared \ + (default 3).' + ) + + parser.add_argument( + '--heartbeat-failure-policy', + required=False, + help='Action to take with failure detection \ + (alarm | rehome | delegate) (default alarm).' + ) + + parser.add_argument( + '--heartbeat-maintenance-timeout', + required=False, + help='Overall failure timeout during maintenance state (in \ + seconds) (default 600).' + ) + + return parser + + def _get_resources(self, parsed_args): + system_peer_ref = parsed_args.peer + dcmanager_client = self.app.client_manager.system_peer_manager + kwargs = dict() + if parsed_args.peer_uuid: + kwargs['peer_uuid'] = parsed_args.peer_uuid + if parsed_args.peer_name: + kwargs['peer_name'] = parsed_args.peer_name + if parsed_args.manager_endpoint: + kwargs['manager_endpoint'] = parsed_args.manager_endpoint + if parsed_args.manager_username: + kwargs['manager_username'] = parsed_args.manager_username + if parsed_args.manager_password: + if parsed_args.manager_password is True: + password = utils.prompt_for_password( + password_type='update', + item_type='system peer') + kwargs["manager_password"] = base64.b64encode( + password.encode("utf-8")).decode("utf-8") + else: + kwargs['manager_password'] = base64.b64encode( + parsed_args.manager_password.encode( + "utf-8")).decode("utf-8") + if parsed_args.peer_controller_gateway_address: + kwargs['peer_controller_gateway_address'] = \ + parsed_args.peer_controller_gateway_address + if parsed_args.administrative_state: + kwargs['administrative_state'] = parsed_args.administrative_state + if parsed_args.heartbeat_interval: + kwargs['heartbeat_interval'] = parsed_args.heartbeat_interval + if parsed_args.heartbeat_failure_threshold: + kwargs['heartbeat_failure_threshold'] = \ + parsed_args.heartbeat_failure_threshold + if parsed_args.heartbeat_failure_policy: + kwargs['heartbeat_failure_policy'] = \ + parsed_args.heartbeat_failure_policy + if parsed_args.heartbeat_maintenance_timeout: + kwargs['heartbeat_maintenance_timeout'] = \ + parsed_args.heartbeat_maintenance_timeout + if len(kwargs) == 0: + error_msg = "Nothing to update" + raise exceptions.DCManagerClientException(error_msg) + + try: + return dcmanager_client. \ + system_peer_manager.update_system_peer( + system_peer_ref, **kwargs) + except Exception as e: + print(e) + msg = "Unable to update system peer %s" % (system_peer_ref) + raise exceptions.DCManagerClientException(msg) diff --git a/distributedcloud-client/dcmanagerclient/shell.py b/distributedcloud-client/dcmanagerclient/shell.py index c803e8c..8d4e085 100644 --- a/distributedcloud-client/dcmanagerclient/shell.py +++ b/distributedcloud-client/dcmanagerclient/shell.py @@ -46,6 +46,7 @@ from dcmanagerclient.commands.v1 import sw_prestage_manager as spr from dcmanagerclient.commands.v1 import sw_update_manager as sum from dcmanagerclient.commands.v1 import sw_update_options_manager as suom from dcmanagerclient.commands.v1 import sw_upgrade_manager as supm +from dcmanagerclient.commands.v1 import system_peer_manager as sp LOG = logging.getLogger(__name__) @@ -488,6 +489,7 @@ class DCManagerShell(app.App): subcloud_backup_manager=self.client, subcloud_group_manager=self.client, subcloud_deploy_manager=self.client, + system_peer_manager=self.client, alarm_manager=self.client, fw_update_manager=self.client, sw_patch_manager=self.client, @@ -555,6 +557,11 @@ class DCManagerShell(app.App): 'subcloud deploy show': sdm.SubcloudDeployShow, 'subcloud-deploy upload': sdm.DeprecatedSubcloudDeployUpload, 'subcloud-deploy show': sdm.DeprecatedSubcloudDeployShow, + 'system-peer add': sp.AddSystemPeer, + 'system-peer list': sp.ListSystemPeer, + 'system-peer show': sp.ShowSystemPeer, + 'system-peer update': sp.UpdateSystemPeer, + 'system-peer delete': sp.DeleteSystemPeer, 'alarm summary': am.ListAlarmSummary, 'fw-update-strategy create': fum.CreateFwUpdateStrategy, 'fw-update-strategy delete': fum.DeleteFwUpdateStrategy, diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_system_peer_manager.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_system_peer_manager.py new file mode 100644 index 0000000..1c9a770 --- /dev/null +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_system_peer_manager.py @@ -0,0 +1,190 @@ +# Copyright (c) 2023 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import copy +import mock + +from oslo_utils import timeutils + +from dcmanagerclient.api.v1 import system_peer_manager as spm +from dcmanagerclient.commands.v1 \ + import system_peer_manager as system_peer_cmd +from dcmanagerclient.tests import base + + +ID = '2' +SYSTEM_PEER_UUID = 'test1234-0dfd-46cd-9a93-e3c2b74ef20f' +SYSTEM_PEER_NAME = 'SystemPeer1' +MANAGER_ENDPOINT = 'http://127.0.0.1:5000' +MANAGER_USERNAME = 'admin' +MANAGER_PASSWORD = 'password' +ADMINISTRATIVE_STATE = 'enabled' +HEARTBEAT_INTERVAL = 10 +HEARTBEAT_FAILURE_THRESHOLD = 3 +HEARTBEAT_FAILURES_POLICY = 'alarm' +HEARTBEAT_MAINTENANCE_TIMEOUT = 600 +PEER_CONTROLLER_GATEWAY_IP = '128.128.128.1' +TIME_NOW = timeutils.utcnow().isoformat() +NEW_PEER_CONTROLLER_GATEWAY_IP = '128.1.1.1' + +SYSTEM_PEER_DICT = { + 'PEER_ID': ID, + 'PEER_UUID': SYSTEM_PEER_UUID, + 'PEER_NAME': SYSTEM_PEER_NAME, + 'MANAGER_ENDPOINT': MANAGER_ENDPOINT, + 'MANAGER_USERNAME': MANAGER_USERNAME, + 'ADMINISTRATIVE_STATE': ADMINISTRATIVE_STATE, + 'HEARTBEAT_INTERVAL': HEARTBEAT_INTERVAL, + 'HEARTBEAT_FAILURE_THRESHOLD': HEARTBEAT_FAILURE_THRESHOLD, + 'HEARTBEAT_FAILURE_POLICY': HEARTBEAT_FAILURES_POLICY, + 'HEARTBEAT_MAINTENANCE_TIMEOUT': HEARTBEAT_MAINTENANCE_TIMEOUT, + 'PEER_CONTROLLER_GATEWAY_IP': PEER_CONTROLLER_GATEWAY_IP, + 'CREATED_AT': TIME_NOW, + 'UPDATED_AT': TIME_NOW +} + + +SYSTEM_PEER = spm.SystemPeer( + mock, + peer_id=SYSTEM_PEER_DICT['PEER_ID'], + peer_name=SYSTEM_PEER_DICT['PEER_NAME'], + peer_uuid=SYSTEM_PEER_DICT['PEER_UUID'], + manager_endpoint=SYSTEM_PEER_DICT['MANAGER_ENDPOINT'], + manager_username=SYSTEM_PEER_DICT['MANAGER_USERNAME'], + administrative_state=SYSTEM_PEER_DICT['ADMINISTRATIVE_STATE'], + heartbeat_interval=SYSTEM_PEER_DICT['HEARTBEAT_INTERVAL'], + heartbeat_failure_threshold=SYSTEM_PEER_DICT[ + 'HEARTBEAT_FAILURE_THRESHOLD'], + heartbeat_failure_policy=SYSTEM_PEER_DICT['HEARTBEAT_FAILURE_POLICY'], + heartbeat_maintenance_timeout=SYSTEM_PEER_DICT[ + 'HEARTBEAT_MAINTENANCE_TIMEOUT'], + peer_controller_gateway_address=SYSTEM_PEER_DICT[ + 'PEER_CONTROLLER_GATEWAY_IP'], + created_at=SYSTEM_PEER_DICT['CREATED_AT'], + updated_at=SYSTEM_PEER_DICT['UPDATED_AT'] +) + + +class TestCLISystemPeerManagerV1(base.BaseCommandTest): + + def setUp(self): + super(TestCLISystemPeerManagerV1, self).setUp() + # The client is the system_peer_manager + self.client = self.app.client_manager.system_peer_manager + + def test_list_system_peers(self): + self.client.system_peer_manager.\ + list_system_peers.return_value = [SYSTEM_PEER] + actual_call = self.call(system_peer_cmd.ListSystemPeer) + self.assertEqual([(ID, SYSTEM_PEER_UUID, SYSTEM_PEER_NAME, + MANAGER_ENDPOINT, PEER_CONTROLLER_GATEWAY_IP)], + actual_call[1]) + + def test_list_system_peers_empty(self): + self.client.system_peer_manager.\ + list_system_peers.return_value = [] + actual_call = self.call(system_peer_cmd.ListSystemPeer) + self.assertEqual((tuple('' for _ in range(5)),), + actual_call[1]) + + def test_delete_system_peer_by_id(self): + self.call(system_peer_cmd.DeleteSystemPeer, app_args=[ID]) + self.client.system_peer_manager.delete_system_peer.\ + assert_called_once_with(ID) + + def test_delete_system_peer_without_id(self): + self.assertRaises(SystemExit, self.call, + system_peer_cmd.DeleteSystemPeer, app_args=[]) + + def test_show_system_peer_with_id(self): + self.client.system_peer_manager.system_peer_detail.\ + return_value = [SYSTEM_PEER] + actual_call = self.call(system_peer_cmd.ShowSystemPeer, + app_args=[ID]) + self.assertEqual((ID, + SYSTEM_PEER_UUID, + SYSTEM_PEER_NAME, + MANAGER_ENDPOINT, + MANAGER_USERNAME, + PEER_CONTROLLER_GATEWAY_IP, + ADMINISTRATIVE_STATE, + HEARTBEAT_INTERVAL, + HEARTBEAT_FAILURE_THRESHOLD, + HEARTBEAT_FAILURES_POLICY, + HEARTBEAT_MAINTENANCE_TIMEOUT, + TIME_NOW, + TIME_NOW), + actual_call[1]) + + def test_show_system_peer_without_id(self): + self.client.system_peer_manager.system_peer_detail.\ + return_value = [] + actual_call = self.call(system_peer_cmd.ShowSystemPeer, + app_args=[ID]) + self.assertEqual((tuple('' for _ in range(13)),), + actual_call[1]) + + def test_add_system_peer(self): + self.client.system_peer_manager.add_system_peer.\ + return_value = [SYSTEM_PEER] + + actual_call = self.call( + system_peer_cmd.AddSystemPeer, + app_args=['--peer-uuid', SYSTEM_PEER_UUID, + '--peer-name', SYSTEM_PEER_NAME, + '--manager-endpoint', MANAGER_ENDPOINT, + '--manager-username', MANAGER_USERNAME, + '--manager-password', MANAGER_PASSWORD, + '--heartbeat-interval', str(HEARTBEAT_INTERVAL), + '--heartbeat-failure-threshold', + str(HEARTBEAT_FAILURE_THRESHOLD), + '--heartbeat-failure-policy', + HEARTBEAT_FAILURES_POLICY, + '--heartbeat-maintenance-timeout', + str(HEARTBEAT_MAINTENANCE_TIMEOUT), + '--peer-controller-gateway-address', + PEER_CONTROLLER_GATEWAY_IP, + '--administrative-state', ADMINISTRATIVE_STATE] + ) + self.assertEqual((ID, + SYSTEM_PEER_UUID, + SYSTEM_PEER_NAME, + MANAGER_ENDPOINT, + MANAGER_USERNAME, + PEER_CONTROLLER_GATEWAY_IP, + ADMINISTRATIVE_STATE, + HEARTBEAT_INTERVAL, + HEARTBEAT_FAILURE_THRESHOLD, + HEARTBEAT_FAILURES_POLICY, + HEARTBEAT_MAINTENANCE_TIMEOUT, + TIME_NOW, + TIME_NOW), + actual_call[1]) + + def test_update_system_peer(self): + UPDATED_SYSTEM_PEER = copy.copy(SYSTEM_PEER) + UPDATED_SYSTEM_PEER.peer_controller_gateway_ip = \ + NEW_PEER_CONTROLLER_GATEWAY_IP + self.client.system_peer_manager.update_system_peer.\ + return_value = [UPDATED_SYSTEM_PEER] + actual_call = self.call( + system_peer_cmd.UpdateSystemPeer, + app_args=[SYSTEM_PEER.peer_id, + '--peer-controller-gateway-address', + NEW_PEER_CONTROLLER_GATEWAY_IP]) + self.assertEqual((ID, + SYSTEM_PEER_UUID, + SYSTEM_PEER_NAME, + MANAGER_ENDPOINT, + MANAGER_USERNAME, + PEER_CONTROLLER_GATEWAY_IP, + ADMINISTRATIVE_STATE, + HEARTBEAT_INTERVAL, + HEARTBEAT_FAILURE_THRESHOLD, + HEARTBEAT_FAILURES_POLICY, + HEARTBEAT_MAINTENANCE_TIMEOUT, + TIME_NOW, + TIME_NOW), + actual_call[1]) diff --git a/distributedcloud-client/dcmanagerclient/utils.py b/distributedcloud-client/dcmanagerclient/utils.py index 701ad3f..99b0f36 100644 --- a/distributedcloud-client/dcmanagerclient/utils.py +++ b/distributedcloud-client/dcmanagerclient/utils.py @@ -82,17 +82,17 @@ def get_contents_if_file(contents_or_file_name): "Error: Could not open file %s: %s" % (contents_or_file_name, e)) -def prompt_for_password(password_type='sysadmin'): +def prompt_for_password(password_type='sysadmin', item_type='subcloud'): while True: try: password = getpass.getpass( - "Enter the " + password_type + " password for the subcloud: ") + f"Enter the {password_type} password for the {item_type}: ") if len(password) < 1: print("Password cannot be empty") continue confirm = getpass.getpass( - "Re-enter " + password_type + " password to confirm: ") + f"Re-enter {password_type} password to confirm: ") if password != confirm: print("Passwords did not match") continue