From 094e5189b7bd4a84b124d17a7c70e4f9aaf7ebc7 Mon Sep 17 00:00:00 2001 From: "zhiyong.dai" Date: Thu, 24 Nov 2016 21:09:55 +0800 Subject: [PATCH] Add "consistency group delete" command Add "consistency group delete" command in volume v2 (v2 only). Change-Id: Ieebc2417df0d45a578d5617bad245d7863f09190 Implements: bp cinder-command-support Partial-Bug: #1613964 --- .../command-objects/consistency-group.rst | 21 ++++ openstackclient/tests/unit/volume/v2/fakes.py | 24 +++++ .../unit/volume/v2/test_consistency_group.py | 101 ++++++++++++++++++ .../volume/v2/consistency_group.py | 45 ++++++++ .../notes/bug-1613964-837196399be16b3d.yaml | 2 + setup.cfg | 1 + 6 files changed, 194 insertions(+) diff --git a/doc/source/command-objects/consistency-group.rst b/doc/source/command-objects/consistency-group.rst index c8c4577ccf..3ab68e90d7 100644 --- a/doc/source/command-objects/consistency-group.rst +++ b/doc/source/command-objects/consistency-group.rst @@ -40,6 +40,27 @@ Create new consistency group. Name of new consistency group (default to None) +consistency group delete +------------------------ + +Delete consistency group(s). + +.. program:: consistency group delete +.. code:: bash + + os consistency group delete + [--force] + [ ...] + +.. option:: --force + + Allow delete in state other than error or available + +.. _consistency_group_delete-consistency-group: +.. describe:: + + Consistency group(s) to delete (name or ID) + consistency group list ---------------------- diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py index 41d8e79475..3137bfb012 100644 --- a/openstackclient/tests/unit/volume/v2/fakes.py +++ b/openstackclient/tests/unit/volume/v2/fakes.py @@ -546,6 +546,30 @@ class FakeConsistencyGroup(object): return consistency_groups + @staticmethod + def get_consistency_groups(consistency_groups=None, count=2): + """Note: + + Get an iterable MagicMock object with a list of faked + consistency_groups. + + If consistency_groups list is provided, then initialize + the Mock object with the list. Otherwise create one. + + :param List consistency_groups: + A list of FakeResource objects faking consistency_groups + :param Integer count: + The number of consistency_groups to be faked + :return + An iterable Mock object with side_effect set to a list of faked + consistency_groups + """ + if consistency_groups is None: + consistency_groups = (FakeConsistencyGroup. + create_consistency_groups(count)) + + return mock.Mock(side_effect=consistency_groups) + class FakeConsistencyGroupSnapshot(object): """Fake one or more consistency group snapshot.""" diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group.py b/openstackclient/tests/unit/volume/v2/test_consistency_group.py index e005642169..835d996024 100644 --- a/openstackclient/tests/unit/volume/v2/test_consistency_group.py +++ b/openstackclient/tests/unit/volume/v2/test_consistency_group.py @@ -12,6 +12,10 @@ # under the License. # +import mock +from mock import call + +from osc_lib import exceptions from osc_lib import utils from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes @@ -161,6 +165,103 @@ class TestConsistencyGroupCreate(TestConsistencyGroup): self.assertEqual(self.data, data) +class TestConsistencyGroupDelete(TestConsistencyGroup): + + consistency_groups =\ + volume_fakes.FakeConsistencyGroup.create_consistency_groups(count=2) + + def setUp(self): + super(TestConsistencyGroupDelete, self).setUp() + + self.consistencygroups_mock.get = volume_fakes.FakeConsistencyGroup.\ + get_consistency_groups(self.consistency_groups) + self.consistencygroups_mock.delete.return_value = None + + # Get the command object to mock + self.cmd = consistency_group.DeleteConsistencyGroup(self.app, None) + + def test_consistency_group_delete(self): + arglist = [ + self.consistency_groups[0].id + ] + verifylist = [ + ("consistency_groups", [self.consistency_groups[0].id]) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.consistencygroups_mock.delete.assert_called_with( + self.consistency_groups[0].id, False) + self.assertIsNone(result) + + def test_consistency_group_delete_with_force(self): + arglist = [ + '--force', + self.consistency_groups[0].id, + ] + verifylist = [ + ('force', True), + ("consistency_groups", [self.consistency_groups[0].id]) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.consistencygroups_mock.delete.assert_called_with( + self.consistency_groups[0].id, True) + self.assertIsNone(result) + + def test_delete_multiple_consistency_groups(self): + arglist = [] + for b in self.consistency_groups: + arglist.append(b.id) + verifylist = [ + ('consistency_groups', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + + calls = [] + for b in self.consistency_groups: + calls.append(call(b.id, False)) + self.consistencygroups_mock.delete.assert_has_calls(calls) + self.assertIsNone(result) + + def test_delete_multiple_consistency_groups_with_exception(self): + arglist = [ + self.consistency_groups[0].id, + 'unexist_consistency_group', + ] + verifylist = [ + ('consistency_groups', arglist), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + find_mock_result = [self.consistency_groups[0], + exceptions.CommandError] + with mock.patch.object(utils, 'find_resource', + side_effect=find_mock_result) as find_mock: + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except exceptions.CommandError as e: + self.assertEqual('1 of 2 consistency groups failed to delete.', + str(e)) + + find_mock.assert_any_call(self.consistencygroups_mock, + self.consistency_groups[0].id) + find_mock.assert_any_call(self.consistencygroups_mock, + 'unexist_consistency_group') + + self.assertEqual(2, find_mock.call_count) + self.consistencygroups_mock.delete.assert_called_once_with( + self.consistency_groups[0].id, False + ) + + class TestConsistencyGroupList(TestConsistencyGroup): consistency_groups = ( diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py index 9316f28737..a90091a69b 100644 --- a/openstackclient/volume/v2/consistency_group.py +++ b/openstackclient/volume/v2/consistency_group.py @@ -17,11 +17,56 @@ import logging from osc_lib.command import command +from osc_lib import exceptions from osc_lib import utils import six from openstackclient.i18n import _ +LOG = logging.getLogger(__name__) + + +class DeleteConsistencyGroup(command.Command): + _description = _("Delete consistency group(s).") + + def get_parser(self, prog_name): + parser = super(DeleteConsistencyGroup, self).get_parser(prog_name) + parser.add_argument( + 'consistency_groups', + metavar='', + nargs="+", + help=_('Consistency group(s) to delete (name or ID)'), + ) + parser.add_argument( + '--force', + action='store_true', + default=False, + help=_("Allow delete in state other than error or available"), + ) + return parser + + def take_action(self, parsed_args): + volume_client = self.app.client_manager.volume + result = 0 + + for i in parsed_args.consistency_groups: + try: + consistency_group_id = utils.find_resource( + volume_client.consistencygroups, i).id + volume_client.consistencygroups.delete( + consistency_group_id, parsed_args.force) + except Exception as e: + result += 1 + LOG.error(_("Failed to delete consistency group with " + "name or ID '%(consistency_group)s':%(e)s") + % {'consistency_group': i, 'e': e}) + + if result > 0: + total = len(parsed_args.consistency_groups) + msg = (_("%(result)s of %(total)s consistency groups failed " + "to delete.") % {'result': result, 'total': total}) + raise exceptions.CommandError(msg) + LOG = logging.getLogger(__name__) diff --git a/releasenotes/notes/bug-1613964-837196399be16b3d.yaml b/releasenotes/notes/bug-1613964-837196399be16b3d.yaml index 0f17930ebb..1d404af5b2 100644 --- a/releasenotes/notes/bug-1613964-837196399be16b3d.yaml +++ b/releasenotes/notes/bug-1613964-837196399be16b3d.yaml @@ -2,3 +2,5 @@ features: - Add ``consistency group create`` command in volume v2. [Bug `1613964 `_] + - Add ``consistency group delete`` command in volume v2. + [Bug `1613964 `_] diff --git a/setup.cfg b/setup.cfg index 871a3dbe00..a42af75fb3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -509,6 +509,7 @@ openstack.volume.v2 = backup_show = openstackclient.volume.v2.backup:ShowBackup consistency_group_create = openstackclient.volume.v2.consistency_group:CreateConsistencyGroup + consistency_group_delete = openstackclient.volume.v2.consistency_group:DeleteConsistencyGroup consistency_group_list = openstackclient.volume.v2.consistency_group:ListConsistencyGroup consistency_group_snapshot_create = openstackclient.volume.v2.consistency_group_snapshot:CreateConsistencyGroupSnapshot