Skip to content

Commit e650c3e

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add DeleteVolumeSnapshot class to v3"
2 parents c47ccb9 + 49c42c7 commit e650c3e

3 files changed

Lines changed: 190 additions & 1 deletion

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
14+
from unittest import mock
15+
16+
from osc_lib import exceptions
17+
from osc_lib import utils
18+
19+
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
20+
from openstackclient.volume.v3 import volume_snapshot
21+
22+
23+
class TestVolumeSnapshot(volume_fakes.TestVolume):
24+
def setUp(self):
25+
super().setUp()
26+
27+
self.snapshots_mock = self.volume_client.volume_snapshots
28+
self.snapshots_mock.reset_mock()
29+
30+
31+
class TestVolumeSnapshotDelete(TestVolumeSnapshot):
32+
snapshots = volume_fakes.create_snapshots(count=2)
33+
34+
def setUp(self):
35+
super().setUp()
36+
37+
self.snapshots_mock.get = volume_fakes.get_snapshots(self.snapshots)
38+
self.snapshots_mock.delete.return_value = None
39+
40+
# Get the command object to mock
41+
self.cmd = volume_snapshot.DeleteVolumeSnapshot(self.app, None)
42+
43+
def test_snapshot_delete(self):
44+
arglist = [self.snapshots[0].id]
45+
verifylist = [("snapshots", [self.snapshots[0].id])]
46+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
47+
48+
result = self.cmd.take_action(parsed_args)
49+
50+
self.snapshots_mock.delete.assert_called_with(
51+
self.snapshots[0].id, False
52+
)
53+
self.assertIsNone(result)
54+
55+
def test_snapshot_delete_with_force(self):
56+
arglist = ['--force', self.snapshots[0].id]
57+
verifylist = [('force', True), ("snapshots", [self.snapshots[0].id])]
58+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
59+
60+
result = self.cmd.take_action(parsed_args)
61+
62+
self.snapshots_mock.delete.assert_called_with(
63+
self.snapshots[0].id, True
64+
)
65+
self.assertIsNone(result)
66+
67+
def test_delete_multiple_snapshots(self):
68+
arglist = []
69+
for s in self.snapshots:
70+
arglist.append(s.id)
71+
verifylist = [
72+
('snapshots', arglist),
73+
]
74+
75+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
76+
result = self.cmd.take_action(parsed_args)
77+
78+
calls = []
79+
for s in self.snapshots:
80+
calls.append(mock.call(s.id, False))
81+
self.snapshots_mock.delete.assert_has_calls(calls)
82+
self.assertIsNone(result)
83+
84+
def test_delete_multiple_snapshots_with_exception(self):
85+
arglist = [
86+
self.snapshots[0].id,
87+
'unexist_snapshot',
88+
]
89+
verifylist = [
90+
('snapshots', arglist),
91+
]
92+
93+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
94+
95+
find_mock_result = [self.snapshots[0], exceptions.CommandError]
96+
with mock.patch.object(
97+
utils, 'find_resource', side_effect=find_mock_result
98+
) as find_mock:
99+
try:
100+
self.cmd.take_action(parsed_args)
101+
self.fail('CommandError should be raised.')
102+
except exceptions.CommandError as e:
103+
self.assertEqual('1 of 2 snapshots failed to delete.', str(e))
104+
105+
find_mock.assert_any_call(
106+
self.snapshots_mock, self.snapshots[0].id
107+
)
108+
find_mock.assert_any_call(self.snapshots_mock, 'unexist_snapshot')
109+
110+
self.assertEqual(2, find_mock.call_count)
111+
self.snapshots_mock.delete.assert_called_once_with(
112+
self.snapshots[0].id, False
113+
)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
#
14+
15+
"""Volume v3 snapshot action implementations"""
16+
17+
import logging
18+
19+
from osc_lib.command import command
20+
from osc_lib import exceptions
21+
from osc_lib import utils
22+
23+
from openstackclient.i18n import _
24+
25+
LOG = logging.getLogger(__name__)
26+
27+
28+
class DeleteVolumeSnapshot(command.Command):
29+
_description = _("Delete volume snapshot(s)")
30+
31+
def get_parser(self, prog_name):
32+
parser = super().get_parser(prog_name)
33+
parser.add_argument(
34+
"snapshots",
35+
metavar="<snapshot>",
36+
nargs="+",
37+
help=_("Snapshot(s) to delete (name or ID)"),
38+
)
39+
parser.add_argument(
40+
'--force',
41+
action='store_true',
42+
help=_(
43+
"Attempt forced removal of snapshot(s), "
44+
"regardless of state (defaults to False)"
45+
),
46+
)
47+
return parser
48+
49+
def take_action(self, parsed_args):
50+
volume_client = self.app.client_manager.volume
51+
result = 0
52+
53+
for i in parsed_args.snapshots:
54+
try:
55+
snapshot_id = utils.find_resource(
56+
volume_client.volume_snapshots, i
57+
).id
58+
volume_client.volume_snapshots.delete(
59+
snapshot_id, parsed_args.force
60+
)
61+
except Exception as e:
62+
result += 1
63+
LOG.error(
64+
_(
65+
"Failed to delete snapshot with "
66+
"name or ID '%(snapshot)s': %(e)s"
67+
)
68+
% {'snapshot': i, 'e': e}
69+
)
70+
71+
if result > 0:
72+
total = len(parsed_args.snapshots)
73+
msg = _(
74+
"%(result)s of %(total)s snapshots failed " "to delete."
75+
) % {'result': result, 'total': total}
76+
raise exceptions.CommandError(msg)

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ openstack.volume.v3 =
825825
block_storage_resource_filter_show = openstackclient.volume.v3.block_storage_resource_filter:ShowBlockStorageResourceFilter
826826

827827
volume_snapshot_create = openstackclient.volume.v2.volume_snapshot:CreateVolumeSnapshot
828-
volume_snapshot_delete = openstackclient.volume.v2.volume_snapshot:DeleteVolumeSnapshot
828+
volume_snapshot_delete = openstackclient.volume.v3.volume_snapshot:DeleteVolumeSnapshot
829829
volume_snapshot_list = openstackclient.volume.v2.volume_snapshot:ListVolumeSnapshot
830830
volume_snapshot_set = openstackclient.volume.v2.volume_snapshot:SetVolumeSnapshot
831831
volume_snapshot_show = openstackclient.volume.v2.volume_snapshot:ShowVolumeSnapshot

0 commit comments

Comments
 (0)