summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-04-30 21:18:34 +0000
committerGerrit Code Review <review@openstack.org>2012-04-30 21:18:34 +0000
commit89be02810fd02497beaf8541b35345c31c03bde0 (patch)
treeb697eda53fbb64e203c42f7abfdfcf53884a739d /nova/api
parent62bcf379597c15606fca6a0255dc731a048a5029 (diff)
parent15c0847341b2a182019c865ec787c129fb21dae6 (diff)
downloadnova-89be02810fd02497beaf8541b35345c31c03bde0.tar.gz
nova-89be02810fd02497beaf8541b35345c31c03bde0.tar.xz
nova-89be02810fd02497beaf8541b35345c31c03bde0.zip
Merge "Port types and extra specs to volume api"
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/volumetypes.py27
-rw-r--r--nova/api/openstack/volume/contrib/types_extra_specs.py152
-rw-r--r--nova/api/openstack/volume/contrib/types_manage.py91
3 files changed, 249 insertions, 21 deletions
diff --git a/nova/api/openstack/compute/contrib/volumetypes.py b/nova/api/openstack/compute/contrib/volumetypes.py
index 16a423f80..4255ac149 100644
--- a/nova/api/openstack/compute/contrib/volumetypes.py
+++ b/nova/api/openstack/compute/contrib/volumetypes.py
@@ -85,8 +85,6 @@ class VolumeTypesController(object):
try:
volume_types.create(context, name, specs)
vol_type = volume_types.get_volume_type_by_name(context, name)
- except exception.QuotaError as error:
- self._handle_quota_error(error)
except exception.NotFound:
raise exc.HTTPNotFound()
@@ -171,12 +169,9 @@ class VolumeTypeExtraSpecsController(object):
authorize(context)
self._check_body(body)
specs = body.get('extra_specs')
- try:
- db.volume_type_extra_specs_update_or_create(context,
- vol_type_id,
- specs)
- except exception.QuotaError as error:
- self._handle_quota_error(error)
+ db.volume_type_extra_specs_update_or_create(context,
+ vol_type_id,
+ specs)
return body
@wsgi.serializers(xml=VolumeTypeExtraSpecTemplate)
@@ -190,13 +185,9 @@ class VolumeTypeExtraSpecsController(object):
if len(body) > 1:
expl = _('Request body contains too many items')
raise exc.HTTPBadRequest(explanation=expl)
- try:
- db.volume_type_extra_specs_update_or_create(context,
- vol_type_id,
- body)
- except exception.QuotaError as error:
- self._handle_quota_error(error)
-
+ db.volume_type_extra_specs_update_or_create(context,
+ vol_type_id,
+ body)
return body
@wsgi.serializers(xml=VolumeTypeExtraSpecTemplate)
@@ -216,12 +207,6 @@ class VolumeTypeExtraSpecsController(object):
authorize(context)
db.volume_type_extra_specs_delete(context, vol_type_id, id)
- def _handle_quota_error(self, error):
- """Reraise quota errors as api-specific http exceptions."""
- if error.code == "MetadataLimitExceeded":
- raise exc.HTTPBadRequest(explanation=error.message)
- raise error
-
class Volumetypes(extensions.ExtensionDescriptor):
"""Volume types support"""
diff --git a/nova/api/openstack/volume/contrib/types_extra_specs.py b/nova/api/openstack/volume/contrib/types_extra_specs.py
new file mode 100644
index 000000000..d70e24538
--- /dev/null
+++ b/nova/api/openstack/volume/contrib/types_extra_specs.py
@@ -0,0 +1,152 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Zadara Storage Inc.
+# Copyright (c) 2011 OpenStack LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""The volume types extra specs extension"""
+
+import webob
+
+from nova.api.openstack import extensions
+from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
+from nova import db
+from nova import exception
+from nova.volume import volume_types
+
+
+authorize = extensions.extension_authorizer('volume', 'types_extra_specs')
+
+
+class VolumeTypeExtraSpecsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.make_flat_dict('extra_specs', selector='extra_specs')
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypeExtraSpecTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ tagname = xmlutil.Selector('key')
+
+ def extraspec_sel(obj, do_raise=False):
+ # Have to extract the key and value for later use...
+ key, value = obj.items()[0]
+ return dict(key=key, value=value)
+
+ root = xmlutil.TemplateElement(tagname, selector=extraspec_sel)
+ root.text = 'value'
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class VolumeTypeExtraSpecsController(object):
+ """ The volume type extra specs API controller for the OpenStack API """
+
+ def _get_extra_specs(self, context, type_id):
+ extra_specs = db.volume_type_extra_specs_get(context, type_id)
+ specs_dict = {}
+ for key, value in extra_specs.iteritems():
+ specs_dict[key] = value
+ return dict(extra_specs=specs_dict)
+
+ def _check_body(self, body):
+ if not body:
+ expl = _('No Request Body')
+ raise webob.exc.HTTPBadRequest(explanation=expl)
+
+ def _check_type(self, context, type_id):
+ try:
+ volume_types.get_volume_type(context, type_id)
+ except exception.NotFound as ex:
+ raise webob.exc.HTTPNotFound(explanation=unicode(ex))
+
+ @wsgi.serializers(xml=VolumeTypeExtraSpecsTemplate)
+ def index(self, req, type_id):
+ """ Returns the list of extra specs for a given volume type """
+ context = req.environ['nova.context']
+ authorize(context)
+ self._check_type(context, type_id)
+ return self._get_extra_specs(context, type_id)
+
+ @wsgi.serializers(xml=VolumeTypeExtraSpecsTemplate)
+ def create(self, req, type_id, body=None):
+ context = req.environ['nova.context']
+ authorize(context)
+ self._check_type(context, type_id)
+ self._check_body(body)
+ specs = body.get('extra_specs')
+ if not isinstance(specs, dict):
+ expl = _('Malformed extra specs')
+ raise webob.exc.HTTPBadRequest(explanation=expl)
+ db.volume_type_extra_specs_update_or_create(context,
+ type_id,
+ specs)
+ return body
+
+ @wsgi.serializers(xml=VolumeTypeExtraSpecTemplate)
+ def update(self, req, type_id, id, body=None):
+ context = req.environ['nova.context']
+ authorize(context)
+ self._check_type(context, type_id)
+ self._check_body(body)
+ if not id in body:
+ expl = _('Request body and URI mismatch')
+ raise webob.exc.HTTPBadRequest(explanation=expl)
+ if len(body) > 1:
+ expl = _('Request body contains too many items')
+ raise webob.exc.HTTPBadRequest(explanation=expl)
+ db.volume_type_extra_specs_update_or_create(context,
+ type_id,
+ body)
+ return body
+
+ @wsgi.serializers(xml=VolumeTypeExtraSpecTemplate)
+ def show(self, req, type_id, id):
+ """Return a single extra spec item."""
+ context = req.environ['nova.context']
+ authorize(context)
+ self._check_type(context, type_id)
+ specs = self._get_extra_specs(context, type_id)
+ if id in specs['extra_specs']:
+ return {id: specs['extra_specs'][id]}
+ else:
+ raise webob.exc.HTTPNotFound()
+
+ def delete(self, req, type_id, id):
+ """ Deletes an existing extra spec """
+ context = req.environ['nova.context']
+ self._check_type(context, type_id)
+ authorize(context)
+ db.volume_type_extra_specs_delete(context, type_id, id)
+ return webob.Response(status_int=202)
+
+
+class Types_extra_specs(extensions.ExtensionDescriptor):
+ """Types extra specs support"""
+
+ name = "TypesExtraSpecs"
+ alias = "os-types-extra-specs"
+ namespace = "http://docs.openstack.org/volume/ext/types-extra-specs/api/v1"
+ updated = "2011-08-24T00:00:00+00:00"
+
+ def get_resources(self):
+ resources = []
+ res = extensions.ResourceExtension('extra_specs',
+ VolumeTypeExtraSpecsController(),
+ parent=dict(
+ member_name='type',
+ collection_name='types'))
+ resources.append(res)
+
+ return resources
diff --git a/nova/api/openstack/volume/contrib/types_manage.py b/nova/api/openstack/volume/contrib/types_manage.py
new file mode 100644
index 000000000..e84f787ab
--- /dev/null
+++ b/nova/api/openstack/volume/contrib/types_manage.py
@@ -0,0 +1,91 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright (c) 2011 Zadara Storage Inc.
+# Copyright (c) 2011 OpenStack LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""The volume types manage extension."""
+
+import webob
+
+from nova.api.openstack import extensions
+from nova.api.openstack.volume import types
+from nova.api.openstack import wsgi
+from nova import exception
+from nova.volume import volume_types
+
+
+authorize = extensions.extension_authorizer('volume', 'types_manage')
+
+
+class VolumeTypesManageController(wsgi.Controller):
+ """ The volume types API controller for the OpenStack API """
+
+ @wsgi.action("create")
+ @wsgi.serializers(xml=types.VolumeTypeTemplate)
+ def _create(self, req, body):
+ """Creates a new volume type."""
+ context = req.environ['nova.context']
+ authorize(context)
+
+ if not body or body == "":
+ raise webob.exc.HTTPUnprocessableEntity()
+
+ vol_type = body.get('volume_type', None)
+ if vol_type is None or vol_type == "":
+ raise webob.exc.HTTPUnprocessableEntity()
+
+ name = vol_type.get('name', None)
+ specs = vol_type.get('extra_specs', {})
+
+ if name is None or name == "":
+ raise webob.exc.HTTPUnprocessableEntity()
+
+ try:
+ volume_types.create(context, name, specs)
+ vol_type = volume_types.get_volume_type_by_name(context, name)
+ except exception.VolumeTypeExists as err:
+ raise webob.exc.HTTPConflict(explanation=str(err))
+ except exception.NotFound:
+ raise webob.exc.HTTPNotFound()
+
+ return {'volume_type': vol_type}
+
+ @wsgi.action("delete")
+ def _delete(self, req, id):
+ """ Deletes an existing volume type """
+ context = req.environ['nova.context']
+ authorize(context)
+
+ try:
+ vol_type = volume_types.get_volume_type(context, id)
+ volume_types.destroy(context, vol_type['name'])
+ except exception.NotFound:
+ raise webob.exc.HTTPNotFound()
+
+ return webob.Response(status_int=202)
+
+
+class Types_manage(extensions.ExtensionDescriptor):
+ """Types manage support"""
+
+ name = "TypesManage"
+ alias = "os-types-manage"
+ namespace = "http://docs.openstack.org/volume/ext/types-manage/api/v1"
+ updated = "2011-08-24T00:00:00+00:00"
+
+ def get_controller_extensions(self):
+ controller = VolumeTypesManageController()
+ extension = extensions.ControllerExtension(self, 'types', controller)
+ return [extension]