From c2fa09cfe85a33ab2233c3735d2eff8541850cdd Mon Sep 17 00:00:00 2001 From: Victor Romano Date: Mon, 5 Jun 2023 22:21:21 -0300 Subject: [PATCH] Add subcloud deploy abort option to dcmanager This commit adds the command "subcloud deploy abort" to dcmanager client. Usage: dcmanager subcloud deploy abort Test Plan: - PASS: Verify the command is succesfully passed to the backend - PASS: Verify that the dcmanager help subcloud deploy abort shows the correct help message containing all options. Story: 2010756 Task: 48103 Depends-on: https://review.opendev.org/c/starlingx/distcloud/+/884710 Signed-off-by: Victor Romano Change-Id: I20e4b7be84e1cacae7f66fc8571dab4715966cdc --- .../api/v1/phased_subcloud_deploy_manager.py | 12 ++++++-- .../v1/phased_subcloud_deploy_manager.py | 30 +++++++++++++++++++ .../dcmanagerclient/shell.py | 1 + .../tests/v1/test_phased_subcloud_deploy.py | 26 ++++++++-------- 4 files changed, 55 insertions(+), 14 deletions(-) diff --git a/distributedcloud-client/dcmanagerclient/api/v1/phased_subcloud_deploy_manager.py b/distributedcloud-client/dcmanagerclient/api/v1/phased_subcloud_deploy_manager.py index c366157..fe081f4 100644 --- a/distributedcloud-client/dcmanagerclient/api/v1/phased_subcloud_deploy_manager.py +++ b/distributedcloud-client/dcmanagerclient/api/v1/phased_subcloud_deploy_manager.py @@ -24,7 +24,7 @@ class phased_subcloud_deploy_manager(base.ResourceManager): raise ValueError("Invalid request method: %s" % method) return getattr(self.http_client, method)(url, body, headers) - def _deploy_operation(self, url, body, data, method="post"): + def _deploy_operation(self, url, body, data, method='post'): fields = dict() for k, v in body.items(): fields.update({k: (v, open(v, 'rb'),)}) @@ -53,10 +53,18 @@ class phased_subcloud_deploy_manager(base.ResourceManager): data = kwargs.get('data') files = kwargs.get('files') url = BASE_URL + "%s/bootstrap" % subcloud_ref - return self._deploy_operation(url, files, data, "patch") + return self._deploy_operation(url, files, data, method='patch') def subcloud_deploy_config(self, subcloud_ref, **kwargs): data = kwargs.get('data') files = kwargs.get('files') url = BASE_URL + "%s/configure" % subcloud_ref return self._deploy_operation(url, files, data, method='patch') + + def subcloud_deploy_abort(self, subcloud_ref, **kwargs): + # Currently it's not passed neither data or files to abort, + # so we pass an empty dict to use the _deploy_operation function + data = kwargs.get('data', {}) + files = kwargs.get('files', {}) + url = BASE_URL + "%s/abort" % subcloud_ref + return self._deploy_operation(url, files, data, method='patch') diff --git a/distributedcloud-client/dcmanagerclient/commands/v1/phased_subcloud_deploy_manager.py b/distributedcloud-client/dcmanagerclient/commands/v1/phased_subcloud_deploy_manager.py index b390ea3..3aec06c 100644 --- a/distributedcloud-client/dcmanagerclient/commands/v1/phased_subcloud_deploy_manager.py +++ b/distributedcloud-client/dcmanagerclient/commands/v1/phased_subcloud_deploy_manager.py @@ -12,6 +12,36 @@ from dcmanagerclient import exceptions from dcmanagerclient import utils +class AbortPhasedSubcloudDeploy(base.DCManagerShowOne): + """Abort the subcloud deploy phase.""" + + def _get_format_function(self): + return utils.subcloud_detail_format + + def get_parser(self, prog_name): + parser = super(AbortPhasedSubcloudDeploy, self).get_parser(prog_name) + + parser.add_argument( + 'subcloud', + help='Name or ID of the subcloud to abort the on-going deployment.' + ) + + return parser + + def _get_resources(self, parsed_args): + subcloud_ref = parsed_args.subcloud + dcmanager_client = self.app.client_manager.\ + phased_subcloud_deploy_manager.phased_subcloud_deploy_manager + + try: + return dcmanager_client.subcloud_deploy_abort( + subcloud_ref=subcloud_ref) + except Exception as e: + print(e) + error_msg = "Unable to abort subcloud deploy %s" % (subcloud_ref) + raise exceptions.DCManagerClientException(error_msg) + + class CreatePhasedSubcloudDeploy(base.DCManagerShowOne): """Creates a new subcloud.""" diff --git a/distributedcloud-client/dcmanagerclient/shell.py b/distributedcloud-client/dcmanagerclient/shell.py index fa0ae90..09dd77c 100644 --- a/distributedcloud-client/dcmanagerclient/shell.py +++ b/distributedcloud-client/dcmanagerclient/shell.py @@ -544,6 +544,7 @@ class DCManagerShell(app.App): 'subcloud-group list-subclouds': gm.ListSubcloudGroupSubclouds, 'subcloud-group show': gm.ShowSubcloudGroup, 'subcloud-group update': gm.UpdateSubcloudGroup, + 'subcloud deploy abort': psdm.AbortPhasedSubcloudDeploy, 'subcloud deploy create': psdm.CreatePhasedSubcloudDeploy, 'subcloud deploy bootstrap': psdm.BootstrapPhasedSubcloudDeploy, 'subcloud deploy config': psdm.ConfigPhasedSubcloudDeploy, diff --git a/distributedcloud-client/dcmanagerclient/tests/v1/test_phased_subcloud_deploy.py b/distributedcloud-client/dcmanagerclient/tests/v1/test_phased_subcloud_deploy.py index 639ee4b..8bc3858 100644 --- a/distributedcloud-client/dcmanagerclient/tests/v1/test_phased_subcloud_deploy.py +++ b/distributedcloud-client/dcmanagerclient/tests/v1/test_phased_subcloud_deploy.py @@ -61,8 +61,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): ]) self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1]) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_install_subcloud(self, getpass): + def test_install_subcloud(self): self.client.subcloud_deploy_install.return_value = [ base.SUBCLOUD_RESOURCE] @@ -75,8 +74,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): ]) self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1]) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_install_subcloud_with_release(self, getpass): + def test_install_subcloud_with_release(self): self.client.subcloud_deploy_install.return_value = [ base.SUBCLOUD_RESOURCE] @@ -91,8 +89,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): ]) self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1]) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_install_subcloud_without_install_values(self, getpass): + def test_install_subcloud_without_install_values(self): self.client.subcloud_deploy_install.return_value = [ base.SUBCLOUD_RESOURCE] @@ -101,8 +98,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1]) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_install_file_does_not_exist(self, getpass): + def test_install_file_does_not_exist(self): self.client.subcloud_deploy_install.return_value = [ base.SUBCLOUD_RESOURCE] with tempfile.NamedTemporaryFile() as f: @@ -117,8 +113,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): self.assertTrue('install-values does not exist' in str(e)) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_success_configure_subcloud(self, getpass): + def test_configure_subcloud(self): self.client.subcloud_deploy_config.return_value = [ base.SUBCLOUD_RESOURCE] @@ -129,8 +124,7 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): app_args=[base.NAME, '--deploy-config', file_path]) self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1]) - @mock.patch('getpass.getpass', return_value='testpassword') - def test_configure_file_does_not_exist(self, getpass): + def test_configure_file_does_not_exist(self): self.client.subcloud_deploy_config.return_value = [ base.SUBCLOUD_RESOURCE] @@ -143,3 +137,11 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest): app_args=[base.NAME, '--deploy-config', file_path]) self.assertTrue('deploy-config file does not exist' in str(e)) + + def test_abort_subcloud(self): + self.client.subcloud_deploy_abort.return_value = [ + base.SUBCLOUD_RESOURCE] + actual_call = self.call( + cmd.AbortPhasedSubcloudDeploy, + app_args=[base.NAME]) + self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])