From 1d00dfcfbb9bdeff358503fefefc7e6e7b4903eb Mon Sep 17 00:00:00 2001 From: Nikola Dipanov Date: Wed, 7 Nov 2012 18:56:35 +0100 Subject: Boot from volume without image supplied This patch allows for booting instances without supplying an image if there is block device mapping supplied. It makes changes to nova API and compute services to handle requests that do not have any image supplied. Also it makes rescue and rebuild work with instances started from volume. Finally the patch introduces tests to make sure the system acts as expected, and in the process fixes and refactors some old tests to make them test for cases this new functionality can introduce. This patch is intended to be a proof of concept and a first step towards a more cleaner interface for booting from volumes, outlined in https://etherpad.openstack.org/grizzly-boot-from-volumes. This patch also introduces a slight modification of the nova API so I am flagging it with DocImpact. The change is that if the os-volumes extension is used ImageRef does not need to be supplied to the create server API call provided there is block_device_mapping provided. Also note that this is the first step towards introducing a 'volume' parameter for starting instances which will replace the somewhat unintuitive block_device_mapping (they will still be used but not for the boot device). This patch is coupled with I5ba9b0f35a5084aa91eca260f46cac83b8b6591e that provides changes to the nova client. Implements: blueprint improve-boot-from-volume Fixes bug #1008622 Change-Id: I530760cfaa5eb0cae590c7383e0840c6b3f896b9 --- nova/api/openstack/compute/servers.py | 23 ++++++++++++++++++++--- nova/api/openstack/compute/views/servers.py | 25 ++++++++++++++----------- 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index 9c019f78f..68c5372c3 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -743,8 +743,7 @@ class Controller(wsgi.Controller): self._validate_server_name(name) name = name.strip() - image_href = self._image_ref_from_req_data(body) - image_href = self._image_uuid_from_href(image_href) + image_uuid = self._image_from_req_data(body) personality = server_dict.get('personality') config_drive = None @@ -855,7 +854,7 @@ class Controller(wsgi.Controller): (instances, resv_id) = self.compute_api.create(context, inst_type, - image_href, + image_uuid, display_name=name, display_description=name, key_name=key_name, @@ -1108,6 +1107,24 @@ class Controller(wsgi.Controller): return image_uuid + def _image_from_req_data(self, data): + """ + Get image data from the request or raise appropriate + exceptions + + If no image is supplied - checks to see if there is + block devices set and proper extesions loaded. + """ + image_ref = data['server'].get('imageRef') + bdm = data['server'].get('block_device_mapping') + + if not image_ref and bdm and self.ext_mgr.is_loaded('os-volumes'): + return '' + else: + image_href = self._image_ref_from_req_data(data) + image_uuid = self._image_uuid_from_href(image_href) + return image_uuid + def _flavor_id_from_req_data(self, data): try: flavor_ref = data['server']['flavorRef'] diff --git a/nova/api/openstack/compute/views/servers.py b/nova/api/openstack/compute/views/servers.py index b423b37d4..d281f6a61 100644 --- a/nova/api/openstack/compute/views/servers.py +++ b/nova/api/openstack/compute/views/servers.py @@ -164,17 +164,20 @@ class ViewBuilder(common.ViewBuilder): def _get_image(self, request, instance): image_ref = instance["image_ref"] - image_id = str(common.get_id_from_href(image_ref)) - bookmark = self._image_builder._get_bookmark_link(request, - image_id, - "images") - return { - "id": image_id, - "links": [{ - "rel": "bookmark", - "href": bookmark, - }], - } + if image_ref: + image_id = str(common.get_id_from_href(image_ref)) + bookmark = self._image_builder._get_bookmark_link(request, + image_id, + "images") + return { + "id": image_id, + "links": [{ + "rel": "bookmark", + "href": bookmark, + }], + } + else: + return "" def _get_flavor(self, request, instance): instance_type = instance["instance_type"] -- cgit