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
This commit is contained in:
qtang 2016-08-25 10:56:58 +08:00 committed by Dean Troyer
parent d2273ecea5
commit 6a914d0056
8 changed files with 126 additions and 1 deletions

View File

@ -193,6 +193,7 @@ Set volume properties
[--property <key=value> [...] ]
[--image-property <key=value> [...] ]
[--state <state>]
[--bootable | --non-bootable]
<volume>
.. option:: --name <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 <key=value>
Set an image property on this volume

View File

@ -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)

View File

@ -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)

View File

@ -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])

View File

@ -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):

View File

@ -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

View File

@ -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:

View File

@ -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 <https://bugs.launchpad.net/bugs/1535704>`_]