diff --git a/bin/nova-api-metadata b/bin/nova-api-metadata new file mode 100755 index 000000000000..199c3918cc3e --- /dev/null +++ b/bin/nova-api-metadata @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# 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. + +"""Starter script for Nova Metadata API.""" + +import eventlet +eventlet.monkey_patch() + +import os +import sys + + +possible_topdir = os.path.normpath(os.path.join(os.path.abspath( + sys.argv[0]), os.pardir, os.pardir)) +if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): + sys.path.insert(0, possible_topdir) + + +from nova import flags +from nova import log as logging +from nova import service +from nova import utils + +if __name__ == '__main__': + utils.default_flagfile() + flags.FLAGS(sys.argv) + logging.setup() + utils.monkey_patch() + server = service.WSGIService('metadata') + service.serve(server) + service.wait() diff --git a/etc/nova/api-paste.ini b/etc/nova/api-paste.ini index af175990fe3b..580191c01022 100644 --- a/etc/nova/api-paste.ini +++ b/etc/nova/api-paste.ini @@ -1,21 +1,39 @@ +############ +# Metadata # +############ +[composite:metadata] +use = egg:Paste#urlmap +/: metaversions +/latest: meta +/2007-01-19: meta +/2007-03-01: meta +/2007-08-29: meta +/2007-10-10: meta +/2007-12-15: meta +/2008-02-01: meta +/2008-09-01: meta +/2009-04-04: meta + +[pipeline:metaversions] +pipeline = ec2faultwrap logrequest metaverapp + +[pipeline:meta] +pipeline = ec2faultwrap logrequest metaapp + +[app:metaverapp] +paste.app_factory = nova.api.metadata.handler:Versions.factory + +[app:metaapp] +paste.app_factory = nova.api.metadata.handler:MetadataRequestHandler.factory + ####### # EC2 # ####### [composite:ec2] use = egg:Paste#urlmap -/: ec2versions /services/Cloud: ec2cloud /services/Admin: ec2admin -/latest: ec2metadata -/2007-01-19: ec2metadata -/2007-03-01: ec2metadata -/2007-08-29: ec2metadata -/2007-10-10: ec2metadata -/2007-12-15: ec2metadata -/2008-02-01: ec2metadata -/2008-09-01: ec2metadata -/2009-04-04: ec2metadata [pipeline:ec2cloud] pipeline = ec2faultwrap logrequest ec2noauth cloudrequest authorizer ec2executor @@ -27,12 +45,6 @@ pipeline = ec2faultwrap logrequest ec2noauth adminrequest authorizer ec2executor # NOTE(vish): use the following pipeline for deprecated auth #pipeline = ec2faultwrap logrequest authenticate adminrequest authorizer ec2executor -[pipeline:ec2metadata] -pipeline = ec2faultwrap logrequest ec2md - -[pipeline:ec2versions] -pipeline = ec2faultwrap logrequest ec2ver - [filter:ec2faultwrap] paste.filter_factory = nova.api.ec2:FaultWrapper.factory @@ -62,12 +74,6 @@ paste.filter_factory = nova.api.ec2:Authorizer.factory [app:ec2executor] paste.app_factory = nova.api.ec2:Executor.factory -[app:ec2ver] -paste.app_factory = nova.api.ec2:Versions.factory - -[app:ec2md] -paste.app_factory = nova.api.ec2.metadatarequesthandler:MetadataRequestHandler.factory - ############# # Openstack # ############# diff --git a/nova/__init__.py b/nova/__init__.py index 884c4a71309f..f2e9684d3033 100644 --- a/nova/__init__.py +++ b/nova/__init__.py @@ -25,7 +25,7 @@ :synopsis: Infrastructure-as-a-Service Cloud platform. .. moduleauthor:: Jesse Andrews .. moduleauthor:: Devin Carlen -.. moduleauthor:: Vishvananda Ishaya +.. moduleauthor:: Vishvananda Ishaya .. moduleauthor:: Joshua McKenty .. moduleauthor:: Manish Singh .. moduleauthor:: Andy Smith diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index db92ca053558..100837631d75 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/manager.py b/nova/api/manager.py index 9cb364e2d8a2..35ea8100c1b1 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 000000000000..f09dfc326cbd --- /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/ec2/metadatarequesthandler.py b/nova/api/metadata/handler.py similarity index 84% rename from nova/api/ec2/metadatarequesthandler.py rename to nova/api/metadata/handler.py index 0198bf4909de..5d63c6dceaeb 100644 --- a/nova/api/ec2/metadatarequesthandler.py +++ b/nova/api/metadata/handler.py @@ -23,18 +23,37 @@ 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') +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 from the EC2 API.""" + """Serve metadata.""" def __init__(self): self.cc = cloud.CloudController() diff --git a/nova/auth/__init__.py b/nova/auth/__init__.py index e2a140e83317..e81c739da735 100644 --- a/nova/auth/__init__.py +++ b/nova/auth/__init__.py @@ -23,6 +23,6 @@ :platform: Unix :synopsis: User-and-Project based RBAC using LDAP, SAML. .. moduleauthor:: Jesse Andrews -.. moduleauthor:: Vishvananda Ishaya +.. moduleauthor:: Vishvananda Ishaya .. moduleauthor:: Joshua McKenty """ diff --git a/nova/cloudpipe/__init__.py b/nova/cloudpipe/__init__.py index cfadc30e9c75..3d683a0e2c03 100644 --- a/nova/cloudpipe/__init__.py +++ b/nova/cloudpipe/__init__.py @@ -24,6 +24,6 @@ :platform: Unix :synopsis: An OpenVPN server for every nova user. .. moduleauthor:: Devin Carlen -.. moduleauthor:: Vishvananda Ishaya +.. moduleauthor:: Vishvananda Ishaya .. moduleauthor:: Joshua McKenty """ diff --git a/nova/flags.py b/nova/flags.py index 9d6ef2a944db..32cec119f85a 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -361,7 +361,7 @@ DEFINE_integer('rabbit_max_retries', 0, 'maximum rabbit connection attempts (0=try forever)') DEFINE_string('control_exchange', 'nova', 'the main exchange to connect to') DEFINE_boolean('rabbit_durable_queues', False, 'use durable queues') -DEFINE_list('enabled_apis', ['ec2', 'osapi'], +DEFINE_list('enabled_apis', ['ec2', 'osapi', 'metadata'], 'list of APIs to enable by default') DEFINE_string('ec2_host', '$my_ip', 'ip of api server') DEFINE_string('ec2_dmz_host', '$my_ip', 'internal ip of api server') @@ -377,7 +377,8 @@ DEFINE_integer('osapi_port', 8774, 'OpenStack API port') DEFINE_string('osapi_path', '/v1.1/', 'suffix for openstack') DEFINE_integer('osapi_max_limit', 1000, 'max number of items returned in a collection response') - +DEFINE_string('metadata_host', '$my_ip', 'ip of metadata server') +DEFINE_integer('metadata_port', 8775, 'Metadata API port') DEFINE_string('default_project', 'openstack', 'default project for openstack') DEFINE_string('default_image', 'ami-11111', 'default image to use, testing only') diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 0cda55b32423..808179b42a85 100755 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -377,7 +377,8 @@ def metadata_forward(): '-s 0.0.0.0/0 -d 169.254.169.254/32 ' '-p tcp -m tcp --dport 80 -j DNAT ' '--to-destination %s:%s' % \ - (FLAGS.ec2_dmz_host, FLAGS.ec2_port)) + (FLAGS.metadata_host, + FLAGS.metadata_port)) iptables_manager.apply() @@ -387,8 +388,8 @@ def metadata_accept(): '-s 0.0.0.0/0 -d %s ' '-p tcp -m tcp --dport %s ' '-j ACCEPT' % \ - (FLAGS.ec2_dmz_host, - FLAGS.ec2_port)) + (FLAGS.metadata_host, + FLAGS.metadata_port)) iptables_manager.apply() diff --git a/nova/objectstore/__init__.py b/nova/objectstore/__init__.py index ecad9be7ca60..f423f88452cf 100644 --- a/nova/objectstore/__init__.py +++ b/nova/objectstore/__init__.py @@ -25,7 +25,7 @@ :synopsis: Currently a trivial file-based system, getting extended w/ swift. .. moduleauthor:: Jesse Andrews .. moduleauthor:: Devin Carlen -.. moduleauthor:: Vishvananda Ishaya +.. moduleauthor:: Vishvananda Ishaya .. moduleauthor:: Joshua McKenty .. moduleauthor:: Manish Singh .. moduleauthor:: Andy Smith diff --git a/nova/service.py b/nova/service.py index b9ad57943442..47c88eede35a 100644 --- a/nova/service.py +++ b/nova/service.py @@ -45,16 +45,18 @@ flags.DEFINE_integer('report_interval', 10, flags.DEFINE_integer('periodic_interval', 60, 'seconds between running periodic tasks', lower_bound=1) -flags.DEFINE_string('ec2_manager', 'nova.api.manager.EC2Manager', - 'EC2 API service manager') flags.DEFINE_string('ec2_listen', "0.0.0.0", 'IP address for EC2 API to listen') flags.DEFINE_integer('ec2_listen_port', 8773, 'port for ec2 api to listen') -flags.DEFINE_string('osapi_manager', None, - 'OpenStack API service manager') flags.DEFINE_string('osapi_listen', "0.0.0.0", 'IP address for OpenStack API to listen') flags.DEFINE_integer('osapi_listen_port', 8774, 'port for os api to listen') +flags.DEFINE_string('metadata_manager', 'nova.api.manager.MetadataManager', + 'OpenStack metadata service manager') +flags.DEFINE_string('metadata_listen', "0.0.0.0", + 'IP address for metadata api to listen') +flags.DEFINE_integer('metadata_listen_port', 8775, + 'port for metadata api to listen') flags.DEFINE_string('api_paste_config', "api-paste.ini", 'File name for the paste.deploy config for nova-api') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index 1109dfb70c18..676518a4829d 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -24,7 +24,7 @@ :platform: Unix .. moduleauthor:: Jesse Andrews .. moduleauthor:: Devin Carlen -.. moduleauthor:: Vishvananda Ishaya +.. moduleauthor:: Vishvananda Ishaya .. moduleauthor:: Joshua McKenty .. moduleauthor:: Manish Singh .. moduleauthor:: Andy Smith diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 5351c53f6dc4..f9e1c76c4b8d 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -93,6 +93,7 @@ class _IntegratedTestBase(test.TestCase): # Auto-assign ports to allow concurrent tests f['ec2_listen_port'] = 0 f['osapi_listen_port'] = 0 + f['metadata_listen_port'] = 0 f['image_service'] = 'nova.image.fake.FakeImageService' f['fake_network'] = True diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py index 5aba8a545090..283b6a7cb2c9 100644 --- a/nova/tests/test_metadata.py +++ b/nova/tests/test_metadata.py @@ -21,7 +21,7 @@ import base64 import webob -from nova.api.ec2 import metadatarequesthandler +from nova.api.metadata import handler from nova.db.sqlalchemy import api from nova import exception from nova import flags @@ -86,7 +86,7 @@ class MetadataTestCase(test.TestCase): self.stubs.Set(api, 'instance_get', instance_get) self.stubs.Set(api, 'instance_get_all_by_filters', instance_get_list) self.stubs.Set(api, 'instance_get_floating_address', floating_get) - self.app = metadatarequesthandler.MetadataRequestHandler() + self.app = handler.MetadataRequestHandler() network_manager = fake_network.FakeNetworkManager() self.stubs.Set(self.app.cc.network_api, 'get_instance_uuids_by_ip_filter', diff --git a/setup.py b/setup.py index 9b11fb95a961..e1c9e6c95aab 100644 --- a/setup.py +++ b/setup.py @@ -119,6 +119,9 @@ setup(name='nova', data_files=find_data_files('share/nova', 'tools'), scripts=['bin/nova-ajax-console-proxy', 'bin/nova-api', + 'bin/nova-api-ec2', + 'bin/nova-api-metadata', + 'bin/nova-api-os', 'bin/nova-compute', 'bin/nova-console', 'bin/nova-dhcpbridge', diff --git a/tools/setup_iptables.sh b/tools/setup_iptables.sh deleted file mode 100755 index 8be8cd812638..000000000000 --- a/tools/setup_iptables.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env bash -# 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. - -# NOTE(vish): This script sets up some reasonable defaults for iptables and -# creates nova-specific chains. If you use this script you should -# run nova-network and nova-compute with --use_nova_chains=True - -# NOTE(vish): If you run nova-api on a different port, make sure to change -# the port here -API_PORT=${API_PORT:-"8773"} -if [ -n "$1" ]; then - CMD=$1 -else - CMD="all" -fi - -if [ -n "$2" ]; then - IP=$2 -else - # NOTE(vish): This will just get the first ip in the list, so if you - # have more than one eth device set up, this will fail, and - # you should explicitly pass in the ip of the instance - IP=`LC_ALL=C ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` -fi - -if [ -n "$3" ]; then - PRIVATE_RANGE=$3 -else - PRIVATE_RANGE="10.0.0.0/12" -fi - - -if [ -n "$4" ]; then - # NOTE(vish): Management IP is the ip over which to allow ssh traffic. It - # will also allow traffic to nova-api - MGMT_IP=$4 -else - MGMT_IP="$IP" -fi -if [ "$CMD" == "clear" ]; then - iptables -P INPUT ACCEPT - iptables -P FORWARD ACCEPT - iptables -P OUTPUT ACCEPT - iptables -F - iptables -t nat -F - iptables -F nova_input - iptables -F nova_output - iptables -F nova_forward - iptables -t nat -F nova_input - iptables -t nat -F nova_output - iptables -t nat -F nova_forward - iptables -t nat -X - iptables -X -fi - -if [ "$CMD" == "base" ] || [ "$CMD" == "all" ]; then - iptables -P INPUT DROP - iptables -A INPUT -m state --state INVALID -j DROP - iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -A INPUT -m tcp -p tcp -d $MGMT_IP --dport 22 -j ACCEPT - iptables -A INPUT -m udp -p udp --dport 123 -j ACCEPT - iptables -N nova_input - iptables -A INPUT -j nova_input - iptables -A INPUT -p icmp -j ACCEPT - iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset - iptables -A INPUT -j REJECT --reject-with icmp-port-unreachable - - iptables -P FORWARD DROP - iptables -A FORWARD -m state --state INVALID -j DROP - iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu - iptables -N nova_forward - iptables -A FORWARD -j nova_forward - - # NOTE(vish): DROP on output is too restrictive for now. We need to add - # in a bunch of more specific output rules to use it. - # iptables -P OUTPUT DROP - iptables -A OUTPUT -m state --state INVALID -j DROP - iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT - iptables -N nova_output - iptables -A OUTPUT -j nova_output - - iptables -t nat -N nova_prerouting - iptables -t nat -A PREROUTING -j nova_prerouting - - iptables -t nat -N nova_postrouting - iptables -t nat -A POSTROUTING -j nova_postrouting - - iptables -t nat -N nova_output - iptables -t nat -A OUTPUT -j nova_output -fi - -if [ "$CMD" == "ganglia" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 8649 -j ACCEPT - iptables -A nova_input -m udp -p udp -d $IP --dport 8649 -j ACCEPT -fi - -if [ "$CMD" == "web" ] || [ "$CMD" == "all" ]; then - # NOTE(vish): This opens up ports for web access, allowing web-based - # dashboards to work. - iptables -A nova_input -m tcp -p tcp -d $IP --dport 80 -j ACCEPT - iptables -A nova_input -m tcp -p tcp -d $IP --dport 443 -j ACCEPT -fi - -if [ "$CMD" == "objectstore" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 3333 -j ACCEPT -fi - -if [ "$CMD" == "api" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport $API_PORT -j ACCEPT - if [ "$IP" != "$MGMT_IP" ]; then - iptables -A nova_input -m tcp -p tcp -d $MGMT_IP --dport $API_PORT -j ACCEPT - fi -fi - -if [ "$CMD" == "redis" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 6379 -j ACCEPT -fi - -if [ "$CMD" == "mysql" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 3306 -j ACCEPT -fi - -if [ "$CMD" == "rabbitmq" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 4369 -j ACCEPT - iptables -A nova_input -m tcp -p tcp -d $IP --dport 5672 -j ACCEPT - iptables -A nova_input -m tcp -p tcp -d $IP --dport 53284 -j ACCEPT -fi - -if [ "$CMD" == "dnsmasq" ] || [ "$CMD" == "all" ]; then - # NOTE(vish): this could theoretically be setup per network - # for each host, but it seems like overkill - iptables -A nova_input -m tcp -p tcp -s $PRIVATE_RANGE --dport 53 -j ACCEPT - iptables -A nova_input -m udp -p udp -s $PRIVATE_RANGE --dport 53 -j ACCEPT - iptables -A nova_input -m udp -p udp --dport 67 -j ACCEPT -fi - -if [ "$CMD" == "ldap" ] || [ "$CMD" == "all" ]; then - iptables -A nova_input -m tcp -p tcp -d $IP --dport 389 -j ACCEPT -fi - -