Merge "Accept new orchestrator config bucket"

This commit is contained in:
Jenkins 2016-01-24 15:20:01 +00:00 committed by Gerrit Code Review
commit 20d413d654
9 changed files with 164 additions and 28 deletions

View File

@ -39,8 +39,11 @@ METADATA_DEST_ADDRESS = '169.254.169.254'
# port for internal network metadata proxy
BASE_METADATA_PORT = 9600
# port for rug metadata service
RUG_META_PORT = 9697
# default address of orchestrator metadata service
ORCHESTRATOR_METADATA_ADDRESS = 'fdca:3ba5:a17a:acda::1'
# default port for orchestrator metadata service
ORCHESTRATOR_METADATA_PORT = 9697
def internal_metadata_port(ifname):

View File

@ -196,7 +196,8 @@ class IPTablesManager(base.Manager):
# Open SSH, the HTTP API (5000) and the Nova metadata proxy (9697)
for port in (
defaults.SSH, defaults.API_SERVICE, defaults.RUG_META_PORT
defaults.SSH, defaults.API_SERVICE,
defaults.ORCHESTRATOR_METADATA_PORT
):
rules.append(Rule(
'-A INPUT -i %s -p tcp -m tcp --dport %s -j ACCEPT' % (

View File

@ -41,7 +41,7 @@ class MetadataManager(base.Manager):
"""
super(MetadataManager, self).__init__(root_helper)
def networks_have_changed(self, config):
def should_restart(self, config):
"""
This function determines if the networks have changed since <config>
was initialized.
@ -59,8 +59,14 @@ class MetadataManager(base.Manager):
except:
# If we can't read the file, assume networks were added/removed
return True
config_dict.pop('tenant_id')
return net_ids != set(config_dict.keys())
orchestrator_addr = config_dict.get('orchestrator_metadata_address')
orchestrator_port = config_dict.get('orchestrator_metadata_port')
return (
net_ids != set(config_dict.get('networks', {}).keys()) or
orchestrator_addr != config.metadata_address or
orchestrator_port != config.metadata_port)
def save_config(self, config):
"""
@ -108,7 +114,7 @@ def build_config(config):
:param config:
:rtype: astara_router.models.Configuration
"""
config_data = {}
network_data = {}
for net in config.networks:
if not net.is_tenant_network:
@ -119,10 +125,14 @@ def build_config(config):
for ip in a.ip_addresses:
ip_instance_map[ip] = a.device_id
config_data[net.id] = {
network_data[net.id] = {
'listen_port': internal_metadata_port(net.interface.ifname),
'ip_instance_map': ip_instance_map
}
config_data['tenant_id'] = config.tenant_id
return config_data
return {
'tenant_id': config.tenant_id,
'orchestrator_metadata_address': config.metadata_address,
'orchestrator_metadata_port': config.metadata_port,
'networks': network_data,
}

View File

@ -97,7 +97,7 @@ class RouterManager(ServiceManagerBase):
def update_metadata(self):
mgr = metadata.MetadataManager()
should_restart = mgr.networks_have_changed(self._config)
should_restart = mgr.should_restart(self._config)
mgr.save_config(self._config)
if should_restart:
mgr.restart()

View File

@ -31,9 +31,6 @@ import requests
from werkzeug import exceptions
from werkzeug import wrappers
from astara_router import defaults
from astara_router.drivers import ip
LOG = logging.getLogger(__name__)
@ -48,8 +45,18 @@ class NetworkMetadataProxyHandler(object):
self.network_id = network_id
self.config_file = config_file
self.config_mtime = 0
self._config_dict = {}
self._ip_instance_map = {}
@property
def config_dict(self):
config_mtime = os.stat(self.config_file).st_mtime
if config_mtime > self.config_mtime:
LOG.debug("Metadata proxy configuration has changed; reloading...")
self._config_dict = json.load(open(self.config_file))
self.config_mtime = config_mtime
return self._config_dict
def __call__(self, environ, start_response):
request = wrappers.Request(environ)
@ -68,16 +75,16 @@ class NetworkMetadataProxyHandler(object):
@property
def ip_instance_map(self):
config_mtime = os.stat(self.config_file).st_mtime
if config_mtime > self.config_mtime:
LOG.debug("Metadata proxy configuration has changed; reloading...")
config_dict = json.load(open(self.config_file))
self._ip_instance_map = config_dict[
self.network_id
]['ip_instance_map']
self.config_mtime = config_mtime
self._ip_instance_map = self.config_dict['networks'][
self.network_id]['ip_instance_map']
return self._ip_instance_map
@property
def orchestrator_loc(self):
addr = self.config_dict['orchestrator_metadata_address']
port = self.config_dict['orchestrator_metadata_port']
return '[%s]:%d' % (addr, port)
def _proxy_request(self, remote_address, path_info, query_string):
headers = {
'X-Forwarded-For': remote_address,
@ -88,7 +95,7 @@ class NetworkMetadataProxyHandler(object):
url = urlparse.urlunsplit((
'http',
'[%s]:%d' % (ip.get_rug_address(), defaults.RUG_META_PORT),
self.orchestrator_loc,
path_info,
query_string,
''))
@ -172,7 +179,7 @@ def main():
pool = eventlet.GreenPool(1000)
tenant_id = config_dict.pop('tenant_id')
for network_id, config in config_dict.items():
for network_id, config in config_dict['networks'].items():
app = NetworkMetadataProxyHandler(tenant_id,
network_id,
args.config_file)

View File

@ -20,6 +20,8 @@ import re
import netaddr
from astara_router import defaults
GROUP_NAME_LENGTH = 15
DEFAULT_AS = 64512
@ -715,6 +717,12 @@ class RouterConfiguration(SystemConfiguration):
Label(name, cidr) for name, cidr in
conf_dict.get('labels', {}).iteritems()]
orchestrator_conf = conf_dict.get('orchestrator', {})
self.metadata_address = orchestrator_conf.get(
'address', defaults.ORCHESTRATOR_METADATA_ADDRESS)
self.metadata_port = orchestrator_conf.get(
'metadata_port', defaults.ORCHESTRATOR_METADATA_PORT)
self.floating_ips = [
FloatingIP.from_dict(fip)
for fip in conf_dict.get('floating_ips', [])

View File

@ -0,0 +1,84 @@
# Copyright 2014 DreamHost, LLC
#
# Author: DreamHost, 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.
import __builtin__
import json
import mock
from unittest2 import TestCase
from astara_router.drivers import metadata
CONFIG = mock.Mock()
CONFIG.hostname = 'astara'
CONFIG.management_address = 'fdca:3ba5:a17a:acda:f816:3eff:fe66:33b6'
class HostnameTestCase(TestCase):
"""
"""
def setUp(self):
self.mgr = metadata.MetadataManager()
self.config_dict = {
'networks': {'tenant_net_id': [], 'public_net_id': []},
'orchestrator_metadata_address': '10.0.0.1',
'orchestrator_metadata_port': '5000',
}
tenant_net = mock.Mock(
is_tenant_network=mock.Mock(return_value=True),
id='tenant_net_id',
)
public_net = mock.Mock(
is_tenant_network=mock.Mock(return_value=False),
id='public_net_id',
)
self.config = mock.Mock()
self.config.networks = [tenant_net, public_net]
self.config.metadata_address = '10.0.0.1'
self.config.metadata_port = '5000'
def _test_should_restart(self, exp_result):
config_json = json.dumps(self.config_dict)
with mock.patch.object(
__builtin__, 'open', mock.mock_open(read_data=config_json)):
self.assertEqual(
self.mgr.should_restart(self.config), exp_result)
def test_should_restart_false(self):
self._test_should_restart(False)
def test_should_restart_true_networks_change(self):
self.config_dict['networks'] = {
'foo_net_id': [], 'public_net_id': []}
self._test_should_restart(True)
def test_should_restart_true_metadata_addr_change(self):
self.config_dict['orchestrator_metadata_address'] = '11.1.1.1'
self._test_should_restart(True)
def test_should_restart_true_metadata_port_change(self):
self.config_dict['orchestrator_metadata_port'] = '6000'
self._test_should_restart(True)
def test_should_restart_true_config_read_err(self):
with mock.patch.object(
__builtin__, 'open', mock.mock_open()) as _o:
_o.side_effect = IOError()
self.assertEqual(
self.mgr.should_restart(self.config), True)

View File

@ -11,8 +11,14 @@ from astara_router import metadata_proxy
config = json.dumps({
"tenant_id": "ABC123",
"net1": {"listen_port": 9602, 'ip_instance_map': {'10.10.10.2': 'VM1'}},
"net2": {"listen_port": 9603, 'ip_instance_map': {'10.10.10.2': 'VM2'}},
"orchestrator_metadata_address": "192.168.25.30",
"orchestrator_metadata_port": 9697,
"networks": {
"net1": {
"listen_port": 9602, 'ip_instance_map': {'10.10.10.2': 'VM1'}},
"net2": {
"listen_port": 9603, 'ip_instance_map': {'10.10.10.2': 'VM2'}},
}
})
class TestMetadataProxy(unittest.TestCase):
@ -66,7 +72,7 @@ class TestMetadataProxy(unittest.TestCase):
get.return_value.status_code = 200
wsgi._proxy_request('10.10.10.2', '/', '')
get.assert_called_once_with(
'http://[fdca:3ba5:a17a:acda::1]:9697/',
'http://[192.168.25.30]:9697/',
headers={
'X-Quantum-Network-ID': 'net1',
'X-Forwarded-For': '10.10.10.2',

View File

@ -23,7 +23,7 @@ import netaddr
from unittest2 import TestCase
from astara_router import models
from astara_router import defaults, models
from test.unit import fakes
@ -439,6 +439,23 @@ class RouterConfigurationTestCase(TestCase):
self.assertEqual(len(c.anchors[0].rules), 1)
self.assertEqual(c.anchors[0].rules[0].action, 'block')
def test_init_metadata_config(self):
c = models.RouterConfiguration({
'orchestrator': {
'address': '192.168.25.30',
'metadata_port': 9697,
}
})
self.assertEqual(c.metadata_address, '192.168.25.30')
self.assertEqual(c.metadata_port, 9697)
def test_init_metadata_config_missing(self):
c = models.RouterConfiguration({})
self.assertEqual(
c.metadata_address, defaults.ORCHESTRATOR_METADATA_ADDRESS)
self.assertEqual(
c.metadata_port, defaults.ORCHESTRATOR_METADATA_PORT)
def test_asn_default(self):
c = models.RouterConfiguration({'networks': []})
self.assertEqual(c.asn, 64512)