Skip to content

Commit daffce3

Browse files
author
Huanxuan Ao
committed
Add "--read-only" and "--read-write" options in "volume set"
Add "--read-only" and "--read-write" options in "volume set" command to set volume access mode. Implements: bp cinder-command-support Change-Id: I76ba85c7d3ff0eb026a9cbd794368d8b2b0d17fe
1 parent 5e3ec1b commit daffce3

6 files changed

Lines changed: 176 additions & 28 deletions

File tree

doc/source/command-objects/volume.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ Set volume properties
213213
[--image-property <key=value> [...] ]
214214
[--state <state>]
215215
[--bootable | --non-bootable]
216+
[--read-only | --read-write]
216217
<volume>
217218
218219
.. option:: --name <name>
@@ -239,6 +240,14 @@ Set volume properties
239240
240241
Mark volume as non-bootable
241242
243+
.. option:: --read-only
244+
245+
Set volume to read-only access mode
246+
247+
.. option:: --read-write
248+
249+
Set volume to read-write access mode
250+
242251
.. option:: --image-property <key=value>
243252
244253
Set an image property on this volume

openstackclient/tests/unit/volume/v1/test_volume.py

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -844,8 +844,7 @@ def test_volume_set_size(self):
844844
)
845845
self.assertIsNone(result)
846846

847-
@mock.patch.object(volume.LOG, 'error')
848-
def test_volume_set_size_smaller(self, mock_log_error):
847+
def test_volume_set_size_smaller(self):
849848
self._volume.status = 'available'
850849
arglist = [
851850
'--size', '1',
@@ -860,15 +859,11 @@ def test_volume_set_size_smaller(self, mock_log_error):
860859
]
861860
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
862861

863-
result = self.cmd.take_action(parsed_args)
864-
865-
mock_log_error.assert_called_with("New size must be greater "
866-
"than %s GB",
867-
self._volume.size)
868-
self.assertIsNone(result)
862+
self.assertRaises(exceptions.CommandError,
863+
self.cmd.take_action,
864+
parsed_args)
869865

870-
@mock.patch.object(volume.LOG, 'error')
871-
def test_volume_set_size_not_available(self, mock_log_error):
866+
def test_volume_set_size_not_available(self):
872867
self._volume.status = 'error'
873868
arglist = [
874869
'--size', '130',
@@ -883,19 +878,18 @@ def test_volume_set_size_not_available(self, mock_log_error):
883878
]
884879
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
885880

886-
result = self.cmd.take_action(parsed_args)
887-
888-
mock_log_error.assert_called_with("Volume is in %s state, it must be "
889-
"available before size can be "
890-
"extended", 'error')
891-
self.assertIsNone(result)
881+
self.assertRaises(exceptions.CommandError,
882+
self.cmd.take_action,
883+
parsed_args)
892884

893885
def test_volume_set_property(self):
894886
arglist = [
895887
'--property', 'myprop=myvalue',
896888
self._volume.display_name,
897889
]
898890
verifylist = [
891+
('read_only', False),
892+
('read_write', False),
899893
('name', None),
900894
('description', None),
901895
('size', None),
@@ -916,6 +910,7 @@ def test_volume_set_property(self):
916910
self._volume.id,
917911
metadata
918912
)
913+
self.volumes_mock.update_readonly_flag.assert_not_called()
919914
self.assertIsNone(result)
920915

921916
def test_volume_set_bootable(self):
@@ -943,6 +938,44 @@ def test_volume_set_bootable(self):
943938
self.volumes_mock.set_bootable.assert_called_with(
944939
self._volume.id, verifylist[index][0][1])
945940

941+
def test_volume_set_readonly(self):
942+
arglist = [
943+
'--read-only',
944+
self._volume.id
945+
]
946+
verifylist = [
947+
('read_only', True),
948+
('read_write', False),
949+
('volume', self._volume.id)
950+
]
951+
952+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
953+
954+
result = self.cmd.take_action(parsed_args)
955+
self.volumes_mock.update_readonly_flag.assert_called_once_with(
956+
self._volume.id,
957+
True)
958+
self.assertIsNone(result)
959+
960+
def test_volume_set_read_write(self):
961+
arglist = [
962+
'--read-write',
963+
self._volume.id
964+
]
965+
verifylist = [
966+
('read_only', False),
967+
('read_write', True),
968+
('volume', self._volume.id)
969+
]
970+
971+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
972+
973+
result = self.cmd.take_action(parsed_args)
974+
self.volumes_mock.update_readonly_flag.assert_called_once_with(
975+
self._volume.id,
976+
False)
977+
self.assertIsNone(result)
978+
946979

947980
class TestVolumeShow(TestVolume):
948981

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,8 @@ def test_volume_set_state(self):
10331033
self.new_volume.id
10341034
]
10351035
verifylist = [
1036+
('read_only', False),
1037+
('read_write', False),
10361038
('state', 'error'),
10371039
('volume', self.new_volume.id)
10381040
]
@@ -1042,6 +1044,7 @@ def test_volume_set_state(self):
10421044
result = self.cmd.take_action(parsed_args)
10431045
self.volumes_mock.reset_state.assert_called_with(
10441046
self.new_volume.id, 'error')
1047+
self.volumes_mock.update_readonly_flag.assert_not_called()
10451048
self.assertIsNone(result)
10461049

10471050
def test_volume_set_state_failed(self):
@@ -1090,6 +1093,44 @@ def test_volume_set_bootable(self):
10901093
self.volumes_mock.set_bootable.assert_called_with(
10911094
self.new_volume.id, verifylist[index][0][1])
10921095

1096+
def test_volume_set_readonly(self):
1097+
arglist = [
1098+
'--read-only',
1099+
self.new_volume.id
1100+
]
1101+
verifylist = [
1102+
('read_only', True),
1103+
('read_write', False),
1104+
('volume', self.new_volume.id)
1105+
]
1106+
1107+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1108+
1109+
result = self.cmd.take_action(parsed_args)
1110+
self.volumes_mock.update_readonly_flag.assert_called_once_with(
1111+
self.new_volume.id,
1112+
True)
1113+
self.assertIsNone(result)
1114+
1115+
def test_volume_set_read_write(self):
1116+
arglist = [
1117+
'--read-write',
1118+
self.new_volume.id
1119+
]
1120+
verifylist = [
1121+
('read_only', False),
1122+
('read_write', True),
1123+
('volume', self.new_volume.id)
1124+
]
1125+
1126+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
1127+
1128+
result = self.cmd.take_action(parsed_args)
1129+
self.volumes_mock.update_readonly_flag.assert_called_once_with(
1130+
self.new_volume.id,
1131+
False)
1132+
self.assertIsNone(result)
1133+
10931134

10941135
class TestVolumeShow(TestVolume):
10951136

openstackclient/volume/v1/volume.py

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -388,38 +388,78 @@ def get_parser(self, prog_name):
388388
action="store_true",
389389
help=_("Mark volume as non-bootable")
390390
)
391+
readonly_group = parser.add_mutually_exclusive_group()
392+
readonly_group.add_argument(
393+
"--read-only",
394+
action="store_true",
395+
help=_("Set volume to read-only access mode")
396+
)
397+
readonly_group.add_argument(
398+
"--read-write",
399+
action="store_true",
400+
help=_("Set volume to read-write access mode")
401+
)
391402
return parser
392403

393404
def take_action(self, parsed_args):
394405
volume_client = self.app.client_manager.volume
395406
volume = utils.find_resource(volume_client.volumes, parsed_args.volume)
396407

408+
result = 0
397409
if parsed_args.size:
398-
if volume.status != 'available':
399-
LOG.error(_("Volume is in %s state, it must be available "
400-
"before size can be extended"), volume.status)
401-
return
402-
if parsed_args.size <= volume.size:
403-
LOG.error(_("New size must be greater than %s GB"),
404-
volume.size)
405-
return
406-
volume_client.volumes.extend(volume.id, parsed_args.size)
407-
410+
try:
411+
if volume.status != 'available':
412+
msg = (_("Volume is in %s state, it must be available "
413+
"before size can be extended") % volume.status)
414+
raise exceptions.CommandError(msg)
415+
if parsed_args.size <= volume.size:
416+
msg = (_("New size must be greater than %s GB")
417+
% volume.size)
418+
raise exceptions.CommandError(msg)
419+
volume_client.volumes.extend(volume.id, parsed_args.size)
420+
except Exception as e:
421+
LOG.error(_("Failed to set volume size: %s"), e)
422+
result += 1
408423
if parsed_args.property:
409-
volume_client.volumes.set_metadata(volume.id, parsed_args.property)
424+
try:
425+
volume_client.volumes.set_metadata(
426+
volume.id,
427+
parsed_args.property)
428+
except Exception as e:
429+
LOG.error(_("Failed to set volume property: %s"), e)
430+
result += 1
410431
if parsed_args.bootable or parsed_args.non_bootable:
411432
try:
412433
volume_client.volumes.set_bootable(
413434
volume.id, parsed_args.bootable)
414435
except Exception as e:
415436
LOG.error(_("Failed to set volume bootable property: %s"), e)
437+
result += 1
438+
if parsed_args.read_only or parsed_args.read_write:
439+
try:
440+
volume_client.volumes.update_readonly_flag(
441+
volume.id,
442+
parsed_args.read_only)
443+
except Exception as e:
444+
LOG.error(_("Failed to set volume read-only access "
445+
"mode flag: %s"), e)
446+
result += 1
416447
kwargs = {}
417448
if parsed_args.name:
418449
kwargs['display_name'] = parsed_args.name
419450
if parsed_args.description:
420451
kwargs['display_description'] = parsed_args.description
421452
if kwargs:
422-
volume_client.volumes.update(volume.id, **kwargs)
453+
try:
454+
volume_client.volumes.update(volume.id, **kwargs)
455+
except Exception as e:
456+
LOG.error(_("Failed to update volume display name "
457+
"or display description: %s"), e)
458+
result += 1
459+
460+
if result > 0:
461+
raise exceptions.CommandError(_("One or more of the "
462+
"set operations failed"))
423463

424464

425465
class ShowVolume(command.ShowOne):

openstackclient/volume/v2/volume.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,17 @@ def get_parser(self, prog_name):
473473
action="store_true",
474474
help=_("Mark volume as non-bootable")
475475
)
476+
readonly_group = parser.add_mutually_exclusive_group()
477+
readonly_group.add_argument(
478+
"--read-only",
479+
action="store_true",
480+
help=_("Set volume to read-only access mode")
481+
)
482+
readonly_group.add_argument(
483+
"--read-write",
484+
action="store_true",
485+
help=_("Set volume to read-write access mode")
486+
)
476487
return parser
477488

478489
def take_action(self, parsed_args):
@@ -523,6 +534,15 @@ def take_action(self, parsed_args):
523534
except Exception as e:
524535
LOG.error(_("Failed to set volume bootable property: %s"), e)
525536
result += 1
537+
if parsed_args.read_only or parsed_args.read_write:
538+
try:
539+
volume_client.volumes.update_readonly_flag(
540+
volume.id,
541+
parsed_args.read_only)
542+
except Exception as e:
543+
LOG.error(_("Failed to set volume read-only access "
544+
"mode flag: %s"), e)
545+
result += 1
526546

527547
kwargs = {}
528548
if parsed_args.name:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
features:
3+
- |
4+
Add ``--read-only`` and ``--read-write`` options to ``volume set`` command.
5+
[Blueprint `cinder-command-support <https://blueprints.launchpad.net/python-openstackclient/+spec/cinder-command-support>`_]

0 commit comments

Comments
 (0)