From e6073532e5020203a8ec2247ca7ddd481c6ec517 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 5 Nov 2011 14:10:17 -0700 Subject: Separate metadata api into its own service part 1 of blueprint separate-nova-metadata * adds api/metadata/ and moves code from ec2 * moves metadata into separate binary * changes metadata forward to use metadata host and port * moves the metadata accept rule to the metadata api * adds nova-api-* to setup.py Change-Id: I7f5d8e6cafc55b5c383cd88991f29c6059fb8d82 --- nova/api/ec2/__init__.py | 23 ------- nova/api/ec2/metadatarequesthandler.py | 93 --------------------------- nova/api/manager.py | 8 +-- nova/api/metadata/__init__.py | 25 ++++++++ nova/api/metadata/handler.py | 112 +++++++++++++++++++++++++++++++++ 5 files changed, 141 insertions(+), 120 deletions(-) delete mode 100644 nova/api/ec2/metadatarequesthandler.py create mode 100644 nova/api/metadata/__init__.py create mode 100644 nova/api/metadata/handler.py (limited to 'nova/api') diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index db92ca053..100837631 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -20,10 +20,7 @@ Starting point for routing EC2 requests. """ -from urlparse import urlparse -import eventlet -from eventlet.green import httplib import webob import webob.dec import webob.exc @@ -437,23 +434,3 @@ class Executor(wsgi.Application): (utils.utf8(code), utils.utf8(message), utils.utf8(context.request_id))) return resp - - -class Versions(wsgi.Application): - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(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) diff --git a/nova/api/ec2/metadatarequesthandler.py b/nova/api/ec2/metadatarequesthandler.py deleted file mode 100644 index 0198bf490..000000000 --- a/nova/api/ec2/metadatarequesthandler.py +++ /dev/null @@ -1,93 +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. - -"""Metadata request handler.""" - -import webob.dec -import webob.exc - -from nova import log as logging -from nova import flags -from nova import utils -from nova import wsgi -from nova.api.ec2 import cloud - - -LOG = logging.getLogger('nova.api.ec2.metadata') -FLAGS = flags.FLAGS -flags.DECLARE('use_forwarded_for', 'nova.api.auth') - - -class MetadataRequestHandler(wsgi.Application): - """Serve metadata from the EC2 API.""" - - def __init__(self): - self.cc = cloud.CloudController() - - def print_data(self, data): - if isinstance(data, dict): - output = '' - for key in data: - if key == '_name': - continue - output += key - if isinstance(data[key], dict): - if '_name' in data[key]: - output += '=' + str(data[key]['_name']) - else: - output += '/' - output += '\n' - # Cut off last \n - return output[:-1] - elif isinstance(data, list): - return '\n'.join(data) - else: - return str(data) - - def lookup(self, path, data): - items = path.split('/') - for item in items: - if item: - if not isinstance(data, dict): - return data - if not item in data: - return None - data = data[item] - return data - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - remote_address = req.remote_addr - if FLAGS.use_forwarded_for: - remote_address = req.headers.get('X-Forwarded-For', remote_address) - try: - meta_data = self.cc.get_metadata(remote_address) - except Exception: - LOG.exception(_('Failed to get metadata for ip: %s'), - remote_address) - msg = _('An unknown error has occurred. ' - 'Please try your request again.') - exc = webob.exc.HTTPInternalServerError(explanation=unicode(msg)) - return exc - if meta_data is None: - LOG.error(_('Failed to get metadata for ip: %s'), remote_address) - raise webob.exc.HTTPNotFound() - data = self.lookup(req.path_info, meta_data) - if data is None: - raise webob.exc.HTTPNotFound() - return self.print_data(data) diff --git a/nova/api/manager.py b/nova/api/manager.py index 9cb364e2d..35ea8100c 100644 --- a/nova/api/manager.py +++ b/nova/api/manager.py @@ -23,14 +23,14 @@ from nova import utils FLAGS = flags.FLAGS -class EC2Manager(manager.Manager): - """EC2 API manager. +class MetadataManager(manager.Manager): + """Metadata Manager. - This class manages the EC2 API service initialization. Currently, it + This class manages the Metadata API service initialization. Currently, it just adds an iptables filter rule for the metadata service. """ def __init__(self, *args, **kwargs): - super(EC2Manager, self).__init__(*args, **kwargs) + super(MetadataManager, self).__init__(*args, **kwargs) self.network_driver = utils.import_object(FLAGS.network_driver) def init_host(self): diff --git a/nova/api/metadata/__init__.py b/nova/api/metadata/__init__.py new file mode 100644 index 000000000..f09dfc326 --- /dev/null +++ b/nova/api/metadata/__init__.py @@ -0,0 +1,25 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Openstack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +:mod:`nova.api.metadata` -- Nova Metadata Server +================================================ + +.. automodule:: nova.api.metadata + :platform: Unix + :synopsis: Metadata Server for Nova +.. moduleauthor:: Vishvananda Ishaya +""" diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py new file mode 100644 index 000000000..5d63c6dce --- /dev/null +++ b/nova/api/metadata/handler.py @@ -0,0 +1,112 @@ +# 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. + +"""Metadata request handler.""" + +import webob.dec +import webob.exc + +from nova import log as logging +from nova import flags +from nova import wsgi +from nova.api.ec2 import cloud + + +LOG = logging.getLogger('nova.api.metadata') +FLAGS = flags.FLAGS +flags.DECLARE('use_forwarded_for', 'nova.api.auth') + + +class Versions(wsgi.Application): + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + """Respond to a request for all 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) + + +class MetadataRequestHandler(wsgi.Application): + """Serve metadata.""" + + def __init__(self): + self.cc = cloud.CloudController() + + def print_data(self, data): + if isinstance(data, dict): + output = '' + for key in data: + if key == '_name': + continue + output += key + if isinstance(data[key], dict): + if '_name' in data[key]: + output += '=' + str(data[key]['_name']) + else: + output += '/' + output += '\n' + # Cut off last \n + return output[:-1] + elif isinstance(data, list): + return '\n'.join(data) + else: + return str(data) + + def lookup(self, path, data): + items = path.split('/') + for item in items: + if item: + if not isinstance(data, dict): + return data + if not item in data: + return None + data = data[item] + return data + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + remote_address = req.remote_addr + if FLAGS.use_forwarded_for: + remote_address = req.headers.get('X-Forwarded-For', remote_address) + try: + meta_data = self.cc.get_metadata(remote_address) + except Exception: + LOG.exception(_('Failed to get metadata for ip: %s'), + remote_address) + msg = _('An unknown error has occurred. ' + 'Please try your request again.') + exc = webob.exc.HTTPInternalServerError(explanation=unicode(msg)) + return exc + if meta_data is None: + LOG.error(_('Failed to get metadata for ip: %s'), remote_address) + raise webob.exc.HTTPNotFound() + data = self.lookup(req.path_info, meta_data) + if data is None: + raise webob.exc.HTTPNotFound() + return self.print_data(data) -- cgit