From 094e5189b7bd4a84b124d17a7c70e4f9aaf7ebc7 Mon Sep 17 00:00:00 2001
From: "zhiyong.dai" <zhiyong.dai@easystack.cn>
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]
+        <consistency-group> [<consistency-group> ...]
+
+.. option:: --force
+
+    Allow delete in state other than error or available
+
+.. _consistency_group_delete-consistency-group:
+.. describe:: <consistency-group>
+
+    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='<consistency-group>',
+            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 <https://bugs.launchpad.net/python-openstackclient/+bug/1613964>`_]
+  - Add ``consistency group delete`` command in volume v2.
+    [Bug `1613964 <https://bugs.launchpad.net/python-openstackclient/+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