Support programmatic use of disk config extension
Allow servers to be created, resized, and rebuilt with the disk_config option: http://api.openstack.org/api-ref.html#ext-os-disk-config There is a separate extension that exists for disk config already, but it only works via the novaclient CLI interface, not via programmatic use of python-novaclient as a library. assert changes in tests/v1_1/fakes allow for other data in rebuild and resize requests. Change-Id: I8051ffb8747cf5c67b0199d22fbbe80306b01499
This commit is contained in:
parent
4ab2b60850
commit
0d454089c9
novaclient
@ -231,7 +231,7 @@ class BootingManagerWithFind(ManagerWithFind):
|
||||
max_count=None, security_groups=None, key_name=None,
|
||||
availability_zone=None, block_device_mapping=None, nics=None,
|
||||
scheduler_hints=None, config_drive=None, admin_pass=None,
|
||||
**kwargs):
|
||||
disk_config=None, **kwargs):
|
||||
"""
|
||||
Create (boot) a new server.
|
||||
|
||||
@ -264,6 +264,8 @@ class BootingManagerWithFind(ManagerWithFind):
|
||||
:param config_drive: (optional extension) value for config drive
|
||||
either boolean, or volume-id
|
||||
:param admin_pass: admin password for the server.
|
||||
:param disk_config: (optional extension) control how the disk is
|
||||
partitioned when the server is created.
|
||||
"""
|
||||
body = {"server": {
|
||||
"name": name,
|
||||
@ -360,6 +362,9 @@ class BootingManagerWithFind(ManagerWithFind):
|
||||
all_net_data.append(net_data)
|
||||
body['server']['networks'] = all_net_data
|
||||
|
||||
if disk_config is not None:
|
||||
body['server']['OS-DCF:diskConfig'] = disk_config
|
||||
|
||||
return self._create(resource_url, body, response_key,
|
||||
return_raw=return_raw, **kwargs)
|
||||
|
||||
|
@ -473,10 +473,11 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
keys = body[action].keys()
|
||||
if 'adminPass' in keys:
|
||||
keys.remove('adminPass')
|
||||
assert keys == ['imageRef']
|
||||
assert 'imageRef' in keys
|
||||
_body = self.get_servers_1234()[2]
|
||||
elif action == 'resize':
|
||||
assert body[action].keys() == ['flavorRef']
|
||||
keys = body[action].keys()
|
||||
assert 'flavorRef' in keys
|
||||
elif action == 'confirmResize':
|
||||
assert body[action] is None
|
||||
# This one method returns a different response code
|
||||
|
@ -135,6 +135,29 @@ class ServersTest(utils.TestCase):
|
||||
cs.assert_called('POST', '/servers')
|
||||
self.assertTrue(isinstance(s, servers.Server))
|
||||
|
||||
def _create_disk_config(self, disk_config):
|
||||
s = cs.servers.create(
|
||||
name="My server",
|
||||
image=1,
|
||||
flavor=1,
|
||||
disk_config=disk_config
|
||||
)
|
||||
cs.assert_called('POST', '/servers')
|
||||
self.assertTrue(isinstance(s, servers.Server))
|
||||
|
||||
# verify disk config param was used in the request:
|
||||
last_request = cs.client.callstack[-1]
|
||||
body = last_request[-1]
|
||||
server = body['server']
|
||||
self.assertTrue('OS-DCF:diskConfig' in server)
|
||||
self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
|
||||
|
||||
def test_create_server_disk_config_auto(self):
|
||||
self._create_disk_config('AUTO')
|
||||
|
||||
def test_create_server_disk_config_manual(self):
|
||||
self._create_disk_config('MANUAL')
|
||||
|
||||
def test_update_server(self):
|
||||
s = cs.servers.get(1234)
|
||||
|
||||
@ -199,6 +222,29 @@ class ServersTest(utils.TestCase):
|
||||
cs.servers.rebuild(s, image=1, password='5678')
|
||||
cs.assert_called('POST', '/servers/1234/action')
|
||||
|
||||
def _rebuild_resize_disk_config(self, disk_config, operation="rebuild"):
|
||||
s = cs.servers.get(1234)
|
||||
|
||||
if operation == "rebuild":
|
||||
s.rebuild(image=1, disk_config=disk_config)
|
||||
elif operation == "resize":
|
||||
s.resize(flavor=1, disk_config=disk_config)
|
||||
cs.assert_called('POST', '/servers/1234/action')
|
||||
|
||||
# verify disk config param was used in the request:
|
||||
last_request = cs.client.callstack[-1]
|
||||
body = last_request[-1]
|
||||
|
||||
d = body[operation]
|
||||
self.assertTrue('OS-DCF:diskConfig' in d)
|
||||
self.assertEqual(disk_config, d['OS-DCF:diskConfig'])
|
||||
|
||||
def test_rebuild_server_disk_config_auto(self):
|
||||
self._rebuild_resize_disk_config('AUTO')
|
||||
|
||||
def test_rebuild_server_disk_config_manual(self):
|
||||
self._rebuild_resize_disk_config('MANUAL')
|
||||
|
||||
def test_resize_server(self):
|
||||
s = cs.servers.get(1234)
|
||||
s.resize(flavor=1)
|
||||
@ -206,6 +252,12 @@ class ServersTest(utils.TestCase):
|
||||
cs.servers.resize(s, flavor=1)
|
||||
cs.assert_called('POST', '/servers/1234/action')
|
||||
|
||||
def test_resize_server_disk_config_auto(self):
|
||||
self._rebuild_resize_disk_config('AUTO', 'resize')
|
||||
|
||||
def test_resize_server_disk_config_manual(self):
|
||||
self._rebuild_resize_disk_config('MANUAL', 'resize')
|
||||
|
||||
def test_confirm_resized_server(self):
|
||||
s = cs.servers.get(1234)
|
||||
s.confirm_resize()
|
||||
|
@ -570,7 +570,7 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
max_count=None, security_groups=None, userdata=None,
|
||||
key_name=None, availability_zone=None,
|
||||
block_device_mapping=None, nics=None, scheduler_hints=None,
|
||||
config_drive=None, **kwargs):
|
||||
config_drive=None, disk_config=None, **kwargs):
|
||||
# TODO(anthony): indicate in doc string if param is an extension
|
||||
# and/or optional
|
||||
"""
|
||||
@ -604,6 +604,9 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
specified by the client to help boot an instance
|
||||
:param config_drive: (optional extension) value for config drive
|
||||
either boolean, or volume-id
|
||||
:param disk_config: (optional extension) control how the disk is
|
||||
partitioned when the server is created. possible
|
||||
values are 'AUTO' or 'MANUAL'.
|
||||
"""
|
||||
if not min_count:
|
||||
min_count = 1
|
||||
@ -620,7 +623,7 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
max_count=max_count, security_groups=security_groups,
|
||||
key_name=key_name, availability_zone=availability_zone,
|
||||
scheduler_hints=scheduler_hints, config_drive=config_drive,
|
||||
**kwargs)
|
||||
disk_config=disk_config, **kwargs)
|
||||
|
||||
if block_device_mapping:
|
||||
resource_url = "/os-volumes_boot"
|
||||
@ -674,17 +677,23 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
"""
|
||||
self._action('reboot', server, {'type': reboot_type})
|
||||
|
||||
def rebuild(self, server, image, password=None, **kwargs):
|
||||
def rebuild(self, server, image, password=None, disk_config=None,
|
||||
**kwargs):
|
||||
"""
|
||||
Rebuild -- shut down and then re-image -- a server.
|
||||
|
||||
:param server: The :class:`Server` (or its ID) to share onto.
|
||||
:param image: the :class:`Image` (or its ID) to re-image with.
|
||||
:param password: string to set as password on the rebuilt server.
|
||||
:param disk_config: partitioning mode to use on the rebuilt server.
|
||||
Valid values are 'AUTO' or 'MANUAL'
|
||||
"""
|
||||
body = {'imageRef': base.getid(image)}
|
||||
if password is not None:
|
||||
body['adminPass'] = password
|
||||
if disk_config is not None:
|
||||
body['OS-DCF:diskConfig'] = disk_config
|
||||
|
||||
_resp, body = self._action('rebuild', server, body, **kwargs)
|
||||
return Server(self, body['server'])
|
||||
|
||||
@ -696,12 +705,14 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
"""
|
||||
self._action('migrate', server)
|
||||
|
||||
def resize(self, server, flavor, **kwargs):
|
||||
def resize(self, server, flavor, disk_config=None, **kwargs):
|
||||
"""
|
||||
Resize a server's resources.
|
||||
|
||||
:param server: The :class:`Server` (or its ID) to share onto.
|
||||
:param flavor: the :class:`Flavor` (or its ID) to resize to.
|
||||
:param disk_config: partitioning mode to use on the rebuilt server.
|
||||
Valid values are 'AUTO' or 'MANUAL'
|
||||
|
||||
Until a resize event is confirmed with :meth:`confirm_resize`, the old
|
||||
server will be kept around and you'll be able to roll back to the old
|
||||
@ -709,6 +720,9 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
automatically confirmed after 24 hours.
|
||||
"""
|
||||
info = {'flavorRef': base.getid(flavor)}
|
||||
if disk_config is not None:
|
||||
info['OS-DCF:diskConfig'] = disk_config
|
||||
|
||||
self._action('resize', server, info=info, **kwargs)
|
||||
|
||||
def confirm_resize(self, server):
|
||||
|
Loading…
x
Reference in New Issue
Block a user