From 64a9c37cbf070345831ba6e4db646c5d972e179b Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sat, 16 Jul 2011 19:17:08 -0400 Subject: Added ServerXMLSerializer with working 'show' method Factored out MetadataXMLSerializer from images and servers into common --- nova/api/openstack/common.py | 50 ++++++++++++++++++++ nova/api/openstack/image_metadata.py | 49 -------------------- nova/api/openstack/images.py | 4 +- nova/api/openstack/servers.py | 89 ++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 51 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 8e12ce0c0..8a78292aa 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -17,12 +17,14 @@ import re from urlparse import urlparse +from xml.dom import minidom import webob from nova import exception from nova import flags from nova import log as logging +from nova.api.openstack import wsgi LOG = logging.getLogger('nova.api.openstack.common') @@ -162,3 +164,51 @@ def remove_version_from_href(href): msg = _('href does not contain version') raise ValueError(msg) return new_href + + +class MetadataXMLSerializer(wsgi.XMLDictSerializer): + def __init__(self, xmlns=wsgi.XMLNS_V11): + super(MetadataXMLSerializer, self).__init__(xmlns=xmlns) + + def _meta_item_to_xml(self, doc, key, value): + node = doc.createElement('meta') + doc.appendChild(node) + node.setAttribute('key', '%s' % key) + text = doc.createTextNode('%s' % value) + node.appendChild(text) + return node + + def meta_list_to_xml(self, xml_doc, meta_items): + container_node = xml_doc.createElement('metadata') + for (key, value) in meta_items: + item_node = self._meta_item_to_xml(xml_doc, key, value) + container_node.appendChild(item_node) + return container_node + + def _meta_list_to_xml_string(self, metadata_dict): + xml_doc = minidom.Document() + items = metadata_dict['metadata'].items() + container_node = self.meta_list_to_xml(xml_doc, items) + xml_doc.appendChild(container_node) + self._add_xmlns(container_node) + return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') + + def index(self, metadata_dict): + return self._meta_list_to_xml_string(metadata_dict) + + def create(self, metadata_dict): + return self._meta_list_to_xml_string(metadata_dict) + + def _meta_item_to_xml_string(self, meta_item_dict): + xml_doc = minidom.Document() + item_key, item_value = meta_item_dict.items()[0] + item_node = self._meta_item_to_xml(xml_doc, item_key, item_value) + xml_doc.appendChild(item_node) + self._add_xmlns(item_node) + return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') + + def show(self, meta_item_dict): + return self._meta_item_to_xml_string(meta_item_dict['meta']) + + def update(self, meta_item_dict): + return self._meta_item_to_xml_string(meta_item_dict['meta']) diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py index 4f33844fa..dd1a3f130 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/image_metadata.py @@ -16,7 +16,6 @@ # under the License. from webob import exc -from xml.dom import minidom from nova import flags from nova import image @@ -111,54 +110,6 @@ class Controller(object): self.image_service.update(context, image_id, img, None) -class ImageMetadataXMLSerializer(wsgi.XMLDictSerializer): - def __init__(self, xmlns=wsgi.XMLNS_V11): - super(ImageMetadataXMLSerializer, self).__init__(xmlns=xmlns) - - def _meta_item_to_xml(self, doc, key, value): - node = doc.createElement('meta') - doc.appendChild(node) - node.setAttribute('key', '%s' % key) - text = doc.createTextNode('%s' % value) - node.appendChild(text) - return node - - def meta_list_to_xml(self, xml_doc, meta_items): - container_node = xml_doc.createElement('metadata') - for (key, value) in meta_items: - item_node = self._meta_item_to_xml(xml_doc, key, value) - container_node.appendChild(item_node) - return container_node - - def _meta_list_to_xml_string(self, metadata_dict): - xml_doc = minidom.Document() - items = metadata_dict['metadata'].items() - container_node = self.meta_list_to_xml(xml_doc, items) - xml_doc.appendChild(container_node) - self._add_xmlns(container_node) - return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') - - def index(self, metadata_dict): - return self._meta_list_to_xml_string(metadata_dict) - - def create(self, metadata_dict): - return self._meta_list_to_xml_string(metadata_dict) - - def _meta_item_to_xml_string(self, meta_item_dict): - xml_doc = minidom.Document() - item_key, item_value = meta_item_dict.items()[0] - item_node = self._meta_item_to_xml(xml_doc, item_key, item_value) - xml_doc.appendChild(item_node) - self._add_xmlns(item_node) - return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') - - def show(self, meta_item_dict): - return self._meta_item_to_xml_string(meta_item_dict['meta']) - - def update(self, meta_item_dict): - return self._meta_item_to_xml_string(meta_item_dict['meta']) - - def create_resource(): body_serializers = { 'application/xml': ImageMetadataXMLSerializer(), diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index d0317583e..6c7c0feb9 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -278,9 +278,9 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer): xmlns = wsgi.XMLNS_V11 def __init__(self): - self.metadata_serializer = image_metadata.ImageMetadataXMLSerializer() + self.metadata_serializer = common.MetadataXMLSerializer() - def _image_to_xml(self, xml_doc, image): + def image_to_xml(self, xml_doc, image): image_node = xml_doc.createElement('image') image_node.setAttribute('id', str(image['id'])) image_node.setAttribute('name', image['name']) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 93f8e832c..b07b903f8 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -17,6 +17,7 @@ import base64 import traceback from webob import exc +from xml.dom import minidom from nova import compute from nova import db @@ -612,6 +613,94 @@ class HeadersSerializer(wsgi.ResponseHeadersSerializer): response.status_int = 204 +class ServerXMLSerializer(wsgi.XMLDictSerializer): + + xmlns = wsgi.XMLNS_V11 + + def __init__(self): + self.metadata_serializer = common.MetadataXMLSerializer() + + def _create_basic_entity_node(self, xml_doc, id, links, name): + basic_node = xml_doc.createElement(name) + basic_node.setAttribute('id', str(id)) + link_nodes = self._create_link_nodes(xml_doc, links) + for link_node in link_nodes: + basic_node.appendChild(link_node) + return basic_node + + def _create_metadata_node(self, xml_doc, metadata): + return self.metadata_serializer.meta_list_to_xml(xml_doc, metadata) + + def _create_addresses_node(self, xml_doc, addresses): + addresses_node = xml_doc.createElement('addresses') + for name, network_dict in addresses.items(): + network_node = self._create_network_node(xml_doc, + name, + network_dict) + addresses_node.appendChild(network_node) + return addresses_node + + def _create_network_node(self, xml_doc, network_name, network_dict): + network_node = xml_doc.createElement('network') + network_node.setAttribute('id', network_name) + for ip in network_dict: + ip_node = xml_doc.createElement('ip') + ip_node.setAttribute('version', str(ip['version'])) + ip_node.setAttribute('addr', ip['addr']) + network_node.appendChild(ip_node) + return network_node + + + def _add_server_attributes(self, node, server): + node.setAttribute('id', str(server['id'])) + node.setAttribute('uuid', str(server['uuid'])) + node.setAttribute('hostId', str(server['hostId'])) + node.setAttribute('name', server['name']) + node.setAttribute('created', server['created']) + node.setAttribute('updated', server['updated']) + node.setAttribute('status', server['status']) + if 'progress' in server: + node.setAttribute('progress', str(server['progress'])) + + def _server_to_xml_detailed(self, xml_doc, server): + server_node = xml_doc.createElement('server') + self._add_server_attributes(server_node, server) + + link_nodes = self._create_link_nodes(xml_doc, + server['links']) + for link_node in link_nodes: + server_node.appendChild(link_node) + + image_node = self._create_basic_entity_node(xml_doc, + server['image']['id'], + server['image']['links'], + 'image') + server_node.appendChild(image_node) + + flavor_node = self._create_basic_entity_node(xml_doc, + server['flavor']['id'], + server['flavor']['links'], + 'flavor') + server_node.appendChild(flavor_node) + + metadata = server.get('metadata', {}).items() + if len(metadata) > 0: + metadata_node = self._create_metadata_node(xml_doc, metadata) + server_node.appendChild(metadata_node) + + addresses_node = self._create_addresses_node(xml_doc, + server['addresses']) + server_node.appendChild(addresses_node) + + return server_node + + def show(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 = { '1.0': ControllerV10, -- cgit From 7af043463a350cfc71c45ff719354511173b5c39 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sat, 16 Jul 2011 19:39:27 -0400 Subject: Moved Metadata Serialization Test --- nova/api/openstack/image_metadata.py | 3 ++- nova/api/openstack/images.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py index dd1a3f130..d1065a4e3 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/image_metadata.py @@ -21,6 +21,7 @@ from nova import flags from nova import image from nova import quota from nova import utils +from nova.api.openstack import common from nova.api.openstack import faults from nova.api.openstack import wsgi @@ -112,7 +113,7 @@ class Controller(object): def create_resource(): body_serializers = { - 'application/xml': ImageMetadataXMLSerializer(), + 'application/xml': common.MetadataXMLSerializer(), } serializer = wsgi.ResponseSerializer(body_serializers) diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 6c7c0feb9..df7bf0cf9 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -280,7 +280,7 @@ class ImageXMLSerializer(wsgi.XMLDictSerializer): def __init__(self): self.metadata_serializer = common.MetadataXMLSerializer() - def image_to_xml(self, xml_doc, image): + def _image_to_xml(self, xml_doc, image): image_node = xml_doc.createElement('image') image_node.setAttribute('id', str(image['id'])) image_node.setAttribute('name', image['name']) -- cgit From c538d38d890e74382e928d225e8abdc57da9760e Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sat, 16 Jul 2011 19:45:28 -0400 Subject: pep8 --- nova/api/openstack/image_metadata.py | 2 +- nova/api/openstack/servers.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py index d1065a4e3..b9b782f92 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/image_metadata.py @@ -21,7 +21,7 @@ from nova import flags from nova import image from nova import quota from nova import utils -from nova.api.openstack import common +from nova.api.openstack import common from nova.api.openstack import faults from nova.api.openstack import wsgi diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index b07b903f8..1a85fda58 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -650,7 +650,6 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): network_node.appendChild(ip_node) return network_node - def _add_server_attributes(self, node, server): node.setAttribute('id', str(server['id'])) node.setAttribute('uuid', str(server['uuid'])) -- cgit From 712493f65415a7a5fc727f6b316c66ef90f1cad5 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sun, 17 Jul 2011 14:50:44 -0400 Subject: added index to servers xml serializer --- nova/api/openstack/servers.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 1a85fda58..8d59c8626 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -661,6 +661,16 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): if 'progress' in server: node.setAttribute('progress', str(server['progress'])) + def _server_to_xml(self, xml_doc, server): + server_node = xml_doc.createElement('server') + server_node.setAttribute('id', str(server['id'])) + server_node.setAttribute('name', server['name']) + link_nodes = self._create_link_nodes(xml_doc, + server['links']) + for link_node in link_nodes: + server_node.appendChild(link_node) + return server_node + def _server_to_xml_detailed(self, xml_doc, server): server_node = xml_doc.createElement('server') self._add_server_attributes(server_node, server) @@ -693,6 +703,25 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): return server_node + def _server_list_to_xml(self, xml_doc, servers, detailed): + container_node = xml_doc.createElement('servers') + if detailed: + server_to_xml = self._server_to_xml_detailed + else: + server_to_xml = self._server_to_xml + + for server in servers: + item_node = server_to_xml(xml_doc, server) + container_node.appendChild(item_node) + return container_node + + def index(self, servers_dict): + xml_doc = minidom.Document() + node = self._server_list_to_xml(xml_doc, + servers_dict['servers'], + detailed=False) + return self.to_xml_string(node, True) + def show(self, server_dict): xml_doc = minidom.Document() node = self._server_to_xml_detailed(xml_doc, -- cgit From baaaa80d36570d5734ac823bc49be8ff2477e5c2 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sun, 17 Jul 2011 21:24:02 -0400 Subject: added 'detail' to server XML serializer --- nova/api/openstack/servers.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 8d59c8626..82630397f 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -722,6 +722,13 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): detailed=False) return self.to_xml_string(node, True) + def detail(self, servers_dict): + xml_doc = minidom.Document() + node = self._server_list_to_xml(xml_doc, + servers_dict['servers'], + detailed=True) + return self.to_xml_string(node, True) + def show(self, server_dict): xml_doc = minidom.Document() node = self._server_to_xml_detailed(xml_doc, -- cgit From 8ab775585fee4af7b30a28a5bffae46c23ec76d1 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sun, 17 Jul 2011 21:36:57 -0400 Subject: added 'create' to server XML serializer --- nova/api/openstack/servers.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 82630397f..4a29e1454 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -735,6 +735,13 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): server_dict['server']) return self.to_xml_string(node, True) + def create(self, server_dict): + xml_doc = minidom.Document() + node = self._server_to_xml_detailed(xml_doc, + server_dict['server']) + node.setAttribute('adminPass', server_dict['server']['adminPass']) + return self.to_xml_string(node, True) + def create_resource(version='1.0'): controller = { -- cgit From e23e70afd096ca1d7ad22c776f6f439986bbc8b5 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sun, 17 Jul 2011 22:28:16 -0400 Subject: updated servers to use ServerXMLSerializer --- nova/api/openstack/servers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 4a29e1454..a6229125d 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -773,8 +773,7 @@ def create_resource(version='1.0'): headers_serializer = HeadersSerializer() body_serializers = { - 'application/xml': wsgi.XMLDictSerializer(metadata=metadata, - xmlns=xmlns), + 'application/xml': ServerXMLSerializer(), } body_deserializers = { -- cgit From b9d316452a1e2a204e56d1434feade1ab0bd281c Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Sun, 17 Jul 2011 22:50:10 -0400 Subject: Updated servers to choose XML serializer based on api version --- nova/api/openstack/servers.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index a6229125d..6d55b856d 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -772,8 +772,13 @@ def create_resource(version='1.0'): headers_serializer = HeadersSerializer() + xml_serializer = { + '1.0': wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V10), + '1.1': ServerXMLSerializer(), + }[version] + body_serializers = { - 'application/xml': ServerXMLSerializer(), + 'application/xml': xml_serializer, } body_deserializers = { -- cgit From 5f75097eb46fa03814fe53c5d9fda84f0000fdd4 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 21 Jul 2011 22:46:57 +0000 Subject: start removing references to AuthManager --- nova/api/direct.py | 3 ++- nova/api/ec2/__init__.py | 10 ++++++---- nova/api/openstack/auth.py | 26 +++++++------------------- 3 files changed, 15 insertions(+), 24 deletions(-) (limited to 'nova/api') diff --git a/nova/api/direct.py b/nova/api/direct.py index ec79151b1..993815fc7 100644 --- a/nova/api/direct.py +++ b/nova/api/direct.py @@ -107,7 +107,8 @@ class DelegatedAuthMiddleware(wsgi.Middleware): def process_request(self, request): os_user = request.headers['X-OpenStack-User'] os_project = request.headers['X-OpenStack-Project'] - context_ref = context.RequestContext(user=os_user, project=os_project) + context_ref = context.RequestContext(user_id=os_user, + project_id=os_project) request.environ['openstack.context'] = context_ref diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index cf1734281..8bb2ea944 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -174,8 +174,8 @@ class Authenticate(wsgi.Middleware): remote_address = req.remote_addr if FLAGS.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) - ctxt = context.RequestContext(user=user, - project=project, + ctxt = context.RequestContext(user_id=user.id, + project_id=project.id, remote_address=remote_address) req.environ['ec2.context'] = ctxt uname = user.name @@ -295,13 +295,15 @@ class Authorizer(wsgi.Middleware): def _matches_any_role(self, context, roles): """Return True if any role in roles is allowed in context.""" - if context.user.is_superuser(): + authman = manager.AuthManager() + user = authman.get_user(context.user_id) + if user.is_superuser(): return True if 'all' in roles: return True if 'none' in roles: return False - return any(context.project.has_role(context.user_id, role) + return any(authman.has_role(context.user_id, role, context.project_id) for role in roles) diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 7c3e683d6..5b387c081 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -48,31 +48,19 @@ class AuthMiddleware(wsgi.Middleware): def __call__(self, req): if not self.has_authentication(req): return self.authenticate(req) - user = self.get_user_by_authentication(req) - if not user: + user_id = self.get_user_by_authentication(req) + if not user_id: token = req.headers["X-Auth-Token"] - msg = _("%(user)s could not be found with token '%(token)s'") + msg = _("%(user_id)s could not be found with token '%(token)s'") LOG.warn(msg % locals()) return faults.Fault(webob.exc.HTTPUnauthorized()) try: - account = req.headers["X-Auth-Project-Id"] + project_id = req.headers["X-Auth-Project-Id"] except KeyError: - # FIXME(usrleon): It needed only for compatibility - # while osapi clients don't use this header - accounts = self.auth.get_projects(user=user) - if accounts: - account = accounts[0] - else: - return faults.Fault(webob.exc.HTTPUnauthorized()) - - if not self.auth.is_admin(user) and \ - not self.auth.is_project_member(user, account): - msg = _("%(user)s must be an admin or a member of %(account)s") - LOG.warn(msg % locals()) - return faults.Fault(webob.exc.HTTPUnauthorized()) + project_id = user_id - req.environ['nova.context'] = context.RequestContext(user, account) + req.environ['nova.context'] = context.RequestContext(user_id, project_id) return self.application def has_authentication(self, req): @@ -133,7 +121,7 @@ class AuthMiddleware(wsgi.Middleware): if delta.days >= 2: self.db.auth_token_destroy(ctxt, token['token_hash']) else: - return self.auth.get_user(token['user_id']) + return token['user_id'] return None def _authorize_user(self, username, key, req): -- cgit From e1cf345fa82c3a9b8088237f1025c41db0f4e829 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 00:39:53 +0000 Subject: fix a whole bunch of tests --- nova/api/ec2/__init__.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 8bb2ea944..edae94331 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -138,8 +138,19 @@ class Lockout(wsgi.Middleware): return res -class Authenticate(wsgi.Middleware): +class InjectContext(wsgi.Middleware): + """Always add a fake 'ec2.context' to WSGI environ.""" + def __init__(self, context, *args, **kwargs): + self.context = context + super(InjectContext, self).__init__(*args, **kwargs) + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + req.environ['ec2.context'] = self.context + return self.application + + +class Authenticate(wsgi.Middleware): """Authenticate an EC2 request and add 'ec2.context' to WSGI environ.""" @webob.dec.wsgify(RequestClass=wsgi.Request) @@ -295,16 +306,13 @@ class Authorizer(wsgi.Middleware): def _matches_any_role(self, context, roles): """Return True if any role in roles is allowed in context.""" - authman = manager.AuthManager() - user = authman.get_user(context.user_id) - if user.is_superuser(): + if context.is_admin: return True if 'all' in roles: return True if 'none' in roles: return False - return any(authman.has_role(context.user_id, role, context.project_id) - for role in roles) + return any(role in context.roles for role in roles) class Executor(wsgi.Application): -- cgit From 44d1024a53b8150cf9542d08d5886f430365f161 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 19:47:41 +0000 Subject: fix all tests --- nova/api/ec2/__init__.py | 29 +++++++++-------------------- nova/api/openstack/auth.py | 20 ++++++++++++++++++-- 2 files changed, 27 insertions(+), 22 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index edae94331..0a743075c 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -66,7 +66,7 @@ class RequestLogging(wsgi.Middleware): else: controller = None action = None - ctxt = request.environ.get('ec2.context', None) + ctxt = request.environ.get('nova.context', None) delta = utils.utcnow() - start seconds = delta.seconds microseconds = delta.microseconds @@ -138,20 +138,8 @@ class Lockout(wsgi.Middleware): return res -class InjectContext(wsgi.Middleware): - """Always add a fake 'ec2.context' to WSGI environ.""" - def __init__(self, context, *args, **kwargs): - self.context = context - super(InjectContext, self).__init__(*args, **kwargs) - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - req.environ['ec2.context'] = self.context - return self.application - - class Authenticate(wsgi.Middleware): - """Authenticate an EC2 request and add 'ec2.context' to WSGI environ.""" + """Authenticate an EC2 request and add 'nova.context' to WSGI environ.""" @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): @@ -187,12 +175,13 @@ class Authenticate(wsgi.Middleware): remote_address = req.headers.get('X-Forwarded-For', remote_address) ctxt = context.RequestContext(user_id=user.id, project_id=project.id, + is_admin=user.is_admin(), remote_address=remote_address) - req.environ['ec2.context'] = ctxt + req.environ['nova.context'] = ctxt uname = user.name pname = project.name msg = _('Authenticated Request For %(uname)s:%(pname)s)') % locals() - LOG.audit(msg, context=req.environ['ec2.context']) + LOG.audit(msg, context=req.environ['nova.context']) return self.application @@ -239,7 +228,7 @@ class Authorizer(wsgi.Middleware): """Authorize an EC2 API request. Return a 401 if ec2.controller and ec2.action in WSGI environ may not be - executed in ec2.context. + executed in nova.context. """ def __init__(self, application): @@ -293,7 +282,7 @@ class Authorizer(wsgi.Middleware): @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): - context = req.environ['ec2.context'] + context = req.environ['nova.context'] controller = req.environ['ec2.request'].controller.__class__.__name__ action = req.environ['ec2.request'].action allowed_roles = self.action_roles[controller].get(action, ['none']) @@ -319,14 +308,14 @@ class Executor(wsgi.Application): """Execute an EC2 API request. - Executes 'ec2.action' upon 'ec2.controller', passing 'ec2.context' and + Executes 'ec2.action' upon 'ec2.controller', passing 'nova.context' and 'ec2.action_args' (all variables in WSGI environ.) Returns an XML response, or a 400 upon failure. """ @webob.dec.wsgify(RequestClass=wsgi.Request) def __call__(self, req): - context = req.environ['ec2.context'] + context = req.environ['nova.context'] api_request = req.environ['ec2.request'] result = None try: diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 5b387c081..9caa14a4e 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -58,9 +58,25 @@ class AuthMiddleware(wsgi.Middleware): try: project_id = req.headers["X-Auth-Project-Id"] except KeyError: - project_id = user_id + # FIXME(usrleon): It needed only for compatibility + # while osapi clients don't use this header + projects = self.auth.get_projects(user_id) + if projects: + project_id = projects[0] + else: + return faults.Fault(webob.exc.HTTPUnauthorized()) + + is_admin = self.auth.is_admin(user_id) + req.environ['nova.context'] = context.RequestContext(user_id, + project_id, + is_admin) + if not is_admin and not self.auth.is_project_member(user_id, + project_id): + msg = _("%(user_id)s must be an admin or a " + "member of %(project_id)s") + LOG.warn(msg % locals()) + return faults.Fault(webob.exc.HTTPUnauthorized()) - req.environ['nova.context'] = context.RequestContext(user_id, project_id) return self.application def has_authentication(self, req): -- cgit From 0f8eee7ff32a91c866742939b1f551f3610f1276 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 20:20:31 +0000 Subject: fix auth tests --- nova/api/openstack/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 9caa14a4e..d42abe1f8 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -62,7 +62,7 @@ class AuthMiddleware(wsgi.Middleware): # while osapi clients don't use this header projects = self.auth.get_projects(user_id) if projects: - project_id = projects[0] + project_id = projects[0].id else: return faults.Fault(webob.exc.HTTPUnauthorized()) -- cgit From e8defa6bdd5af85486d0d3acce8956670ca16882 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 20:41:46 +0000 Subject: fix test_access --- nova/api/ec2/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 0a743075c..1ea26fdeb 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -156,8 +156,9 @@ class Authenticate(wsgi.Middleware): auth_params.pop('Signature') # Authenticate the request. + authman = manager.AuthManager() try: - (user, project) = manager.AuthManager().authenticate( + (user, project) = authman.authenticate( access, signature, auth_params, @@ -173,9 +174,12 @@ class Authenticate(wsgi.Middleware): remote_address = req.remote_addr if FLAGS.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) + roles = authman.get_active_roles(user, project) + LOG.warn(roles) ctxt = context.RequestContext(user_id=user.id, project_id=project.id, is_admin=user.is_admin(), + roles=roles, remote_address=remote_address) req.environ['nova.context'] = ctxt uname = user.name @@ -295,6 +299,7 @@ class Authorizer(wsgi.Middleware): def _matches_any_role(self, context, roles): """Return True if any role in roles is allowed in context.""" + LOG.info(context.roles) if context.is_admin: return True if 'all' in roles: -- cgit From ccb5119280d341a2ea1b3e8352acbf32b7f243af Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 21:36:41 +0000 Subject: clean up fake auth manager in other places --- nova/api/ec2/__init__.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 1ea26fdeb..af232edda 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -175,7 +175,6 @@ class Authenticate(wsgi.Middleware): if FLAGS.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) roles = authman.get_active_roles(user, project) - LOG.warn(roles) ctxt = context.RequestContext(user_id=user.id, project_id=project.id, is_admin=user.is_admin(), @@ -299,7 +298,6 @@ class Authorizer(wsgi.Middleware): def _matches_any_role(self, context, roles): """Return True if any role in roles is allowed in context.""" - LOG.info(context.roles) if context.is_admin: return True if 'all' in roles: -- cgit From 164afd51017721b9cbaf2880b9dada3d4cd9b42c Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 22 Jul 2011 22:04:52 +0000 Subject: remove auth manager from instance helper --- nova/api/openstack/create_instance_helper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 7249f1261..2034e8ada 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -20,6 +20,7 @@ import webob from webob import exc from xml.dom import minidom +from nova import db from nova import exception from nova import flags from nova import log as logging @@ -29,7 +30,6 @@ from nova import utils from nova.compute import instance_types from nova.api.openstack import wsgi -from nova.auth import manager as auth_manager LOG = logging.getLogger('nova.api.openstack.create_instance_helper') @@ -77,7 +77,8 @@ class CreateInstanceHelper(object): key_name = None key_data = None - key_pairs = auth_manager.AuthManager.get_key_pairs(context) + key_pairs = db.key_pair_get_all_by_user(context.elevated(), + context.user_id) if key_pairs: key_pair = key_pairs[0] key_name = key_pair['name'] -- cgit From 8de3c0fcaee546fae3d415ef5ddcbb51fb1db6d7 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 25 Jul 2011 17:49:09 +0000 Subject: fix for reviews --- nova/api/openstack/create_instance_helper.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/api') diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 2034e8ada..573153f68 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -77,6 +77,8 @@ class CreateInstanceHelper(object): key_name = None key_data = None + # TODO(vish): Key pair access should move into a common library + # instead of being accessed directly from the db. key_pairs = db.key_pair_get_all_by_user(context.elevated(), context.user_id) if key_pairs: -- cgit From 422d5329276f5c2252d7328d4112be7c696a274a Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Tue, 26 Jul 2011 09:57:39 -0400 Subject: Updated ServerXMLSerializer to utilize the IPXMLSerializer --- nova/api/openstack/servers.py | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 4e6f0d7b5..11dafc272 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -28,6 +28,7 @@ from nova import log as logging from nova import utils from nova.api.openstack import common from nova.api.openstack import create_instance_helper as helper +from nova.api.openstack import ips import nova.api.openstack.views.addresses import nova.api.openstack.views.flavors import nova.api.openstack.views.images @@ -608,6 +609,7 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): def __init__(self): self.metadata_serializer = common.MetadataXMLSerializer() + self.addresses_serializer = ips.IPXMLSerializer() def _create_basic_entity_node(self, xml_doc, id, links, name): basic_node = xml_doc.createElement(name) @@ -621,23 +623,7 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): return self.metadata_serializer.meta_list_to_xml(xml_doc, metadata) def _create_addresses_node(self, xml_doc, addresses): - addresses_node = xml_doc.createElement('addresses') - for name, network_dict in addresses.items(): - network_node = self._create_network_node(xml_doc, - name, - network_dict) - addresses_node.appendChild(network_node) - return addresses_node - - def _create_network_node(self, xml_doc, network_name, network_dict): - network_node = xml_doc.createElement('network') - network_node.setAttribute('id', network_name) - for ip in network_dict: - ip_node = xml_doc.createElement('ip') - ip_node.setAttribute('version', str(ip['version'])) - ip_node.setAttribute('addr', ip['addr']) - network_node.appendChild(ip_node) - return network_node + return self.addresses_serializer.networks_to_xml(xml_doc, addresses) def _add_server_attributes(self, node, server): node.setAttribute('id', str(server['id'])) -- cgit From 7cd146e7e658c51cc94664d8da8d2bc15b0141fc Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Tue, 26 Jul 2011 13:49:04 -0400 Subject: fixed minor issues --- nova/api/openstack/servers.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 11dafc272..194ec82d5 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -630,8 +630,8 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): node.setAttribute('uuid', str(server['uuid'])) node.setAttribute('hostId', str(server['hostId'])) node.setAttribute('name', server['name']) - node.setAttribute('created', server['created']) - node.setAttribute('updated', server['updated']) + node.setAttribute('created', str(server['created'])) + node.setAttribute('updated', str(server['updated'])) node.setAttribute('status', server['status']) if 'progress' in server: node.setAttribute('progress', str(server['progress'])) @@ -655,17 +655,19 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): for link_node in link_nodes: server_node.appendChild(link_node) - image_node = self._create_basic_entity_node(xml_doc, + if 'image' in server: + image_node = self._create_basic_entity_node(xml_doc, server['image']['id'], server['image']['links'], 'image') - server_node.appendChild(image_node) + server_node.appendChild(image_node) - flavor_node = self._create_basic_entity_node(xml_doc, + if 'flavor' in server: + flavor_node = self._create_basic_entity_node(xml_doc, server['flavor']['id'], server['flavor']['links'], 'flavor') - server_node.appendChild(flavor_node) + server_node.appendChild(flavor_node) metadata = server.get('metadata', {}).items() if len(metadata) > 0: -- cgit From 2e652f4cc72976ecc471a6c6f3b48afb3eb5a420 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Tue, 26 Jul 2011 16:42:16 -0400 Subject: Updated test stubs to contain the correct data Updated created and updated in responses to use correct time format --- nova/api/openstack/views/servers.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index be25e1e40..c90801724 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/views/servers.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime import hashlib import os @@ -149,8 +150,10 @@ class ViewBuilderV11(ViewBuilder): def _build_detail(self, inst): response = super(ViewBuilderV11, self)._build_detail(inst) - response['server']['created'] = inst['created_at'] - response['server']['updated'] = inst['updated_at'] + response['server']['created'] = \ + self._convert_timeformat(inst['created_at']) + response['server']['updated'] = \ + self._convert_timeformat(inst['updated_at']) if 'status' in response['server']: if response['server']['status'] == "ACTIVE": response['server']['progress'] = 100 @@ -221,3 +224,11 @@ class ViewBuilderV11(ViewBuilder): """Create an url that refers to a specific flavor id.""" return os.path.join(common.remove_version_from_href(self.base_url), "servers", str(server_id)) + + def _convert_timeformat(self, time): + """Converts the given time into the common time format + + :param time: should be a datetime + + """ + return time.strftime(utils.TIME_FORMAT) -- cgit From 0300c952d925ccaad2d3d4191d87c08656d4b413 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Wed, 27 Jul 2011 12:54:12 -0400 Subject: removed unused import --- nova/api/openstack/image_metadata.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py index da753dee5..aaf64a123 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/image_metadata.py @@ -22,7 +22,6 @@ from nova import image from nova import quota from nova import utils from nova.api.openstack import common -from nova.api.openstack import faults from nova.api.openstack import wsgi -- cgit From b8183e11e56781fce27ec1af261c5e53bca78ca5 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Wed, 27 Jul 2011 15:15:48 -0400 Subject: change local variable name --- nova/api/openstack/views/servers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index c90801724..659a43522 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/views/servers.py @@ -225,10 +225,10 @@ class ViewBuilderV11(ViewBuilder): return os.path.join(common.remove_version_from_href(self.base_url), "servers", str(server_id)) - def _convert_timeformat(self, time): + def _convert_timeformat(self, date_time): """Converts the given time into the common time format - :param time: should be a datetime + :param date_time: the datetime object to convert """ - return time.strftime(utils.TIME_FORMAT) + return date_time.strftime(utils.TIME_FORMAT) -- cgit From 7a165843aa5c1a98b1dbf13dedf556878a3d0435 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 29 Jul 2011 11:06:02 -0400 Subject: Updated resize to call compute API with instance_type identifiers instead of flavor identifiers. Updated tests. --- nova/api/openstack/servers.py | 63 +++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index f6841318d..096fb229c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -17,11 +17,10 @@ import base64 import traceback from webob import exc -import webob from xml.dom import minidom +import webob from nova import compute -from nova import db from nova import exception from nova import flags from nova import log as logging @@ -29,13 +28,14 @@ from nova import utils from nova.api.openstack import common from nova.api.openstack import create_instance_helper as helper from nova.api.openstack import ips +from nova.api.openstack import wsgi +from nova.compute import instance_types +from nova.scheduler import api as scheduler_api +import nova.api.openstack import nova.api.openstack.views.addresses import nova.api.openstack.views.flavors import nova.api.openstack.views.images import nova.api.openstack.views.servers -from nova.api.openstack import wsgi -import nova.api.openstack -from nova.scheduler import api as scheduler_api LOG = logging.getLogger('nova.api.openstack.servers') @@ -438,13 +438,21 @@ class ControllerV10(Controller): def _action_resize(self, input_dict, req, id): """ Resizes a given instance to the flavor size requested """ - if 'resize' in input_dict and 'flavorId' in input_dict['resize']: - flavor_id = input_dict['resize']['flavorId'] - self.compute_api.resize(req.environ['nova.context'], id, - flavor_id) - else: - LOG.exception(_("Missing 'flavorId' argument for resize")) - raise exc.HTTPUnprocessableEntity() + try: + flavor_id = input_dict["resize"]["flavorId"] + except (KeyError, TypeError): + msg = _("Resize requests require 'flavorId' attribute.") + raise exc.HTTPBadRequest(explanation=msg) + + try: + i_type = instance_types.get_instance_type_by_flavor_id(flavor_id) + except exception.FlavorNotFound: + msg = _("Unable to locate requested flavor.") + raise exc.HTTPBadRequest(explanation=msg) + + context = req.environ["nova.context"] + self.compute_api.resize(context, id, i_type["id"]) + return webob.Response(status_int=202) def _action_rebuild(self, info, request, instance_id): @@ -555,17 +563,26 @@ class ControllerV11(Controller): def _action_resize(self, input_dict, req, id): """ Resizes a given instance to the flavor size requested """ try: - if 'resize' in input_dict and 'flavorRef' in input_dict['resize']: - flavor_ref = input_dict['resize']['flavorRef'] - flavor_id = common.get_id_from_href(flavor_ref) - self.compute_api.resize(req.environ['nova.context'], id, - flavor_id) - else: - LOG.exception(_("Missing 'flavorRef' argument for resize")) - raise exc.HTTPUnprocessableEntity() - except Exception, e: - LOG.exception(_("Error in resize %s"), e) - raise exc.HTTPBadRequest() + flavor = input_dict["resize"]["flavor"] + except (KeyError, TypeError): + msg = _("Resize requests require a flavor to resize instance.") + raise exc.HTTPBadRequest(explanation=msg) + + try: + flavor_id = flavor["id"] + except (KeyError, TypeError): + msg = _("Resize flavor requires 'id' attribute.") + raise exc.HTTPBadRequest(explanation=msg) + + try: + i_type = instance_types.get_instance_type_by_flavor_id(flavor_id) + except exception.FlavorNotFound: + msg = _("Unable to locate requested flavor.") + raise exc.HTTPBadRequest(explanation=msg) + + context = req.environ["nova.context"] + self.compute_api.resize(context, id, i_type["id"]) + return webob.Response(status_int=202) def _action_rebuild(self, info, request, instance_id): -- cgit From 50abd79432ff82a23da1934cc4d297c0c5051668 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 29 Jul 2011 11:57:40 -0400 Subject: Oops, I wasn't actually being compatible with the spec here. --- nova/api/openstack/servers.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 096fb229c..30169d450 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -563,19 +563,13 @@ class ControllerV11(Controller): def _action_resize(self, input_dict, req, id): """ Resizes a given instance to the flavor size requested """ try: - flavor = input_dict["resize"]["flavor"] + flavor_ref = input_dict["resize"]["flavorRef"] except (KeyError, TypeError): - msg = _("Resize requests require a flavor to resize instance.") + msg = _("Resize requests require 'flavorRef' attribute.") raise exc.HTTPBadRequest(explanation=msg) try: - flavor_id = flavor["id"] - except (KeyError, TypeError): - msg = _("Resize flavor requires 'id' attribute.") - raise exc.HTTPBadRequest(explanation=msg) - - try: - i_type = instance_types.get_instance_type_by_flavor_id(flavor_id) + i_type = instance_types.get_instance_type_by_flavor_id(flavor_ref) except exception.FlavorNotFound: msg = _("Unable to locate requested flavor.") raise exc.HTTPBadRequest(explanation=msg) -- cgit