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:
parent
d2273ecea5
commit
6a914d0056
@ -193,6 +193,7 @@ Set volume properties
|
|||||||
[--property <key=value> [...] ]
|
[--property <key=value> [...] ]
|
||||||
[--image-property <key=value> [...] ]
|
[--image-property <key=value> [...] ]
|
||||||
[--state <state>]
|
[--state <state>]
|
||||||
|
[--bootable | --non-bootable]
|
||||||
<volume>
|
<volume>
|
||||||
|
|
||||||
.. option:: --name <name>
|
.. option:: --name <name>
|
||||||
@ -211,6 +212,14 @@ Set volume properties
|
|||||||
|
|
||||||
Set a property on this volume (repeat option to set multiple 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>
|
.. option:: --image-property <key=value>
|
||||||
|
|
||||||
Set an image property on this volume
|
Set an image property on this volume
|
||||||
|
@ -75,3 +75,14 @@ class VolumeTests(common.BaseVolumeTests):
|
|||||||
opts = self.get_opts(["display_name", "size"])
|
opts = self.get_opts(["display_name", "size"])
|
||||||
raw_output = self.openstack('volume show ' + self.NAME + opts)
|
raw_output = self.openstack('volume show ' + self.NAME + opts)
|
||||||
self.assertEqual(self.NAME + "\n2\n", raw_output)
|
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)
|
||||||
|
@ -91,6 +91,17 @@ class VolumeTests(common.BaseVolumeTests):
|
|||||||
raw_output = self.openstack('volume show ' + self.NAME + opts)
|
raw_output = self.openstack('volume show ' + self.NAME + opts)
|
||||||
self.assertEqual(self.NAME + "\n2\n", raw_output)
|
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):
|
def test_volume_snapshot(self):
|
||||||
opts = self.get_opts(self.FIELDS)
|
opts = self.get_opts(self.FIELDS)
|
||||||
|
|
||||||
|
@ -844,6 +844,8 @@ class TestVolumeSet(TestVolume):
|
|||||||
('size', None),
|
('size', None),
|
||||||
('property', {'myprop': 'myvalue'}),
|
('property', {'myprop': 'myvalue'}),
|
||||||
('volume', volume_fakes.volume_name),
|
('volume', volume_fakes.volume_name),
|
||||||
|
('bootable', False),
|
||||||
|
('non_bootable', False)
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -858,3 +860,28 @@ class TestVolumeSet(TestVolume):
|
|||||||
metadata
|
metadata
|
||||||
)
|
)
|
||||||
self.assertIsNone(result)
|
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])
|
||||||
|
@ -905,6 +905,8 @@ class TestVolumeSet(TestVolume):
|
|||||||
verifylist = [
|
verifylist = [
|
||||||
('image_property', {'Alpha': 'a', 'Beta': 'b'}),
|
('image_property', {'Alpha': 'a', 'Beta': 'b'}),
|
||||||
('volume', self.new_volume.id),
|
('volume', self.new_volume.id),
|
||||||
|
('bootable', False),
|
||||||
|
('non_bootable', False)
|
||||||
]
|
]
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
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.volumes_mock.reset_state.assert_called_with(
|
||||||
self.new_volume.id, 'error')
|
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):
|
class TestVolumeShow(TestVolume):
|
||||||
|
|
||||||
|
@ -363,6 +363,17 @@ class SetVolume(command.Command):
|
|||||||
help=_('Set a property on this volume '
|
help=_('Set a property on this volume '
|
||||||
'(repeat option to set multiple properties)'),
|
'(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
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -382,7 +393,12 @@ class SetVolume(command.Command):
|
|||||||
|
|
||||||
if parsed_args.property:
|
if parsed_args.property:
|
||||||
volume_client.volumes.set_metadata(volume.id, 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 = {}
|
kwargs = {}
|
||||||
if parsed_args.name:
|
if parsed_args.name:
|
||||||
kwargs['display_name'] = parsed_args.name
|
kwargs['display_name'] = parsed_args.name
|
||||||
|
@ -404,6 +404,17 @@ class SetVolume(command.Command):
|
|||||||
'"deleting", "in-use", "attaching", "detaching", '
|
'"deleting", "in-use", "attaching", "detaching", '
|
||||||
'"error_deleting" or "maintenance")'),
|
'"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
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -446,6 +457,13 @@ class SetVolume(command.Command):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error(_("Failed to set volume state: %s"), e)
|
LOG.error(_("Failed to set volume state: %s"), e)
|
||||||
result += 1
|
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 = {}
|
kwargs = {}
|
||||||
if parsed_args.name:
|
if parsed_args.name:
|
||||||
|
6
releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml
Normal file
6
releasenotes/notes/bug-1535704-d6f013bfa22ab668.yaml
Normal 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>`_]
|
Loading…
Reference in New Issue
Block a user