[project-calico,r=james-page] Add support for Calico plugin
This commit is contained in:
commit
f87ad07e29
10
config.yaml
10
config.yaml
@ -99,6 +99,7 @@ options:
|
||||
.
|
||||
ovs - OpenvSwitch Plugin
|
||||
nsx - VMWare NSX
|
||||
Calico - Project Calico Networking
|
||||
.
|
||||
overlay-network-type:
|
||||
default: gre
|
||||
@ -388,3 +389,12 @@ options:
|
||||
description: |
|
||||
If True neutron-server will install neutron packages for the plugin
|
||||
configured.
|
||||
# Calico plugin configuration
|
||||
calico-origin:
|
||||
default:
|
||||
type: string
|
||||
description: |
|
||||
Repository from which to install Calico packages. If set, must be
|
||||
a PPA URL, of the form ppa:somecustom/ppa. Changing this value
|
||||
after installation will force an immediate software upgrade.
|
||||
# End of Calico plugin configuration
|
||||
|
1
hooks/etcd-proxy-relation-broken
Symbolic link
1
hooks/etcd-proxy-relation-broken
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/etcd-proxy-relation-changed
Symbolic link
1
hooks/etcd-proxy-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/etcd-proxy-relation-departed
Symbolic link
1
hooks/etcd-proxy-relation-departed
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/etcd-proxy-relation-joined
Symbolic link
1
hooks/etcd-proxy-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
@ -240,6 +240,28 @@ class HAProxyContext(context.HAProxyContext):
|
||||
return ctxt
|
||||
|
||||
|
||||
class EtcdContext(context.OSContextGenerator):
|
||||
interfaces = ['etcd-proxy']
|
||||
|
||||
def __call__(self):
|
||||
ctxt = {'cluster': ''}
|
||||
cluster_string = ''
|
||||
|
||||
if not config('neutron-plugin') == 'Calico':
|
||||
return ctxt
|
||||
|
||||
for rid in relation_ids('etcd-proxy'):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
cluster_string = rdata.get('cluster')
|
||||
if cluster_string:
|
||||
break
|
||||
|
||||
ctxt['cluster'] = cluster_string
|
||||
|
||||
return ctxt
|
||||
|
||||
|
||||
class NeutronApiSDNContext(context.SubordinateConfigContext):
|
||||
interfaces = 'neutron-plugin-api-subordinate'
|
||||
|
||||
|
@ -60,6 +60,8 @@ from neutron_api_utils import (
|
||||
services,
|
||||
setup_ipv6,
|
||||
get_topics,
|
||||
additional_install_locations,
|
||||
force_etcd_restart,
|
||||
)
|
||||
from neutron_api_context import (
|
||||
get_dvr,
|
||||
@ -67,6 +69,7 @@ from neutron_api_context import (
|
||||
get_l2population,
|
||||
get_overlay_network_type,
|
||||
IdentityServiceContext,
|
||||
EtcdContext,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
@ -143,6 +146,9 @@ def configure_https():
|
||||
def install():
|
||||
execd_preinstall()
|
||||
configure_installation_source(config('openstack-origin'))
|
||||
additional_install_locations(
|
||||
config('neutron-plugin'), config('openstack-origin')
|
||||
)
|
||||
|
||||
apt_update()
|
||||
apt_install(determine_packages(config('openstack-origin')),
|
||||
@ -183,6 +189,10 @@ def config_changed():
|
||||
if openstack_upgrade_available('neutron-common'):
|
||||
do_openstack_upgrade(CONFIGS)
|
||||
|
||||
additional_install_locations(
|
||||
config('neutron-plugin'),
|
||||
config('openstack-origin')
|
||||
)
|
||||
apt_install(filter_installed_packages(
|
||||
determine_packages(config('openstack-origin'))),
|
||||
fatal=True)
|
||||
@ -352,6 +362,7 @@ def neutron_plugin_api_relation_joined(rid=None):
|
||||
'enable-dvr': get_dvr(),
|
||||
'enable-l3ha': get_l3ha(),
|
||||
'overlay-network-type': get_overlay_network_type(),
|
||||
'addr': unit_get('private-address'),
|
||||
}
|
||||
|
||||
# Provide this value to relations since it needs to be set in multiple
|
||||
@ -500,6 +511,20 @@ def update_nrpe_config():
|
||||
nrpe_setup.write()
|
||||
|
||||
|
||||
@hooks.hook('etcd-proxy-relation-joined')
|
||||
@hooks.hook('etcd-proxy-relation-changed')
|
||||
def etcd_proxy_force_restart(relation_id=None):
|
||||
# note(cory.benfield): Mostly etcd does not require active management,
|
||||
# but occasionally it does require a full config nuking. This does not
|
||||
# play well with the standard neutron-api config management, so we
|
||||
# treat etcd like the special snowflake it insists on being.
|
||||
CONFIGS.register('/etc/init/etcd.conf', [EtcdContext()])
|
||||
CONFIGS.write('/etc/init/etcd.conf')
|
||||
|
||||
if 'etcd-proxy' in CONFIGS.complete_contexts():
|
||||
force_etcd_restart()
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
hooks.execute(sys.argv)
|
||||
|
@ -4,6 +4,7 @@ from functools import partial
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import glob
|
||||
from base64 import b64encode
|
||||
from charmhelpers.contrib.openstack import context, templating
|
||||
from charmhelpers.contrib.openstack.neutron import (
|
||||
@ -38,11 +39,13 @@ from charmhelpers.fetch import (
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release,
|
||||
adduser,
|
||||
add_group,
|
||||
add_user_to_group,
|
||||
mkdir,
|
||||
lsb_release,
|
||||
service_stop,
|
||||
service_start,
|
||||
service_restart,
|
||||
write_file,
|
||||
)
|
||||
@ -160,6 +163,37 @@ def api_port(service):
|
||||
return API_PORTS[service]
|
||||
|
||||
|
||||
def additional_install_locations(plugin, source):
|
||||
'''
|
||||
Add any required additional package locations for the charm, based
|
||||
on the Neutron plugin being used. This will also force an immediate
|
||||
package upgrade.
|
||||
'''
|
||||
if plugin == 'Calico':
|
||||
if config('calico-origin'):
|
||||
calico_source = config('calico-origin')
|
||||
else:
|
||||
release = get_os_codename_install_source(source)
|
||||
calico_source = 'ppa:project-calico/%s' % release
|
||||
|
||||
add_source(calico_source)
|
||||
|
||||
apt_update()
|
||||
apt_upgrade()
|
||||
|
||||
|
||||
def force_etcd_restart():
|
||||
'''
|
||||
If etcd has been reconfigured we need to force it to fully restart.
|
||||
This is necessary because etcd has some config flags that it ignores
|
||||
after the first time it starts, so we need to make it forget them.
|
||||
'''
|
||||
service_stop('etcd')
|
||||
for directory in glob.glob('/var/lib/etcd/*'):
|
||||
shutil.rmtree(directory)
|
||||
service_start('etcd')
|
||||
|
||||
|
||||
def manage_plugin():
|
||||
return config('manage-neutron-plugin-legacy-mode')
|
||||
|
||||
|
@ -40,6 +40,8 @@ requires:
|
||||
neutron-plugin-api-subordinate:
|
||||
interface: neutron-plugin-api-subordinate
|
||||
scope: container
|
||||
etcd-proxy:
|
||||
interface: etcd-proxy
|
||||
peers:
|
||||
cluster:
|
||||
interface: neutron-api-ha
|
||||
|
16
templates/icehouse/etcd.conf
Normal file
16
templates/icehouse/etcd.conf
Normal file
@ -0,0 +1,16 @@
|
||||
# managed by juju, DO NOT EDIT
|
||||
description "etcd"
|
||||
author "etcd maintainers"
|
||||
|
||||
start on stopped rc RUNLEVEL=[2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
setuid etcd
|
||||
|
||||
env ETCD_DATA_DIR=/var/lib/etcd
|
||||
export ETCD_DATA_DIR
|
||||
|
||||
exec /usr/bin/etcd -proxy on \
|
||||
-initial-cluster {{ cluster }}
|
@ -4,6 +4,10 @@
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[ml2]
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
type_drivers = local,flat
|
||||
mechanism_drivers = calico
|
||||
{% else -%}
|
||||
type_drivers = {{ overlay_network_type }},vlan,flat
|
||||
tenant_network_types = {{ overlay_network_type }},vlan,flat
|
||||
mechanism_drivers = openvswitch,hyperv,l2population
|
||||
@ -26,11 +30,16 @@ local_ip = {{ local_ip }}
|
||||
|
||||
[agent]
|
||||
tunnel_types = {{ overlay_network_type }}
|
||||
{% endif -%}
|
||||
|
||||
[securitygroup]
|
||||
{% if neutron_security_groups -%}
|
||||
enable_security_group = True
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
|
||||
{% else -%}
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
enable_security_group = False
|
||||
{% endif -%}
|
||||
|
@ -30,7 +30,7 @@ core_plugin = {{ core_plugin }}
|
||||
{% if service_plugins -%}
|
||||
service_plugins = {{ service_plugins }}
|
||||
{% else -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2', 'Calico'] -%}
|
||||
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
@ -38,8 +38,16 @@ service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neu
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
|
||||
{% else -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
dhcp_agents_per_network = 1000
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
|
@ -31,15 +31,23 @@ bind_port = 9696
|
||||
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2', 'Calico'] -%}
|
||||
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
|
||||
{% else -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
dhcp_agents_per_network = 1000
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
|
@ -4,6 +4,10 @@
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[ml2]
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
type_drivers = local,flat
|
||||
mechanism_drivers = calico
|
||||
{% else -%}
|
||||
type_drivers = {{ overlay_network_type }},vlan,flat
|
||||
tenant_network_types = {{ overlay_network_type }},vlan,flat
|
||||
mechanism_drivers = openvswitch,l2population
|
||||
@ -26,11 +30,16 @@ local_ip = {{ local_ip }}
|
||||
|
||||
[agent]
|
||||
tunnel_types = {{ overlay_network_type }}
|
||||
{% endif -%}
|
||||
|
||||
[securitygroup]
|
||||
{% if neutron_security_groups -%}
|
||||
enable_security_group = True
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
|
||||
{% else -%}
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
enable_security_group = False
|
||||
{% endif -%}
|
||||
|
@ -34,7 +34,7 @@ core_plugin = {{ core_plugin }}
|
||||
{% if service_plugins -%}
|
||||
service_plugins = {{ service_plugins }}
|
||||
{% else -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
{% if neutron_plugin in ['ovs', 'ml2', 'Calico'] -%}
|
||||
service_plugins = router,firewall,lbaas,vpnaas,metering
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
@ -42,8 +42,16 @@ service_plugins = router,firewall,lbaas,vpnaas,metering
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
|
||||
{% else -%}
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin == 'Calico' -%}
|
||||
dhcp_agents_per_network = 1000
|
||||
{% endif -%}
|
||||
|
||||
notify_nova_on_port_status_changes = True
|
||||
notify_nova_on_port_data_changes = True
|
||||
|
@ -438,6 +438,53 @@ class NeutronCCContextTest(CharmTestCase):
|
||||
self.assertEquals(napi_ctxt[key], expect[key])
|
||||
|
||||
|
||||
class EtcdContextTest(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(EtcdContextTest, self).setUp(context, TO_PATCH)
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.test_config.set('neutron-plugin', 'Calico')
|
||||
|
||||
def tearDown(self):
|
||||
super(EtcdContextTest, self).tearDown()
|
||||
|
||||
def test_etcd_no_related_units(self):
|
||||
self.related_units.return_value = []
|
||||
ctxt = context.EtcdContext()()
|
||||
expect = {'cluster': ''}
|
||||
|
||||
self.assertEquals(expect, ctxt)
|
||||
|
||||
def test_some_related_units(self):
|
||||
self.related_units.return_value = ['unit1']
|
||||
self.relation_ids.return_value = ['rid2', 'rid3']
|
||||
result = (
|
||||
'testname=http://172.18.18.18:8888,'
|
||||
'testname=http://172.18.18.18:8888'
|
||||
)
|
||||
self.test_relation.set({'cluster': result})
|
||||
|
||||
ctxt = context.EtcdContext()()
|
||||
expect = {'cluster': result}
|
||||
|
||||
self.assertEquals(expect, ctxt)
|
||||
|
||||
def test_early_exit(self):
|
||||
self.test_config.set('neutron-plugin', 'notCalico')
|
||||
|
||||
self.related_units.return_value = ['unit1']
|
||||
self.relation_ids.return_value = ['rid2', 'rid3']
|
||||
self.test_relation.set({'ip': '172.18.18.18',
|
||||
'port': 8888,
|
||||
'name': 'testname'})
|
||||
|
||||
ctxt = context.EtcdContext()()
|
||||
expect = {'cluster': ''}
|
||||
|
||||
self.assertEquals(expect, ctxt)
|
||||
|
||||
|
||||
class NeutronApiSDNContextTest(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -62,6 +62,7 @@ TO_PATCH = [
|
||||
'update_nrpe_config',
|
||||
'service_reload',
|
||||
'IdentityServiceContext',
|
||||
'force_etcd_restart',
|
||||
]
|
||||
NEUTRON_CONF_DIR = "/etc/neutron"
|
||||
|
||||
@ -440,12 +441,14 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_nol2(self):
|
||||
self.unit_get.return_value = '172.18.18.18'
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': False,
|
||||
'enable-l3ha': False,
|
||||
'addr': '172.18.18.18',
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
@ -470,12 +473,14 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_dvr(self):
|
||||
self.unit_get.return_value = '172.18.18.18'
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': True,
|
||||
'enable-l3ha': False,
|
||||
'addr': '172.18.18.18',
|
||||
'l2-population': True,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
@ -500,12 +505,14 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_l3ha(self):
|
||||
self.unit_get.return_value = '172.18.18.18'
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': False,
|
||||
'enable-l3ha': True,
|
||||
'addr': '172.18.18.18',
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
@ -530,11 +537,13 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_w_mtu(self):
|
||||
self.unit_get.return_value = '172.18.18.18'
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
self.test_config.set('network-device-mtu', 1500)
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'addr': '172.18.18.18',
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'network-device-mtu': 1500,
|
||||
@ -750,3 +759,8 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
'Not running neutron database migration as migrations are handled '
|
||||
'by the neutron-server process or nova-cloud-controller charm.'
|
||||
)
|
||||
|
||||
def test_etcd_peer_joined(self):
|
||||
self._call_hook('etcd-proxy-relation-joined')
|
||||
self.assertTrue(self.CONFIGS.register.called)
|
||||
self.CONFIGS.write.assert_called_with('/etc/init/etcd.conf')
|
||||
|
@ -24,6 +24,7 @@ TO_PATCH = [
|
||||
'apt_install',
|
||||
'apt_update',
|
||||
'apt_upgrade',
|
||||
'add_source',
|
||||
'b64encode',
|
||||
'config',
|
||||
'configure_installation_source',
|
||||
@ -34,6 +35,9 @@ TO_PATCH = [
|
||||
'pip_install',
|
||||
'subprocess',
|
||||
'is_elected_leader',
|
||||
'service_stop',
|
||||
'service_start',
|
||||
'glob',
|
||||
]
|
||||
|
||||
openstack_origin_git = \
|
||||
@ -559,3 +563,30 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
self.test_config.set('manage-neutron-plugin-legacy-mode', False)
|
||||
manage = nutils.manage_plugin()
|
||||
self.assertFalse(manage)
|
||||
|
||||
def test_additional_install_locations_calico(self):
|
||||
self.get_os_codename_install_source.return_value = 'icehouse'
|
||||
nutils.additional_install_locations('Calico', '')
|
||||
self.add_source.assert_called_with('ppa:project-calico/icehouse')
|
||||
|
||||
def test_unusual_calico_install_location(self):
|
||||
self.test_config.set('calico-origin', 'ppa:testppa/project-calico')
|
||||
nutils.additional_install_locations('Calico', '')
|
||||
self.add_source.assert_called_with('ppa:testppa/project-calico')
|
||||
|
||||
def test_follows_openstack_origin(self):
|
||||
self.get_os_codename_install_source.return_value = 'juno'
|
||||
nutils.additional_install_locations('Calico', 'cloud:trusty-juno')
|
||||
self.add_source.assert_called_with('ppa:project-calico/juno')
|
||||
|
||||
@patch('shutil.rmtree')
|
||||
def test_force_etcd_restart(self, rmtree):
|
||||
self.glob.glob.return_value = [
|
||||
'/var/lib/etcd/one', '/var/lib/etcd/two'
|
||||
]
|
||||
nutils.force_etcd_restart()
|
||||
self.service_stop.assert_called_once_with('etcd')
|
||||
self.glob.glob.assert_called_once_with('/var/lib/etcd/*')
|
||||
rmtree.assert_any_call('/var/lib/etcd/one')
|
||||
rmtree.assert_any_call('/var/lib/etcd/two')
|
||||
self.service_start.assert_called_once_with('etcd')
|
||||
|
Loading…
Reference in New Issue
Block a user