From 6a914d0056e810e1ef37eaf4f01cd5c85217aba6 Mon Sep 17 00:00:00 2001 From: qtang Date: Thu, 25 Aug 2016 10:56:58 +0800 Subject: [PATCH] Support mark volume as bootable in volume set Add --bootable | --non-bootable option in volume set to mark or unmark volume as bootable. Change-Id: Ifa6c2dd1642202f55b6d50e3b8614d3513d488f6 Closes-Bug:#1535704 --- doc/source/command-objects/volume.rst | 9 +++++++ .../tests/functional/volume/v1/test_volume.py | 11 ++++++++ .../tests/functional/volume/v2/test_volume.py | 11 ++++++++ .../tests/unit/volume/v1/test_volume.py | 27 +++++++++++++++++++ .../tests/unit/volume/v2/test_volume.py | 27 +++++++++++++++++++ openstackclient/volume/v1/volume.py | 18 ++++++++++++- openstackclient/volume/v2/volume.py | 18 +++++++++++++ .../notes/bug-1535704-d6f013bfa22ab668.yaml | 6 +++++ 8 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml diff --git a/doc/source/command-objects/volume.rst b/doc/source/command-objects/volume.rst index 141c980ab..26d4ead6f 100644 --- a/doc/source/command-objects/volume.rst +++ b/doc/source/command-objects/volume.rst @@ -193,6 +193,7 @@ Set volume properties [--property [...] ] [--image-property [...] ] [--state ] + [--bootable | --non-bootable] .. option:: --name @@ -211,6 +212,14 @@ Set volume properties Set a property on this volume (repeat option to set multiple properties) +.. option:: --bootable + + Mark volume as bootable + +.. option:: --non-bootable + + Mark volume as non-bootable + .. option:: --image-property Set an image property on this volume diff --git a/openstackclient/tests/functional/volume/v1/test_volume.py b/openstackclient/tests/functional/volume/v1/test_volume.py index 6ac7f2bf7..5e4bcbea9 100644 --- a/openstackclient/tests/functional/volume/v1/test_volume.py +++ b/openstackclient/tests/functional/volume/v1/test_volume.py @@ -75,3 +75,14 @@ class VolumeTests(common.BaseVolumeTests): opts = self.get_opts(["display_name", "size"]) raw_output = self.openstack('volume show ' + self.NAME + opts) self.assertEqual(self.NAME + "\n2\n", raw_output) + + def test_volume_set_bootable(self): + self.openstack('volume set --bootable ' + self.NAME) + opts = self.get_opts(["bootable"]) + raw_output = self.openstack('volume show ' + self.NAME + opts) + self.assertEqual("true\n", raw_output) + + self.openstack('volume set --non-bootable ' + self.NAME) + opts = self.get_opts(["bootable"]) + raw_output = self.openstack('volume show ' + self.NAME + opts) + self.assertEqual("false\n", raw_output) diff --git a/openstackclient/tests/functional/volume/v2/test_volume.py b/openstackclient/tests/functional/volume/v2/test_volume.py index 73273573a..fb880578c 100644 --- a/openstackclient/tests/functional/volume/v2/test_volume.py +++ b/openstackclient/tests/functional/volume/v2/test_volume.py @@ -91,6 +91,17 @@ class VolumeTests(common.BaseVolumeTests): raw_output = self.openstack('volume show ' + self.NAME + opts) self.assertEqual(self.NAME + "\n2\n", raw_output) + def test_volume_set_bootable(self): + self.openstack('volume set --bootable ' + self.NAME) + opts = self.get_opts(["bootable"]) + raw_output = self.openstack('volume show ' + self.NAME + opts) + self.assertEqual("true\n", raw_output) + + self.openstack('volume set --non-bootable ' + self.NAME) + opts = self.get_opts(["bootable"]) + raw_output = self.openstack('volume show ' + self.NAME + opts) + self.assertEqual("false\n", raw_output) + def test_volume_snapshot(self): opts = self.get_opts(self.FIELDS) diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py index 54ec9e7ee..e95f42d03 100644 --- a/openstackclient/tests/unit/volume/v1/test_volume.py +++ b/openstackclient/tests/unit/volume/v1/test_volume.py @@ -844,6 +844,8 @@ class TestVolumeSet(TestVolume): ('size', None), ('property', {'myprop': 'myvalue'}), ('volume', volume_fakes.volume_name), + ('bootable', False), + ('non_bootable', False) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -858,3 +860,28 @@ class TestVolumeSet(TestVolume): metadata ) self.assertIsNone(result) + + def test_volume_set_bootable(self): + arglist = [ + ['--bootable', volume_fakes.volume_id], + ['--non-bootable', volume_fakes.volume_id] + ] + verifylist = [ + [ + ('bootable', True), + ('non_bootable', False), + ('volume', volume_fakes.volume_id) + ], + [ + ('bootable', False), + ('non_bootable', True), + ('volume', volume_fakes.volume_id) + ] + ] + for index in range(len(arglist)): + parsed_args = self.check_parser( + self.cmd, arglist[index], verifylist[index]) + + self.cmd.take_action(parsed_args) + self.volumes_mock.set_bootable.assert_called_with( + volume_fakes.volume_id, verifylist[index][0][1]) diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py index de059b1b5..a42ce22bf 100644 --- a/openstackclient/tests/unit/volume/v2/test_volume.py +++ b/openstackclient/tests/unit/volume/v2/test_volume.py @@ -905,6 +905,8 @@ class TestVolumeSet(TestVolume): verifylist = [ ('image_property', {'Alpha': 'a', 'Beta': 'b'}), ('volume', self.new_volume.id), + ('bootable', False), + ('non_bootable', False) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -952,6 +954,31 @@ class TestVolumeSet(TestVolume): self.volumes_mock.reset_state.assert_called_with( self.new_volume.id, 'error') + def test_volume_set_bootable(self): + arglist = [ + ['--bootable', self.new_volume.id], + ['--non-bootable', self.new_volume.id] + ] + verifylist = [ + [ + ('bootable', True), + ('non_bootable', False), + ('volume', self.new_volume.id) + ], + [ + ('bootable', False), + ('non_bootable', True), + ('volume', self.new_volume.id) + ] + ] + for index in range(len(arglist)): + parsed_args = self.check_parser( + self.cmd, arglist[index], verifylist[index]) + + self.cmd.take_action(parsed_args) + self.volumes_mock.set_bootable.assert_called_with( + self.new_volume.id, verifylist[index][0][1]) + class TestVolumeShow(TestVolume): diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py index 16f0d6dba..69bf38034 100644 --- a/openstackclient/volume/v1/volume.py +++ b/openstackclient/volume/v1/volume.py @@ -363,6 +363,17 @@ class SetVolume(command.Command): help=_('Set a property on this volume ' '(repeat option to set multiple properties)'), ) + bootable_group = parser.add_mutually_exclusive_group() + bootable_group.add_argument( + "--bootable", + action="store_true", + help=_("Mark volume as bootable") + ) + bootable_group.add_argument( + "--non-bootable", + action="store_true", + help=_("Mark volume as non-bootable") + ) return parser def take_action(self, parsed_args): @@ -382,7 +393,12 @@ class SetVolume(command.Command): if parsed_args.property: volume_client.volumes.set_metadata(volume.id, parsed_args.property) - + if parsed_args.bootable or parsed_args.non_bootable: + try: + volume_client.volumes.set_bootable( + volume.id, parsed_args.bootable) + except Exception as e: + LOG.error(_("Failed to set volume bootable property: %s"), e) kwargs = {} if parsed_args.name: kwargs['display_name'] = parsed_args.name diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py index 28946a5f7..804e23372 100644 --- a/openstackclient/volume/v2/volume.py +++ b/openstackclient/volume/v2/volume.py @@ -404,6 +404,17 @@ class SetVolume(command.Command): '"deleting", "in-use", "attaching", "detaching", ' '"error_deleting" or "maintenance")'), ) + bootable_group = parser.add_mutually_exclusive_group() + bootable_group.add_argument( + "--bootable", + action="store_true", + help=_("Mark volume as bootable") + ) + bootable_group.add_argument( + "--non-bootable", + action="store_true", + help=_("Mark volume as non-bootable") + ) return parser def take_action(self, parsed_args): @@ -446,6 +457,13 @@ class SetVolume(command.Command): except Exception as e: LOG.error(_("Failed to set volume state: %s"), e) result += 1 + if parsed_args.bootable or parsed_args.non_bootable: + try: + volume_client.volumes.set_bootable( + volume.id, parsed_args.bootable) + except Exception as e: + LOG.error(_("Failed to set volume bootable property: %s"), e) + result += 1 kwargs = {} if parsed_args.name: diff --git a/releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml b/releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml new file mode 100644 index 000000000..5d9077010 --- /dev/null +++ b/releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Add ``--bootable`` and ``--non-bootable`` options to ``os volume set`` + command to mark volume as bootable or non-bootable. + [Bug `1535704 `_] \ No newline at end of file