From 7407a1a86c4039bdc541e9a26cc68c9c93f49bc3 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Fri, 5 Aug 2011 18:29:32 +0900 Subject: Added virtual interfaces REST API extension controller --- nova/api/openstack/contrib/virtual_interfaces.py | 102 +++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 nova/api/openstack/contrib/virtual_interfaces.py (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py new file mode 100644 index 000000000..3466d31c7 --- /dev/null +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -0,0 +1,102 @@ +# Copyright (C) 2011 Midokura KK +# 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. + +"""The virtual interfaces extension.""" + +from webob import exc +import webob + +from nova import compute +from nova import exception +from nova import log as logging +from nova.api.openstack import common +from nova.api.openstack import extensions +from nova.api.openstack import faults + + +LOG = logging.getLogger("nova.api.virtual_interfaces") + + +def _translate_vif_summary_view(_context, vif): + """Maps keys for attachment summary view.""" + d = {} + d['id'] = vif['uuid'] + d['macAddress'] = vif['address'] + d['serverId'] = vif['instance_id'] + return d + + +class ServerVirtualInterfaceController(object): + """The instance VIF API controller for the Openstack API. + """ + + _serialization_metadata = { + 'application/xml': { + 'attributes': { + 'serverVirtualInterface': ['id', + 'macAddress']}}} + + def __init__(self): + self.compute_api = compute.API() + super(ServerVirtualInterfaceController, self).__init__() + + def _items(self, req, server_id, entity_maker): + """Returns a list of VIFs, transformed through entity_maker.""" + context = req.environ['nova.context'] + + try: + instance = self.compute_api.get(context, server_id) + except exception.NotFound: + return faults.Fault(exc.HTTPNotFound()) + + vifs = instance['virtual_interfaces'] + limited_list = common.limited(vifs, req) + res = [entity_maker(context, vif) for vif in limited_list] + return {'serverVirtualInterfaces': res} + + def index(self, req, server_id): + """Returns the list of VIFs for a given instance.""" + return self._items(req, server_id, + entity_maker=_translate_vif_summary_view) + + +class VirtualInterfaces(extensions.ExtensionDescriptor): + + def get_name(self): + return "VirtualInterfaces" + + def get_alias(self): + return "os-virtual_interfaces" + + def get_description(self): + return "Virtual interface support" + + def get_namespace(self): + return "http://docs.openstack.org/ext/virtual_interfaces/api/v1.1" + + def get_updated(self): + return "2011-08-05T00:00:00+00:00" + + def get_resources(self): + resources = [] + + res = extensions.ResourceExtension('os-virtual_interfaces', + ServerVirtualInterfaceController(), + parent=dict( + member_name='server', + collection_name='servers')) + resources.append(res) + + return resources -- cgit From ca7bf95e610bdc47f01b8fb7b459269bb8e5df66 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Thu, 11 Aug 2011 18:11:59 -0700 Subject: Initial version --- nova/api/__init__.py | 6 ++ nova/api/ec2/__init__.py | 3 - nova/api/openstack/create_instance_helper.py | 4 +- nova/api/openstack/userdatarequesthandler.py | 110 +++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 nova/api/openstack/userdatarequesthandler.py (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 747015af5..6e6b092b3 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -15,3 +15,9 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +from nova import flags + + +flags.DEFINE_boolean('use_forwarded_for', False, + 'Treat X-Forwarded-For as the canonical remote address. ' + 'Only enable this if you have a sanitizing proxy.') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 8b6e47cfb..e497b499a 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -37,9 +37,6 @@ from nova.auth import manager FLAGS = flags.FLAGS LOG = logging.getLogger("nova.api") -flags.DEFINE_boolean('use_forwarded_for', False, - 'Treat X-Forwarded-For as the canonical remote address. ' - 'Only enable this if you have a sanitizing proxy.') flags.DEFINE_integer('lockout_attempts', 5, 'Number of failed auths before lockout.') flags.DEFINE_integer('lockout_minutes', 15, diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 1425521a9..144697790 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -122,6 +122,7 @@ class CreateInstanceHelper(object): raise exc.HTTPBadRequest(explanation=msg) zone_blob = server_dict.get('blob') + user_data = server_dict.get('user_data') name = server_dict['name'] self._validate_server_name(name) name = name.strip() @@ -161,7 +162,8 @@ class CreateInstanceHelper(object): zone_blob=zone_blob, reservation_id=reservation_id, min_count=min_count, - max_count=max_count)) + max_count=max_count, + user_data=user_data)) except quota.QuotaError as error: self._handle_quota_error(error) except exception.ImageNotFound as error: diff --git a/nova/api/openstack/userdatarequesthandler.py b/nova/api/openstack/userdatarequesthandler.py new file mode 100644 index 000000000..5daa37e95 --- /dev/null +++ b/nova/api/openstack/userdatarequesthandler.py @@ -0,0 +1,110 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +"""User data request handler.""" + +import base64 +import webob.dec +import webob.exc + +from nova import log as logging +from nova import context +from nova import exception +from nova import db +from nova import flags +from nova import wsgi + + +LOG = logging.getLogger('nova.api.openstack.userdata') +FLAGS = flags.FLAGS + + +class Controller(object): + """ The server user-data API controller for the Openstack API """ + + def __init__(self): + super(Controller, self).__init__() + + @staticmethod + def _format_user_data(instance_ref): + return base64.b64decode(instance_ref['user_data']) + + def get_user_data(self, address): + ctxt = context.get_admin_context() + try: + instance_ref = db.instance_get_by_fixed_ip(ctxt, address) + except exception.NotFound: + instance_ref = None + if not instance_ref: + return None + + data = {'user-data': self._format_user_data(instance_ref)} + return data + + +class UserdataRequestHandler(wsgi.Application): + """Serve user-data from the OS API.""" + + def __init__(self): + self.cc = Controller() + + def print_data(self, data): + if isinstance(data, dict): + output = '' + for key in data: + if key == '_name': + continue + output += key + if isinstance(data[key], dict): + if '_name' in data[key]: + output += '=' + str(data[key]['_name']) + else: + output += '/' + output += '\n' + # Cut off last \n + return output[:-1] + elif isinstance(data, list): + return '\n'.join(data) + else: + return str(data) + + def lookup(self, path, data): + items = path.split('/') + for item in items: + if item: + if not isinstance(data, dict): + return data + if not item in data: + return None + data = data[item] + return data + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + remote_address = "10.0.1.6"#req.remote_addr + if FLAGS.use_forwarded_for: + remote_address = req.headers.get('X-Forwarded-For', remote_address) + + data = self.cc.get_user_data(remote_address) + if data is None: + LOG.error(_('Failed to get user data for ip: %s'), remote_address) + raise webob.exc.HTTPNotFound() + data = self.lookup(req.path_info, data) + if data is None: + raise webob.exc.HTTPNotFound() + return self.print_data(data) -- cgit From 7507ba23004c989c75962c47efbd2ce5e5178a90 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Thu, 11 Aug 2011 18:22:35 -0700 Subject: added userdata entry in the api paste ini --- nova/api/openstack/userdatarequesthandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/userdatarequesthandler.py b/nova/api/openstack/userdatarequesthandler.py index 5daa37e95..f0205419b 100644 --- a/nova/api/openstack/userdatarequesthandler.py +++ b/nova/api/openstack/userdatarequesthandler.py @@ -96,7 +96,7 @@ class UserdataRequestHandler(wsgi.Application): @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): - remote_address = "10.0.1.6"#req.remote_addr + remote_address = req.remote_addr if FLAGS.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) -- cgit From 8666aca320ce95840a378231bfe81bc4e759df6e Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Mon, 15 Aug 2011 11:50:54 -0700 Subject: Fixed merging issue --- nova/api/openstack/create_instance_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 7e9d48c02..c8798536e 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -164,7 +164,7 @@ class CreateInstanceHelper(object): reservation_id=reservation_id, min_count=min_count, max_count=max_count, - user_data=user_data)) + user_data=user_data, availability_zone=availability_zone)) except quota.QuotaError as error: self._handle_quota_error(error) -- cgit From 9a4b1deb5f9abdc88809ff80bccdfb503e66dccd Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Mon, 15 Aug 2011 15:09:42 -0700 Subject: Removed newly added userdatarequesthandler for OS API, there is no need to add this handler since the existing Ec2 API metadatarequesthandler does the same job --- nova/api/__init__.py | 6 -- nova/api/ec2/__init__.py | 3 + nova/api/openstack/userdatarequesthandler.py | 110 --------------------------- 3 files changed, 3 insertions(+), 116 deletions(-) delete mode 100644 nova/api/openstack/userdatarequesthandler.py (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 6e6b092b3..747015af5 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -15,9 +15,3 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. -from nova import flags - - -flags.DEFINE_boolean('use_forwarded_for', False, - 'Treat X-Forwarded-For as the canonical remote address. ' - 'Only enable this if you have a sanitizing proxy.') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 2e9278b52..96df97393 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -37,6 +37,9 @@ from nova.auth import manager FLAGS = flags.FLAGS LOG = logging.getLogger("nova.api") +flags.DEFINE_boolean('use_forwarded_for', False, + 'Treat X-Forwarded-For as the canonical remote address. ' + 'Only enable this if you have a sanitizing proxy.') flags.DEFINE_integer('lockout_attempts', 5, 'Number of failed auths before lockout.') flags.DEFINE_integer('lockout_minutes', 15, diff --git a/nova/api/openstack/userdatarequesthandler.py b/nova/api/openstack/userdatarequesthandler.py deleted file mode 100644 index f0205419b..000000000 --- a/nova/api/openstack/userdatarequesthandler.py +++ /dev/null @@ -1,110 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -"""User data request handler.""" - -import base64 -import webob.dec -import webob.exc - -from nova import log as logging -from nova import context -from nova import exception -from nova import db -from nova import flags -from nova import wsgi - - -LOG = logging.getLogger('nova.api.openstack.userdata') -FLAGS = flags.FLAGS - - -class Controller(object): - """ The server user-data API controller for the Openstack API """ - - def __init__(self): - super(Controller, self).__init__() - - @staticmethod - def _format_user_data(instance_ref): - return base64.b64decode(instance_ref['user_data']) - - def get_user_data(self, address): - ctxt = context.get_admin_context() - try: - instance_ref = db.instance_get_by_fixed_ip(ctxt, address) - except exception.NotFound: - instance_ref = None - if not instance_ref: - return None - - data = {'user-data': self._format_user_data(instance_ref)} - return data - - -class UserdataRequestHandler(wsgi.Application): - """Serve user-data from the OS API.""" - - def __init__(self): - self.cc = Controller() - - def print_data(self, data): - if isinstance(data, dict): - output = '' - for key in data: - if key == '_name': - continue - output += key - if isinstance(data[key], dict): - if '_name' in data[key]: - output += '=' + str(data[key]['_name']) - else: - output += '/' - output += '\n' - # Cut off last \n - return output[:-1] - elif isinstance(data, list): - return '\n'.join(data) - else: - return str(data) - - def lookup(self, path, data): - items = path.split('/') - for item in items: - if item: - if not isinstance(data, dict): - return data - if not item in data: - return None - data = data[item] - return data - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - remote_address = req.remote_addr - if FLAGS.use_forwarded_for: - remote_address = req.headers.get('X-Forwarded-For', remote_address) - - data = self.cc.get_user_data(remote_address) - if data is None: - LOG.error(_('Failed to get user data for ip: %s'), remote_address) - raise webob.exc.HTTPNotFound() - data = self.lookup(req.path_info, data) - if data is None: - raise webob.exc.HTTPNotFound() - return self.print_data(data) -- cgit From 92c6ee9dc7eeaa44bf6162387b5815fc0cdb1c71 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Tue, 16 Aug 2011 17:51:45 +0900 Subject: Fixed the naming of the extension --- nova/api/openstack/contrib/virtual_interfaces.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index 3466d31c7..38246aeb5 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -72,13 +72,13 @@ class ServerVirtualInterfaceController(object): entity_maker=_translate_vif_summary_view) -class VirtualInterfaces(extensions.ExtensionDescriptor): +class Virtual_interfaces(extensions.ExtensionDescriptor): def get_name(self): - return "VirtualInterfaces" + return "Virtual_interfaces" def get_alias(self): - return "os-virtual_interfaces" + return "os-virtual-interfaces" def get_description(self): return "Virtual interface support" @@ -92,7 +92,7 @@ class VirtualInterfaces(extensions.ExtensionDescriptor): def get_resources(self): resources = [] - res = extensions.ResourceExtension('os-virtual_interfaces', + res = extensions.ResourceExtension('os-virtual-interfaces', ServerVirtualInterfaceController(), parent=dict( member_name='server', -- cgit From 44a278bc5a456c8eda74c61aaa68cfd74ee0d6e8 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 16 Aug 2011 11:31:29 -0400 Subject: Small bug fix...don't cast DB objects to dicts. --- nova/api/openstack/views/servers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index 8222f6766..60fdf54be 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/views/servers.py @@ -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) -- cgit From 71935201aed268e94ee9674e887d67b4b9f217a6 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 16 Aug 2011 13:44:03 -0400 Subject: Updated ViewBuilderV10 as per feedback. --- nova/api/openstack/views/servers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index 60fdf54be..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): -- cgit From 79f3b1512166a37790c5cb2863140d696c717455 Mon Sep 17 00:00:00 2001 From: Troy Toman Date: Wed, 17 Aug 2011 02:41:17 -0500 Subject: Changed return code to 413 for metadata, personality and instance quota issues --- nova/api/openstack/common.py | 3 ++- nova/api/openstack/create_instance_helper.py | 13 ++++++++++--- nova/api/openstack/faults.py | 2 +- nova/api/openstack/server_metadata.py | 3 ++- 4 files changed, 15 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index b2a675653..d9eb832f2 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -241,7 +241,8 @@ def check_img_metadata_quota_limit(context, metadata): quota_metadata = quota.allowed_metadata_items(context, num_metadata) if quota_metadata < num_metadata: expl = _("Image metadata limit exceeded") - raise webob.exc.HTTPBadRequest(explanation=expl) + raise webob.exc.HTTPRequestEntityTooLarge(explanation=expl, + headers={'Retry-After': 0}) class MetadataXMLDeserializer(wsgi.XMLDeserializer): diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 4e1da549e..b4a08dac0 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -180,13 +180,20 @@ class CreateInstanceHelper(object): """ if error.code == "OnsetFileLimitExceeded": expl = _("Personality file limit exceeded") - raise exc.HTTPBadRequest(explanation=expl) + raise exc.HTTPRequestEntityTooLarge(explanation=error.message, + headers={'Retry-After': 0}) if error.code == "OnsetFilePathLimitExceeded": expl = _("Personality file path too long") - raise exc.HTTPBadRequest(explanation=expl) + raise exc.HTTPRequestEntityTooLarge(explanation=error.message, + headers={'Retry-After': 0}) if error.code == "OnsetFileContentLimitExceeded": expl = _("Personality file content too long") - raise exc.HTTPBadRequest(explanation=expl) + raise exc.HTTPRequestEntityTooLarge(explanation=error.message, + headers={'Retry-After': 0}) + if error.code == "InstanceLimitExceeded": + expl = _("Instance quotas have been exceeded") + raise exc.HTTPRequestEntityTooLarge(explanation=error.message, + headers={'Retry-After': 0}) # if the original error is okay, just reraise it raise error diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py index 1ab45d4f1..0ed6f1ff0 100644 --- a/nova/api/openstack/faults.py +++ b/nova/api/openstack/faults.py @@ -53,7 +53,7 @@ class Fault(webob.exc.HTTPException): fault_name: { 'code': code, 'message': self.wrapped_exc.explanation}} - if code == 413: + if code == 413 and self.wrapped_exc.headers['Retry-After']: retry = self.wrapped_exc.headers['Retry-After'] fault_data[fault_name]['retryAfter'] = retry diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/server_metadata.py index 2b235f79a..8ac3319c9 100644 --- a/nova/api/openstack/server_metadata.py +++ b/nova/api/openstack/server_metadata.py @@ -151,7 +151,8 @@ class Controller(object): 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 exc.HTTPRequestEntityTooLarge(explanation=error.message, + headers={'Retry-After': 0}) raise error -- cgit From 228b185f1366df62da42b646ce98711de4195a5d Mon Sep 17 00:00:00 2001 From: Troy Toman Date: Wed, 17 Aug 2011 03:03:25 -0500 Subject: Removed a change from faults.py that was not required." --- nova/api/openstack/faults.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py index 0ed6f1ff0..1ab45d4f1 100644 --- a/nova/api/openstack/faults.py +++ b/nova/api/openstack/faults.py @@ -53,7 +53,7 @@ class Fault(webob.exc.HTTPException): fault_name: { 'code': code, 'message': self.wrapped_exc.explanation}} - if code == 413 and self.wrapped_exc.headers['Retry-After']: + if code == 413: retry = self.wrapped_exc.headers['Retry-After'] fault_data[fault_name]['retryAfter'] = retry -- cgit From 77e1e0d3359bce9e5e30134f141151fc271a2e4b Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Wed, 17 Aug 2011 19:05:29 +0900 Subject: Removed serverId from the response --- nova/api/openstack/contrib/virtual_interfaces.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index 38246aeb5..86d1128fd 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -34,7 +34,6 @@ def _translate_vif_summary_view(_context, vif): d = {} d['id'] = vif['uuid'] d['macAddress'] = vif['address'] - d['serverId'] = vif['instance_id'] return d -- cgit From 751c8b4ff0e94b4f665af5541b9249637623d193 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Wed, 17 Aug 2011 19:58:26 +0900 Subject: Added XML support and changed JSON output keys --- nova/api/openstack/contrib/virtual_interfaces.py | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index 86d1128fd..715a54d52 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -24,16 +24,17 @@ from nova import log as logging from nova.api.openstack import common from nova.api.openstack import extensions from nova.api.openstack import faults +from nova.api.openstack import wsgi LOG = logging.getLogger("nova.api.virtual_interfaces") def _translate_vif_summary_view(_context, vif): - """Maps keys for attachment summary view.""" + """Maps keys for VIF summary view.""" d = {} d['id'] = vif['uuid'] - d['macAddress'] = vif['address'] + d['mac_address'] = vif['address'] return d @@ -41,12 +42,6 @@ class ServerVirtualInterfaceController(object): """The instance VIF API controller for the Openstack API. """ - _serialization_metadata = { - 'application/xml': { - 'attributes': { - 'serverVirtualInterface': ['id', - 'macAddress']}}} - def __init__(self): self.compute_api = compute.API() super(ServerVirtualInterfaceController, self).__init__() @@ -63,7 +58,7 @@ class ServerVirtualInterfaceController(object): vifs = instance['virtual_interfaces'] limited_list = common.limited(vifs, req) res = [entity_maker(context, vif) for vif in limited_list] - return {'serverVirtualInterfaces': res} + return {'virtual_interfaces': res} def index(self, req, server_id): """Returns the list of VIFs for a given instance.""" @@ -91,11 +86,24 @@ class Virtual_interfaces(extensions.ExtensionDescriptor): def get_resources(self): resources = [] + metadata = _get_metadata() + body_serializers = { + 'application/xml': wsgi.XMLDictSerializer(metadata=metadata, + xmlns=wsgi.XMLNS_V11)} + serializer = wsgi.ResponseSerializer(body_serializers, None) res = extensions.ResourceExtension('os-virtual-interfaces', ServerVirtualInterfaceController(), parent=dict( member_name='server', - collection_name='servers')) + collection_name='servers'), + serializer=serializer) resources.append(res) return resources + + +def _get_metadata(): + metadata = { + "attributes": { + 'virtual_interface': ["id", "mac_address"]}} + return metadata -- cgit From 4407405244c3797ed1c0433eec7686e15340dca7 Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Wed, 17 Aug 2011 20:12:24 +0900 Subject: Cleaned up the file --- nova/api/openstack/contrib/virtual_interfaces.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index 715a54d52..2d3850e12 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -38,6 +38,13 @@ def _translate_vif_summary_view(_context, vif): return d +def _get_metadata(): + metadata = { + "attributes": { + 'virtual_interface': ["id", "mac_address"]}} + return metadata + + class ServerVirtualInterfaceController(object): """The instance VIF API controller for the Openstack API. """ @@ -100,10 +107,3 @@ class Virtual_interfaces(extensions.ExtensionDescriptor): resources.append(res) return resources - - -def _get_metadata(): - metadata = { - "attributes": { - 'virtual_interface': ["id", "mac_address"]}} - return metadata -- cgit From 5415a59d473fb9ed374e746fb36f30fc664c4dec Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Wed, 17 Aug 2011 20:17:09 +0900 Subject: Updated get_updated time --- nova/api/openstack/contrib/virtual_interfaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index 2d3850e12..b3bb00a8f 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -88,7 +88,7 @@ class Virtual_interfaces(extensions.ExtensionDescriptor): return "http://docs.openstack.org/ext/virtual_interfaces/api/v1.1" def get_updated(self): - return "2011-08-05T00:00:00+00:00" + return "2011-08-17T00:00:00+00:00" def get_resources(self): resources = [] -- cgit From 2e44657a20cdd620d982b252ca35413c07fd3c2b Mon Sep 17 00:00:00 2001 From: Ryu Ishimoto Date: Wed, 17 Aug 2011 20:23:21 +0900 Subject: Cleaned up the extension metadata API data --- nova/api/openstack/contrib/virtual_interfaces.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/contrib/virtual_interfaces.py index b3bb00a8f..dab61efc8 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/contrib/virtual_interfaces.py @@ -76,10 +76,10 @@ class ServerVirtualInterfaceController(object): class Virtual_interfaces(extensions.ExtensionDescriptor): def get_name(self): - return "Virtual_interfaces" + return "VirtualInterfaces" def get_alias(self): - return "os-virtual-interfaces" + return "virtual_interfaces" def get_description(self): return "Virtual interface support" @@ -98,12 +98,11 @@ class Virtual_interfaces(extensions.ExtensionDescriptor): 'application/xml': wsgi.XMLDictSerializer(metadata=metadata, xmlns=wsgi.XMLNS_V11)} serializer = wsgi.ResponseSerializer(body_serializers, None) - res = extensions.ResourceExtension('os-virtual-interfaces', - ServerVirtualInterfaceController(), - parent=dict( - member_name='server', - collection_name='servers'), - serializer=serializer) + res = extensions.ResourceExtension( + 'os-virtual-interfaces', + controller=ServerVirtualInterfaceController(), + parent=dict(member_name='server', collection_name='servers'), + serializer=serializer) resources.append(res) return resources -- cgit From 9011bf57d8caf8a0bd11dfb33cf968b2b65fe294 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 11:21:35 -0500 Subject: Added rescue mode extension. --- nova/api/openstack/contrib/rescue.py | 72 ++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 nova/api/openstack/contrib/rescue.py (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py new file mode 100644 index 000000000..efb882fd6 --- /dev/null +++ b/nova/api/openstack/contrib/rescue.py @@ -0,0 +1,72 @@ +# Copyright 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 rescue mode extension.""" + +import webob +from webob import exc + +from nova import compute +from nova import log as logging +from nova.api.openstack import extensions as exts +from nova.api.openstack import faults + +LOG = logging.getLogger("nova.api.contrib.rescue") + + +class Rescue(exts.ExtensionDescriptor): + """The Rescue API controller for the OpenStack API.""" + def __init__(self): + super(Rescue, self).__init__() + self.compute_api = compute.API() + + def _rescue(self, input_dict, req, instance_id): + """Enable or disable rescue mode.""" + context = req.environ["nova.context"] + action = input_dict["rescue"]["action"] + + try: + if action == "rescue": + self.compute_api.rescue(context, instance_id) + elif action == "unrescue": + self.compute_api.unrescue(context, instance_id) + except Exception, e: + LOG.exception(_("Error in %(action)s: %(e)s") % locals()) + return faults.Fault(exc.HTTPBadRequest()) + + return webob.Response(status_int=202) + + def get_name(self): + return "Rescue" + + def get_alias(self): + return "rescue" + + def get_description(self): + return "Instance rescue mode" + + def get_namespace(self): + return "http://docs.openstack.org/ext/rescue/api/v1.1" + + def get_updated(self): + return "2011-08-18T00:00:00+00:00" + + def get_actions(self): + """Return the actions the extension adds, as required by contract.""" + actions = [ + exts.ActionExtension("servers", "rescue", self._rescue), + exts.ActionExtension("servers", "unrescue", self._rescue), + ] + + return actions -- cgit From a68c1cde2e73e6d39d7ff6024cd3ff289c465619 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 12:20:40 -0500 Subject: Refactored a little and updated unit test. --- nova/api/openstack/contrib/rescue.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index efb882fd6..dac269efb 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -31,10 +31,10 @@ class Rescue(exts.ExtensionDescriptor): super(Rescue, self).__init__() self.compute_api = compute.API() - def _rescue(self, input_dict, req, instance_id): - """Enable or disable rescue mode.""" + def _rescue(self, input_dict, req, instance_id, exit_rescue=False): + """Rescue an instance.""" context = req.environ["nova.context"] - action = input_dict["rescue"]["action"] + action = "unrescue" if exit_rescue else "rescue" try: if action == "rescue": @@ -47,6 +47,10 @@ class Rescue(exts.ExtensionDescriptor): return webob.Response(status_int=202) + def _unrescue(self, input_dict, req, instance_id): + """Unrescue an instance.""" + self._rescue(input_dict, req, instance_id, exit_rescue=True) + def get_name(self): return "Rescue" @@ -66,7 +70,7 @@ class Rescue(exts.ExtensionDescriptor): """Return the actions the extension adds, as required by contract.""" actions = [ exts.ActionExtension("servers", "rescue", self._rescue), - exts.ActionExtension("servers", "unrescue", self._rescue), + exts.ActionExtension("servers", "unrescue", self._unrescue), ] return actions -- cgit From a9d87715133ae79518cef6aafd87c95e26f20765 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 12:25:22 -0500 Subject: Minor housecleaning. --- nova/api/openstack/contrib/rescue.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index dac269efb..65ce2874b 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -22,17 +22,22 @@ from nova import log as logging from nova.api.openstack import extensions as exts from nova.api.openstack import faults + LOG = logging.getLogger("nova.api.contrib.rescue") class Rescue(exts.ExtensionDescriptor): - """The Rescue API controller for the OpenStack API.""" + """The Rescue controller for the OpenStack API.""" def __init__(self): super(Rescue, self).__init__() self.compute_api = compute.API() def _rescue(self, input_dict, req, instance_id, exit_rescue=False): - """Rescue an instance.""" + """Rescue an instance. + + If exit_rescue is True, rescue mode should be torn down and the + instance restored to its original state. + """ context = req.environ["nova.context"] action = "unrescue" if exit_rescue else "rescue" -- cgit From fe28c88a6bfff9d8e0d83751ab89e83173aaf092 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 14:56:22 -0500 Subject: Review feedback. --- nova/api/openstack/contrib/rescue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index 65ce2874b..5ee071696 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -48,7 +48,7 @@ class Rescue(exts.ExtensionDescriptor): self.compute_api.unrescue(context, instance_id) except Exception, e: LOG.exception(_("Error in %(action)s: %(e)s") % locals()) - return faults.Fault(exc.HTTPBadRequest()) + return faults.Fault(exc.HTTPInternalServerError()) return webob.Response(status_int=202) @@ -60,7 +60,7 @@ class Rescue(exts.ExtensionDescriptor): return "Rescue" def get_alias(self): - return "rescue" + return "os-rescue" def get_description(self): return "Instance rescue mode" -- cgit From 508b45a3fda9caa92c90282045495acb6e2f638b Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 15:08:51 -0500 Subject: Better docstring for _unrescue(). --- nova/api/openstack/contrib/rescue.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index 5ee071696..a30ed6dff 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -53,7 +53,11 @@ class Rescue(exts.ExtensionDescriptor): return webob.Response(status_int=202) def _unrescue(self, input_dict, req, instance_id): - """Unrescue an instance.""" + """Unrescue an instance. + + We pass exit_rescue=True here so _rescue() knows we would like to exit + rescue mode. + """ self._rescue(input_dict, req, instance_id, exit_rescue=True) def get_name(self): -- cgit From 041dcdb2eba968d5be17c9a10bf333e1307f0537 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Thu, 18 Aug 2011 16:56:23 -0400 Subject: Added 'update' method to ServersXMLSerializer --- nova/api/openstack/servers.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 335ecad86..41e63ec3c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -923,6 +923,12 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): node.setAttribute('adminPass', server_dict['server']['adminPass']) return self.to_xml_string(node, True) + def update(self, server_dict): + xml_doc = minidom.Document() + node = self._server_to_xml_detailed(xml_doc, + server_dict['server']) + return self.to_xml_string(node, True) + def create_resource(version='1.0'): controller = { -- cgit From f86a5cc4bc43923077ffe1d4098e550841f1c4f0 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 15:58:12 -0500 Subject: Review feedback. --- nova/api/openstack/contrib/rescue.py | 40 +++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index a30ed6dff..399bb7f35 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -26,39 +26,37 @@ from nova.api.openstack import faults LOG = logging.getLogger("nova.api.contrib.rescue") +def wrap_errors(fn): + """"Ensure errors are not passed along.""" + def wrapped(*args): + try: + fn(*args) + except Exception, e: + return faults.Fault(exc.HTTPInternalServerError()) + return wrapped + + class Rescue(exts.ExtensionDescriptor): """The Rescue controller for the OpenStack API.""" def __init__(self): super(Rescue, self).__init__() self.compute_api = compute.API() - def _rescue(self, input_dict, req, instance_id, exit_rescue=False): - """Rescue an instance. - - If exit_rescue is True, rescue mode should be torn down and the - instance restored to its original state. - """ + @wrap_errors + def _rescue(self, input_dict, req, instance_id): + """Rescue an instance.""" context = req.environ["nova.context"] - action = "unrescue" if exit_rescue else "rescue" - - try: - if action == "rescue": - self.compute_api.rescue(context, instance_id) - elif action == "unrescue": - self.compute_api.unrescue(context, instance_id) - except Exception, e: - LOG.exception(_("Error in %(action)s: %(e)s") % locals()) - return faults.Fault(exc.HTTPInternalServerError()) + self.compute_api.rescue(context, instance_id) return webob.Response(status_int=202) + @wrap_errors def _unrescue(self, input_dict, req, instance_id): - """Unrescue an instance. + """Rescue an instance.""" + context = req.environ["nova.context"] + self.compute_api.unrescue(context, instance_id) - We pass exit_rescue=True here so _rescue() knows we would like to exit - rescue mode. - """ - self._rescue(input_dict, req, instance_id, exit_rescue=True) + return webob.Response(status_int=202) def get_name(self): return "Rescue" -- cgit From 22ba538b3cb3ddd22cef0fc06b136db433a8d202 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 18 Aug 2011 16:07:02 -0500 Subject: Oops. --- nova/api/openstack/contrib/rescue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/contrib/rescue.py index 399bb7f35..3de128895 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/contrib/rescue.py @@ -52,7 +52,7 @@ class Rescue(exts.ExtensionDescriptor): @wrap_errors def _unrescue(self, input_dict, req, instance_id): - """Rescue an instance.""" + """Unrescue an instance.""" context = req.environ["nova.context"] self.compute_api.unrescue(context, instance_id) -- cgit