diff options
| author | Tushar Patil <tushar.vitthal.patil@gmail.com> | 2011-08-17 17:17:47 -0700 |
|---|---|---|
| committer | Tushar Patil <tushar.vitthal.patil@gmail.com> | 2011-08-17 17:17:47 -0700 |
| commit | c3ef50fd4b866ec6dc90ad114e36b16c857ca206 (patch) | |
| tree | 68d6b7c352d7b0a6ab0fc2096486ba983af46ed8 /nova/api | |
| parent | 19a4ddaf157ebb388cce37ddc142dfad304b8cf0 (diff) | |
| parent | aca07a42fabb7f506cf132b995b4ad0139987b02 (diff) | |
| download | nova-c3ef50fd4b866ec6dc90ad114e36b16c857ca206.tar.gz nova-c3ef50fd4b866ec6dc90ad114e36b16c857ca206.tar.xz nova-c3ef50fd4b866ec6dc90ad114e36b16c857ca206.zip | |
Merged with trunk and fixed broken testcases
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/ec2/__init__.py | 4 | ||||
| -rw-r--r-- | nova/api/ec2/cloud.py | 2 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/floating_ips.py | 6 | ||||
| -rw-r--r-- | nova/api/openstack/contrib/quotas.py | 100 | ||||
| -rw-r--r-- | nova/api/openstack/create_instance_helper.py | 17 | ||||
| -rw-r--r-- | nova/api/openstack/servers.py | 29 | ||||
| -rw-r--r-- | nova/api/openstack/views/servers.py | 8 |
7 files changed, 141 insertions, 25 deletions
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 8b6e47cfb..96df97393 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -358,6 +358,10 @@ class Executor(wsgi.Application): LOG.debug(_('InvalidParameterValue raised: %s'), unicode(ex), context=context) return self._error(req, context, type(ex).__name__, unicode(ex)) + except exception.InvalidPortRange as ex: + LOG.debug(_('InvalidPortRange raised: %s'), unicode(ex), + context=context) + return self._error(req, context, type(ex).__name__, unicode(ex)) except Exception as ex: extra = {'environment': req.environ} LOG.exception(_('Unexpected error raised: %s'), unicode(ex), diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 87bba58c3..9aebf92e3 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -305,7 +305,7 @@ class CloudController(object): 'hostname': hostname, 'instance-action': 'none', 'instance-id': ec2_id, - 'instance-type': instance_ref['instance_type'], + 'instance-type': instance_ref['instance_type']['name'], 'local-hostname': hostname, 'local-ipv4': address, 'placement': {'availability-zone': availability_zone}, diff --git a/nova/api/openstack/contrib/floating_ips.py b/nova/api/openstack/contrib/floating_ips.py index c07bfdf09..44b35c385 100644 --- a/nova/api/openstack/contrib/floating_ips.py +++ b/nova/api/openstack/contrib/floating_ips.py @@ -43,8 +43,8 @@ def _translate_floating_ip_view(floating_ip): def _translate_floating_ips_view(floating_ips): - return {'floating_ips': [_translate_floating_ip_view(floating_ip) - for floating_ip in floating_ips]} + return {'floating_ips': [_translate_floating_ip_view(ip)['floating_ip'] + for ip in floating_ips]} class FloatingIPController(object): @@ -131,7 +131,7 @@ class FloatingIPController(object): "floating_ip": floating_ip, "fixed_ip": fixed_ip}} - def disassociate(self, req, id): + def disassociate(self, req, id, body=None): """ POST /floating_ips/{id}/disassociate """ context = req.environ['nova.context'] floating_ip = self.network_api.get_floating_ip(context, id) diff --git a/nova/api/openstack/contrib/quotas.py b/nova/api/openstack/contrib/quotas.py new file mode 100644 index 000000000..459b71dfd --- /dev/null +++ b/nova/api/openstack/contrib/quotas.py @@ -0,0 +1,100 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import webob + +from nova import db +from nova import exception +from nova import quota +from nova.api.openstack import extensions + + +class QuotaSetsController(object): + + def _format_quota_set(self, project_id, quota_set): + """Convert the quota object to a result dict""" + + return {'quota_set': { + 'id': str(project_id), + 'metadata_items': quota_set['metadata_items'], + 'injected_file_content_bytes': + quota_set['injected_file_content_bytes'], + 'volumes': quota_set['volumes'], + 'gigabytes': quota_set['gigabytes'], + 'ram': quota_set['ram'], + 'floating_ips': quota_set['floating_ips'], + 'instances': quota_set['instances'], + 'injected_files': quota_set['injected_files'], + 'cores': quota_set['cores'], + }} + + def show(self, req, id): + context = req.environ['nova.context'] + try: + db.sqlalchemy.api.authorize_project_context(context, id) + return self._format_quota_set(id, + quota.get_project_quotas(context, id)) + except exception.NotAuthorized: + return webob.Response(status_int=403) + + def update(self, req, id, body): + context = req.environ['nova.context'] + project_id = id + resources = ['metadata_items', 'injected_file_content_bytes', + 'volumes', 'gigabytes', 'ram', 'floating_ips', 'instances', + 'injected_files', 'cores'] + for key in body['quota_set'].keys(): + if key in resources: + value = int(body['quota_set'][key]) + try: + db.quota_update(context, project_id, key, value) + except exception.ProjectQuotaNotFound: + db.quota_create(context, project_id, key, value) + except exception.AdminRequired: + return webob.Response(status_int=403) + return {'quota_set': quota.get_project_quotas(context, project_id)} + + def defaults(self, req, id): + return self._format_quota_set(id, quota._get_default_quotas()) + + +class Quotas(extensions.ExtensionDescriptor): + + def get_name(self): + return "Quotas" + + def get_alias(self): + return "os-quota-sets" + + def get_description(self): + return "Quotas management support" + + def get_namespace(self): + return "http://docs.openstack.org/ext/quotas-sets/api/v1.1" + + def get_updated(self): + return "2011-08-08T00:00:00+00:00" + + def get_resources(self): + resources = [] + + res = extensions.ResourceExtension('os-quota-sets', + QuotaSetsController(), + member_actions={'defaults': 'GET'}) + resources.append(res) + + return resources diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 4ceb972c0..cf1e21cc6 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -113,13 +113,12 @@ class CreateInstanceHelper(object): sg_names = [] security_groups = server_dict.get('security_groups') - if security_groups: + if security_groups is not None: sg_names = [sg['name'] for sg in security_groups if sg.get('name')] if not sg_names: sg_names.append('default') sg_names = list(set(sg_names)) - LOG.debug(sg_names) try: flavor_id = self.controller._flavor_id_from_req_data(body) @@ -132,6 +131,7 @@ class CreateInstanceHelper(object): raise exc.HTTPBadRequest(explanation=msg) zone_blob = server_dict.get('blob') + availability_zone = server_dict.get('availability_zone') name = server_dict['name'] self._validate_server_name(name) name = name.strip() @@ -172,7 +172,8 @@ class CreateInstanceHelper(object): reservation_id=reservation_id, min_count=min_count, max_count=max_count, - security_group=sg_names)) + security_group=sg_names, + availability_zone=availability_zone)) except quota.QuotaError as error: self._handle_quota_error(error) except exception.ImageNotFound as error: @@ -467,7 +468,9 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer): if personality is not None: server["personality"] = personality - server["security_groups"] = self._extract_security_groups(server_node) + security_groups = self._extract_security_groups(server_node) + if security_groups is not None: + server["security_groups"] = security_groups return server @@ -489,12 +492,14 @@ class ServerXMLDeserializerV11(wsgi.MetadataXMLDeserializer): def _extract_security_groups(self, server_node): """Marshal the security_groups attribute of a parsed request""" node = self.find_first_child_named(server_node, "security_groups") - security_groups = [] if node is not None: + security_groups = [] for sg_node in self.find_children_named(node, "security_group"): item = {} name_node = self.find_first_child_named(sg_node, "name") if name_node: item["name"] = self.extract_text(name_node) security_groups.append(item) - return security_groups + return security_groups + else: + return None diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 736fdf6ce..335ecad86 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -163,7 +163,7 @@ class Controller(object): @scheduler_api.redirect_handler def update(self, req, id, body): - """ Updates the server name or password """ + """Update server name then pass on to version-specific controller""" if len(req.body) == 0: raise exc.HTTPUnprocessableEntity() @@ -178,17 +178,15 @@ class Controller(object): self.helper._validate_server_name(name) update_dict['display_name'] = name.strip() - self._parse_update(ctxt, id, body, update_dict) - try: self.compute_api.update(ctxt, id, **update_dict) except exception.NotFound: raise exc.HTTPNotFound() - return exc.HTTPNoContent() + return self._update(ctxt, req, id, body) - def _parse_update(self, context, id, inst_dict, update_dict): - pass + def _update(self, context, req, id, inst_dict): + return exc.HTTPNotImplemented() @scheduler_api.redirect_handler def action(self, req, id, body): @@ -210,11 +208,15 @@ class Controller(object): } self.actions.update(admin_actions) - for key in self.actions.keys(): - if key in body: + for key in body: + if key in self.actions: return self.actions[key](body, req, id) + else: + msg = _("There is no such server action: %s") % (key,) + raise exc.HTTPBadRequest(explanation=msg) - raise exc.HTTPNotImplemented() + msg = _("Invalid request body") + raise exc.HTTPBadRequest(explanation=msg) def _action_create_backup(self, input_dict, req, instance_id): """Backup a server instance. @@ -568,10 +570,11 @@ class ControllerV10(Controller): def _limit_items(self, items, req): return common.limited(items, req) - def _parse_update(self, context, server_id, inst_dict, update_dict): + def _update(self, context, req, id, inst_dict): if 'adminPass' in inst_dict['server']: - self.compute_api.set_admin_password(context, server_id, + self.compute_api.set_admin_password(context, id, inst_dict['server']['adminPass']) + return exc.HTTPNoContent() def _action_resize(self, input_dict, req, id): """ Resizes a given instance to the flavor size requested """ @@ -693,6 +696,10 @@ class ControllerV11(Controller): LOG.info(msg) raise exc.HTTPBadRequest(explanation=msg) + def _update(self, context, req, id, inst_dict): + instance = self.compute_api.routing_get(context, id) + return self._build_view(req, instance, is_detail=True) + def _action_resize(self, input_dict, req, id): """ Resizes a given instance to the flavor size requested """ try: diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index 8222f6766..edc328129 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/views/servers.py @@ -111,14 +111,14 @@ class ViewBuilderV10(ViewBuilder): response['uuid'] = inst['uuid'] def _build_image(self, response, inst): - if 'image_ref' in dict(inst): + if inst.get('image_ref', None): image_ref = inst['image_ref'] if str(image_ref).startswith('http'): raise exception.ListingImageRefsNotSupported() response['imageId'] = int(image_ref) def _build_flavor(self, response, inst): - if 'instance_type' in dict(inst): + if inst.get('instance_type', None): response['flavorId'] = inst['instance_type']['flavorid'] def _build_addresses(self, response, inst): @@ -146,7 +146,7 @@ class ViewBuilderV11(ViewBuilder): return response def _build_image(self, response, inst): - if 'image_ref' in dict(inst): + if inst.get("image_ref", None): image_href = inst['image_ref'] image_id = str(common.get_id_from_href(image_href)) _bookmark = self.image_builder.generate_bookmark(image_id) @@ -161,7 +161,7 @@ class ViewBuilderV11(ViewBuilder): } def _build_flavor(self, response, inst): - if "instance_type" in dict(inst): + if inst.get("instance_type", None): flavor_id = inst["instance_type"]['flavorid'] flavor_ref = self.flavor_builder.generate_href(flavor_id) flavor_bookmark = self.flavor_builder.generate_bookmark(flavor_id) |
