Skip to content

Commit 01bdf5f

Browse files
committed
Cinder: Adds a api mv 3.66 check for snapshot creation
Since api mv 3.66 the --force parameter is not requied for snapshot creation. In-use volumes snapshot can be taken by default without requiring the force flag. This is already handled in cinder side. fixed conflict master -> 2026.1: added import: from openstack import utils as sdk_utils fixed conflict stable/2025.2 -> stable/2025.1: - placed backport fix/changes to v2/volume_snapshot.py because CreateVolumeSnapshot class is in v2, not v3 - added import: from cinderclient import api_versions - changed mv check from sdk_utils.supports_microversion() to volume_client.api_version < api_versions.APIVersion('3.66') - set default api_version in tests to fix existing tests that now trigger mv check take_action() Closes-Bug: #2089188 Change-Id: I452ad973c76fa7f039797e8ea02556bf9fe7315c Signed-off-by: Amit Uniyal <auniyal@redhat.com> (cherry picked from commit ede91ec) (cherry picked from commit 97d6641) (cherry picked from commit 896a167)
1 parent 3b8c543 commit 01bdf5f

3 files changed

Lines changed: 106 additions & 9 deletions

File tree

openstackclient/tests/unit/volume/v2/test_volume_snapshot.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from unittest import mock
1515

16+
from cinderclient import api_versions
1617
from osc_lib.cli import format_columns
1718
from osc_lib import exceptions
1819
from osc_lib import utils
@@ -69,6 +70,10 @@ def setUp(self):
6970
self.volumes_mock.get.return_value = self.volume
7071
self.snapshots_mock.create.return_value = self.new_snapshot
7172
self.snapshots_mock.manage.return_value = self.new_snapshot
73+
# Set default api_version for all tests
74+
# CreateVolumeSnapshot now checks api_version to handle mv 3.66 logic
75+
# in take_action()
76+
self.volume_client.api_version = api_versions.APIVersion('3.0')
7277
# Get the command object to test
7378
self.cmd = volume_snapshot.CreateVolumeSnapshot(self.app, None)
7479

@@ -183,6 +188,77 @@ def test_snapshot_create_with_remote_source(self):
183188
self.assertEqual(self.columns, columns)
184189
self.assertEqual(self.data, data)
185190

191+
def test_snapshot_create_pre_v366(self):
192+
self.volume_client.api_version = api_versions.APIVersion('3.65')
193+
194+
arglist = ["--force", self.new_snapshot.name]
195+
verifylist = [
196+
("force", True),
197+
("snapshot_name", self.new_snapshot.name),
198+
]
199+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
200+
201+
columns, data = self.cmd.take_action(parsed_args)
202+
203+
# force parameter should be passed
204+
self.snapshots_mock.create.assert_called_with(
205+
self.new_snapshot.volume_id,
206+
force=True,
207+
name=self.new_snapshot.name,
208+
description=None,
209+
metadata=None,
210+
)
211+
212+
self.assertEqual(self.columns, columns)
213+
self.assertEqual(self.data, data)
214+
215+
def test_snapshot_create_v366_or_later(self):
216+
self.volume_client.api_version = api_versions.APIVersion('3.66')
217+
218+
arglist = [self.new_snapshot.name]
219+
verifylist = [
220+
("force", False),
221+
("snapshot_name", self.new_snapshot.name),
222+
]
223+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
224+
225+
columns, data = self.cmd.take_action(parsed_args)
226+
227+
# force parameter should not be passed, for >=3.66
228+
self.snapshots_mock.create.assert_called_with(
229+
self.new_snapshot.volume_id,
230+
name=self.new_snapshot.name,
231+
description=None,
232+
metadata=None,
233+
)
234+
235+
self.assertEqual(self.columns, columns)
236+
self.assertEqual(self.data, data)
237+
238+
def test_snapshot_create_v366_or_later_with_force(self):
239+
"""--force should be ignored for microversion >= 3.66."""
240+
self.volume_client.api_version = api_versions.APIVersion('3.66')
241+
242+
arglist = ["--force", self.new_snapshot.name]
243+
verifylist = [
244+
("force", True),
245+
("snapshot_name", self.new_snapshot.name),
246+
]
247+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
248+
249+
columns, data = self.cmd.take_action(parsed_args)
250+
251+
# passed but ignored
252+
self.snapshots_mock.create.assert_called_with(
253+
self.new_snapshot.volume_id,
254+
name=self.new_snapshot.name,
255+
description=None,
256+
metadata=None,
257+
)
258+
259+
self.assertEqual(self.columns, columns)
260+
self.assertEqual(self.data, data)
261+
186262

187263
class TestVolumeSnapshotDelete(TestVolumeSnapshot):
188264
snapshots = volume_fakes.create_snapshots(count=2)

openstackclient/volume/v2/volume_snapshot.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import functools
1919
import logging
2020

21+
from cinderclient import api_versions
2122
from cliff import columns as cliff_columns
2223
from osc_lib.cli import format_columns
2324
from osc_lib.cli import parseractions
@@ -88,8 +89,9 @@ def get_parser(self, prog_name):
8889
action="store_true",
8990
default=False,
9091
help=_(
91-
"Create a snapshot attached to an instance. "
92-
"Default is False"
92+
"Allow snapshot of in-use (attached) volume. "
93+
"Only needed for microversions prior to 3.66; "
94+
"ignored for 3.66+"
9395
),
9496
)
9597
parser.add_argument(
@@ -138,13 +140,23 @@ def take_action(self, parsed_args):
138140
)
139141
else:
140142
# create a new snapshot from scratch
141-
snapshot = volume_client.volume_snapshots.create(
142-
volume_id,
143-
force=parsed_args.force,
144-
name=parsed_args.snapshot_name,
145-
description=parsed_args.description,
146-
metadata=parsed_args.property,
147-
)
143+
# only for microversion < 3.66, pass force parameter
144+
# for backward compatibility
145+
if volume_client.api_version < api_versions.APIVersion('3.66'):
146+
snapshot = volume_client.volume_snapshots.create(
147+
volume_id,
148+
force=parsed_args.force,
149+
name=parsed_args.snapshot_name,
150+
description=parsed_args.description,
151+
metadata=parsed_args.property,
152+
)
153+
else:
154+
snapshot = volume_client.volume_snapshots.create(
155+
volume_id,
156+
name=parsed_args.snapshot_name,
157+
description=parsed_args.description,
158+
metadata=parsed_args.property,
159+
)
148160
snapshot._info.update(
149161
{
150162
'properties': format_columns.DictColumn(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
fixes:
3+
- |
4+
Fix ``volume snapshot create`` to work with Cinder API microversion 3.66
5+
and later. Since version 3.66, the 'force' parameter is no longer
6+
needed for snapshot creation as in-use volumes can be snapshotted by
7+
default. The command now only passes the 'force' parameter for version
8+
prior to 3.66.
9+
[Bug `2089188 <https://bugs.launchpad.net/python-openstackclient/+bug/2089188>`_]

0 commit comments

Comments
 (0)