[gnuoy,r=james-page] Add support for Neutron DVR and Router HA

This commit is contained in:
James Page 2015-03-31 08:58:21 +01:00
commit c85c3170bc
8 changed files with 165 additions and 22 deletions

View File

@ -99,6 +99,7 @@ def core_plugin():
class L3AgentContext(OSContextGenerator):
def __call__(self):
api_settings = NeutronAPIContext()()
ctxt = {}
if config('run-internal-router') == 'leader':
ctxt['handle_internal_only_router'] = eligible_leader(None)
@ -111,16 +112,19 @@ class L3AgentContext(OSContextGenerator):
if config('external-network-id'):
ctxt['ext_net_id'] = config('external-network-id')
if config('plugin'):
ctxt['plugin'] = config('plugin')
if api_settings['enable_dvr']:
ctxt['agent_mode'] = 'dvr_snat'
else:
ctxt['agent_mode'] = 'legacy'
return ctxt
class QuantumGatewayContext(OSContextGenerator):
def __call__(self):
neutron_api_settings = NeutronAPIContext()()
api_settings = NeutronAPIContext()()
ctxt = {
'shared_secret': get_shared_secret(),
'local_ip':
@ -131,9 +135,11 @@ class QuantumGatewayContext(OSContextGenerator):
'debug': config('debug'),
'verbose': config('verbose'),
'instance_mtu': config('instance-mtu'),
'l2_population': neutron_api_settings['l2_population'],
'l2_population': api_settings['l2_population'],
'enable_dvr': api_settings['enable_dvr'],
'enable_l3ha': api_settings['enable_l3ha'],
'overlay_network_type':
neutron_api_settings['overlay_network_type'],
api_settings['overlay_network_type'],
}
mappings = config('bridge-mappings')
@ -147,7 +153,7 @@ class QuantumGatewayContext(OSContextGenerator):
ctxt['network_providers'] = ' '.join(providers)
ctxt['vlan_ranges'] = vlan_ranges
net_dev_mtu = neutron_api_settings.get('network_device_mtu')
net_dev_mtu = api_settings['network_device_mtu']
if net_dev_mtu:
ctxt['network_device_mtu'] = net_dev_mtu
ctxt['veth_mtu'] = net_dev_mtu

View File

@ -40,6 +40,7 @@ from charmhelpers.contrib.charmsupport import nrpe
import sys
from quantum_utils import (
L3HA_PACKAGES,
register_configs,
restart_map,
services,
@ -56,7 +57,8 @@ from quantum_utils import (
install_legacy_ha_files,
cleanup_ovs_netns,
reassign_agent_resources,
stop_neutron_ha_monitor_daemon
stop_neutron_ha_monitor_daemon,
use_l3ha,
)
hooks = Hooks()
@ -193,13 +195,23 @@ def amqp_departed():
'pgsql-db-relation-changed',
'amqp-relation-changed',
'cluster-relation-changed',
'cluster-relation-joined',
'neutron-plugin-api-relation-changed')
'cluster-relation-joined')
@restart_on_change(restart_map())
def db_amqp_changed():
CONFIGS.write_all()
@hooks.hook('neutron-plugin-api-relation-changed')
@restart_on_change(restart_map())
def neutron_plugin_api_changed():
if use_l3ha():
apt_update()
apt_install(L3HA_PACKAGES, fatal=True)
else:
apt_purge(L3HA_PACKAGES, fatal=True)
CONFIGS.write_all()
@hooks.hook('quantum-network-service-relation-changed')
@restart_on_change(restart_map())
def nm_changed():

View File

@ -42,6 +42,7 @@ from charmhelpers.contrib.openstack.neutron import (
import charmhelpers.contrib.openstack.context as context
from charmhelpers.contrib.openstack.context import (
SyslogContext,
NeutronAPIContext,
NetworkServiceContext,
ExternalPortContext,
PhyNICMTUContext,
@ -55,7 +56,7 @@ from quantum_contexts import (
networking_name,
QuantumGatewayContext,
L3AgentContext,
remap_plugin
remap_plugin,
)
from charmhelpers.contrib.openstack.neutron import (
parse_bridge_mappings,
@ -171,6 +172,7 @@ LEGACY_FILES_MAP = {
},
}
LEGACY_RES_MAP = ['res_monitor']
L3HA_PACKAGES = ['keepalived']
def get_early_packages():
@ -201,15 +203,26 @@ def get_packages():
packages.append('openswan')
if source >= 'kilo':
packages.append('python-neutron-fwaas')
packages.extend(determine_l3ha_packages())
return packages
def determine_l3ha_packages():
if use_l3ha():
return L3HA_PACKAGES
return []
def get_common_package():
if get_os_codename_package('quantum-common', fatal=False) is not None:
return 'quantum-common'
else:
return 'neutron-common'
def use_l3ha():
return NeutronAPIContext()()['enable_l3ha']
EXT_PORT_CONF = '/etc/init/ext-port.conf'
PHY_NIC_MTU_CONF = '/etc/init/os-charm-phy-nic-mtu.conf'
TEMPLATES = 'templates'
@ -322,7 +335,7 @@ NEUTRON_OVS_CONFIG_FILES = {
'hook_contexts': [NetworkServiceContext(),
L3AgentContext(),
QuantumGatewayContext()],
'services': ['neutron-l3-agent']
'services': ['neutron-l3-agent', 'neutron-vpn-agent']
},
NEUTRON_METERING_AGENT_CONF: {
'hook_contexts': [QuantumGatewayContext()],
@ -340,7 +353,7 @@ NEUTRON_OVS_CONFIG_FILES = {
},
NEUTRON_FWAAS_CONF: {
'hook_contexts': [QuantumGatewayContext()],
'services': ['neutron-l3-agent']
'services': ['neutron-l3-agent', 'neutron-vpn-agent']
},
NEUTRON_OVS_PLUGIN_CONF: {
'hook_contexts': [QuantumGatewayContext()],

View File

@ -0,0 +1,25 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
[DEFAULT]
interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
auth_url = {{ service_protocol }}://{{ keystone_host }}:{{ service_port }}/v2.0
auth_region = {{ region }}
admin_tenant_name = {{ service_tenant }}
admin_user = {{ service_username }}
admin_password = {{ service_password }}
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
handle_internal_only_routers = {{ handle_internal_only_router }}
{% if plugin == 'n1kv' %}
l3_agent_manager = neutron.agent.l3_agent.L3NATAgentWithStateReport
external_network_bridge = br-int
ovs_use_veth = False
use_namespaces = True
{% else %}
ovs_use_veth = True
{% endif %}
{% if ext_net_id -%}
gateway_external_network_id = {{ ext_net_id }}
{% endif -%}
agent_mode = {{ agent_mode }}

View File

@ -0,0 +1,36 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
[ml2]
type_drivers = gre,vxlan,vlan,flat
tenant_network_types = gre,vxlan,vlan,flat
mechanism_drivers = openvswitch,l2population
[ml2_type_gre]
tunnel_id_ranges = 1:1000
[ml2_type_vxlan]
vni_ranges = 1001:2000
[ml2_type_vlan]
network_vlan_ranges = {{ vlan_ranges }}
[ml2_type_flat]
flat_networks = {{ network_providers }}
[ovs]
enable_tunneling = True
local_ip = {{ local_ip }}
bridge_mappings = {{ bridge_mappings }}
[agent]
tunnel_types = {{ overlay_network_type }}
l2_population = {{ l2_population }}
enable_distributed_routing = {{ enable_dvr }}
{% if veth_mtu -%}
veth_mtu = {{ veth_mtu }}
{% endif %}
[securitygroup]
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver

View File

@ -38,6 +38,15 @@ def patch_open():
yield mock_open, mock_file
class DummyNeutronAPIContext():
def __init__(self, return_value):
self.return_value = return_value
def __call__(self):
return self.return_value
class TestL3AgentContext(CharmTestCase):
def setUp(self):
@ -45,32 +54,51 @@ class TestL3AgentContext(CharmTestCase):
TO_PATCH)
self.config.side_effect = self.test_config.get
def test_no_ext_netid(self):
@patch('quantum_contexts.NeutronAPIContext')
def test_no_ext_netid(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': False})
self.test_config.set('run-internal-router', 'none')
self.test_config.set('external-network-id', '')
self.eligible_leader.return_value = False
self.assertEquals(quantum_contexts.L3AgentContext()(),
{'handle_internal_only_router': False,
{'agent_mode': 'legacy',
'handle_internal_only_router': False,
'plugin': 'ovs'})
def test_hior_leader(self):
@patch('quantum_contexts.NeutronAPIContext')
def test_hior_leader(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': False})
self.test_config.set('run-internal-router', 'leader')
self.test_config.set('external-network-id', 'netid')
self.eligible_leader.return_value = True
self.assertEquals(quantum_contexts.L3AgentContext()(),
{'handle_internal_only_router': True,
{'agent_mode': 'legacy',
'handle_internal_only_router': True,
'ext_net_id': 'netid',
'plugin': 'ovs'})
def test_hior_all(self):
@patch('quantum_contexts.NeutronAPIContext')
def test_hior_all(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': False})
self.test_config.set('run-internal-router', 'all')
self.test_config.set('external-network-id', 'netid')
self.eligible_leader.return_value = True
self.assertEquals(quantum_contexts.L3AgentContext()(),
{'handle_internal_only_router': True,
{'agent_mode': 'legacy',
'handle_internal_only_router': True,
'ext_net_id': 'netid',
'plugin': 'ovs'})
@patch('quantum_contexts.NeutronAPIContext')
def test_dvr(self, _NeutronAPIContext):
_NeutronAPIContext.return_value = \
DummyNeutronAPIContext(return_value={'enable_dvr': True})
self.assertEquals(quantum_contexts.L3AgentContext()()['agent_mode'],
'dvr_snat')
class TestQuantumGatewayContext(CharmTestCase):
@ -78,6 +106,7 @@ class TestQuantumGatewayContext(CharmTestCase):
super(TestQuantumGatewayContext, self).setUp(quantum_contexts,
TO_PATCH)
self.config.side_effect = self.test_config.get
self.maxDiff = None
@patch('charmhelpers.contrib.openstack.context.relation_get')
@patch('charmhelpers.contrib.openstack.context.related_units')
@ -85,6 +114,11 @@ class TestQuantumGatewayContext(CharmTestCase):
@patch.object(quantum_contexts, 'get_shared_secret')
@patch.object(quantum_contexts, 'get_host_ip')
def test_all(self, _host_ip, _secret, _rids, _runits, _rget):
rdata = {'l2-population': 'True',
'enable-dvr': 'True',
'overlay-network-type': 'gre',
'enable-l3ha': 'True',
'network-device-mtu': 9000}
self.test_config.set('plugin', 'ovs')
self.test_config.set('debug', False)
self.test_config.set('verbose', True)
@ -94,7 +128,6 @@ class TestQuantumGatewayContext(CharmTestCase):
# Provided by neutron-api relation
_rids.return_value = ['neutron-plugin-api:0']
_runits.return_value = ['neutron-api/0']
rdata = {'network-device-mtu': 9000, 'l2-population': 'False'}
_rget.side_effect = lambda *args, **kwargs: rdata
self.get_os_codename_install_source.return_value = 'folsom'
_host_ip.return_value = '10.5.0.1'
@ -102,6 +135,8 @@ class TestQuantumGatewayContext(CharmTestCase):
ctxt = quantum_contexts.QuantumGatewayContext()()
self.assertEquals(ctxt, {
'shared_secret': 'testsecret',
'enable_dvr': True,
'enable_l3ha': True,
'local_ip': '10.5.0.1',
'instance_mtu': 1420,
'core_plugin': "quantum.plugins.openvswitch.ovs_quantum_plugin."
@ -109,7 +144,7 @@ class TestQuantumGatewayContext(CharmTestCase):
'plugin': 'ovs',
'debug': False,
'verbose': True,
'l2_population': False,
'l2_population': True,
'overlay_network_type': 'gre',
'bridge_mappings': 'physnet1:br-data',
'network_providers': 'physnet1 physnet2',

View File

@ -48,6 +48,7 @@ TO_PATCH = [
'remove_legacy_ha_files',
'cleanup_ovs_netns',
'stop_neutron_ha_monitor_daemon',
'use_l3ha',
]
@ -246,6 +247,12 @@ class TestQuantumHooks(CharmTestCase):
self.assertTrue(self.CONFIGS.write_all.called)
self.install_ca_cert.assert_called_with('cert')
def test_neutron_plugin_changed(self):
self.use_l3ha.return_value = True
self._call_hook('neutron-plugin-api-relation-changed')
self.apt_install.assert_called_with(['keepalived'], fatal=True)
self.assertTrue(self.CONFIGS.write_all.called)
def test_cluster_departed_nvp(self):
self.test_config.set('plugin', 'nvp')
self._call_hook('cluster-relation-departed')

View File

@ -45,7 +45,8 @@ TO_PATCH = [
'is_relation_made',
'lsb_release',
'mkdir',
'copy2'
'copy2',
'NeutronAPIContext',
]
@ -138,6 +139,11 @@ class TestQuantumUtils(CharmTestCase):
self.get_os_codename_install_source.return_value = 'kilo'
self.assertTrue('python-neutron-fwaas' in quantum_utils.get_packages())
def test_get_packages_l3ha(self):
self.config.return_value = 'ovs'
self.get_os_codename_install_source.return_value = 'juno'
self.assertTrue('keepalived' in quantum_utils.get_packages())
@patch('charmhelpers.contrib.openstack.context.config')
def test_configure_ovs_starts_service_if_required(self, mock_config):
mock_config.side_effect = self.test_config.get
@ -256,6 +262,7 @@ class TestQuantumUtils(CharmTestCase):
def test_restart_map_ovs(self):
self.config.return_value = 'ovs'
self.get_os_codename_install_source.return_value = 'havana'
ex_map = {
quantum_utils.NEUTRON_CONF: ['neutron-l3-agent',
'neutron-dhcp-agent',
@ -276,9 +283,11 @@ class TestQuantumUtils(CharmTestCase):
quantum_utils.NEUTRON_VPNAAS_AGENT_CONF: [
'neutron-plugin-vpn-agent',
'neutron-vpn-agent'],
quantum_utils.NEUTRON_L3_AGENT_CONF: ['neutron-l3-agent'],
quantum_utils.NEUTRON_L3_AGENT_CONF: ['neutron-l3-agent',
'neutron-vpn-agent'],
quantum_utils.NEUTRON_DHCP_AGENT_CONF: ['neutron-dhcp-agent'],
quantum_utils.NEUTRON_FWAAS_CONF: ['neutron-l3-agent'],
quantum_utils.NEUTRON_FWAAS_CONF: ['neutron-l3-agent',
'neutron-vpn-agent'],
quantum_utils.NEUTRON_METERING_AGENT_CONF:
['neutron-metering-agent', 'neutron-plugin-metering-agent'],
quantum_utils.NOVA_CONF: ['nova-api-metadata'],