Merge "Accept new orchestrator config bucket"
This commit is contained in:
commit
20d413d654
@ -39,8 +39,11 @@ METADATA_DEST_ADDRESS = '169.254.169.254'
|
|||||||
# port for internal network metadata proxy
|
# port for internal network metadata proxy
|
||||||
BASE_METADATA_PORT = 9600
|
BASE_METADATA_PORT = 9600
|
||||||
|
|
||||||
# port for rug metadata service
|
# default address of orchestrator metadata service
|
||||||
RUG_META_PORT = 9697
|
ORCHESTRATOR_METADATA_ADDRESS = 'fdca:3ba5:a17a:acda::1'
|
||||||
|
|
||||||
|
# default port for orchestrator metadata service
|
||||||
|
ORCHESTRATOR_METADATA_PORT = 9697
|
||||||
|
|
||||||
|
|
||||||
def internal_metadata_port(ifname):
|
def internal_metadata_port(ifname):
|
||||||
|
@ -196,7 +196,8 @@ class IPTablesManager(base.Manager):
|
|||||||
|
|
||||||
# Open SSH, the HTTP API (5000) and the Nova metadata proxy (9697)
|
# Open SSH, the HTTP API (5000) and the Nova metadata proxy (9697)
|
||||||
for port in (
|
for port in (
|
||||||
defaults.SSH, defaults.API_SERVICE, defaults.RUG_META_PORT
|
defaults.SSH, defaults.API_SERVICE,
|
||||||
|
defaults.ORCHESTRATOR_METADATA_PORT
|
||||||
):
|
):
|
||||||
rules.append(Rule(
|
rules.append(Rule(
|
||||||
'-A INPUT -i %s -p tcp -m tcp --dport %s -j ACCEPT' % (
|
'-A INPUT -i %s -p tcp -m tcp --dport %s -j ACCEPT' % (
|
||||||
|
@ -41,7 +41,7 @@ class MetadataManager(base.Manager):
|
|||||||
"""
|
"""
|
||||||
super(MetadataManager, self).__init__(root_helper)
|
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>
|
This function determines if the networks have changed since <config>
|
||||||
was initialized.
|
was initialized.
|
||||||
@ -59,8 +59,14 @@ class MetadataManager(base.Manager):
|
|||||||
except:
|
except:
|
||||||
# If we can't read the file, assume networks were added/removed
|
# If we can't read the file, assume networks were added/removed
|
||||||
return True
|
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):
|
def save_config(self, config):
|
||||||
"""
|
"""
|
||||||
@ -108,7 +114,7 @@ def build_config(config):
|
|||||||
:param config:
|
:param config:
|
||||||
:rtype: astara_router.models.Configuration
|
:rtype: astara_router.models.Configuration
|
||||||
"""
|
"""
|
||||||
config_data = {}
|
network_data = {}
|
||||||
|
|
||||||
for net in config.networks:
|
for net in config.networks:
|
||||||
if not net.is_tenant_network:
|
if not net.is_tenant_network:
|
||||||
@ -119,10 +125,14 @@ def build_config(config):
|
|||||||
for ip in a.ip_addresses:
|
for ip in a.ip_addresses:
|
||||||
ip_instance_map[ip] = a.device_id
|
ip_instance_map[ip] = a.device_id
|
||||||
|
|
||||||
config_data[net.id] = {
|
network_data[net.id] = {
|
||||||
'listen_port': internal_metadata_port(net.interface.ifname),
|
'listen_port': internal_metadata_port(net.interface.ifname),
|
||||||
'ip_instance_map': ip_instance_map
|
'ip_instance_map': ip_instance_map
|
||||||
}
|
}
|
||||||
|
|
||||||
config_data['tenant_id'] = config.tenant_id
|
return {
|
||||||
return config_data
|
'tenant_id': config.tenant_id,
|
||||||
|
'orchestrator_metadata_address': config.metadata_address,
|
||||||
|
'orchestrator_metadata_port': config.metadata_port,
|
||||||
|
'networks': network_data,
|
||||||
|
}
|
||||||
|
@ -97,7 +97,7 @@ class RouterManager(ServiceManagerBase):
|
|||||||
|
|
||||||
def update_metadata(self):
|
def update_metadata(self):
|
||||||
mgr = metadata.MetadataManager()
|
mgr = metadata.MetadataManager()
|
||||||
should_restart = mgr.networks_have_changed(self._config)
|
should_restart = mgr.should_restart(self._config)
|
||||||
mgr.save_config(self._config)
|
mgr.save_config(self._config)
|
||||||
if should_restart:
|
if should_restart:
|
||||||
mgr.restart()
|
mgr.restart()
|
||||||
|
@ -31,9 +31,6 @@ import requests
|
|||||||
from werkzeug import exceptions
|
from werkzeug import exceptions
|
||||||
from werkzeug import wrappers
|
from werkzeug import wrappers
|
||||||
|
|
||||||
from astara_router import defaults
|
|
||||||
from astara_router.drivers import ip
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -48,8 +45,18 @@ class NetworkMetadataProxyHandler(object):
|
|||||||
self.network_id = network_id
|
self.network_id = network_id
|
||||||
self.config_file = config_file
|
self.config_file = config_file
|
||||||
self.config_mtime = 0
|
self.config_mtime = 0
|
||||||
|
self._config_dict = {}
|
||||||
self._ip_instance_map = {}
|
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):
|
def __call__(self, environ, start_response):
|
||||||
request = wrappers.Request(environ)
|
request = wrappers.Request(environ)
|
||||||
|
|
||||||
@ -68,16 +75,16 @@ class NetworkMetadataProxyHandler(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def ip_instance_map(self):
|
def ip_instance_map(self):
|
||||||
config_mtime = os.stat(self.config_file).st_mtime
|
self._ip_instance_map = self.config_dict['networks'][
|
||||||
if config_mtime > self.config_mtime:
|
self.network_id]['ip_instance_map']
|
||||||
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
|
|
||||||
return self._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):
|
def _proxy_request(self, remote_address, path_info, query_string):
|
||||||
headers = {
|
headers = {
|
||||||
'X-Forwarded-For': remote_address,
|
'X-Forwarded-For': remote_address,
|
||||||
@ -88,7 +95,7 @@ class NetworkMetadataProxyHandler(object):
|
|||||||
|
|
||||||
url = urlparse.urlunsplit((
|
url = urlparse.urlunsplit((
|
||||||
'http',
|
'http',
|
||||||
'[%s]:%d' % (ip.get_rug_address(), defaults.RUG_META_PORT),
|
self.orchestrator_loc,
|
||||||
path_info,
|
path_info,
|
||||||
query_string,
|
query_string,
|
||||||
''))
|
''))
|
||||||
@ -172,7 +179,7 @@ def main():
|
|||||||
pool = eventlet.GreenPool(1000)
|
pool = eventlet.GreenPool(1000)
|
||||||
|
|
||||||
tenant_id = config_dict.pop('tenant_id')
|
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,
|
app = NetworkMetadataProxyHandler(tenant_id,
|
||||||
network_id,
|
network_id,
|
||||||
args.config_file)
|
args.config_file)
|
||||||
|
@ -20,6 +20,8 @@ import re
|
|||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
|
from astara_router import defaults
|
||||||
|
|
||||||
GROUP_NAME_LENGTH = 15
|
GROUP_NAME_LENGTH = 15
|
||||||
DEFAULT_AS = 64512
|
DEFAULT_AS = 64512
|
||||||
|
|
||||||
@ -715,6 +717,12 @@ class RouterConfiguration(SystemConfiguration):
|
|||||||
Label(name, cidr) for name, cidr in
|
Label(name, cidr) for name, cidr in
|
||||||
conf_dict.get('labels', {}).iteritems()]
|
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 = [
|
self.floating_ips = [
|
||||||
FloatingIP.from_dict(fip)
|
FloatingIP.from_dict(fip)
|
||||||
for fip in conf_dict.get('floating_ips', [])
|
for fip in conf_dict.get('floating_ips', [])
|
||||||
|
84
test/unit/drivers/test_metadata.py
Normal file
84
test/unit/drivers/test_metadata.py
Normal 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)
|
@ -11,8 +11,14 @@ from astara_router import metadata_proxy
|
|||||||
|
|
||||||
config = json.dumps({
|
config = json.dumps({
|
||||||
"tenant_id": "ABC123",
|
"tenant_id": "ABC123",
|
||||||
"net1": {"listen_port": 9602, 'ip_instance_map': {'10.10.10.2': 'VM1'}},
|
"orchestrator_metadata_address": "192.168.25.30",
|
||||||
"net2": {"listen_port": 9603, 'ip_instance_map': {'10.10.10.2': 'VM2'}},
|
"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):
|
class TestMetadataProxy(unittest.TestCase):
|
||||||
@ -66,7 +72,7 @@ class TestMetadataProxy(unittest.TestCase):
|
|||||||
get.return_value.status_code = 200
|
get.return_value.status_code = 200
|
||||||
wsgi._proxy_request('10.10.10.2', '/', '')
|
wsgi._proxy_request('10.10.10.2', '/', '')
|
||||||
get.assert_called_once_with(
|
get.assert_called_once_with(
|
||||||
'http://[fdca:3ba5:a17a:acda::1]:9697/',
|
'http://[192.168.25.30]:9697/',
|
||||||
headers={
|
headers={
|
||||||
'X-Quantum-Network-ID': 'net1',
|
'X-Quantum-Network-ID': 'net1',
|
||||||
'X-Forwarded-For': '10.10.10.2',
|
'X-Forwarded-For': '10.10.10.2',
|
||||||
|
@ -23,7 +23,7 @@ import netaddr
|
|||||||
|
|
||||||
from unittest2 import TestCase
|
from unittest2 import TestCase
|
||||||
|
|
||||||
from astara_router import models
|
from astara_router import defaults, models
|
||||||
from test.unit import fakes
|
from test.unit import fakes
|
||||||
|
|
||||||
|
|
||||||
@ -439,6 +439,23 @@ class RouterConfigurationTestCase(TestCase):
|
|||||||
self.assertEqual(len(c.anchors[0].rules), 1)
|
self.assertEqual(len(c.anchors[0].rules), 1)
|
||||||
self.assertEqual(c.anchors[0].rules[0].action, 'block')
|
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):
|
def test_asn_default(self):
|
||||||
c = models.RouterConfiguration({'networks': []})
|
c = models.RouterConfiguration({'networks': []})
|
||||||
self.assertEqual(c.asn, 64512)
|
self.assertEqual(c.asn, 64512)
|
||||||
|
Loading…
Reference in New Issue
Block a user