diff options
| author | Anthony Young <sleepsonthefloor@gmail.com> | 2011-08-24 11:45:12 -0700 |
|---|---|---|
| committer | Anthony Young <sleepsonthefloor@gmail.com> | 2011-08-24 11:45:12 -0700 |
| commit | e2e32589c247bfa790f4459a51742cc335581d0c (patch) | |
| tree | f96c056cab1658ce01f307981f90fce07cdf6db8 /nova/api | |
| parent | 3d17d22926e2f589648fdac26302a58e8c4e9069 (diff) | |
| parent | 4a99c3f134e20445eb1f6bdabf0f0c53ff9c39c5 (diff) | |
merge trunk, fix tests
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/auth.py | 1 | ||||
| -rw-r--r-- | nova/api/ec2/__init__.py | 21 | ||||
| -rw-r--r-- | nova/api/ec2/admin.py | 4 | ||||
| -rw-r--r-- | nova/api/openstack/auth.py | 52 | ||||
| -rw-r--r-- | nova/api/openstack/create_instance_helper.py | 6 | ||||
| -rw-r--r-- | nova/api/openstack/servers.py | 29 | ||||
| -rw-r--r-- | nova/api/openstack/views/addresses.py | 23 | ||||
| -rw-r--r-- | nova/api/openstack/views/servers.py | 5 | ||||
| -rw-r--r-- | nova/api/openstack/wsgi.py | 6 |
9 files changed, 132 insertions, 15 deletions
diff --git a/nova/api/auth.py b/nova/api/auth.py index cd3e3e8a0..cd0d38b3f 100644 --- a/nova/api/auth.py +++ b/nova/api/auth.py @@ -62,6 +62,7 @@ class KeystoneContext(wsgi.Middleware): req.headers.get('X_STORAGE_TOKEN')) # Build a context, including the auth_token... + remote_address = getattr(req, 'remote_address', '127.0.0.1') remote_address = req.remote_addr if FLAGS.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 17969099d..5430f443d 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -183,6 +183,27 @@ class ToToken(wsgi.Middleware): return self.application +class NoAuth(wsgi.Middleware): + """Add user:project as 'nova.context' to WSGI environ.""" + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + if 'AWSAccessKeyId' not in req.params: + raise webob.exc.HTTPBadRequest() + user_id, _sep, project_id = req.params['AWSAccessKeyId'].partition(':') + project_id = project_id or user_id + remote_address = getattr(req, 'remote_address', '127.0.0.1') + if FLAGS.use_forwarded_for: + remote_address = req.headers.get('X-Forwarded-For', remote_address) + ctx = context.RequestContext(user_id, + project_id, + is_admin=True, + remote_address=remote_address) + + req.environ['nova.context'] = ctx + return self.application + + class Authenticate(wsgi.Middleware): """Authenticate an EC2 request and add 'nova.context' to WSGI environ.""" diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index df7876b9d..dfbbc0a2b 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -283,8 +283,10 @@ class AdminController(object): # NOTE(vish) import delayed because of __init__.py from nova.cloudpipe import pipelib pipe = pipelib.CloudPipe() + proj = manager.AuthManager().get_project(project) + user_id = proj.project_manager_id try: - pipe.launch_vpn_instance(project) + pipe.launch_vpn_instance(project, user_id) except db.NoMoreNetworks: raise exception.ApiError("Unable to claim IP for VPN instance" ", ensure it isn't running, and try " diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index b6ff1126b..6754fea27 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -33,6 +33,46 @@ from nova.api.openstack import faults LOG = logging.getLogger('nova.api.openstack') FLAGS = flags.FLAGS +flags.DECLARE('use_forwarded_for', 'nova.api.auth') + + +class NoAuthMiddleware(wsgi.Middleware): + """Return a fake token if one isn't specified.""" + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + if 'X-Auth-Token' not in req.headers: + os_url = req.url + version = common.get_version_from_href(os_url) + user_id = req.headers.get('X-Auth-User', 'admin') + project_id = req.headers.get('X-Auth-Project-Id', 'admin') + if version == '1.1': + os_url += '/' + project_id + res = webob.Response() + # NOTE(vish): This is expecting and returning Auth(1.1), whereas + # keystone uses 2.0 auth. We should probably allow + # 2.0 auth here as well. + res.headers['X-Auth-Token'] = '%s:%s' % (user_id, project_id) + res.headers['X-Server-Management-Url'] = os_url + res.headers['X-Storage-Url'] = '' + res.headers['X-CDN-Management-Url'] = '' + res.content_type = 'text/plain' + res.status = '204' + return res + + token = req.headers['X-Auth-Token'] + user_id, _sep, project_id = token.partition(':') + project_id = project_id or user_id + remote_address = getattr(req, 'remote_address', '127.0.0.1') + if FLAGS.use_forwarded_for: + remote_address = req.headers.get('X-Forwarded-For', remote_address) + ctx = context.RequestContext(user_id, + project_id, + is_admin=True, + remote_address=remote_address) + + req.environ['nova.context'] = ctx + return self.application class AuthMiddleware(wsgi.Middleware): @@ -85,9 +125,15 @@ class AuthMiddleware(wsgi.Middleware): project_id = projects[0].id is_admin = self.auth.is_admin(user_id) - req.environ['nova.context'] = context.RequestContext(user_id, - project_id, - is_admin) + remote_address = getattr(req, 'remote_address', '127.0.0.1') + if FLAGS.use_forwarded_for: + remote_address = req.headers.get('X-Forwarded-For', remote_address) + ctx = context.RequestContext(user_id, + project_id, + is_admin=is_admin, + remote_address=remote_address) + req.environ['nova.context'] = ctx + 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 " diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 76b903599..4acee2211 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -1,4 +1,5 @@ # Copyright 2011 OpenStack LLC. +# Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -106,6 +107,7 @@ class CreateInstanceHelper(object): raise exc.HTTPBadRequest(explanation=msg) personality = server_dict.get('personality') + config_drive = server_dict.get('config_drive') injected_files = [] if personality: @@ -159,6 +161,7 @@ class CreateInstanceHelper(object): extra_values = { 'instance_type': inst_type, 'image_ref': image_href, + 'config_drive': config_drive, 'password': password} return (extra_values, @@ -184,7 +187,8 @@ class CreateInstanceHelper(object): requested_networks=requested_networks, security_group=sg_names, user_data=user_data, - availability_zone=availability_zone)) + availability_zone=availability_zone, + config_drive=config_drive,)) except quota.QuotaError as error: self._handle_quota_error(error) except exception.ImageNotFound as error: diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 8a358b532..3e76fa1a0 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -612,8 +612,10 @@ class ControllerV10(Controller): LOG.debug(msg) raise exc.HTTPBadRequest(explanation=msg) + password = utils.generate_password(16) + try: - self.compute_api.rebuild(context, instance_id, image_id) + self.compute_api.rebuild(context, instance_id, image_id, password) except exception.BuildInProgress: msg = _("Instance %s is currently being rebuilt.") % instance_id LOG.debug(msg) @@ -749,15 +751,26 @@ class ControllerV11(Controller): self._validate_metadata(metadata) self._decode_personalities(personalities) + password = info["rebuild"].get("adminPass", + utils.generate_password(16)) + try: - self.compute_api.rebuild(context, instance_id, image_href, name, - metadata, personalities) + self.compute_api.rebuild(context, instance_id, image_href, + password, name=name, metadata=metadata, + files_to_inject=personalities) except exception.BuildInProgress: msg = _("Instance %s is currently being rebuilt.") % instance_id LOG.debug(msg) raise exc.HTTPConflict(explanation=msg) + except exception.InstanceNotFound: + msg = _("Instance %s could not be found") % instance_id + raise exc.HTTPNotFound(explanation=msg) - return webob.Response(status_int=202) + instance = self.compute_api.routing_get(context, instance_id) + view = self._build_view(request, instance, is_detail=True) + view['server']['adminPass'] = password + + return view @common.check_snapshots_enabled def _action_create_image(self, input_dict, req, instance_id): @@ -824,6 +837,9 @@ class HeadersSerializer(wsgi.ResponseHeadersSerializer): def delete(self, response, data): response.status_int = 204 + def action(self, response, data): + response.status_int = 202 + class ServerXMLSerializer(wsgi.XMLDictSerializer): @@ -948,6 +964,11 @@ class ServerXMLSerializer(wsgi.XMLDictSerializer): node.setAttribute('adminPass', server_dict['server']['adminPass']) return self.to_xml_string(node, True) + def action(self, server_dict): + #NOTE(bcwaldon): We need a way to serialize actions individually. This + # assumes all actions return a server entity + return self.create(server_dict) + def update(self, server_dict): xml_doc = minidom.Document() node = self._server_to_xml_detailed(xml_doc, diff --git a/nova/api/openstack/views/addresses.py b/nova/api/openstack/views/addresses.py index ddbf7a144..8f07a2289 100644 --- a/nova/api/openstack/views/addresses.py +++ b/nova/api/openstack/views/addresses.py @@ -17,9 +17,11 @@ from nova import flags from nova import utils +from nova import log as logging from nova.api.openstack import common FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.api.openstack.views.addresses') class ViewBuilder(object): @@ -48,7 +50,10 @@ class ViewBuilderV11(ViewBuilder): def build(self, interfaces): networks = {} for interface in interfaces: - network_label = interface['network']['label'] + try: + network_label = self._extract_network_label(interface) + except TypeError: + continue if network_label not in networks: networks[network_label] = [] @@ -64,9 +69,14 @@ class ViewBuilderV11(ViewBuilder): return networks - def build_network(self, interfaces, network_label): + def build_network(self, interfaces, requested_network): for interface in interfaces: - if interface['network']['label'] == network_label: + try: + network_label = self._extract_network_label(interface) + except TypeError: + continue + + if network_label == requested_network: ips = list(self._extract_ipv4_addresses(interface)) ipv6 = self._extract_ipv6_address(interface) if ipv6 is not None: @@ -74,6 +84,13 @@ class ViewBuilderV11(ViewBuilder): return {network_label: ips} return None + def _extract_network_label(self, interface): + try: + return interface['network']['label'] + except (TypeError, KeyError) as exc: + LOG.exception(exc) + raise TypeError + def _extract_ipv4_addresses(self, interface): for fixed_ip in interface['fixed_ips']: yield self._build_ip_entity(fixed_ip['address'], 4) diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py index 0bef58edc..fd7c040d4 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/views/servers.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2010-2011 OpenStack LLC. +# Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -190,6 +191,7 @@ class ViewBuilderV11(ViewBuilder): def _build_extra(self, response, inst): self._build_links(response, inst) response['uuid'] = inst['uuid'] + self._build_config_drive(response, inst) def _build_links(self, response, inst): href = self.generate_href(inst["id"]) @@ -208,6 +210,9 @@ class ViewBuilderV11(ViewBuilder): response["links"] = links + def _build_config_drive(self, response, inst): + response['config_drive'] = inst.get('config_drive') + def generate_href(self, server_id): """Create an url that refers to a specific server id.""" return os.path.join(self.base_url, self.project_id, diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index dc0f1b93e..8641e960a 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -520,6 +520,6 @@ class Resource(wsgi.Application): controller_method = getattr(self.controller, action) try: return controller_method(req=request, **action_args) - except TypeError, exc: - LOG.debug(str(exc)) - return webob.exc.HTTPBadRequest() + except TypeError as exc: + LOG.exception(exc) + return faults.Fault(webob.exc.HTTPBadRequest()) |
