From f127d85d7790585d6e735648dfab13416d79fbde Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 6 Nov 2010 00:02:36 +0000 Subject: Per-project vpns, certificates, and revocation --- nova/api/__init__.py | 2 -- nova/api/cloudpipe/__init__.py | 69 ------------------------------------------ 2 files changed, 71 deletions(-) delete mode 100644 nova/api/cloudpipe/__init__.py (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 707c1623e..176d571a8 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -25,7 +25,6 @@ import webob.dec from nova import flags from nova import wsgi -from nova.api import cloudpipe from nova.api import ec2 from nova.api import openstack from nova.api.ec2 import metadatarequesthandler @@ -74,7 +73,6 @@ class API(wsgi.Router): mapper.connect('%s/{path_info:.*}' % s, controller=mrh, conditions=ec2api_subdomain) - mapper.connect("/cloudpipe/{path_info:.*}", controller=cloudpipe.API()) super(API, self).__init__(mapper) @webob.dec.wsgify diff --git a/nova/api/cloudpipe/__init__.py b/nova/api/cloudpipe/__init__.py deleted file mode 100644 index 6d40990a8..000000000 --- a/nova/api/cloudpipe/__init__.py +++ /dev/null @@ -1,69 +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. - -""" -REST API Request Handlers for CloudPipe -""" - -import logging -import urllib -import webob -import webob.dec -import webob.exc - -from nova import crypto -from nova import wsgi -from nova.auth import manager -from nova.api.ec2 import cloud - - -_log = logging.getLogger("api") -_log.setLevel(logging.DEBUG) - - -class API(wsgi.Application): - - def __init__(self): - self.controller = cloud.CloudController() - - @webob.dec.wsgify - def __call__(self, req): - if req.method == 'POST': - return self.sign_csr(req) - _log.debug("Cloudpipe path is %s" % req.path_info) - if req.path_info.endswith("/getca/"): - return self.send_root_ca(req) - return webob.exc.HTTPNotFound() - - def get_project_id_from_ip(self, ip): - # TODO(eday): This was removed with the ORM branch, fix! - instance = self.controller.get_instance_by_ip(ip) - return instance['project_id'] - - def send_root_ca(self, req): - _log.debug("Getting root ca") - project_id = self.get_project_id_from_ip(req.remote_addr) - res = webob.Response() - res.headers["Content-Type"] = "text/plain" - res.body = crypto.fetch_ca(project_id) - return res - - def sign_csr(self, req): - project_id = self.get_project_id_from_ip(req.remote_addr) - cert = self.str_params['cert'] - return crypto.sign_csr(urllib.unquote(cert), project_id) -- cgit From 398ec325160acf039e1070718e898339a4b2d268 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 15 Nov 2010 01:25:42 -0400 Subject: base commit --- nova/api/openstack/__init__.py | 49 +++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 1dd3ba770..338d642bc 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -47,6 +47,9 @@ flags.DEFINE_string('nova_api_auth', 'nova.api.openstack.auth.BasicApiAuthManager', 'The auth mechanism to use for the OpenStack API implemenation') +flags.DEFINE_list('nova_api_permitted_operations', + [], + 'A comma-separated list of permitted api operations. Empty for all.') class API(wsgi.Middleware): """WSGI entry point for all OpenStack API requests.""" @@ -165,21 +168,37 @@ class APIRouter(wsgi.Router): def __init__(self): mapper = routes.Mapper() - mapper.resource("server", "servers", controller=servers.Controller(), - collection={'detail': 'GET'}, - member={'action': 'POST'}) - - mapper.resource("backup_schedule", "backup_schedules", - controller=backup_schedules.Controller(), - parent_resource=dict(member_name='server', - collection_name='servers')) - - mapper.resource("image", "images", controller=images.Controller(), - collection={'detail': 'GET'}) - mapper.resource("flavor", "flavors", controller=flavors.Controller(), - collection={'detail': 'GET'}) - mapper.resource("sharedipgroup", "sharedipgroups", - controller=sharedipgroups.Controller()) + commands = { + "server" : dict(plural='servers', + controller=servers.Controller(), + collection={'detail': 'GET'}, + member={'action': 'POST'}), + "backup_schedule" : dict(plural='backup_schedules', + controller=backup_schedules.Controller(), + parent_resource=dict(member_name='server', + collection_name='servers')), + "image" : dict(plural='images', + controller=images.Controller(), + collection={'detail': 'GET'}), + "flavor" : dict(plural='flavors', + controller=flavors.Controller(), + collection={'detail': 'GET'}), + "sharedipgroup" : dict(plural="sharedipgroups", + controller=sharedipgroups.Controller()), + } + + permitted = commands.keys() + if len(FLAGS.nova_api_permitted_operations) > 0: + permitted = FLAGS.nova_api_permitted_operations + logging.debug("Permitted operation set: %s" % (permitted,)) + for command in permitted: + options = commands.get(command, None) + if not options: + logging.warning("Unknown option in nova_api_permitted_operations: '%s' (skipping)" % (command,)) + continue + collection = options['plural'] + del options['plural'] + mapper.resource(command, collection, **options) super(APIRouter, self).__init__(mapper) -- cgit From 66a5ac31c4a5f24da9c0335cf934bbf545c0d95f Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 16 Nov 2010 02:54:13 -0400 Subject: Changed from fine-grained operation control to binary admin on/off setting. --- nova/api/openstack/__init__.py | 56 +++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 338d642bc..23ac033cf 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -47,9 +47,9 @@ flags.DEFINE_string('nova_api_auth', 'nova.api.openstack.auth.BasicApiAuthManager', 'The auth mechanism to use for the OpenStack API implemenation') -flags.DEFINE_list('nova_api_permitted_operations', - [], - 'A comma-separated list of permitted api operations. Empty for all.') +flags.DEFINE_bool('allow_admin_api', + False, + 'When True, this API service will accept admin operations.') class API(wsgi.Middleware): """WSGI entry point for all OpenStack API requests.""" @@ -168,37 +168,25 @@ class APIRouter(wsgi.Router): def __init__(self): mapper = routes.Mapper() - commands = { - "server" : dict(plural='servers', - controller=servers.Controller(), - collection={'detail': 'GET'}, - member={'action': 'POST'}), - "backup_schedule" : dict(plural='backup_schedules', - controller=backup_schedules.Controller(), - parent_resource=dict(member_name='server', - collection_name='servers')), - "image" : dict(plural='images', - controller=images.Controller(), - collection={'detail': 'GET'}), - "flavor" : dict(plural='flavors', - controller=flavors.Controller(), - collection={'detail': 'GET'}), - "sharedipgroup" : dict(plural="sharedipgroups", - controller=sharedipgroups.Controller()), - } - - permitted = commands.keys() - if len(FLAGS.nova_api_permitted_operations) > 0: - permitted = FLAGS.nova_api_permitted_operations - logging.debug("Permitted operation set: %s" % (permitted,)) - for command in permitted: - options = commands.get(command, None) - if not options: - logging.warning("Unknown option in nova_api_permitted_operations: '%s' (skipping)" % (command,)) - continue - collection = options['plural'] - del options['plural'] - mapper.resource(command, collection, **options) + mapper.resource("server", "servers", controller=servers.Controller(), + collection={'detail': 'GET'}, + member={'action': 'POST'}) + + mapper.resource("backup_schedule", "backup_schedules", + controller=backup_schedules.Controller(), + parent_resource=dict(member_name='server', + collection_name='servers')) + + mapper.resource("image", "images", controller=images.Controller(), + collection={'detail': 'GET'}) + mapper.resource("flavor", "flavors", controller=flavors.Controller(), + collection={'detail': 'GET'}) + mapper.resource("sharedipgroup", "sharedipgroups", + controller=sharedipgroups.Controller()) + + if FLAGS.allow_admin_api: + logging.debug("Including admin operations in API.") + # TODO: Place routes for admin operations here. super(APIRouter, self).__init__(mapper) -- cgit From f0b53131569cd409a95c68b435ec56a69dcdc897 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 16 Nov 2010 05:53:21 -0400 Subject: PEP8 fixes --- nova/api/openstack/__init__.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 23ac033cf..80b27c7e5 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -51,6 +51,7 @@ flags.DEFINE_bool('allow_admin_api', False, 'When True, this API service will accept admin operations.') + class API(wsgi.Middleware): """WSGI entry point for all OpenStack API requests.""" -- cgit From 4b74a1b243d87d53e660029728d12a9c067deeac Mon Sep 17 00:00:00 2001 From: Rick Clark Date: Tue, 30 Nov 2010 13:08:39 -0600 Subject: Cleaned up pep8 errors --- nova/api/ec2/cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 1cf4abcc9..a5acd1f6d 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -801,7 +801,7 @@ class CloudController(object): if kernel_id == str(FLAGS.null_kernel): kernel_id = None ramdisk_id = None - + # make sure we have access to kernel and ramdisk if kernel_id: self.image_service.show(context, kernel_id) -- cgit From 88c0e3e380d50d5794970063bbe464171089f260 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 7 Dec 2010 04:41:53 +0000 Subject: modified a few files --- nova/api/ec2/cloud.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index e50906ae1..a05dc0f1c 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -760,7 +760,6 @@ class CloudController(object): ramdisk_id=kwargs.get('ramdisk_id'), name=kwargs.get('display_name'), description=kwargs.get('display_description'), - user_data=kwargs.get('user_data', ''), key_name=kwargs.get('key_name'), security_group=kwargs.get('security_group'), generate_hostname=internal_id_to_ec2_id) -- cgit From 50ac7dc67686742c3e57cc3a408ca9e8c988b89b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 9 Dec 2010 17:30:03 +0000 Subject: filter describe volumes by supplied ids. Includes unittest. --- nova/api/ec2/cloud.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 05f8c3d0b..ebb13aedc 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -450,13 +450,15 @@ class CloudController(object): "Timestamp": now, "output": base64.b64encode(output)} - def describe_volumes(self, context, **kwargs): + def describe_volumes(self, context, volume_id=None, **kwargs): if context.user.is_admin(): volumes = db.volume_get_all(context) else: volumes = db.volume_get_all_by_project(context, context.project_id) - volumes = [self._format_volume(context, v) for v in volumes] + # NOTE(vish): volume_id is an optional list of volume ids to filter by. + volumes = [self._format_volume(context, v) for v in volumes + if volume_id is None or v['ec2_id'] in volume_id] return {'volumeSet': volumes} -- cgit From 1c323efd0777587b44b275827187b7c5cd6afdc5 Mon Sep 17 00:00:00 2001 From: Eric Day Date: Thu, 9 Dec 2010 09:57:15 -0800 Subject: Changed OpenStack API auth layer to inject a RequestContext rather than building one everywhere we need it. --- nova/api/openstack/__init__.py | 9 ++++----- nova/api/openstack/auth.py | 4 +--- nova/api/openstack/images.py | 9 ++------- nova/api/openstack/servers.py | 41 +++++++++++++++++------------------------ 4 files changed, 24 insertions(+), 39 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c9efe5222..b9ecbd9b8 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -30,6 +30,7 @@ import webob.dec import webob.exc import webob +from nova import context from nova import flags from nova import utils from nova import wsgi @@ -88,9 +89,7 @@ class AuthMiddleware(wsgi.Middleware): if not user: return faults.Fault(webob.exc.HTTPUnauthorized()) - if 'nova.context' not in req.environ: - req.environ['nova.context'] = {} - req.environ['nova.context']['user'] = user + req.environ['nova.context'] = context.RequestContext(user, user) return self.application @@ -125,12 +124,12 @@ class RateLimitingMiddleware(wsgi.Middleware): If the request should be rate limited, return a 413 status with a Retry-After header giving the time when the request would succeed. """ - user_id = req.environ['nova.context']['user']['id'] action_name = self.get_action_name(req) if not action_name: # Not rate limited return self.application - delay = self.get_delay(action_name, user_id) + delay = self.get_delay(action_name, + req.environ['nova.context'].user_id) if delay: # TODO(gundlach): Get the retry-after format correct. exc = webob.exc.HTTPRequestEntityTooLarge( diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 205035915..fcda97ab1 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -74,9 +74,7 @@ class BasicApiAuthManager(object): if delta.days >= 2: self.db.auth_destroy_token(self.context, token) else: - #TODO(gundlach): Why not just return dict(id=token.user_id)? - user = self.auth.get_user(token.user_id) - return {'id': user.id} + return self.auth.get_user(token.user_id) return None def _authorize_user(self, username, key, req): diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index cdbdc9bdd..4a0a8e6f1 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -17,7 +17,6 @@ from webob import exc -from nova import context from nova import flags from nova import utils from nova import wsgi @@ -47,10 +46,8 @@ class Controller(wsgi.Controller): def detail(self, req): """Return all public images in detail.""" - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) try: - images = self._service.detail(ctxt) + images = self._service.detail(req.environ['nova.context']) images = nova.api.openstack.limited(images, req) except NotImplementedError: # Emulate detail() using repeated calls to show() @@ -61,9 +58,7 @@ class Controller(wsgi.Controller): def show(self, req, id): """Return data about the given image id.""" - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) - return dict(image=self._service.show(ctxt, id)) + return dict(image=self._service.show(req.environ['nova.context'], id)) def delete(self, req, id): # Only public images are supported for now. diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 6f2f6fed9..7704f48f1 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -17,7 +17,6 @@ from webob import exc -from nova import context from nova import exception from nova import wsgi from nova.api.openstack import faults @@ -90,29 +89,26 @@ class Controller(wsgi.Controller): entity_maker - either _entity_detail or _entity_inst """ - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) - instance_list = self.compute_api.get_instances(ctxt) + instance_list = self.compute_api.get_instances( + req.environ['nova.context']) limited_list = nova.api.openstack.limited(instance_list, req) res = [entity_maker(inst)['server'] for inst in limited_list] return _entity_list(res) def show(self, req, id): """ Returns server details by server id """ - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) - inst = self.compute_api.get_instance(ctxt, int(id)) - if inst: - if inst.user_id == user_id: - return _entity_detail(inst) - raise faults.Fault(exc.HTTPNotFound()) + try: + instance = self.compute_api.get_instance( + req.environ['nova.context'], int(id)) + return _entity_detail(instance) + except exception.NotFound: + return faults.Fault(exc.HTTPNotFound()) def delete(self, req, id): """ Destroys a server """ - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) try: - self.compute_api.delete_instance(ctxt, int(id)) + self.compute_api.delete_instance(req.environ['nova.context'], + int(id)) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) return exc.HTTPAccepted() @@ -123,10 +119,10 @@ class Controller(wsgi.Controller): if not env: return faults.Fault(exc.HTTPUnprocessableEntity()) - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) - key_pair = auth_manager.AuthManager.get_key_pairs(ctxt)[0] - instances = self.compute_api.create_instances(ctxt, + key_pair = auth_manager.AuthManager.get_key_pairs( + req.environ['nova.context'])[0] + instances = self.compute_api.create_instances( + req.environ['nova.context'], instance_types.get_by_flavor_id(env['server']['flavorId']), env['server']['imageId'], display_name=env['server']['name'], @@ -137,8 +133,6 @@ class Controller(wsgi.Controller): def update(self, req, id): """ Updates the server name or password """ - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) inst_dict = self._deserialize(req.body, req) if not inst_dict: return faults.Fault(exc.HTTPUnprocessableEntity()) @@ -150,7 +144,8 @@ class Controller(wsgi.Controller): update_dict['display_name'] = inst_dict['server']['name'] try: - self.compute_api.update_instance(ctxt, instance['id'], + self.compute_api.update_instance(req.environ['nova.context'], + instance['id'], **update_dict) except exception.NotFound: return faults.Fault(exc.HTTPNotFound()) @@ -159,8 +154,6 @@ class Controller(wsgi.Controller): def action(self, req, id): """ Multi-purpose method used to reboot, rebuild, and resize a server """ - user_id = req.environ['nova.context']['user']['id'] - ctxt = context.RequestContext(user_id, user_id) input_dict = self._deserialize(req.body, req) try: reboot_type = input_dict['reboot']['type'] @@ -169,7 +162,7 @@ class Controller(wsgi.Controller): try: # TODO(gundlach): pass reboot_type, support soft reboot in # virt driver - self.compute_api.reboot(ctxt, id) + self.compute_api.reboot(req.environ['nova.context'], id) except: return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() -- cgit From 90c89f5f7b24bb6c95d405d42f7f15292b5452a9 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 9 Dec 2010 17:03:49 -0400 Subject: pause and unpause code/tests in place. To the point it stuffs request in the queue. --- nova/api/openstack/__init__.py | 13 ++++++++----- nova/api/openstack/servers.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) (limited to 'nova/api') diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c9efe5222..24042b42b 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -171,9 +171,16 @@ class APIRouter(wsgi.Router): def __init__(self): mapper = routes.Mapper() + + server_members = {'action': 'POST'} + if FLAGS.allow_admin_api: + logging.debug("Including admin operations in API.") + server_members['pause'] = 'POST' + server_members['unpause'] = 'POST' + mapper.resource("server", "servers", controller=servers.Controller(), collection={'detail': 'GET'}, - member={'action': 'POST'}) + member=server_members) mapper.resource("backup_schedule", "backup_schedules", controller=backup_schedules.Controller(), @@ -187,10 +194,6 @@ class APIRouter(wsgi.Router): mapper.resource("sharedipgroup", "sharedipgroups", controller=sharedipgroups.Controller()) - if FLAGS.allow_admin_api: - logging.debug("Including admin operations in API.") - # TODO: Place routes for admin operations here. - super(APIRouter, self).__init__(mapper) diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 6f2f6fed9..ade0d7eb9 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -15,6 +15,9 @@ # License for the specific language governing permissions and limitations # under the License. +import logging +import traceback + from webob import exc from nova import context @@ -28,6 +31,10 @@ from nova.compute import power_state import nova.api.openstack +LOG = logging.getLogger('server') +LOG.setLevel(logging.DEBUG) + + def _entity_list(entities): """ Coerces a list of servers into proper dictionary format """ return dict(servers=entities) @@ -173,3 +180,29 @@ class Controller(wsgi.Controller): except: return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() + + def pause(self, req, id): + """ Permit Admins to Pause the server. """ + user_id = req.environ['nova.context']['user']['id'] + ctxt = context.RequestContext(user_id, user_id) + try: + self.compute_api.pause(ctxt, id) + except: + readable = traceback.format_exc() + logging.error("Compute.api::pause %s", readable) + return faults.Fault(exc.HTTPUnprocessableEntity()) + return exc.HTTPAccepted() + + def unpause(self, req, id): + """ Permit Admins to Unpause the server. """ + user_id = req.environ['nova.context']['user']['id'] + ctxt = context.RequestContext(user_id, user_id) + try: + self.compute_api.unpause(ctxt, id) + except: + readable = traceback.format_exc() + logging.error("Compute.api::unpause %s", readable) + return faults.Fault(exc.HTTPUnprocessableEntity()) + return exc.HTTPAccepted() + + -- cgit From 12802a76c775a35e9d5a651bf896cfa25bec547f Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Sat, 11 Dec 2010 15:23:40 -0500 Subject: First round of i18n-ifying strings in Nova --- nova/api/cloudpipe/__init__.py | 4 +-- nova/api/ec2/__init__.py | 6 ++-- nova/api/ec2/apirequest.py | 4 +-- nova/api/ec2/cloud.py | 51 ++++++++++++++++++---------------- nova/api/ec2/metadatarequesthandler.py | 2 +- nova/api/openstack/__init__.py | 6 ++-- 6 files changed, 38 insertions(+), 35 deletions(-) (limited to 'nova/api') diff --git a/nova/api/cloudpipe/__init__.py b/nova/api/cloudpipe/__init__.py index 6d40990a8..00ad38913 100644 --- a/nova/api/cloudpipe/__init__.py +++ b/nova/api/cloudpipe/__init__.py @@ -45,7 +45,7 @@ class API(wsgi.Application): def __call__(self, req): if req.method == 'POST': return self.sign_csr(req) - _log.debug("Cloudpipe path is %s" % req.path_info) + _log.debug(_("Cloudpipe path is %s") % req.path_info) if req.path_info.endswith("/getca/"): return self.send_root_ca(req) return webob.exc.HTTPNotFound() @@ -56,7 +56,7 @@ class API(wsgi.Application): return instance['project_id'] def send_root_ca(self, req): - _log.debug("Getting root ca") + _log.debug(_("Getting root ca")) project_id = self.get_project_id_from_ip(req.remote_addr) res = webob.Response() res.headers["Content-Type"] = "text/plain" diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index a6ee16c33..dd87d1f71 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -77,7 +77,7 @@ class Authenticate(wsgi.Middleware): req.host, req.path) except exception.Error, ex: - logging.debug("Authentication Failure: %s" % ex) + logging.debug(_("Authentication Failure: %s") % ex) raise webob.exc.HTTPForbidden() # Authenticated! @@ -120,9 +120,9 @@ class Router(wsgi.Middleware): except: raise webob.exc.HTTPBadRequest() - _log.debug('action: %s' % action) + _log.debug(_('action: %s') % action) for key, value in args.items(): - _log.debug('arg: %s\t\tval: %s' % (key, value)) + _log.debug(_('arg: %s\t\tval: %s') % (key, value)) # Success! req.environ['ec2.controller'] = controller diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py index 5758781b6..a90fbeb0c 100644 --- a/nova/api/ec2/apirequest.py +++ b/nova/api/ec2/apirequest.py @@ -92,8 +92,8 @@ class APIRequest(object): method = getattr(self.controller, _camelcase_to_underscore(self.action)) except AttributeError: - _error = ('Unsupported API request: controller = %s,' - 'action = %s') % (self.controller, self.action) + _error = _('Unsupported API request: controller = %s,' + 'action = %s') % (self.controller, self.action) _log.warning(_error) # TODO: Raise custom exception, trap in apiserver, # and reraise as 400 error. diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 05f8c3d0b..896e6c223 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -114,7 +114,7 @@ class CloudController(object): start = os.getcwd() os.chdir(FLAGS.ca_path) # TODO(vish): Do this with M2Crypto instead - utils.runthis("Generating root CA: %s", "sh genrootca.sh") + utils.runthis(_("Generating root CA: %s", "sh genrootca.sh")) os.chdir(start) def _get_mpi_data(self, context, project_id): @@ -318,11 +318,11 @@ class CloudController(object): ip_protocol = str(ip_protocol) if ip_protocol.upper() not in ['TCP', 'UDP', 'ICMP']: - raise InvalidInputException('%s is not a valid ipProtocol' % + raise InvalidInputException(_('%s is not a valid ipProtocol') % (ip_protocol,)) if ((min(from_port, to_port) < -1) or (max(from_port, to_port) > 65535)): - raise InvalidInputException('Invalid port range') + raise InvalidInputException(_('Invalid port range')) values['protocol'] = ip_protocol values['from_port'] = from_port @@ -360,7 +360,7 @@ class CloudController(object): criteria = self._revoke_rule_args_to_dict(context, **kwargs) if criteria == None: - raise exception.ApiError("No rule for the specified parameters.") + raise exception.ApiError(_("No rule for the specified parameters.")) for rule in security_group.rules: match = True @@ -371,7 +371,7 @@ class CloudController(object): db.security_group_rule_destroy(context, rule['id']) self._trigger_refresh_security_group(context, security_group) return True - raise exception.ApiError("No rule for the specified parameters.") + raise exception.ApiError(_("No rule for the specified parameters.")) # TODO(soren): This has only been tested with Boto as the client. # Unfortunately, it seems Boto is using an old API @@ -387,8 +387,8 @@ class CloudController(object): values['parent_group_id'] = security_group.id if self._security_group_rule_exists(security_group, values): - raise exception.ApiError('This rule already exists in group %s' % - group_name) + raise exception.ApiError(_('This rule already exists in group %s') + % group_name) security_group_rule = db.security_group_rule_create(context, values) @@ -416,7 +416,7 @@ class CloudController(object): def create_security_group(self, context, group_name, group_description): self.compute_api.ensure_default_security_group(context) if db.security_group_exists(context, context.project_id, group_name): - raise exception.ApiError('group %s already exists' % group_name) + raise exception.ApiError(_('group %s already exists') % group_name) group = {'user_id': context.user.id, 'project_id': context.project_id, @@ -527,13 +527,13 @@ class CloudController(object): def attach_volume(self, context, volume_id, instance_id, device, **kwargs): volume_ref = db.volume_get_by_ec2_id(context, volume_id) if not re.match("^/dev/[a-z]d[a-z]+$", device): - raise exception.ApiError("Invalid device specified: %s. " - "Example device: /dev/vdb" % device) + raise exception.ApiError(_("Invalid device specified: %s. " + "Example device: /dev/vdb") % device) # TODO(vish): abstract status checking? if volume_ref['status'] != "available": - raise exception.ApiError("Volume status must be available") + raise exception.ApiError(_("Volume status must be available")) if volume_ref['attach_status'] == "attached": - raise exception.ApiError("Volume is already attached") + raise exception.ApiError(_("Volume is already attached")) internal_id = ec2_id_to_internal_id(instance_id) instance_ref = self.compute_api.get_instance(context, internal_id) host = instance_ref['host'] @@ -555,10 +555,10 @@ class CloudController(object): instance_ref = db.volume_get_instance(context.elevated(), volume_ref['id']) if not instance_ref: - raise exception.ApiError("Volume isn't attached to anything!") + raise exception.ApiError(_("Volume isn't attached to anything!")) # TODO(vish): abstract status checking? if volume_ref['status'] == "available": - raise exception.ApiError("Volume is already detached") + raise exception.ApiError(_("Volume is already detached")) try: host = instance_ref['host'] rpc.cast(context, @@ -687,10 +687,11 @@ class CloudController(object): def allocate_address(self, context, **kwargs): # check quota if quota.allowed_floating_ips(context, 1) < 1: - logging.warn("Quota exceeeded for %s, tried to allocate address", + logging.warn(_("Quota exceeeded for %s, tried to allocate " + "address"), context.project_id) - raise quota.QuotaError("Address quota exceeded. You cannot " - "allocate any more addresses") + raise quota.QuotaError(_("Address quota exceeded. You cannot " + "allocate any more addresses")) network_topic = self._get_network_topic(context) public_ip = rpc.call(context, network_topic, @@ -803,7 +804,7 @@ class CloudController(object): # TODO: return error if not authorized volume_ref = db.volume_get_by_ec2_id(context, volume_id) if volume_ref['status'] != "available": - raise exception.ApiError("Volume status must be available") + raise exception.ApiError(_("Volume status must be available")) now = datetime.datetime.utcnow() db.volume_update(context, volume_ref['id'], {'status': 'deleting', 'terminated_at': now}) @@ -834,11 +835,12 @@ class CloudController(object): def describe_image_attribute(self, context, image_id, attribute, **kwargs): if attribute != 'launchPermission': - raise exception.ApiError('attribute not supported: %s' % attribute) + raise exception.ApiError(_('attribute not supported: %s') + % attribute) try: image = self.image_service.show(context, image_id) except IndexError: - raise exception.ApiError('invalid id: %s' % image_id) + raise exception.ApiError(_('invalid id: %s') % image_id) result = {'image_id': image_id, 'launchPermission': []} if image['isPublic']: result['launchPermission'].append({'group': 'all'}) @@ -848,13 +850,14 @@ class CloudController(object): operation_type, **kwargs): # TODO(devcamcar): Support users and groups other than 'all'. if attribute != 'launchPermission': - raise exception.ApiError('attribute not supported: %s' % attribute) + raise exception.ApiError(_('attribute not supported: %s') + % attribute) if not 'user_group' in kwargs: - raise exception.ApiError('user or group not specified') + raise exception.ApiError(_('user or group not specified')) if len(kwargs['user_group']) != 1 and kwargs['user_group'][0] != 'all': - raise exception.ApiError('only group "all" is supported') + raise exception.ApiError(_('only group "all" is supported')) if not operation_type in ['add', 'remove']: - raise exception.ApiError('operation_type must be add or remove') + raise exception.ApiError(_('operation_type must be add or remove')) return self.image_service.modify(context, image_id, operation_type) def update_image(self, context, image_id, **kwargs): diff --git a/nova/api/ec2/metadatarequesthandler.py b/nova/api/ec2/metadatarequesthandler.py index 2f4f414cc..0e9e686ff 100644 --- a/nova/api/ec2/metadatarequesthandler.py +++ b/nova/api/ec2/metadatarequesthandler.py @@ -65,7 +65,7 @@ class MetadataRequestHandler(object): cc = cloud.CloudController() meta_data = cc.get_metadata(req.remote_addr) if meta_data is None: - logging.error('Failed to get metadata for ip: %s' % + logging.error(_('Failed to get metadata for ip: %s') % req.remote_addr) raise webob.exc.HTTPNotFound() data = self.lookup(req.path_info, meta_data) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index c9efe5222..45a2549c0 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -65,7 +65,7 @@ class API(wsgi.Middleware): try: return req.get_response(self.application) except Exception as ex: - logging.warn("Caught error: %s" % str(ex)) + logging.warn(_("Caught error: %s") % str(ex)) logging.debug(traceback.format_exc()) exc = webob.exc.HTTPInternalServerError(explanation=str(ex)) return faults.Fault(exc) @@ -134,7 +134,7 @@ class RateLimitingMiddleware(wsgi.Middleware): if delay: # TODO(gundlach): Get the retry-after format correct. exc = webob.exc.HTTPRequestEntityTooLarge( - explanation='Too many requests.', + explanation=_('Too many requests.'), headers={'Retry-After': time.time() + delay}) raise faults.Fault(exc) return self.application @@ -188,7 +188,7 @@ class APIRouter(wsgi.Router): controller=sharedipgroups.Controller()) if FLAGS.allow_admin_api: - logging.debug("Including admin operations in API.") + logging.debug(_("Including admin operations in API.")) # TODO: Place routes for admin operations here. super(APIRouter, self).__init__(mapper) -- cgit From fa7d288e6af3d997d6275d9e6778e932be9f1c3f Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 14 Dec 2010 17:56:42 -0400 Subject: pep8 --- nova/api/ec2/admin.py | 1 + nova/api/openstack/backup_schedules.py | 1 + nova/api/openstack/servers.py | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/admin.py b/nova/api/ec2/admin.py index 1c6ab688d..fac01369e 100644 --- a/nova/api/ec2/admin.py +++ b/nova/api/ec2/admin.py @@ -168,6 +168,7 @@ class AdminController(object): # FIXME(vish): these host commands don't work yet, perhaps some of the # required data can be retrieved from service objects? + def describe_hosts(self, _context, **_kwargs): """Returns status info for all nodes. Includes: * Disk Space diff --git a/nova/api/openstack/backup_schedules.py b/nova/api/openstack/backup_schedules.py index 3ed691d7b..fc70b5c6c 100644 --- a/nova/api/openstack/backup_schedules.py +++ b/nova/api/openstack/backup_schedules.py @@ -24,6 +24,7 @@ import nova.image.service class Controller(wsgi.Controller): + def __init__(self): pass diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index dcd959ae7..5c3322f7c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -195,5 +195,3 @@ class Controller(wsgi.Controller): logging.error("Compute.api::unpause %s", readable) return faults.Fault(exc.HTTPUnprocessableEntity()) return exc.HTTPAccepted() - - -- cgit From 99347717ed2c7e92b3dc3bd33c12a3a05e8e349d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 15 Dec 2010 00:25:04 +0000 Subject: Lockout middleware for ec2 api --- nova/api/ec2/__init__.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index a6ee16c33..19eb666cd 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -22,12 +22,13 @@ Starting point for routing EC2 requests. import logging import routes +import time import webob import webob.dec import webob.exc -from nova import exception from nova import context +from nova import exception from nova import flags from nova import wsgi from nova.api.ec2 import apirequest @@ -37,6 +38,16 @@ from nova.auth import manager FLAGS = flags.FLAGS +flags.DEFINE_boolean('use_lockout', False, + 'Whether or not to use lockout middleware.') +flags.DEFINE_integer('lockout_attempts', 5, + 'Number of failed auths before lockout.') +flags.DEFINE_integer('lockout_minutes', 15, + 'Number of minutes to lockout if triggered.') +flags.DEFINE_list('lockout_memcached_servers', None, + 'Memcached servers or None for in process cache.') + + _log = logging.getLogger("api") _log.setLevel(logging.DEBUG) @@ -47,6 +58,63 @@ class API(wsgi.Middleware): def __init__(self): self.application = Authenticate(Router(Authorizer(Executor()))) + if FLAGS.use_lockout: + self.application = Lockout(self.application) + + +class Lockout(wsgi.Middleware): + """Only allow x failed auths in a y minute period. + + x = lockout_attempts flag + y = lockout_timeout flag + + Uses memcached if lockout_memcached_servers flag is set, otherwise it + uses a very simple in-proccess cache. Due to the simplicity of + the implementation, the timeout window is reset with every failed + request, so it actually blocks if there are x failed logins with no + more than y minutes between any two failures. + + There is a possible race condition where simultaneous requests could + sneak in before the lockout hits, but this is extremely rare and would + only result in a couple of extra failed attempts.""" + + def __init__(self, application, time_fn=time.time): + """The middleware can use a custom time function for testing.""" + self.time_fn = time_fn + if FLAGS.lockout_memcached_servers: + import memcache + else: + from nova import fakememcache as memcache + self.mc = memcache.Client(FLAGS.lockout_memcached_servers, debug=0) + super(Lockout, self).__init__(application) + + @webob.dec.wsgify + def __call__(self, req): + access_key = req.params['AWSAccessKeyId'] + failures_key = "%s-failures" % access_key + last_key = "%s-last" % access_key + now = self.time_fn() + timeout = now - FLAGS.lockout_minutes * 60 + # NOTE(vish): To use incr, failures has to be a string. + failures = int(self.mc.get(failures_key) or 0) + last = self.mc.get(last_key) + if (failures and failures >= FLAGS.lockout_attempts + and last > timeout): + self.mc.set(last_key, now) + detail = "Too many failed authentications." + raise webob.exc.HTTPForbidden(detail=detail) + res = req.get_response(self.application) + if res.status_int == 403: + if last > timeout: + failures = int(self.mc.incr(failures_key)) + if failures >= FLAGS.lockout_attempts: + _log.warn('Access key %s has had %d failed authentications' + ' and will be locked out for %d minutes.' % + (access_key, failures, FLAGS.lockout_minutes)) + else: + self.mc.set(failures_key, '1') + self.mc.set(last_key, now) + return res class Authenticate(wsgi.Middleware): -- cgit From b0279030127b7fe8df21db12a8727ea623ca46e2 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Dec 2010 09:38:38 -0800 Subject: clean up code to use timeout instead of two keys --- nova/api/ec2/__init__.py | 58 ++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 19eb666cd..381b0e871 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -22,7 +22,6 @@ Starting point for routing EC2 requests. import logging import routes -import time import webob import webob.dec import webob.exc @@ -44,6 +43,8 @@ flags.DEFINE_integer('lockout_attempts', 5, 'Number of failed auths before lockout.') flags.DEFINE_integer('lockout_minutes', 15, 'Number of minutes to lockout if triggered.') +flags.DEFINE_integer('lockout_window', 15, + 'Number of minutes for lockout window.') flags.DEFINE_list('lockout_memcached_servers', None, 'Memcached servers or None for in process cache.') @@ -53,7 +54,6 @@ _log.setLevel(logging.DEBUG) class API(wsgi.Middleware): - """Routing for all EC2 API requests.""" def __init__(self): @@ -63,57 +63,53 @@ class API(wsgi.Middleware): class Lockout(wsgi.Middleware): - """Only allow x failed auths in a y minute period. + """Lockout for x minutes on y failed auths in a z minute period. - x = lockout_attempts flag - y = lockout_timeout flag + x = lockout_timeout flag + y = lockout_window flag + z = lockout_attempts flag Uses memcached if lockout_memcached_servers flag is set, otherwise it uses a very simple in-proccess cache. Due to the simplicity of - the implementation, the timeout window is reset with every failed - request, so it actually blocks if there are x failed logins with no - more than y minutes between any two failures. + the implementation, the timeout window is started with the first + failed request, so it will block if there are x failed logins within + that period. There is a possible race condition where simultaneous requests could sneak in before the lockout hits, but this is extremely rare and would only result in a couple of extra failed attempts.""" - def __init__(self, application, time_fn=time.time): - """The middleware can use a custom time function for testing.""" - self.time_fn = time_fn + def __init__(self, application, time_fn=None): + """middleware can pass a custom time function to fake for testing.""" if FLAGS.lockout_memcached_servers: import memcache + self.mc = memcache.Client(FLAGS.lockout_memcached_servers, + debug=0) else: - from nova import fakememcache as memcache - self.mc = memcache.Client(FLAGS.lockout_memcached_servers, debug=0) + from nova import fakememcache + self.mc = fakememcache.Client(time_fn=time_fn) super(Lockout, self).__init__(application) @webob.dec.wsgify def __call__(self, req): access_key = req.params['AWSAccessKeyId'] - failures_key = "%s-failures" % access_key - last_key = "%s-last" % access_key - now = self.time_fn() - timeout = now - FLAGS.lockout_minutes * 60 - # NOTE(vish): To use incr, failures has to be a string. + failures_key = "authfailures-%s" % access_key failures = int(self.mc.get(failures_key) or 0) - last = self.mc.get(last_key) - if (failures and failures >= FLAGS.lockout_attempts - and last > timeout): - self.mc.set(last_key, now) + if failures >= FLAGS.lockout_attempts: detail = "Too many failed authentications." raise webob.exc.HTTPForbidden(detail=detail) res = req.get_response(self.application) if res.status_int == 403: - if last > timeout: - failures = int(self.mc.incr(failures_key)) - if failures >= FLAGS.lockout_attempts: - _log.warn('Access key %s has had %d failed authentications' - ' and will be locked out for %d minutes.' % - (access_key, failures, FLAGS.lockout_minutes)) - else: - self.mc.set(failures_key, '1') - self.mc.set(last_key, now) + failures = self.mc.incr(failures_key) + if failures is None: + # NOTE(vish): To use incr, failures has to be a string. + self.mc.set(failures_key, '1', time=FLAGS.lockout_window * 60) + elif failures >= FLAGS.lockout_attempts: + _log.warn('Access key %s has had %d failed authentications' + ' and will be locked out for %d minutes.' % + (access_key, failures, FLAGS.lockout_minutes)) + self.mc.set(failures_key, str(failures), + time=FLAGS.lockout_minutes * 60) return res -- cgit From dd4ee43cc2042299ed7a56b4690999fa1df120a1 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Dec 2010 11:23:33 -0800 Subject: clean up tests and add overriden time method to utils --- nova/api/ec2/__init__.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 381b0e871..5ae15f2ae 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -79,15 +79,14 @@ class Lockout(wsgi.Middleware): sneak in before the lockout hits, but this is extremely rare and would only result in a couple of extra failed attempts.""" - def __init__(self, application, time_fn=None): - """middleware can pass a custom time function to fake for testing.""" + def __init__(self, application): + """middleware can use fake for testing.""" if FLAGS.lockout_memcached_servers: import memcache - self.mc = memcache.Client(FLAGS.lockout_memcached_servers, - debug=0) else: - from nova import fakememcache - self.mc = fakememcache.Client(time_fn=time_fn) + from nova import fakememcache as memcache + self.mc = memcache.Client(FLAGS.lockout_memcached_servers, + debug=0) super(Lockout, self).__init__(application) @webob.dec.wsgify -- cgit From e1da5d66b2e33a043e7e9ee357d9769276d6e302 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Dec 2010 13:14:28 -0800 Subject: memcached requires strings not unicode --- nova/api/ec2/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 5ae15f2ae..def0ee207 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -91,7 +91,7 @@ class Lockout(wsgi.Middleware): @webob.dec.wsgify def __call__(self, req): - access_key = req.params['AWSAccessKeyId'] + access_key = str(req.params['AWSAccessKeyId']) failures_key = "authfailures-%s" % access_key failures = int(self.mc.get(failures_key) or 0) if failures >= FLAGS.lockout_attempts: -- cgit From d283922defdda6ede5fa2e09656cd8d411a90096 Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Thu, 16 Dec 2010 14:47:42 -0500 Subject: PEP8 cleanups --- nova/api/ec2/cloud.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 4b8b85b4c..d638582a7 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -360,7 +360,8 @@ class CloudController(object): criteria = self._revoke_rule_args_to_dict(context, **kwargs) if criteria == None: - raise exception.ApiError(_("No rule for the specified parameters.")) + raise exception.ApiError(_("No rule for the specified " + "parameters.")) for rule in security_group.rules: match = True -- cgit From 86f71493fa5a02762bc7c56308c85b9182913efb Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 17 Dec 2010 00:43:18 +0000 Subject: move some flags around --- nova/api/__init__.py | 2 +- nova/api/ec2/cloud.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'nova/api') diff --git a/nova/api/__init__.py b/nova/api/__init__.py index 95fc6b145..803470570 100644 --- a/nova/api/__init__.py +++ b/nova/api/__init__.py @@ -29,7 +29,6 @@ import routes import webob.dec from nova import flags -from nova import utils from nova import wsgi from nova.api import ec2 from nova.api import openstack @@ -40,6 +39,7 @@ flags.DEFINE_string('osapi_subdomain', 'api', 'subdomain running the OpenStack API') flags.DEFINE_string('ec2api_subdomain', 'ec2', 'subdomain running the EC2 API') + FLAGS = flags.FLAGS diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index ebb13aedc..684e29ee1 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -196,15 +196,19 @@ class CloudController(object): if FLAGS.region_list: regions = [] for region in FLAGS.region_list: - name, _sep, url = region.partition('=') + name, _sep, host = region.partition('=') + endpoint = '%s://%s:%s%s' % (FLAGS.ec2_prefix, + host, + FLAGS.cc_port, + FLAGS.ec2_suffix) regions.append({'regionName': name, - 'regionEndpoint': url}) + 'regionEndpoint': endpoint}) else: regions = [{'regionName': 'nova', - 'regionEndpoint': FLAGS.ec2_url}] - if region_name: - regions = [r for r in regions if r['regionName'] in region_name] - return {'regionInfo': regions} + 'regionEndpoint': '%s://%s:%s%s' % (FLAGS.ec2_prefix, + FLAGS.cc_host, + FLAGS.cc_port, + FLAGS.ec2_suffix)}] def describe_snapshots(self, context, -- cgit From 83cf1f7140c20ea2188272b57e4e2c1a95f8ff9e Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 21 Dec 2010 03:26:50 +0000 Subject: remove extra print statements --- nova/api/ec2/cloud.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 91b2f0064..ad6debb11 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -723,10 +723,8 @@ class CloudController(object): floating_ip_ref = db.floating_ip_get_by_address(context, public_ip) # NOTE(vish): Perhaps we should just pass this on to compute and # let compute communicate with network. - print "in cloud get" network_topic = self.compute_api.get_network_topic(context, internal_id) - print "got the network topic", network_topic rpc.cast(context, network_topic, {"method": "associate_floating_ip", -- cgit From db938f975da64540ebb942e9dfd640db4dd7f939 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 21 Dec 2010 21:34:51 +0000 Subject: removed unused import and fix docstring --- nova/api/ec2/cloud.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index ad6debb11..c845e6a2e 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -27,7 +27,6 @@ import datetime import logging import re import os -import time from nova import context import IPy @@ -706,7 +705,7 @@ class CloudController(object): def release_address(self, context, public_ip, **kwargs): floating_ip_ref = db.floating_ip_get_by_address(context, public_ip) # NOTE(vish): We don't know which network host should get the ip - # when we allocate, so just send it to any one. This + # when we deallocate, so just send it to any one. This # will probably need to move into a network supervisor # at some point. rpc.cast(context, -- cgit From 7af11742b6bab492eb87c212d05bf77c0c13aea9 Mon Sep 17 00:00:00 2001 From: Thierry Carrez Date: Wed, 22 Dec 2010 12:24:53 +0100 Subject: Populate user_data field from run-instances call parameter, default to empty string to avoid metadata base64 decoding failure, LP: #691598 --- nova/api/ec2/cloud.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 8375c4399..13c2b4574 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -756,6 +756,7 @@ class CloudController(object): display_name=kwargs.get('display_name'), description=kwargs.get('display_description'), key_name=kwargs.get('key_name'), + user_data=kwargs.get('user_data'), security_group=kwargs.get('security_group'), generate_hostname=internal_id_to_ec2_id) return self._format_run_instances(context, -- cgit From 46c4d44affb289209dd6024cbb289b265d9c89c7 Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Wed, 22 Dec 2010 10:40:24 -0500 Subject: Problem was with a missplaced parentheses. ugh. --- nova/api/ec2/cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/api') diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index de5079286..503a5fd6c 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -114,7 +114,7 @@ class CloudController(object): start = os.getcwd() os.chdir(FLAGS.ca_path) # TODO(vish): Do this with M2Crypto instead - utils.runthis(_("Generating root CA: %s", "sh genrootca.sh")) + utils.runthis(_("Generating root CA: %s"), "sh genrootca.sh") os.chdir(start) def _get_mpi_data(self, context, project_id): -- cgit