summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/command-objects/volume-type.rst6
-rw-r--r--functional/tests/volume/v1/test_volume_type.py13
-rw-r--r--functional/tests/volume/v2/test_volume_type.py13
-rw-r--r--openstackclient/tests/volume/v2/test_type.py4
-rw-r--r--openstackclient/volume/v1/volume_type.py35
-rw-r--r--openstackclient/volume/v2/volume_type.py29
-rw-r--r--releasenotes/notes/bug-1592906-e69b37377278d9c2.yaml5
7 files changed, 88 insertions, 17 deletions
diff --git a/doc/source/command-objects/volume-type.rst b/doc/source/command-objects/volume-type.rst
index 50acf9fa..dfc169cd 100644
--- a/doc/source/command-objects/volume-type.rst
+++ b/doc/source/command-objects/volume-type.rst
@@ -48,18 +48,18 @@ Create new volume type
volume type delete
------------------
-Delete volume type
+Delete volume type(s)
.. program:: volume type delete
.. code:: bash
os volume type delete
- <volume-type>
+ <volume-type> [<volume-type> ...]
.. _volume_type_delete-volume-type:
.. describe:: <volume-type>
- Volume type to delete (name or ID)
+ Volume type(s) to delete (name or ID)
volume type list
----------------
diff --git a/functional/tests/volume/v1/test_volume_type.py b/functional/tests/volume/v1/test_volume_type.py
index 824b20d7..5f1f957e 100644
--- a/functional/tests/volume/v1/test_volume_type.py
+++ b/functional/tests/volume/v1/test_volume_type.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import time
import uuid
from functional.tests.volume.v1 import common
@@ -59,3 +60,15 @@ class VolumeTypeTests(common.BaseVolumeTests):
self.assertEqual("", raw_output)
raw_output = self.openstack('volume type show ' + self.NAME + opts)
self.assertEqual("c='d'\n", raw_output)
+
+ def test_multi_delete(self):
+ vol_type1 = uuid.uuid4().hex
+ vol_type2 = uuid.uuid4().hex
+ self.openstack('volume type create ' + vol_type1)
+ time.sleep(5)
+ self.openstack('volume type create ' + vol_type2)
+ time.sleep(5)
+ cmd = 'volume type delete %s %s' % (vol_type1, vol_type2)
+ time.sleep(5)
+ raw_output = self.openstack(cmd)
+ self.assertOutput('', raw_output)
diff --git a/functional/tests/volume/v2/test_volume_type.py b/functional/tests/volume/v2/test_volume_type.py
index 4c315334..114e4298 100644
--- a/functional/tests/volume/v2/test_volume_type.py
+++ b/functional/tests/volume/v2/test_volume_type.py
@@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import time
import uuid
from functional.tests.volume.v2 import common
@@ -69,3 +70,15 @@ class VolumeTypeTests(common.BaseVolumeTests):
raw_output = self.openstack(
'volume type unset --project admin ' + self.NAME)
self.assertEqual("", raw_output)
+
+ def test_multi_delete(self):
+ vol_type1 = uuid.uuid4().hex
+ vol_type2 = uuid.uuid4().hex
+ self.openstack('volume type create ' + vol_type1)
+ time.sleep(5)
+ self.openstack('volume type create ' + vol_type2)
+ time.sleep(5)
+ cmd = 'volume type delete %s %s' % (vol_type1, vol_type2)
+ time.sleep(5)
+ raw_output = self.openstack(cmd)
+ self.assertOutput('', raw_output)
diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py
index 7eea1c3c..174f33f2 100644
--- a/openstackclient/tests/volume/v2/test_type.py
+++ b/openstackclient/tests/volume/v2/test_type.py
@@ -128,13 +128,13 @@ class TestTypeDelete(TestType):
self.volume_type.id
]
verifylist = [
- ("volume_type", self.volume_type.id)
+ ("volume_types", [self.volume_type.id])
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
- self.types_mock.delete.assert_called_with(self.volume_type.id)
+ self.types_mock.delete.assert_called_with(self.volume_type)
self.assertIsNone(result)
diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py
index 289966e5..3fe4fa05 100644
--- a/openstackclient/volume/v1/volume_type.py
+++ b/openstackclient/volume/v1/volume_type.py
@@ -15,14 +15,20 @@
"""Volume v1 Type action implementations"""
+import logging
+
from osc_lib.cli import parseractions
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 CreateVolumeType(command.ShowOne):
"""Create new volume type"""
@@ -56,22 +62,39 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type"""
+ """Delete volume type(s)"""
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
parser.add_argument(
- 'volume_type',
+ 'volume_types',
metavar='<volume-type>',
- help=_('Volume type to delete (name or ID)'),
+ nargs='+',
+ help=_('Volume type(s) to delete (name or ID)'),
)
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- volume_type_id = utils.find_resource(
- volume_client.volume_types, parsed_args.volume_type).id
- volume_client.volume_types.delete(volume_type_id)
+ result = 0
+
+ for volume_type in parsed_args.volume_types:
+ try:
+ vol_type = utils.find_resource(volume_client.volume_types,
+ volume_type)
+
+ volume_client.volume_types.delete(vol_type)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete volume type with "
+ "name or ID '%(volume_type)s': %(e)s")
+ % {'volume_type': volume_type, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.volume_types)
+ msg = (_("%(result)s of %(total)s volume types failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListVolumeType(command.Lister):
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 5e9faa1d..87f4c547 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -92,22 +92,39 @@ class CreateVolumeType(command.ShowOne):
class DeleteVolumeType(command.Command):
- """Delete volume type"""
+ """Delete volume type(s)"""
def get_parser(self, prog_name):
parser = super(DeleteVolumeType, self).get_parser(prog_name)
parser.add_argument(
- "volume_type",
+ "volume_types",
metavar="<volume-type>",
- help=_("Volume type to delete (name or ID)")
+ nargs="+",
+ help=_("Volume type(s) to delete (name or ID)")
)
return parser
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- volume_type = utils.find_resource(
- volume_client.volume_types, parsed_args.volume_type)
- volume_client.volume_types.delete(volume_type.id)
+ result = 0
+
+ for volume_type in parsed_args.volume_types:
+ try:
+ vol_type = utils.find_resource(volume_client.volume_types,
+ volume_type)
+
+ volume_client.volume_types.delete(vol_type)
+ except Exception as e:
+ result += 1
+ LOG.error(_("Failed to delete volume type with "
+ "name or ID '%(volume_type)s': %(e)s")
+ % {'volume_type': volume_type, 'e': e})
+
+ if result > 0:
+ total = len(parsed_args.volume_types)
+ msg = (_("%(result)s of %(total)s volume types failed "
+ "to delete.") % {'result': result, 'total': total})
+ raise exceptions.CommandError(msg)
class ListVolumeType(command.Lister):
diff --git a/releasenotes/notes/bug-1592906-e69b37377278d9c2.yaml b/releasenotes/notes/bug-1592906-e69b37377278d9c2.yaml
new file mode 100644
index 00000000..fee971d6
--- /dev/null
+++ b/releasenotes/notes/bug-1592906-e69b37377278d9c2.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - Support bulk deletion for ``volume type delete``.
+ [Bug `1592906 <https://bugs.launchpad.net/bugs/1592906>`_]
+