Skip to content

Commit 4e62e1e

Browse files
committed
support multi-delete for volume-type
Added the ability to delete multiple volume types at once. Note there are no unit tests exist for v1 volume-types, so instead a functional test was created. Partial-Bug: #1592906 Change-Id: I99f3f22901ab35252b91a3072b14de7d19cb17ca
1 parent f5ae23a commit 4e62e1e

7 files changed

Lines changed: 88 additions & 17 deletions

File tree

doc/source/command-objects/volume-type.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ Create new volume type
4848
volume type delete
4949
------------------
5050

51-
Delete volume type
51+
Delete volume type(s)
5252

5353
.. program:: volume type delete
5454
.. code:: bash
5555
5656
os volume type delete
57-
<volume-type>
57+
<volume-type> [<volume-type> ...]
5858
5959
.. _volume_type_delete-volume-type:
6060
.. describe:: <volume-type>
6161

62-
Volume type to delete (name or ID)
62+
Volume type(s) to delete (name or ID)
6363

6464
volume type list
6565
----------------

functional/tests/volume/v1/test_volume_type.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# License for the specific language governing permissions and limitations
1111
# under the License.
1212

13+
import time
1314
import uuid
1415

1516
from functional.tests.volume.v1 import common
@@ -59,3 +60,15 @@ def test_volume_type_set_unset_properties(self):
5960
self.assertEqual("", raw_output)
6061
raw_output = self.openstack('volume type show ' + self.NAME + opts)
6162
self.assertEqual("c='d'\n", raw_output)
63+
64+
def test_multi_delete(self):
65+
vol_type1 = uuid.uuid4().hex
66+
vol_type2 = uuid.uuid4().hex
67+
self.openstack('volume type create ' + vol_type1)
68+
time.sleep(5)
69+
self.openstack('volume type create ' + vol_type2)
70+
time.sleep(5)
71+
cmd = 'volume type delete %s %s' % (vol_type1, vol_type2)
72+
time.sleep(5)
73+
raw_output = self.openstack(cmd)
74+
self.assertOutput('', raw_output)

functional/tests/volume/v2/test_volume_type.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# License for the specific language governing permissions and limitations
1111
# under the License.
1212

13+
import time
1314
import uuid
1415

1516
from functional.tests.volume.v2 import common
@@ -69,3 +70,15 @@ def test_volume_type_set_unset_project(self):
6970
raw_output = self.openstack(
7071
'volume type unset --project admin ' + self.NAME)
7172
self.assertEqual("", raw_output)
73+
74+
def test_multi_delete(self):
75+
vol_type1 = uuid.uuid4().hex
76+
vol_type2 = uuid.uuid4().hex
77+
self.openstack('volume type create ' + vol_type1)
78+
time.sleep(5)
79+
self.openstack('volume type create ' + vol_type2)
80+
time.sleep(5)
81+
cmd = 'volume type delete %s %s' % (vol_type1, vol_type2)
82+
time.sleep(5)
83+
raw_output = self.openstack(cmd)
84+
self.assertOutput('', raw_output)

openstackclient/tests/volume/v2/test_type.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,13 @@ def test_type_delete(self):
128128
self.volume_type.id
129129
]
130130
verifylist = [
131-
("volume_type", self.volume_type.id)
131+
("volume_types", [self.volume_type.id])
132132
]
133133
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
134134

135135
result = self.cmd.take_action(parsed_args)
136136

137-
self.types_mock.delete.assert_called_with(self.volume_type.id)
137+
self.types_mock.delete.assert_called_with(self.volume_type)
138138
self.assertIsNone(result)
139139

140140

openstackclient/volume/v1/volume_type.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,20 @@
1515

1616
"""Volume v1 Type action implementations"""
1717

18+
import logging
19+
1820
from osc_lib.cli import parseractions
1921
from osc_lib.command import command
22+
from osc_lib import exceptions
2023
from osc_lib import utils
2124
import six
2225

2326
from openstackclient.i18n import _
2427

2528

29+
LOG = logging.getLogger(__name__)
30+
31+
2632
class CreateVolumeType(command.ShowOne):
2733
"""Create new volume type"""
2834

@@ -56,22 +62,39 @@ def take_action(self, parsed_args):
5662

5763

5864
class DeleteVolumeType(command.Command):
59-
"""Delete volume type"""
65+
"""Delete volume type(s)"""
6066

6167
def get_parser(self, prog_name):
6268
parser = super(DeleteVolumeType, self).get_parser(prog_name)
6369
parser.add_argument(
64-
'volume_type',
70+
'volume_types',
6571
metavar='<volume-type>',
66-
help=_('Volume type to delete (name or ID)'),
72+
nargs='+',
73+
help=_('Volume type(s) to delete (name or ID)'),
6774
)
6875
return parser
6976

7077
def take_action(self, parsed_args):
7178
volume_client = self.app.client_manager.volume
72-
volume_type_id = utils.find_resource(
73-
volume_client.volume_types, parsed_args.volume_type).id
74-
volume_client.volume_types.delete(volume_type_id)
79+
result = 0
80+
81+
for volume_type in parsed_args.volume_types:
82+
try:
83+
vol_type = utils.find_resource(volume_client.volume_types,
84+
volume_type)
85+
86+
volume_client.volume_types.delete(vol_type)
87+
except Exception as e:
88+
result += 1
89+
LOG.error(_("Failed to delete volume type with "
90+
"name or ID '%(volume_type)s': %(e)s")
91+
% {'volume_type': volume_type, 'e': e})
92+
93+
if result > 0:
94+
total = len(parsed_args.volume_types)
95+
msg = (_("%(result)s of %(total)s volume types failed "
96+
"to delete.") % {'result': result, 'total': total})
97+
raise exceptions.CommandError(msg)
7598

7699

77100
class ListVolumeType(command.Lister):

openstackclient/volume/v2/volume_type.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,39 @@ def take_action(self, parsed_args):
9292

9393

9494
class DeleteVolumeType(command.Command):
95-
"""Delete volume type"""
95+
"""Delete volume type(s)"""
9696

9797
def get_parser(self, prog_name):
9898
parser = super(DeleteVolumeType, self).get_parser(prog_name)
9999
parser.add_argument(
100-
"volume_type",
100+
"volume_types",
101101
metavar="<volume-type>",
102-
help=_("Volume type to delete (name or ID)")
102+
nargs="+",
103+
help=_("Volume type(s) to delete (name or ID)")
103104
)
104105
return parser
105106

106107
def take_action(self, parsed_args):
107108
volume_client = self.app.client_manager.volume
108-
volume_type = utils.find_resource(
109-
volume_client.volume_types, parsed_args.volume_type)
110-
volume_client.volume_types.delete(volume_type.id)
109+
result = 0
110+
111+
for volume_type in parsed_args.volume_types:
112+
try:
113+
vol_type = utils.find_resource(volume_client.volume_types,
114+
volume_type)
115+
116+
volume_client.volume_types.delete(vol_type)
117+
except Exception as e:
118+
result += 1
119+
LOG.error(_("Failed to delete volume type with "
120+
"name or ID '%(volume_type)s': %(e)s")
121+
% {'volume_type': volume_type, 'e': e})
122+
123+
if result > 0:
124+
total = len(parsed_args.volume_types)
125+
msg = (_("%(result)s of %(total)s volume types failed "
126+
"to delete.") % {'result': result, 'total': total})
127+
raise exceptions.CommandError(msg)
111128

112129

113130
class ListVolumeType(command.Lister):
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- Support bulk deletion for ``volume type delete``.
4+
[Bug `1592906 <https://bugs.launchpad.net/bugs/1592906>`_]
5+

0 commit comments

Comments
 (0)