From 1d26671b3f3b2aa43d2a3f082f20bd08515fdc4a Mon Sep 17 00:00:00 2001 From: Adam Gandelman Date: Mon, 16 Nov 2015 14:22:29 -0800 Subject: [PATCH] Allow API listening address to be specified in config This allows users to configure a specific API listening address for the astara administrative API. This also updates devstack plugin to publish this into the keystone catalog, for easier lookup by astara-horizon. Partially-implements: blueprint astara-horizon-mitaka Partial-bug: #1516787 Change-Id: I2b96137c05b832a68ad01a11ec0cfb2371111c3c --- astara/api/rug.py | 24 ++++++++++++++----- astara/main.py | 1 - astara/test/unit/api/test_rug_api.py | 36 ++++++++++++++++++++++------ devstack/plugin.sh | 14 ++++++++++- etc/orchestrator.ini | 4 ++++ 5 files changed, 64 insertions(+), 15 deletions(-) diff --git a/astara/api/rug.py b/astara/api/rug.py index 77c080ea..3bf4bc4a 100644 --- a/astara/api/rug.py +++ b/astara/api/rug.py @@ -33,8 +33,13 @@ from astara.common.i18n import _, _LE, _LI, _LW LOG = logging.getLogger(__name__) RUG_API_OPTS = [ - cfg.IntOpt('rug_api_port', default=44250, - help='RUG API listening port') + cfg.IntOpt('api_port', default=44250, + help='Astara administrative API listening port', + deprecated_opts=[ + cfg.DeprecatedOpt('rug_api_port', + group='DEFAULT')]), + cfg.StrOpt('api_listen', default='0.0.0.0', + help='Astara administrative API listening address') ] cfg.CONF.register_opts(RUG_API_OPTS) @@ -76,8 +81,15 @@ class RugAPIServer(object): def __init__(self): self.pool = eventlet.GreenPool(1000) - def run(self, ip_address, port=cfg.CONF.rug_api_port): + def run(self, ip_address, port): app = RugAPI() + + try: + socket.inet_pton(socket.AF_INET6, ip_address) + family = socket.AF_INET6 + except Exception: + family = socket.AF_INET + for i in six.moves.range(5): LOG.info(_LI( 'Starting the rug-api on %s:%s'), @@ -86,7 +98,7 @@ class RugAPIServer(object): try: sock = eventlet.listen( (ip_address, port), - family=socket.AF_INET6, + family=family, backlog=128 ) except socket.error as err: @@ -109,5 +121,5 @@ class RugAPIServer(object): log=loggers.WritableLogger(LOG)) -def serve(ip_address): - RugAPIServer().run(ip_address) +def serve(): + RugAPIServer().run(cfg.CONF.api_listen, cfg.CONF.api_port) diff --git a/astara/main.py b/astara/main.py index 076f9271..6f747928 100644 --- a/astara/main.py +++ b/astara/main.py @@ -170,7 +170,6 @@ def main(argv=sys.argv[1:]): from astara.api import rug as rug_api rug_api_proc = multiprocessing.Process( target=rug_api.serve, - args=(mgt_ip_address,), name='rug-api' ) rug_api_proc.start() diff --git a/astara/test/unit/api/test_rug_api.py b/astara/test/unit/api/test_rug_api.py index 4b34acc7..8c44f4d3 100644 --- a/astara/test/unit/api/test_rug_api.py +++ b/astara/test/unit/api/test_rug_api.py @@ -161,12 +161,31 @@ class TestRugAPIServer(unittest.TestCase): @mock.patch('eventlet.listen') @mock.patch('eventlet.wsgi') - def test_bind_and_serve(self, wsgi, listen): + def test_bind_and_serve_ipv4(self, wsgi, listen): sock = listen.return_value server = rug.RugAPIServer() - server.run('::1/128') + server.run('10.0.0.250', 44250) listen.assert_called_with( - ('::1/128', 44250), + ('10.0.0.250', 44250), + family=socket.AF_INET, + backlog=128 + ) + args, kwargs = wsgi.server.call_args + assert all([ + args[0] == sock, + isinstance(args[1], rug.RugAPI), + kwargs['custom_pool'] == server.pool, + isinstance(kwargs['log'], loggers.WritableLogger) + ]) + + @mock.patch('eventlet.listen') + @mock.patch('eventlet.wsgi') + def test_bind_and_serve_ipv6(self, wsgi, listen): + sock = listen.return_value + server = rug.RugAPIServer() + server.run('fdca:3ba5:a17a:acda::1', 44250) + listen.assert_called_with( + ('fdca:3ba5:a17a:acda::1', 44250), family=socket.AF_INET6, backlog=128 ) @@ -188,10 +207,12 @@ class TestRugAPIServer(unittest.TestCase): self.assertRaises( RuntimeError, server.run, - '::1/128' + 'fdca:3ba5:a17a:acda::1', + 44250, ) assert listen.call_args_list == [ - mock.call(('::1/128', 44250), family=socket.AF_INET6, backlog=128) + mock.call(('fdca:3ba5:a17a:acda::1', 44250), + family=socket.AF_INET6, backlog=128) for i in range(5) ] @@ -205,9 +226,10 @@ class TestRugAPIServer(unittest.TestCase): sock ] server = rug.RugAPIServer() - server.run('::1/128') + server.run('fdca:3ba5:a17a:acda::1', 44250) assert listen.call_args_list == [ - mock.call(('::1/128', 44250), family=socket.AF_INET6, backlog=128) + mock.call(('fdca:3ba5:a17a:acda::1', 44250), + family=socket.AF_INET6, backlog=128) for i in range(2) # fails the first time, succeeds the second ] args, kwargs = wsgi.server.call_args diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 3da82d87..3b992265 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -34,6 +34,7 @@ ROUTER_INSTANCE_FLAVOR_CPUS=${ROUTER_INSTANCE_FLAVOR_CPUS:-1} PUBLIC_INTERFACE_DEFAULT='eth0' ASTARA_MANAGEMENT_PREFIX=${ASTARA_MANAGEMENT_PREFIX:-"fdca:3ba5:a17a:acda::/64"} ASTARA_MANAGEMENT_PORT=${ASTARA_MANAGEMENT_PORT:-5000} +ASTARA_API_LISTEN=${ASTARA_API_LISTEN:-$SERVICE_HOST} ASTARA_API_PORT=${ASTARA_API_PORT:-44250} HORIZON_LOCAL_SETTINGS=$HORIZON_DIR/openstack_dashboard/local/local_settings.py @@ -83,7 +84,8 @@ function configure_astara() { iniset $ASTARA_CONF DEFAULT management_prefix $ASTARA_MANAGEMENT_PREFIX iniset $ASTARA_CONF DEFAULT astara_mgt_service_port $ASTARA_MANAGEMENT_PORT - iniset $ASTARA_CONF DEFAULT rug_api_port $ASTARA_API_PORT + iniset $ASTARA_CONF DEFAULT api_listen $ASTARA_API_LISTEN + iniset $ASTARA_CONF DEFAULT api_port $ASTARA_API_PORT if [[ "$Q_AGENT" == "linuxbridge" ]]; then iniset $ASTARA_CONF DEFAULT interface_driver "astara.common.linux.interface.BridgeInterfaceDriver" @@ -337,6 +339,15 @@ function set_demo_tenant_sec_group_private_traffic() { neutron $auth_args security-group-rule-create --direction ingress --remote-ip-prefix $FIXED_RANGE default } +function create_astara_endpoint() { + # Publish the API endpoint of the administrative API (used by Horizon) + get_or_create_service "astara" "astara" "Astara Network Orchestration Administrative API" + get_or_create_endpoint "astara" \ + "$REGION_NAME" \ + "http://$ASTARA_API_LISTEN:$ASTARA_API_PORT" \ + "http://$ASTARA_API_LISTEN:$ASTARA_API_PORT" \ + "http://$ASTARA_API_LISTEN:$ASTARA_API_PORT" +} function check_prereqs() { # Fail devstack as early as possible if system does not satisfy some known @@ -366,6 +377,7 @@ if is_service_enabled astara; then if is_service_enabled horizon; then configure_astara_horizon fi + create_astara_endpoint cd $old_cwd elif [[ "$1" == "stack" && "$2" == "extra" ]]; then diff --git a/etc/orchestrator.ini b/etc/orchestrator.ini index 97be7c10..9a079de8 100644 --- a/etc/orchestrator.ini +++ b/etc/orchestrator.ini @@ -55,6 +55,10 @@ provider_rules_path=/opt/stack/astara/etc/provider_rules.json control_exchange = quantum neutron_port_security_extension_enabled = True +# api_listen address and port for the astara administrative API +api_listen = 0.0.0.0 +api_port = 44250 + [AGENT] root_helper=sudo astara-rootwrap /etc/astara/rootwrap.conf