From cdb8db5e5e9f7547436621dd3dd0f2a9f44fd6d4 Mon Sep 17 00:00:00 2001 From: Antoni Segura Puimedon Date: Fri, 22 Jan 2016 16:14:59 +0100 Subject: [PATCH] MidoNet support up until Liberty --- config.yaml | 23 +++++++++++++ files/midokura.key | 19 +++++++++++ files/midonet.key | 24 +++++++++++++ .../charmhelpers/contrib/openstack/neutron.py | 7 ++++ hooks/midonet-relation-broken | 1 + hooks/midonet-relation-changed | 1 + hooks/midonet-relation-joined | 1 + hooks/neutron_api_context.py | 24 +++++++++++++ hooks/neutron_api_hooks.py | 25 ++++++++++---- hooks/neutron_api_utils.py | 32 ++++++++++++++++- metadata.yaml | 2 ++ templates/juno/midonet.ini | 11 ++++++ templates/juno/neutron.conf | 2 ++ templates/kilo/neutron.conf | 6 +++- templates/liberty/neutron.conf | 4 ++- templates/liberty/neutron_lbaas.conf | 6 +++- unit_tests/test_neutron_api_context.py | 34 +++++++++++++++++++ 17 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 files/midokura.key create mode 100644 files/midonet.key create mode 120000 hooks/midonet-relation-broken create mode 120000 hooks/midonet-relation-changed create mode 120000 hooks/midonet-relation-joined create mode 100644 templates/juno/midonet.ini diff --git a/config.yaml b/config.yaml index d2f0b4b0..5c19d516 100755 --- a/config.yaml +++ b/config.yaml @@ -101,6 +101,7 @@ options: vsp - Nuage Networks VSP nsx - VMWare NSX Calico - Project Calico Networking + midonet - MidoNet . overlay-network-type: default: gre @@ -487,3 +488,25 @@ options: description: | Connect timeout configuration in ms for haproxy, used in HA configurations. If not provided, default value of 5000ms is used. + midonet-origin: + default: midonet-2015.06 + type: string + description: | + 'mem-1.8', 'mem-1.9', + 'midonet-2015.06' + + NOTE: updating this setting to a source that is known to provide a later + version of MidoNet (do not change between MEM and MidoNet) will + trigger a software upgrade. + mem-username: + type: string + default: + description: | + The Midokura Enterprise MidoNet username credentials to access the + repository. + mem-password: + type: string + default: + description: | + The Midokura Enterprise MidoNet password credentials to access the + repository. diff --git a/files/midokura.key b/files/midokura.key new file mode 100644 index 00000000..fc8c7e3b --- /dev/null +++ b/files/midokura.key @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.5 +Comment: Hostname: keyserver.ubuntu.com + +mI0ETb6aOgEEAMVw8Vnwk+zpDtsc0gSW10JEe48zKr2vpl9tQgWAFOPgOA1NglYMw/xT6Rns +7CrYxPR0cb3DeMFtFdMkfWXO0R6x4yHrozMDY/DpvwgYQclIIbcYYe0p83nlBp793D2dSq60 +HWuXJu3oi0wQQuR0/jTmOnjxzCzu5jKdJeXihl95ABEBAAG0Jk1pZG9rdXJhIChNaWRva3Vy +YSkgPGluZm9AbWlkb2t1cmEuanA+iLgEEwECACIFAk2+mjoCGwMGCwkIBwMCBhUIAgkKCwQW +AgMBAh4BAheAAAoJEGezjToFQxTNAp0D/2c+PLnRFzEXCztXT+05xoO1mPzpm3x2p5ecVPGH +R8IxhozlN9DDGDdnvNfMOhi6nv/G2l86+9Fj8Dz01ne0RZzZHSS1DF/zb6dMYrPJqiT1DXKH +0Y73OL/+M7rsutEq0B/DKhjdBfFPutk3gerEUZPNfIhScE3tnwCnVGJKPQbFuI0ETb6aOgEE +ANLJK3gmXrsp1VKnt663RoxZgoFQgQ6wHaZZWhULTteafjoThX9tj7FidR2+7qJLwpa57M9d +rib4OlbW+rE4PW199/Uqfy86gLv76Q2GZMpzaYB1ZZow0Ny1RTCwh7apkhR/8fCUpq37aODQ +4YwBpZC54iXVKfcntpdJFoObIqXtABEBAAGInwQYAQIACQUCTb6aOgIbDAAKCRBns406BUMU +zfzOBACKx4jChKTAl6HfldOxVN7o8DQpd5rgkHIEj062ym4Zq5t2v3oaz0H0P2WV66MAhOuj +gX0V1duZi8fKHdIsdk0nvEa/mV0QS6pEAeZh+dbLkKyu1J4MSi5l+L+te5XjYBGpoRa3ZGrI +R3CkA0oQDCOh312SrcH6Tn9RBPChVSigzg== +=zF5K +-----END PGP PUBLIC KEY BLOCK----- diff --git a/files/midonet.key b/files/midonet.key new file mode 100644 index 00000000..2d57fa4e --- /dev/null +++ b/files/midonet.key @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.5 +Comment: Hostname: keyserver.ubuntu.com + +mQGiBFRF760RBADwIz8rK0K1qiXbq0/cda42oKZW+jvcqUIDsNeKYSWI5YRfS4NX+jRJM/rL +PzQD+JZtLeFHeLK0qxpr5b2acxleOgNfw3hzxz4DNQsVbkts3n1s7YT80DwNdYPBbFCAOOkJ +jH7CL2PN4fTs5eP/0QpMOZT+s5DTqozPDgTYWhhVrwCgoc5H2zYVW86Ok3c0fOru9VZPJxsE +AIexw3sBv9FZyvVr6rehiVlzOtwfHwSEQZQ511so46H5GdLqQFwThKmWVvxyDAGshtpjLJbs +KHilEJVkfzhs/xyCjwAPl8VbIYgUy/FlhKtFWWxkQLlUwuC5iOPLdzhoL1PEzZuCYmMkSr0E +XASN83nbzIIqdQgvEZrAUGUzTf68A/9eSiry88vEIIGL7hT2rw/NockwCGsc2xrjqrfs9PpU +rg7ksTPua1UQUkMeWoKEoYpGppGd5XXEvo6287i8eAB4B9qr4AGbz8NKmVI2lC9V641Ecu3/ +kmhaGQRBmCZgcW3B987rTyY5lsLc66+tNai6L72y1fj5nBtY2MVYg6ixZrRNTWlkb2t1cmEg +UlBNICYgREVCIFJlcG9zaXRvcnkgQXV0b21hdGljIFNpZ25pbmcgS2V5ICgyMDE0KSA8b3Bz +QG1pZG9rdXJhLmNvbT6IYgQTEQIAIgUCVEXvrQIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ/ONA0lDxj8+EZgCdEqXQrZ8PiemTgQK7044Deed5OpsAnjL8Cw4GnGJZHmW24pKQ +IkzTvb1SuQENBFRF760QBADJD9aLzLYAehNITLlrNao+bZsSAAeKRYWjtyf6Z620/WiQw6a+ +01/ZwrthvXNUcnIVIKKokPVpXR29AUV0T7npDMTkQCXfw24X+9NedBCquJpHnBS/YySHP+EJ +vNeLc0xdwnOcGehe7IeaDN0eEWx+HVhEfC/lXa/Pebs4OpIo/wADBwQAwyCTQ7Vod3jO7JFP +6R6mS5gX3Sx6s3ocE4laDFBmh9d8GPWpdzHwzPzrVaIw/xSaxP2zXeWFcDoY3zT7PH3dm+xj +cEG23iTqvmMAr7EXirKu9pL/DKuBPncNMTS6JoltGGVzZLoJF2OJZX81c+U1mGyLpWg/hK3K +t9VpzNjFGc2ISQQYEQIACQUCVEXvrQIbDAAKCRD840DSUPGPz0PiAJ9QXGyMCTymuuCdYyEX +3D94y0Z8FgCaAwYNRahgGw/HN04xkqfrN7bXajE= +=hLRg +-----END PGP PUBLIC KEY BLOCK----- diff --git a/hooks/charmhelpers/contrib/openstack/neutron.py b/hooks/charmhelpers/contrib/openstack/neutron.py index d17c847e..8d78f352 100644 --- a/hooks/charmhelpers/contrib/openstack/neutron.py +++ b/hooks/charmhelpers/contrib/openstack/neutron.py @@ -233,6 +233,13 @@ def neutron_plugins(): 'neutron-plugin-ml2'] # NOTE: patch in vmware renames nvp->nsx for icehouse onwards plugins['nvp'] = plugins['nsx'] + if release >= 'kilo': + plugins['midonet']['driver'] = ( + 'neutron.plugins.midonet.plugin.MidonetPluginV2') + if release >= 'liberty': + if config('midonet-origin')[4:5] == '1': + plugins['midonet']['driver'] = ( + 'midonet.neutron.plugin_v1.MidonetPluginV2') return plugins diff --git a/hooks/midonet-relation-broken b/hooks/midonet-relation-broken new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/midonet-relation-broken @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/midonet-relation-changed b/hooks/midonet-relation-changed new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/midonet-relation-changed @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/midonet-relation-joined b/hooks/midonet-relation-joined new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/midonet-relation-joined @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 5af5aa26..d33da637 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -166,6 +166,12 @@ class NeutronCCContext(context.NeutronContext): ctxt['pg_username'] = config('plumgrid-username') ctxt['pg_password'] = config('plumgrid-password') ctxt['virtual_ip'] = config('plumgrid-virtual-ip') + elif config('neutron-plugin') == 'midonet': + ctxt.update(MidonetContext()()) + identity_context = IdentityServiceContext(service='neutron', + service_user='neutron')() + if identity_context is not None: + ctxt.update(identity_context) ctxt['l2_population'] = self.neutron_l2_population ctxt['enable_dvr'] = self.neutron_dvr ctxt['l3_ha'] = self.neutron_l3ha @@ -342,3 +348,21 @@ class NeutronApiSDNConfigFileContext(context.OSContextGenerator): if neutron_server_plugin_conf: return {'config': neutron_server_plugin_conf} return {'config': '/etc/neutron/plugins/ml2/ml2_conf.ini'} + + +class MidonetContext(context.OSContextGenerator): + def __init__(self, rel_name='midonet'): + self.rel_name = rel_name + self.interfaces = [rel_name] + + def __call__(self): + for rid in relation_ids(self.rel_name): + for unit in related_units(rid): + rdata = relation_get(rid=rid, unit=unit) + ctxt = { + 'midonet_api_ip': rdata.get('host'), + 'midonet_api_port': rdata.get('port'), + } + if self.context_complete(ctxt): + return ctxt + return {} diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 1fb8ddca..335d9155 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -25,6 +25,7 @@ from charmhelpers.core.hookenv import ( ) from charmhelpers.core.host import ( + mkdir, restart_on_change, service_reload, service_restart, @@ -162,18 +163,18 @@ def configure_https(): def install(): status_set('maintenance', 'Executing pre-install') execd_preinstall() - configure_installation_source(config('openstack-origin')) - additional_install_locations( - config('neutron-plugin'), config('openstack-origin') - ) + openstack_origin = config('openstack-origin') + configure_installation_source(openstack_origin) + neutron_plugin = config('neutron-plugin') + additional_install_locations(neutron_plugin, openstack_origin) add_source(config('extra-source'), config('extra-key')) status_set('maintenance', 'Installing apt packages') apt_update(fatal=True) - packages = determine_packages(config('openstack-origin')) + packages = determine_packages(openstack_origin) apt_install(packages, fatal=True) - if config('neutron-plugin') == 'vsp': + if neutron_plugin == 'vsp': source = config('nuage-tarball-url') if source is not None: try: @@ -201,6 +202,10 @@ def install(): [open_port(port) for port in determine_ports()] + if neutron_plugin == 'midonet': + mkdir('/etc/neutron/plugins/midonet', owner='neutron', group='neutron', + perms=0o755, force=False) + @hooks.hook('vsd-rest-api-relation-changed') @restart_on_change(restart_map(), stopstart=True) @@ -593,6 +598,14 @@ def etcd_proxy_force_restart(relation_id=None): force_etcd_restart() +@hooks.hook('midonet-relation-joined') +@hooks.hook('midonet-relation-changed') +@hooks.hook('midonet-relation-departed') +@restart_on_change(restart_map()) +def midonet_changed(): + CONFIGS.write_all() + + def main(): try: hooks.execute(sys.argv) diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py index 2d5818c9..62d89185 100755 --- a/hooks/neutron_api_utils.py +++ b/hooks/neutron_api_utils.py @@ -28,6 +28,7 @@ from charmhelpers.contrib.python.packages import ( ) from charmhelpers.core.hookenv import ( + charm_dir, config, log, relation_ids, @@ -198,14 +199,43 @@ def additional_install_locations(plugin, source): on the Neutron plugin being used. This will also force an immediate package upgrade. ''' + release = get_os_codename_install_source(source) 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) + elif plugin == 'midonet': + midonet_origin = config('midonet-origin') + release_num = midonet_origin.split('-')[1] + + if midonet_origin.startswith('mem'): + with open(os.path.join(charm_dir(), + 'files/midokura.key')) as midokura_gpg_key: + priv_gpg_key = midokura_gpg_key.read() + mem_username = config('mem-username') + mem_password = config('mem-password') + if release in ('juno', 'kilo', 'liberty'): + add_source( + 'deb http://%s:%s@apt.midokura.com/openstack/%s/stable ' + 'trusty main' % (mem_username, mem_password, release), + key=priv_gpg_key) + add_source('http://%s:%s@apt.midokura.com/midonet/v%s/stable ' + 'main' % (mem_username, mem_password, release_num), + key=priv_gpg_key) + else: + with open(os.path.join(charm_dir(), + 'files/midonet.key')) as midonet_gpg_key: + pub_gpg_key = midonet_gpg_key.read() + if release in ('juno', 'kilo', 'liberty'): + add_source( + 'deb http://repo.midonet.org/openstack-%s stable main' % + release, key=pub_gpg_key) + + add_source('deb http://repo.midonet.org/midonet/v%s stable main' % + release_num, key=pub_gpg_key) apt_update(fatal=True) apt_upgrade(fatal=True) diff --git a/metadata.yaml b/metadata.yaml index 028fd3e7..333f0617 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -44,6 +44,8 @@ requires: scope: container etcd-proxy: interface: etcd-proxy + midonet: + interface: midonet peers: cluster: interface: neutron-api-ha diff --git a/templates/juno/midonet.ini b/templates/juno/midonet.ini new file mode 100644 index 00000000..3e060281 --- /dev/null +++ b/templates/juno/midonet.ini @@ -0,0 +1,11 @@ +############################################################################### +# [ WARNING ] +# Configuration file maintained by Juju. Local changes may be overwritten. +############################################################################### +[MIDONET] +# MidoNet API URL +midonet_uri = http://{{ midonet_api_ip }}:{{ midonet_api_port }}/midonet-api +# credentials +username = {{ admin_user }} +password = {{ admin_password }} +project_id = {{ admin_tenant_name }} diff --git a/templates/juno/neutron.conf b/templates/juno/neutron.conf index 2e91e1af..ee37e40e 100644 --- a/templates/juno/neutron.conf +++ b/templates/juno/neutron.conf @@ -102,4 +102,6 @@ admin_password = {{ admin_password }} [service_providers] service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default +{% if not neutron_plugin or neutron_plugin != 'midonet' -%} service_provider=FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default +{% endif -%} diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index 6c56c153..f1c17fc9 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -107,9 +107,13 @@ root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf {% include "section-rabbitmq-oslo" %} [service_providers] -service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default service_provider=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default +{% if neutron_plugin and neutron_plugin == 'midonet' -%} +service_provider = LOADBALANCER:Midonet:midonet.neutron.services.loadbalancer.driver.MidonetLoadbalancerDriver:default +{% else -%} +service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default service_provider=FIREWALL:Iptables:neutron_fwaas.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default +{% endif -%} [oslo_concurrency] lock_path = $state_path/lock diff --git a/templates/liberty/neutron.conf b/templates/liberty/neutron.conf index 2f5d6997..a66bb9d2 100644 --- a/templates/liberty/neutron.conf +++ b/templates/liberty/neutron.conf @@ -36,6 +36,8 @@ service_plugins = {{ service_plugins }} {% else -%} {% if neutron_plugin in ['ovs', 'ml2', 'Calico'] -%} service_plugins = router,firewall,lbaas,vpnaas,metering +{% elif neutron_plugin == 'midonet' -%} +service_plugins = lbaas {% endif -%} {% endif -%} {% endif -%} @@ -44,7 +46,7 @@ service_plugins = router,firewall,lbaas,vpnaas,metering allow_overlapping_ips = True {% if neutron_plugin == 'Calico' -%} neutron_firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver -{% else -%} +{% elif neutron_plugin != 'midonet' -%} neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver {% endif -%} {% endif -%} diff --git a/templates/liberty/neutron_lbaas.conf b/templates/liberty/neutron_lbaas.conf index 37d10c22..71090757 100644 --- a/templates/liberty/neutron_lbaas.conf +++ b/templates/liberty/neutron_lbaas.conf @@ -15,5 +15,9 @@ # auth_version = 2 [service_providers] +{% if neutron_plugin and neutron_plugin == 'midonet' -%} +service_provider = LOADBALANCER:Midonet:midonet.neutron.services.loadbalancer.driver.MidonetLoadbalancerDriver:default +{% else -%} service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default -# service_provider=LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default \ No newline at end of file +# service_provider=LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default +{% endif %} diff --git a/unit_tests/test_neutron_api_context.py b/unit_tests/test_neutron_api_context.py index ea414f67..9e59b203 100644 --- a/unit_tests/test_neutron_api_context.py +++ b/unit_tests/test_neutron_api_context.py @@ -283,6 +283,9 @@ class NeutronCCContextTest(CharmTestCase): self.test_config.set('plumgrid-username', 'plumgrid') self.test_config.set('plumgrid-password', 'plumgrid') self.test_config.set('plumgrid-virtual-ip', '192.168.100.250') + self.test_config.set('midonet-origin', 'mem-1.9') + self.test_config.set('mem-username', 'yousir') + self.test_config.set('mem-password', 'heslo') self.test_config.set('enable-ml2-port-security', True) self.test_config.set('dhcp-agents-per-network', 3) @@ -654,3 +657,34 @@ class NeutronApiSDNConfigFileContextTest(CharmTestCase): self.assertEquals(napisdn_ctxt, { 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini' }) + + +class MidonetContextTest(CharmTestCase): + + def setUp(self): + super(MidonetContextTest, 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', 'midonet') + self.test_config.set('midonet-origin', 'midonet-2015.06') + + def tearDown(self): + super(MidonetContextTest, self).tearDown() + + def test_midonet_no_related_units(self): + self.related_units.return_value = [] + ctxt = context.MidonetContext()() + expect = {} + + self.assertEquals(expect, ctxt) + + def test_some_related_units(self): + self.related_units.return_value = ['unit1'] + self.relation_ids.return_value = ['rid1'] + self.test_relation.set({'host': '11.11.11.11', + 'port': '8080'}) + ctxt = context.MidonetContext()() + expect = {'midonet_api_ip': '11.11.11.11', + 'midonet_api_port': '8080'} + + self.assertEquals(expect, ctxt)