Skip to content

Instantly share code, notes, and snippets.

@mgagne
Created May 2, 2016 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgagne/161bd7eaeb4c747fa1ae97c0bc43c093 to your computer and use it in GitHub Desktop.
Save mgagne/161bd7eaeb4c747fa1ae97c0bc43c093 to your computer and use it in GitHub Desktop.
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