summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorTodd Willey <todd@ansolabs.com>2011-01-17 18:49:11 +0000
committerTarmac <>2011-01-17 18:49:11 +0000
commit3b94033b06ccc2d503d899e9fd7a3c8c6e2a7cba (patch)
tree170ef113ef53cae8d24012ac9db92d03d067fdd9 /nova/api
parent93deb2e9a375a18300eff258f2353e597932c47b (diff)
parent6906137b99181925f091ca547d019499c3bc1701 (diff)
downloadnova-3b94033b06ccc2d503d899e9fd7a3c8c6e2a7cba.tar.gz
nova-3b94033b06ccc2d503d899e9fd7a3c8c6e2a7cba.tar.xz
nova-3b94033b06ccc2d503d899e9fd7a3c8c6e2a7cba.zip
Further decouple api routing decisions and move into paste.deploy configuration. This makes paste back the nova-api binary.
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/__init__.py93
-rw-r--r--nova/api/ec2/__init__.py80
-rw-r--r--nova/api/ec2/apirequest.py7
-rw-r--r--nova/api/ec2/cloud.py6
-rw-r--r--nova/api/openstack/__init__.py28
5 files changed, 49 insertions, 165 deletions
diff --git a/nova/api/__init__.py b/nova/api/__init__.py
index 803470570..0fedbbfad 100644
--- a/nova/api/__init__.py
+++ b/nova/api/__init__.py
@@ -15,96 +15,5 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-"""
-Root WSGI middleware for all API controllers.
-**Related Flags**
-
-:osapi_subdomain: subdomain running the OpenStack API (default: api)
-:ec2api_subdomain: subdomain running the EC2 API (default: ec2)
-
-"""
-
-import routes
-import webob.dec
-
-from nova import flags
-from nova import wsgi
-from nova.api import ec2
-from nova.api import openstack
-from nova.api.ec2 import metadatarequesthandler
-
-
-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
-
-
-class API(wsgi.Router):
- """Routes top-level requests to the appropriate controller."""
-
- def __init__(self, default_api):
- osapi_subdomain = {'sub_domain': [FLAGS.osapi_subdomain]}
- ec2api_subdomain = {'sub_domain': [FLAGS.ec2api_subdomain]}
- if default_api == 'os':
- osapi_subdomain = {}
- elif default_api == 'ec2':
- ec2api_subdomain = {}
- mapper = routes.Mapper()
- mapper.sub_domains = True
-
- mapper.connect("/", controller=self.osapi_versions,
- conditions=osapi_subdomain)
- mapper.connect("/v1.0/{path_info:.*}", controller=openstack.API(),
- conditions=osapi_subdomain)
-
- mapper.connect("/", controller=self.ec2api_versions,
- conditions=ec2api_subdomain)
- mapper.connect("/services/{path_info:.*}", controller=ec2.API(),
- conditions=ec2api_subdomain)
- mrh = metadatarequesthandler.MetadataRequestHandler()
- for s in ['/latest',
- '/2009-04-04',
- '/2008-09-01',
- '/2008-02-01',
- '/2007-12-15',
- '/2007-10-10',
- '/2007-08-29',
- '/2007-03-01',
- '/2007-01-19',
- '/1.0']:
- mapper.connect('%s/{path_info:.*}' % s, controller=mrh,
- conditions=ec2api_subdomain)
-
- super(API, self).__init__(mapper)
-
- @webob.dec.wsgify
- def osapi_versions(self, req):
- """Respond to a request for all OpenStack API versions."""
- response = {
- "versions": [
- dict(status="CURRENT", id="v1.0")]}
- metadata = {
- "application/xml": {
- "attributes": dict(version=["status", "id"])}}
- return wsgi.Serializer(req.environ, metadata).to_content_type(response)
-
- @webob.dec.wsgify
- def ec2api_versions(self, req):
- """Respond to a request for all EC2 versions."""
- # available api versions
- versions = [
- '1.0',
- '2007-01-19',
- '2007-03-01',
- '2007-08-29',
- '2007-10-10',
- '2007-12-15',
- '2008-02-01',
- '2008-09-01',
- '2009-04-04',
- ]
- return ''.join('%s\n' % v for v in versions)
+"""No-op __init__ for directory full of api goodies."""
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index 2fa1f636c..d0adf5e21 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -30,10 +30,9 @@ from nova import context
from nova import exception
from nova import flags
from nova import log as logging
+from nova import utils
from nova import wsgi
from nova.api.ec2 import apirequest
-from nova.api.ec2 import admin
-from nova.api.ec2 import cloud
from nova.auth import manager
@@ -42,8 +41,6 @@ LOG = logging.getLogger("nova.api")
flags.DEFINE_boolean('use_forwarded_for', False,
'Treat X-Forwarded-For as the canonical remote address. '
'Only enable this if you have a sanitizing proxy.')
-flags.DEFINE_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,
@@ -54,13 +51,8 @@ flags.DEFINE_list('lockout_memcached_servers', None,
'Memcached servers or None for in process cache.')
-class API(wsgi.Middleware):
- """Routing for all EC2 API requests."""
-
- def __init__(self):
- self.application = Authenticate(Router(Authorizer(Executor())))
- if FLAGS.use_lockout:
- self.application = Lockout(self.application)
+class RequestLogging(wsgi.Middleware):
+ """Access-Log akin logging for all EC2 API requests."""
@webob.dec.wsgify
def __call__(self, req):
@@ -192,26 +184,14 @@ class Authenticate(wsgi.Middleware):
return self.application
-class Router(wsgi.Middleware):
-
- """Add ec2.'controller', .'action', and .'action_args' to WSGI environ."""
+class Requestify(wsgi.Middleware):
- def __init__(self, application):
- super(Router, self).__init__(application)
- self.map = routes.Mapper()
- self.map.connect("/{controller_name}/")
- self.controllers = dict(Cloud=cloud.CloudController(),
- Admin=admin.AdminController())
+ def __init__(self, app, controller_name):
+ super(Requestify, self).__init__(app)
+ self.controller = utils.import_class(controller_name)()
@webob.dec.wsgify
def __call__(self, req):
- # Obtain the appropriate controller and action for this request.
- try:
- match = self.map.match(req.path_info)
- controller_name = match['controller_name']
- controller = self.controllers[controller_name]
- except:
- raise webob.exc.HTTPNotFound()
non_args = ['Action', 'Signature', 'AWSAccessKeyId', 'SignatureMethod',
'SignatureVersion', 'Version', 'Timestamp']
args = dict(req.params)
@@ -229,8 +209,8 @@ class Router(wsgi.Middleware):
LOG.debug(_('arg: %s\t\tval: %s'), key, value)
# Success!
- req.environ['ec2.controller'] = controller
- req.environ['ec2.action'] = action
+ api_request = apirequest.APIRequest(self.controller, action, args)
+ req.environ['ec2.request'] = api_request
req.environ['ec2.action_args'] = args
return self.application
@@ -291,16 +271,14 @@ class Authorizer(wsgi.Middleware):
@webob.dec.wsgify
def __call__(self, req):
context = req.environ['ec2.context']
- controller_name = req.environ['ec2.controller'].__class__.__name__
- action = req.environ['ec2.action']
- allowed_roles = self.action_roles[controller_name].get(action,
- ['none'])
+ controller = req.environ['ec2.request'].controller.__class__.__name__
+ action = req.environ['ec2.request'].action
+ allowed_roles = self.action_roles[controller].get(action, ['none'])
if self._matches_any_role(context, allowed_roles):
return self.application
else:
LOG.audit(_("Unauthorized request for controller=%s "
- "and action=%s"), controller_name, action,
- context=context)
+ "and action=%s"), controller, action, context=context)
raise webob.exc.HTTPUnauthorized()
def _matches_any_role(self, context, roles):
@@ -327,14 +305,10 @@ class Executor(wsgi.Application):
@webob.dec.wsgify
def __call__(self, req):
context = req.environ['ec2.context']
- controller = req.environ['ec2.controller']
- action = req.environ['ec2.action']
- args = req.environ['ec2.action_args']
-
- api_request = apirequest.APIRequest(controller, action)
+ api_request = req.environ['ec2.request']
result = None
try:
- result = api_request.send(context, **args)
+ result = api_request.invoke(context)
except exception.NotFound as ex:
LOG.info(_('NotFound raised: %s'), str(ex), context=context)
return self._error(req, context, type(ex).__name__, str(ex))
@@ -393,18 +367,18 @@ class Versions(wsgi.Application):
return ''.join('%s\n' % v for v in versions)
+def request_logging_factory(global_args, **local_args):
+ def logger(app):
+ return RequestLogging(app)
+ return logger
+
+
def authenticate_factory(global_args, **local_args):
def authenticator(app):
return Authenticate(app)
return authenticator
-def router_factory(global_args, **local_args):
- def router(app):
- return Router(app)
- return router
-
-
def authorizer_factory(global_args, **local_args):
def authorizer(app):
return Authorizer(app)
@@ -417,3 +391,15 @@ def executor_factory(global_args, **local_args):
def versions_factory(global_args, **local_args):
return Versions()
+
+
+def requestify_factory(global_args, **local_args):
+ def requestifier(app):
+ return Requestify(app, local_args['controller'])
+ return requestifier
+
+
+def lockout_factory(global_args, **local_args):
+ def locksmith(app):
+ return Lockout(app)
+ return locksmith
diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py
index d0b417db1..78576470a 100644
--- a/nova/api/ec2/apirequest.py
+++ b/nova/api/ec2/apirequest.py
@@ -83,11 +83,12 @@ def _try_convert(value):
class APIRequest(object):
- def __init__(self, controller, action):
+ def __init__(self, controller, action, args):
self.controller = controller
self.action = action
+ self.args = args
- def send(self, context, **kwargs):
+ def invoke(self, context):
try:
method = getattr(self.controller,
_camelcase_to_underscore(self.action))
@@ -100,7 +101,7 @@ class APIRequest(object):
raise Exception(_error)
args = {}
- for key, value in kwargs.items():
+ for key, value in self.args.items():
parts = key.split(".")
key = _camelcase_to_underscore(parts[0])
if isinstance(value, str) or isinstance(value, unicode):
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index a1ae70fb0..57d41ed67 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -254,15 +254,15 @@ class CloudController(object):
name, _sep, host = region.partition('=')
endpoint = '%s://%s:%s%s' % (FLAGS.ec2_prefix,
host,
- FLAGS.cc_port,
+ FLAGS.ec2_port,
FLAGS.ec2_suffix)
regions.append({'regionName': name,
'regionEndpoint': endpoint})
else:
regions = [{'regionName': 'nova',
'regionEndpoint': '%s://%s:%s%s' % (FLAGS.ec2_prefix,
- FLAGS.cc_host,
- FLAGS.cc_port,
+ FLAGS.ec2_host,
+ FLAGS.ec2_port,
FLAGS.ec2_suffix)}]
return {'regionInfo': regions}
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index f96e2af91..302d50ac8 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -23,11 +23,9 @@ WSGI middleware for OpenStack API controllers.
import routes
import webob.dec
import webob.exc
-import webob
from nova import flags
from nova import log as logging
-from nova import utils
from nova import wsgi
from nova.api.openstack import faults
from nova.api.openstack import backup_schedules
@@ -40,32 +38,16 @@ from nova.api.openstack import shared_ip_groups
LOG = logging.getLogger('nova.api.openstack')
FLAGS = flags.FLAGS
-flags.DEFINE_string('os_api_auth',
- 'nova.api.openstack.auth.AuthMiddleware',
- 'The auth mechanism to use for the OpenStack API implemenation')
-
-flags.DEFINE_string('os_api_ratelimiting',
- 'nova.api.openstack.ratelimiting.RateLimitingMiddleware',
- 'Default ratelimiting implementation for the Openstack API')
-
flags.DEFINE_string('os_krm_mapping_file',
'krm_mapping.json',
'Location of OpenStack Flavor/OS:EC2 Kernel/Ramdisk/Machine JSON file.')
-
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."""
-
- def __init__(self):
- auth_middleware = utils.import_class(FLAGS.os_api_auth)
- ratelimiting_middleware = \
- utils.import_class(FLAGS.os_api_ratelimiting)
- app = auth_middleware(ratelimiting_middleware(APIRouter()))
- super(API, self).__init__(app)
+class FaultWrapper(wsgi.Middleware):
+ """Calls down the middleware stack, making exceptions into faults."""
@webob.dec.wsgify
def __call__(self, req):
@@ -140,3 +122,9 @@ def router_factory(global_cof, **local_conf):
def versions_factory(global_conf, **local_conf):
return Versions()
+
+
+def fault_wrapper_factory(global_conf, **local_conf):
+ def fwrap(app):
+ return FaultWrapper(app)
+ return fwrap