Add method to set bootable flag on volumes
If a person wants to create a bootable volume not from an image, they need to set a flag, which is done with this action call. Change-Id: I765eb97501a5ba9e54325c8c56573bb7311deb72
This commit is contained in:
parent
b653090489
commit
8cda430e8b
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Added a ``set_volume_bootable`` call to allow toggling the bootable state
|
||||
of a volume.
|
@ -4806,7 +4806,7 @@ class OpenStackCloud(
|
||||
|
||||
def create_volume(
|
||||
self, size,
|
||||
wait=True, timeout=None, image=None, **kwargs):
|
||||
wait=True, timeout=None, image=None, bootable=None, **kwargs):
|
||||
"""Create a volume.
|
||||
|
||||
:param size: Size, in GB of the volume to create.
|
||||
@ -4816,6 +4816,8 @@ class OpenStackCloud(
|
||||
:param timeout: Seconds to wait for volume creation. None is forever.
|
||||
:param image: (optional) Image name, ID or object from which to create
|
||||
the volume
|
||||
:param bootable: (optional) Make this volume bootable. If set, wait
|
||||
will also be set to true.
|
||||
:param kwargs: Keyword arguments as expected for cinder client.
|
||||
|
||||
:returns: The created volume object.
|
||||
@ -4823,6 +4825,9 @@ class OpenStackCloud(
|
||||
:raises: OpenStackCloudTimeout if wait time exceeded.
|
||||
:raises: OpenStackCloudException on operation error.
|
||||
"""
|
||||
if bootable is not None:
|
||||
wait = True
|
||||
|
||||
if image:
|
||||
image_obj = self.get_image(image)
|
||||
if not image_obj:
|
||||
@ -4858,6 +4863,10 @@ class OpenStackCloud(
|
||||
continue
|
||||
|
||||
if volume['status'] == 'available':
|
||||
if bootable is not None:
|
||||
self.set_volume_bootable(volume, bootable=bootable)
|
||||
# no need to re-fetch to update the flag, just set it.
|
||||
volume['bootable'] = bootable
|
||||
return volume
|
||||
|
||||
if volume['status'] == 'error':
|
||||
@ -4865,6 +4874,31 @@ class OpenStackCloud(
|
||||
|
||||
return self._normalize_volume(volume)
|
||||
|
||||
def set_volume_bootable(self, name_or_id, bootable=True):
|
||||
"""Set a volume's bootable flag.
|
||||
|
||||
:param name_or_id: Name, unique ID of the volume or a volume dict.
|
||||
:param bool bootable: Whether the volume should be bootable.
|
||||
(Defaults to True)
|
||||
|
||||
:raises: OpenStackCloudTimeout if wait time exceeded.
|
||||
:raises: OpenStackCloudException on operation error.
|
||||
"""
|
||||
|
||||
volume = self.get_volume(name_or_id)
|
||||
|
||||
if not volume:
|
||||
raise OpenStackCloudException(
|
||||
"Volume {name_or_id} does not exist".format(
|
||||
name_or_id=name_or_id))
|
||||
|
||||
self._volume_client.post(
|
||||
'volumes/{id}/action'.format(id=volume['id']),
|
||||
json={'os-set_bootable': {'bootable': bootable}},
|
||||
error_message="Error setting bootable on volume {volume}".format(
|
||||
volume=volume['id'])
|
||||
)
|
||||
|
||||
def delete_volume(self, name_or_id=None, wait=True, timeout=None,
|
||||
force=False):
|
||||
"""Delete a volume.
|
||||
|
@ -292,7 +292,8 @@ class TestVolume(base.RequestsMockTestCase):
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', volume.id, 'action']),
|
||||
json={'os-force_delete': None}),
|
||||
validate=dict(
|
||||
json={'os-force_delete': None})),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public', append=['volumes', 'detail']),
|
||||
@ -300,6 +301,42 @@ class TestVolume(base.RequestsMockTestCase):
|
||||
self.assertTrue(self.cloud.delete_volume(volume['id'], force=True))
|
||||
self.assert_calls()
|
||||
|
||||
def test_set_volume_bootable(self):
|
||||
vol = {'id': 'volume001', 'status': 'attached',
|
||||
'name': '', 'attachments': []}
|
||||
volume = meta.obj_to_munch(fakes.FakeVolume(**vol))
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public', append=['volumes', 'detail']),
|
||||
json={'volumes': [volume]}),
|
||||
dict(method='POST',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', volume.id, 'action']),
|
||||
json={'os-set_bootable': {'bootable': True}}),
|
||||
])
|
||||
self.cloud.set_volume_bootable(volume['id'])
|
||||
self.assert_calls()
|
||||
|
||||
def test_set_volume_bootable_false(self):
|
||||
vol = {'id': 'volume001', 'status': 'attached',
|
||||
'name': '', 'attachments': []}
|
||||
volume = meta.obj_to_munch(fakes.FakeVolume(**vol))
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public', append=['volumes', 'detail']),
|
||||
json={'volumes': [volume]}),
|
||||
dict(method='POST',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', volume.id, 'action']),
|
||||
json={'os-set_bootable': {'bootable': False}}),
|
||||
])
|
||||
self.cloud.set_volume_bootable(volume['id'])
|
||||
self.assert_calls()
|
||||
|
||||
def test_list_volumes_with_pagination(self):
|
||||
vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1'))
|
||||
vol2 = meta.obj_to_munch(fakes.FakeVolume('02', 'available', 'vol2'))
|
||||
@ -448,3 +485,53 @@ class TestVolume(base.RequestsMockTestCase):
|
||||
self.cloud._normalize_volume(vol1),
|
||||
self.cloud.get_volume_by_id('01'))
|
||||
self.assert_calls()
|
||||
|
||||
def test_create_volume(self):
|
||||
vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1'))
|
||||
self.register_uris([
|
||||
dict(method='POST',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public', append=['volumes']),
|
||||
json={'volume': vol1},
|
||||
validate=dict(json={
|
||||
'volume': {
|
||||
'size': 50,
|
||||
'name': 'vol1',
|
||||
}})),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', 'detail']),
|
||||
json={'volumes': [vol1]}),
|
||||
])
|
||||
|
||||
self.cloud.create_volume(50, name='vol1')
|
||||
self.assert_calls()
|
||||
|
||||
def test_create_bootable_volume(self):
|
||||
vol1 = meta.obj_to_munch(fakes.FakeVolume('01', 'available', 'vol1'))
|
||||
self.register_uris([
|
||||
dict(method='POST',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public', append=['volumes']),
|
||||
json={'volume': vol1},
|
||||
validate=dict(json={
|
||||
'volume': {
|
||||
'size': 50,
|
||||
'name': 'vol1',
|
||||
}})),
|
||||
dict(method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', 'detail']),
|
||||
json={'volumes': [vol1]}),
|
||||
dict(method='POST',
|
||||
uri=self.get_mock_url(
|
||||
'volumev2', 'public',
|
||||
append=['volumes', '01', 'action']),
|
||||
validate=dict(
|
||||
json={'os-set_bootable': {'bootable': True}})),
|
||||
])
|
||||
|
||||
self.cloud.create_volume(50, name='vol1', bootable=True)
|
||||
self.assert_calls()
|
||||
|
Loading…
Reference in New Issue
Block a user