Force boot from volume
From: =?UTF-8?q?Mathieu=20Gagn=C3=A9?= <mgagne@iweb.com> | |
Date: Tue, 25 Feb 2014 13:38:00 -0500 | |
Subject: Add FlavorDiskBackendMiddleware | |
Adds the ability to change default disk backend from flavor extra_specs by | |
setting 'disk:default_backend' to 'volume'. | |
--- | |
.../compute/plugins/v3/flavor_diskbackend.py | 104 ++++++++++++++++++++ | |
1 file changed, 104 insertions(+) | |
create mode 100644 nova/api/openstack/compute/plugins/v3/flavor_diskbackend.py | |
diff --git a/nova/api/openstack/compute/plugins/v3/flavor_diskbackend.py b/nova/api/openstack/compute/plugins/v3/flavor_diskbackend.py | |
new file mode 100644 | |
index 0000000..ed4fcef | |
--- /dev/null | |
+++ b/nova/api/openstack/compute/plugins/v3/flavor_diskbackend.py | |
@@ -0,0 +1,104 @@ | |
+""" | |
+Flavor default disk backend Middleware plugin. | |
+ | |
+Adds the ability to change default disk backend from flavor extra_specs by | |
+setting 'disk:default_backend' to 'volume'. | |
+ | |
+This middleware plugin should be added to the openstack_compute_api_v2 pipeline | |
+defined in the paste config, /etc/nova/api-paste.ini | |
+ | |
+The filter should be added to the pipeline just before the osapi_compute_app_v2: | |
+ | |
+ [filter:flavor_diskbackend] | |
+ paste.filter_factory = nova.api.openstack.compute.plugins.v3.flavor_diskbackend:FlavorDiskBackendMiddleware.factory | |
+ | |
+ [composite:openstack_compute_api_v2] | |
+ use = call:nova.api.auth:pipeline_factory | |
+ noauth = faultwrap sizelimit noauth ratelimit flavor_diskbackend osapi_compute_app_v2 | |
+ keystone = faultwrap sizelimit authtoken keystonecontext ratelimit flavor_diskbackend osapi_compute_app_v2 | |
+ keystone_nolimit = faultwrap sizelimit authtoken keystonecontext flavor_diskbackend osapi_compute_app_v2 | |
+""" | |
+ | |
+import json | |
+import posixpath | |
+ | |
+from oslo_log import log as logging | |
+import webob.dec | |
+import webob.exc | |
+ | |
+from nova.api.openstack import wsgi | |
+from nova import db | |
+from nova import exception | |
+from nova import wsgi as base_wsgi | |
+ | |
+ | |
+LOG = logging.getLogger(__name__) | |
+ | |
+ | |
+class FlavorDiskBackendMiddleware(base_wsgi.Middleware): | |
+ | |
+ @webob.dec.wsgify(RequestClass=wsgi.Request) | |
+ def __call__(self, request): | |
+ method = request.method | |
+ path = posixpath.normpath(request.path) | |
+ path_tokens = path.split('/')[1:] | |
+ # path_tokens[0] == version | |
+ # path_tokens[1] == project_id | |
+ # path_tokens[2] == resource | |
+ if (len(path_tokens) < 3): | |
+ return self.application | |
+ resource = path_tokens[2] | |
+ LOG.debug("Resource=%s Method=%s" % (resource, method)) | |
+ if method == 'POST' and resource == 'servers': | |
+ self._create_server(request) | |
+ return self.application | |
+ | |
+ def _create_server(self, request): | |
+ LOG.debug('Processing server create') | |
+ ctxt = request.environ.get("nova.context") | |
+ payload = json.loads(request.body) | |
+ server = payload.get('server') | |
+ | |
+ if not server: | |
+ return | |
+ if 'block_device_mapping' in server: | |
+ return | |
+ if 'block_device_mapping_v2' in server: | |
+ return | |
+ | |
+ flavor_id = server.get('flavorRef') | |
+ if not flavor_id: | |
+ return | |
+ | |
+ try: | |
+ extra_specs = db.flavor_extra_specs_get(ctxt, flavor_id) | |
+ except exception.NotFound: | |
+ return | |
+ | |
+ default_backend = extra_specs.get('disk:default_backend', 'local') | |
+ if default_backend != 'volume': | |
+ return | |
+ | |
+ image_id = server.get('imageRef') | |
+ if not image_id: | |
+ return | |
+ | |
+ # NOTE(mgagne) When using BFV, imageRef must be empty | |
+ server['imageRef'] = '' | |
+ | |
+ flavor = db.flavor_get_by_flavor_id(ctxt, flavor_id) | |
+ | |
+ # NOTE(mgagne) Use root_gb from flavor as volume size | |
+ server['block_device_mapping_v2'] = [{ | |
+ 'source_type': 'image', | |
+ 'boot_index': '0', | |
+ 'destination_type': 'volume', | |
+ 'uuid': image_id, | |
+ 'volume_size': flavor['root_gb'], | |
+ 'delete_on_termination': True, | |
+ }] | |
+ | |
+ payload['server'] = server | |
+ request.body = json.dumps(payload) | |
+ LOG.debug('Create payload rewritten for boot-from-volume') | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment