From f54243db7ef3d929be74551ac4f4fd91b6bf5d96 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 11 Jun 2015 14:17:54 +0000 Subject: [PATCH 01/18] Support a neutron api sdn plugin --- config.yaml | 6 ++++ hooks/neutron_api_context.py | 59 +++++++++++++++++++++++++++++++++ hooks/neutron_api_utils.py | 51 +++++++++++++++++----------- metadata.yaml | 6 ++++ templates/icehouse/neutron.conf | 4 +++ templates/kilo/neutron.conf | 5 +++ 6 files changed, 111 insertions(+), 20 deletions(-) diff --git a/config.yaml b/config.yaml index 05d366cd..3affd361 100644 --- a/config.yaml +++ b/config.yaml @@ -355,3 +355,9 @@ options: description: | A comma-separated list of nagios servicegroups. If left empty, the nagios_context will be used as the servicegroup + manage-neutron-plugin-legacy-mode: + type: boolean + default: True + description: | + If True neutron-server will install neutron packages for the plugin + stipulated. diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index c2cd990f..4a957f4f 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -234,3 +234,62 @@ class HAProxyContext(context.HAProxyContext): # for haproxy.conf ctxt['service_ports'] = port_mapping return ctxt + + +class NeutronApiSDNContext(context.OSContextGenerator): + interfaces = ['neutron-test'] + + def __call__(self): + ctxt = {} + defaults = { + 'core-plugin': { + 'templ_key': 'core_plugin', + 'value': 'neutron.plugins.ml2.plugin.Ml2Plugin', + }, + 'neutron-plugin-config': { + 'templ_key': 'neutron_plugin_config', + 'value': '/etc/neutron/plugins/ml2/ml2_conf.ini', + }, + 'service-plugins': { + 'templ_key': 'service_plugins', + 'value': 'router,firewall,lbaas,vpnaas,metering', + }, + } + for rid in relation_ids('neutron-test'): + for unit in related_units(rid): + rdata = relation_get(rid=rid, unit=unit) + ctxt = { + 'neutron_plugin': rdata.get('neutron-plugin'), + } + if not context.context_complete(ctxt): + continue + for key in defaults.keys(): + remote_value = rdata.get(key) + ctxt_key = defaults[key]['templ_key'] + if remote_value: + ctxt[ctxt_key] = remote_value + else: + ctxt[ctxt_key] = defaults[key]['value'] + print ctxt + return ctxt + return ctxt + +class NeutronApiSDNConfigFileContext(context.OSContextGenerator): + interfaces = ['neutron-test'] + + def __call__(self): + ctxt = {} + defaults = { + 'neutron-plugin-config': { + 'templ_key': 'neutron_plugin_config', + 'value': '/etc/neutron/plugins/ml2/ml2_conf.ini', + }, + } + for rid in relation_ids('neutron-test'): + for unit in related_units(rid): + rdata = relation_get(rid=rid, unit=unit) + neutron_server_plugin_config = rdata.get('neutron-plugin-config') + print neutron_server_plugin_config + if neutron_server_plugin_config: + return { 'config': neutron_server_plugin_config } + return { 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini' } diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py index 9f3724aa..a1fc6389 100644 --- a/hooks/neutron_api_utils.py +++ b/hooks/neutron_api_utils.py @@ -158,16 +158,20 @@ def api_port(service): return API_PORTS[service] +def manage_plugin(): + return config('manage-neutron-plugin-legacy-mode') + def determine_packages(source=None): # currently all packages match service names packages = [] + BASE_PACKAGES for v in resource_map().values(): packages.extend(v['services']) - pkgs = neutron_plugin_attribute(config('neutron-plugin'), - 'server_packages', - 'neutron') - packages.extend(pkgs) + if manage_plugin(): + pkgs = neutron_plugin_attribute(config('neutron-plugin'), + 'server_packages', + 'neutron') + packages.extend(pkgs) if get_os_codename_install_source(source) >= 'kilo': packages.extend(KILO_PACKAGES) @@ -209,24 +213,31 @@ def resource_map(): else: resource_map.pop(APACHE_24_CONF) - # add neutron plugin requirements. nova-c-c only needs the neutron-server - # associated with configs, not the plugin agent. - plugin = config('neutron-plugin') - conf = neutron_plugin_attribute(plugin, 'config', 'neutron') - ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron') - or []) - services = neutron_plugin_attribute(plugin, 'server_services', - 'neutron') - resource_map[conf] = {} - resource_map[conf]['services'] = services - resource_map[conf]['contexts'] = ctxts - resource_map[conf]['contexts'].append( - neutron_api_context.NeutronCCContext()) + if manage_plugin(): + # add neutron plugin requirements. nova-c-c only needs the neutron-server + # associated with configs, not the plugin agent. + plugin = config('neutron-plugin') + conf = neutron_plugin_attribute(plugin, 'config', 'neutron') + ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron') + or []) + services = neutron_plugin_attribute(plugin, 'server_services', + 'neutron') + resource_map[conf] = {} + resource_map[conf]['services'] = services + resource_map[conf]['contexts'] = ctxts + resource_map[conf]['contexts'].append( + neutron_api_context.NeutronCCContext()) - # update for postgres - resource_map[conf]['contexts'].append( - context.PostgresqlDBContext(database=config('database'))) + # update for postgres + resource_map[conf]['contexts'].append( + context.PostgresqlDBContext(database=config('database'))) + else: + resource_map[NEUTRON_CONF]['contexts'].append( + neutron_api_context.NeutronApiSDNContext() + ) + resource_map[NEUTRON_DEFAULT]['contexts'] = \ + neutron_api_context.NeutronApiSDNConfigFileContext() return resource_map diff --git a/metadata.yaml b/metadata.yaml index 0c8256be..26bda6f3 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -37,6 +37,12 @@ requires: zeromq-configuration: interface: zeromq-configuration scope: container + neutron-plugin: + interface: neutron-plugin + scope: container + neutron-test: + interface: neutron-test + scope: container peers: cluster: interface: neutron-api-ha diff --git a/templates/icehouse/neutron.conf b/templates/icehouse/neutron.conf index c78169d5..08d14fc7 100644 --- a/templates/icehouse/neutron.conf +++ b/templates/icehouse/neutron.conf @@ -27,10 +27,14 @@ bind_port = 9696 {% if core_plugin -%} core_plugin = {{ core_plugin }} +{% if service_plugins -%} +service_plugins = {{ service_plugins }} +{% else -%} {% if neutron_plugin in ['ovs', 'ml2'] -%} 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 -%} +{% endif -%} {% if neutron_security_groups -%} allow_overlapping_ips = True diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index a6a3c664..5afd6e5c 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -29,12 +29,17 @@ bind_port = {{ neutron_bind_port }} bind_port = 9696 {% endif -%} +# {{ service_plugins }} {% if core_plugin -%} core_plugin = {{ core_plugin }} +{% if service_plugins -%} +service_plugins = {{ service_plugins }} +{% else -%} {% if neutron_plugin in ['ovs', 'ml2'] -%} service_plugins = router,firewall,lbaas,vpnaas,metering {% endif -%} {% endif -%} +{% endif -%} {% if neutron_security_groups -%} allow_overlapping_ips = True From b619f1cc68c3ec38b5afd5a757d9ccd9682fa9b4 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Thu, 11 Jun 2015 16:48:46 +0000 Subject: [PATCH 02/18] Add restart trigger support --- hooks/neutron_api_context.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 4a957f4f..240fa1b3 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -254,6 +254,10 @@ class NeutronApiSDNContext(context.OSContextGenerator): 'templ_key': 'service_plugins', 'value': 'router,firewall,lbaas,vpnaas,metering', }, + 'restart-trigger': { + 'templ_key': 'restart_trigger', + 'value': '', + }, } for rid in relation_ids('neutron-test'): for unit in related_units(rid): @@ -270,7 +274,6 @@ class NeutronApiSDNContext(context.OSContextGenerator): ctxt[ctxt_key] = remote_value else: ctxt[ctxt_key] = defaults[key]['value'] - print ctxt return ctxt return ctxt @@ -289,7 +292,6 @@ class NeutronApiSDNConfigFileContext(context.OSContextGenerator): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) neutron_server_plugin_config = rdata.get('neutron-plugin-config') - print neutron_server_plugin_config if neutron_server_plugin_config: return { 'config': neutron_server_plugin_config } return { 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini' } From 7a2fa1b185e04cf1b8c42ec4eb14f22e9fa4db93 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Fri, 12 Jun 2015 09:26:59 +0000 Subject: [PATCH 03/18] Add support for config for neutron-server coming from subordinate --- hooks/neutron_api_context.py | 15 +++++++++------ hooks/neutron_api_utils.py | 1 + templates/kilo/neutron.conf | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 240fa1b3..25c6ac34 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -236,11 +236,16 @@ class HAProxyContext(context.HAProxyContext): return ctxt -class NeutronApiSDNContext(context.OSContextGenerator): - interfaces = ['neutron-test'] +class NeutronApiSDNContext(context.SubordinateConfigContext): + interfaces = 'neutron-test' + + def __init__(self): + super(NeutronApiSDNContext, self).__init__(interface='neutron-test', + service='neutron-api', + config_file='/etc/neutron/neutron.conf') def __call__(self): - ctxt = {} + ctxt = super(NeutronApiSDNContext, self).__call__() defaults = { 'core-plugin': { 'templ_key': 'core_plugin', @@ -262,9 +267,7 @@ class NeutronApiSDNContext(context.OSContextGenerator): for rid in relation_ids('neutron-test'): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) - ctxt = { - 'neutron_plugin': rdata.get('neutron-plugin'), - } + ctxt['neutron_plugin'] = rdata.get('neutron-plugin') if not context.context_complete(ctxt): continue for key in defaults.keys(): diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py index a1fc6389..ca105a0e 100644 --- a/hooks/neutron_api_utils.py +++ b/hooks/neutron_api_utils.py @@ -233,6 +233,7 @@ def resource_map(): context.PostgresqlDBContext(database=config('database'))) else: + print "Adding NeutronApiSDNContext" resource_map[NEUTRON_CONF]['contexts'].append( neutron_api_context.NeutronApiSDNContext() ) diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index 5afd6e5c..bf62a467 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -59,6 +59,12 @@ nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0 {% include "section-zeromq" %} +{% if sections and 'DEFAULT' in sections -%} +{% for key, value in sections['DEFAULT'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} + [quotas] quota_driver = neutron.db.quota_db.DbQuotaDriver {% if neutron_security_groups -%} @@ -77,6 +83,11 @@ quota_member = {{ quota_member }} quota_health_monitors = {{ quota_health_monitors }} quota_router = {{ quota_router }} quota_floatingip = {{ quota_floatingip }} +{% if sections and 'quotas' in sections -%} +{% for key, value in sections['quotas'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} [agent] root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf @@ -86,11 +97,26 @@ root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf {% include "parts/section-database" %} {% include "section-rabbitmq-oslo" %} +{% if sections and 'agent' in sections -%} +{% for key, value in sections['agent'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} [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 service_provider=FIREWALL:Iptables:neutron_fwaas.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default +{% if sections and 'service_providers' in sections -%} +{% for key, value in sections['service_providers'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} [oslo_concurrency] lock_path = $state_path/lock +{% if sections and 'oslo_concurrency' in sections -%} +{% for key, value in sections['oslo_concurrency'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} From d835d0c9e5247dfb1369e1aec6f466627839afc1 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Fri, 12 Jun 2015 12:23:29 +0000 Subject: [PATCH 04/18] Update relation name --- hooks/neutron_api_context.py | 10 +++++----- metadata.yaml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 25c6ac34..80662841 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -237,10 +237,10 @@ class HAProxyContext(context.HAProxyContext): class NeutronApiSDNContext(context.SubordinateConfigContext): - interfaces = 'neutron-test' + interfaces = 'neutron-plugin-api-subordinate' def __init__(self): - super(NeutronApiSDNContext, self).__init__(interface='neutron-test', + super(NeutronApiSDNContext, self).__init__(interface='neutron-plugin-api-subordinate', service='neutron-api', config_file='/etc/neutron/neutron.conf') @@ -264,7 +264,7 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): 'value': '', }, } - for rid in relation_ids('neutron-test'): + for rid in relation_ids('neutron-plugin-api-subordinate'): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) ctxt['neutron_plugin'] = rdata.get('neutron-plugin') @@ -281,7 +281,7 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): return ctxt class NeutronApiSDNConfigFileContext(context.OSContextGenerator): - interfaces = ['neutron-test'] + interfaces = ['neutron-plugin-api-subordinate'] def __call__(self): ctxt = {} @@ -291,7 +291,7 @@ class NeutronApiSDNConfigFileContext(context.OSContextGenerator): 'value': '/etc/neutron/plugins/ml2/ml2_conf.ini', }, } - for rid in relation_ids('neutron-test'): + for rid in relation_ids('neutron-plugin-api-subordinate'): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) neutron_server_plugin_config = rdata.get('neutron-plugin-config') diff --git a/metadata.yaml b/metadata.yaml index 26bda6f3..be2bd85a 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -40,8 +40,8 @@ requires: neutron-plugin: interface: neutron-plugin scope: container - neutron-test: - interface: neutron-test + neutron-plugin-api-subordinate: + interface: neutron-plugin-api-subordinate scope: container peers: cluster: From 2ba62d1903c3074563ca6ceb2cb224204ec87bec Mon Sep 17 00:00:00 2001 From: Liam Young Date: Sat, 13 Jun 2015 09:05:22 +0000 Subject: [PATCH 05/18] Remove unused interface --- metadata.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/metadata.yaml b/metadata.yaml index be2bd85a..3ef46991 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -37,9 +37,6 @@ requires: zeromq-configuration: interface: zeromq-configuration scope: container - neutron-plugin: - interface: neutron-plugin - scope: container neutron-plugin-api-subordinate: interface: neutron-plugin-api-subordinate scope: container From bc7438a700624362089664b38d993e00e47064db Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 24 Jun 2015 18:12:33 +0000 Subject: [PATCH 06/18] Add temporary ppa with patched neutron code --- hooks/neutron_api_hooks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index fde9e188..843d4242 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -143,6 +143,8 @@ def configure_https(): def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) + # XXX Remove me when patched nova and neutron are in the main ppa + configure_installation_source('ppa:gnuoy/sdn-test') apt_update() apt_install(determine_packages(config('openstack-origin')), From d189c5ebe19f9055003d828f6f048015121d47ff Mon Sep 17 00:00:00 2001 From: Liam Young Date: Mon, 29 Jun 2015 13:21:05 +0100 Subject: [PATCH 07/18] Lint and tipdyup --- hooks/neutron_api_context.py | 23 +++++++++-------------- hooks/neutron_api_hooks.py | 2 -- hooks/neutron_api_utils.py | 5 +++-- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 80662841..86d3172c 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -240,9 +240,10 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): interfaces = 'neutron-plugin-api-subordinate' def __init__(self): - super(NeutronApiSDNContext, self).__init__(interface='neutron-plugin-api-subordinate', - service='neutron-api', - config_file='/etc/neutron/neutron.conf') + super(NeutronApiSDNContext, self).__init__( + interface='neutron-plugin-api-subordinate', + service='neutron-api', + config_file='/etc/neutron/neutron.conf') def __call__(self): ctxt = super(NeutronApiSDNContext, self).__call__() @@ -280,21 +281,15 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): return ctxt return ctxt + class NeutronApiSDNConfigFileContext(context.OSContextGenerator): interfaces = ['neutron-plugin-api-subordinate'] def __call__(self): - ctxt = {} - defaults = { - 'neutron-plugin-config': { - 'templ_key': 'neutron_plugin_config', - 'value': '/etc/neutron/plugins/ml2/ml2_conf.ini', - }, - } for rid in relation_ids('neutron-plugin-api-subordinate'): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) - neutron_server_plugin_config = rdata.get('neutron-plugin-config') - if neutron_server_plugin_config: - return { 'config': neutron_server_plugin_config } - return { 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini' } + neutron_server_plugin_conf = rdata.get('neutron-plugin-config') + if neutron_server_plugin_conf: + return {'config': neutron_server_plugin_conf} + return {'config': '/etc/neutron/plugins/ml2/ml2_conf.ini'} diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 843d4242..fde9e188 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -143,8 +143,6 @@ def configure_https(): def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) - # XXX Remove me when patched nova and neutron are in the main ppa - configure_installation_source('ppa:gnuoy/sdn-test') apt_update() apt_install(determine_packages(config('openstack-origin')), diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py index ca105a0e..b6f11493 100644 --- a/hooks/neutron_api_utils.py +++ b/hooks/neutron_api_utils.py @@ -161,6 +161,7 @@ def api_port(service): def manage_plugin(): return config('manage-neutron-plugin-legacy-mode') + def determine_packages(source=None): # currently all packages match service names packages = [] + BASE_PACKAGES @@ -214,8 +215,8 @@ def resource_map(): resource_map.pop(APACHE_24_CONF) if manage_plugin(): - # add neutron plugin requirements. nova-c-c only needs the neutron-server - # associated with configs, not the plugin agent. + # add neutron plugin requirements. nova-c-c only needs the + # neutron-server associated with configs, not the plugin agent. plugin = config('neutron-plugin') conf = neutron_plugin_attribute(plugin, 'config', 'neutron') ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron') From 36fc3a0fcbc5b6e5d2d0bfb5874504458afb4112 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Tue, 30 Jun 2015 09:26:51 +0100 Subject: [PATCH 08/18] Add unit tests for new contexts --- hooks/neutron_api_context.py | 5 +- unit_tests/test_neutron_api_context.py | 133 +++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 2 deletions(-) diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 86d3172c..a7e60af3 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -268,9 +268,10 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): for rid in relation_ids('neutron-plugin-api-subordinate'): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) - ctxt['neutron_plugin'] = rdata.get('neutron-plugin') - if not context.context_complete(ctxt): + plugin = rdata.get('neutron-plugin') + if not plugin: continue + ctxt['neutron_plugin'] = plugin for key in defaults.keys(): remote_value = rdata.get(key) ctxt_key = defaults[key]['templ_key'] diff --git a/unit_tests/test_neutron_api_context.py b/unit_tests/test_neutron_api_context.py index 11edcffa..a0ef6af4 100644 --- a/unit_tests/test_neutron_api_context.py +++ b/unit_tests/test_neutron_api_context.py @@ -1,3 +1,4 @@ +import json from test_utils import CharmTestCase from mock import patch import neutron_api_context as context @@ -432,3 +433,135 @@ class NeutronCCContextTest(CharmTestCase): } for key in expect.iterkeys(): self.assertEquals(napi_ctxt[key], expect[key]) + + +class NeutronApiSDNContextTest(CharmTestCase): + + def setUp(self): + super(NeutronApiSDNContextTest, self).setUp(context, TO_PATCH) + self.relation_get.side_effect = self.test_relation.get + + def tearDown(self): + super(NeutronApiSDNContextTest, self).tearDown() + + def test_init(self): + napisdn_ctxt = context.NeutronApiSDNContext() + self.assertEquals( + napisdn_ctxt.interface, + 'neutron-plugin-api-subordinate' + ) + self.assertEquals(napisdn_ctxt.service, 'neutron-api') + self.assertEquals( + napisdn_ctxt.config_file, + '/etc/neutron/neutron.conf' + ) + + @patch.object(charmhelpers.contrib.openstack.context, 'log') + @patch.object(charmhelpers.contrib.openstack.context, 'relation_get') + @patch.object(charmhelpers.contrib.openstack.context, 'related_units') + @patch.object(charmhelpers.contrib.openstack.context, 'relation_ids') + def ctxt_check(self, rel_settings, expect, _rids, _runits, _rget, _log): + self.test_relation.set(rel_settings) + _runits.return_value = ['unit1'] + _rids.return_value = ['rid2'] + _rget.side_effect = self.test_relation.get + self.relation_ids.return_value = ['rid2'] + self.related_units.return_value = ['unit1'] + napisdn_ctxt = context.NeutronApiSDNContext()() + self.assertEquals(napisdn_ctxt, expect) + + def test_defaults(self): + self.ctxt_check( + {'neutron-plugin': 'ovs'}, + { + 'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin', + 'neutron_plugin_config': ('/etc/neutron/plugins/ml2/' + 'ml2_conf.ini'), + 'service_plugins': 'router,firewall,lbaas,vpnaas,metering', + 'restart_trigger': '', + 'neutron_plugin': 'ovs', + 'sections': {}, + } + ) + + def test_overrides(self): + self.ctxt_check( + { + 'neutron-plugin': 'ovs', + 'core-plugin': 'neutron.plugins.ml2.plugin.MidoPlumODL', + 'neutron-plugin-config': '/etc/neutron/plugins/fl/flump.ini', + 'service-plugins': 'router,unicorn,rainbows', + 'restart-trigger': 'restartnow', + }, + { + 'core_plugin': 'neutron.plugins.ml2.plugin.MidoPlumODL', + 'neutron_plugin_config': '/etc/neutron/plugins/fl/flump.ini', + 'service_plugins': 'router,unicorn,rainbows', + 'restart_trigger': 'restartnow', + 'neutron_plugin': 'ovs', + 'sections': {}, + } + ) + + def test_subordinateconfig(self): + principle_config = { + "neutron-api": { + "/etc/neutron/neutron.conf": { + "sections": { + 'DEFAULT': [ + ('neutronboost', True) + ], + } + } + } + } + self.ctxt_check( + { + 'neutron-plugin': 'ovs', + 'subordinate_configuration': json.dumps(principle_config), + }, + { + 'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin', + 'neutron_plugin_config': ('/etc/neutron/plugins/ml2/' + 'ml2_conf.ini'), + 'service_plugins': 'router,firewall,lbaas,vpnaas,metering', + 'restart_trigger': '', + 'neutron_plugin': 'ovs', + 'sections': {u'DEFAULT': [[u'neutronboost', True]]}, + } + ) + + def test_empty(self): + self.ctxt_check( + {}, + {'sections': {}}, + ) + + +class NeutronApiSDNConfigFileContextTest(CharmTestCase): + + def setUp(self): + super(NeutronApiSDNConfigFileContextTest, self).setUp( + context, TO_PATCH) + self.relation_get.side_effect = self.test_relation.get + + def tearDown(self): + super(NeutronApiSDNConfigFileContextTest, self).tearDown() + + def test_configset(self): + self.test_relation.set({ + 'neutron-plugin-config': '/etc/neutron/superplugin.ini' + }) + self.relation_ids.return_value = ['rid2'] + self.related_units.return_value = ['unit1'] + napisdn_ctxt = context.NeutronApiSDNConfigFileContext()() + self.assertEquals(napisdn_ctxt, { + 'config': '/etc/neutron/superplugin.ini' + }) + + def test_default(self): + self.relation_ids.return_value = [] + napisdn_ctxt = context.NeutronApiSDNConfigFileContext()() + self.assertEquals(napisdn_ctxt, { + 'config': '/etc/neutron/plugins/ml2/ml2_conf.ini' + }) From a6c3663eb806bdff86a82fe25a97027cec2b4544 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Tue, 30 Jun 2015 10:03:16 +0100 Subject: [PATCH 09/18] Add unit tests for new utils and add missing relation hook links --- ...on-plugin-api-subordinate-relation-changed | 1 + ...n-plugin-api-subordinate-relation-departed | 1 + ...ron-plugin-api-subordinate-relation-joined | 1 + hooks/neutron_api_utils.py | 3 +- unit_tests/test_neutron_api_utils.py | 43 ++++++++++++++++++- 5 files changed, 45 insertions(+), 4 deletions(-) create mode 120000 hooks/neutron-plugin-api-subordinate-relation-changed create mode 120000 hooks/neutron-plugin-api-subordinate-relation-departed create mode 120000 hooks/neutron-plugin-api-subordinate-relation-joined diff --git a/hooks/neutron-plugin-api-subordinate-relation-changed b/hooks/neutron-plugin-api-subordinate-relation-changed new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/neutron-plugin-api-subordinate-relation-changed @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/neutron-plugin-api-subordinate-relation-departed b/hooks/neutron-plugin-api-subordinate-relation-departed new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/neutron-plugin-api-subordinate-relation-departed @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/neutron-plugin-api-subordinate-relation-joined b/hooks/neutron-plugin-api-subordinate-relation-joined new file mode 120000 index 00000000..1fb10fd5 --- /dev/null +++ b/hooks/neutron-plugin-api-subordinate-relation-joined @@ -0,0 +1 @@ +neutron_api_hooks.py \ No newline at end of file diff --git a/hooks/neutron_api_utils.py b/hooks/neutron_api_utils.py index b6f11493..e5589178 100644 --- a/hooks/neutron_api_utils.py +++ b/hooks/neutron_api_utils.py @@ -234,12 +234,11 @@ def resource_map(): context.PostgresqlDBContext(database=config('database'))) else: - print "Adding NeutronApiSDNContext" resource_map[NEUTRON_CONF]['contexts'].append( neutron_api_context.NeutronApiSDNContext() ) resource_map[NEUTRON_DEFAULT]['contexts'] = \ - neutron_api_context.NeutronApiSDNConfigFileContext() + [neutron_api_context.NeutronApiSDNConfigFileContext()] return resource_map diff --git a/unit_tests/test_neutron_api_utils.py b/unit_tests/test_neutron_api_utils.py index 7de08226..207dcda1 100644 --- a/unit_tests/test_neutron_api_utils.py +++ b/unit_tests/test_neutron_api_utils.py @@ -103,28 +103,57 @@ class TestNeutronAPIUtils(CharmTestCase): expect.extend(nutils.KILO_PACKAGES) self.assertItemsEqual(pkg_list, expect) + @patch.object(nutils, 'git_install_requested') + def test_determine_packages_noplugin(self, git_requested): + git_requested.return_value = False + self.test_config.set('manage-neutron-plugin-legacy-mode', False) + pkg_list = nutils.determine_packages() + expect = deepcopy(nutils.BASE_PACKAGES) + expect.extend(['neutron-server']) + self.assertItemsEqual(pkg_list, expect) + def test_determine_ports(self): port_list = nutils.determine_ports() self.assertItemsEqual(port_list, [9696]) + @patch.object(nutils, 'manage_plugin') @patch('os.path.exists') - def test_resource_map(self, _path_exists): + def test_resource_map(self, _path_exists, _manage_plugin): _path_exists.return_value = False + _manage_plugin.return_value = True _map = nutils.resource_map() confs = [nutils.NEUTRON_CONF, nutils.NEUTRON_DEFAULT, nutils.APACHE_CONF] [self.assertIn(q_conf, _map.keys()) for q_conf in confs] self.assertTrue(nutils.APACHE_24_CONF not in _map.keys()) + @patch.object(nutils, 'manage_plugin') @patch('os.path.exists') - def test_resource_map_apache24(self, _path_exists): + def test_resource_map_apache24(self, _path_exists, _manage_plugin): _path_exists.return_value = True + _manage_plugin.return_value = True _map = nutils.resource_map() confs = [nutils.NEUTRON_CONF, nutils.NEUTRON_DEFAULT, nutils.APACHE_24_CONF] [self.assertIn(q_conf, _map.keys()) for q_conf in confs] self.assertTrue(nutils.APACHE_CONF not in _map.keys()) + @patch.object(nutils, 'manage_plugin') + @patch('os.path.exists') + def test_resource_map_noplugin(self, _path_exists, _manage_plugin): + _path_exists.return_value = True + _manage_plugin.return_value = False + _map = nutils.resource_map() + found_sdn_ctxt = False + found_sdnconfig_ctxt = False + for ctxt in _map[nutils.NEUTRON_CONF]['contexts']: + if isinstance(ctxt, ncontext.NeutronApiSDNContext): + found_sdn_ctxt = True + for ctxt in _map[nutils.NEUTRON_DEFAULT]['contexts']: + if isinstance(ctxt, ncontext.NeutronApiSDNConfigFileContext): + found_sdnconfig_ctxt = True + self.assertTrue(found_sdn_ctxt and found_sdnconfig_ctxt) + @patch('os.path.exists') def test_restart_map(self, mock_path_exists): mock_path_exists.return_value = False @@ -477,3 +506,13 @@ class TestNeutronAPIUtils(CharmTestCase): 'upgrade', 'head'] self.subprocess.check_output.assert_called_with(cmd) + + def test_manage_plugin_true(self): + self.test_config.set('manage-neutron-plugin-legacy-mode', True) + manage = nutils.manage_plugin() + self.assertTrue(manage) + + def test_manage_plugin_false(self): + self.test_config.set('manage-neutron-plugin-legacy-mode', False) + manage = nutils.manage_plugin() + self.assertFalse(manage) From 141fef1dbeda551492a6f54e9183b499f8c89b5c Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 8 Jul 2015 08:19:34 +0000 Subject: [PATCH 10/18] Point at ppa and pin packages --- files/patched-icehouse | 4 ++++ hooks/neutron_api_hooks.py | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 files/patched-icehouse diff --git a/files/patched-icehouse b/files/patched-icehouse new file mode 100644 index 00000000..c7bea34c --- /dev/null +++ b/files/patched-icehouse @@ -0,0 +1,4 @@ +[ /etc/apt/preferences.d/patched-icehouse ] +Package: * +Pin: release o=LP-PPA-sdn-charmers-cisco-vpp-testing +Pin-Priority: 990 diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 843d4242..919da5d1 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -9,6 +9,7 @@ from subprocess import ( from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, + charm_dir, config, is_relation_made, local_unit, @@ -144,8 +145,10 @@ def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) # XXX Remove me when patched nova and neutron are in the main ppa - configure_installation_source('ppa:gnuoy/sdn-test') - + configure_installation_source('ppa:sdn-charmers/cisco-vpp-testing') + apt_pin_file = charm_dir() + '/files/patched-icehouse' + import shutil + shutil.copyfile(apt_pin_file, '/etc/apt/preferences.d/patched-icehouse') apt_update() apt_install(determine_packages(config('openstack-origin')), fatal=True) From 1ee42477dd02c338753e632775127688f953f930 Mon Sep 17 00:00:00 2001 From: James Page Date: Wed, 15 Jul 2015 10:53:12 +0100 Subject: [PATCH 11/18] Drop temporary PPA and pin, ensure subordinate changes are detected --- files/patched-icehouse | 4 ---- hooks/neutron_api_hooks.py | 10 +++------- 2 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 files/patched-icehouse diff --git a/files/patched-icehouse b/files/patched-icehouse deleted file mode 100644 index c7bea34c..00000000 --- a/files/patched-icehouse +++ /dev/null @@ -1,4 +0,0 @@ -[ /etc/apt/preferences.d/patched-icehouse ] -Package: * -Pin: release o=LP-PPA-sdn-charmers-cisco-vpp-testing -Pin-Priority: 990 diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 919da5d1..b79571e1 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -9,7 +9,6 @@ from subprocess import ( from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, - charm_dir, config, is_relation_made, local_unit, @@ -144,11 +143,7 @@ def configure_https(): def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) - # XXX Remove me when patched nova and neutron are in the main ppa - configure_installation_source('ppa:sdn-charmers/cisco-vpp-testing') - apt_pin_file = charm_dir() + '/files/patched-icehouse' - import shutil - shutil.copyfile(apt_pin_file, '/etc/apt/preferences.d/patched-icehouse') + apt_update() apt_install(determine_packages(config('openstack-origin')), fatal=True) @@ -484,7 +479,8 @@ def zeromq_configuration_relation_joined(relid=None): users="neutron") -@hooks.hook('zeromq-configuration-relation-changed') +@hooks.hook('zeromq-configuration-relation-changed', + 'neutron-plugin-api-subordinate-relation-changed') @restart_on_change(restart_map(), stopstart=True) def zeromq_configuration_relation_changed(): CONFIGS.write_all() From 40fde79e55b9ca37fb6624b7bac08f458d75ebdd Mon Sep 17 00:00:00 2001 From: Liam Young Date: Tue, 21 Jul 2015 15:31:39 +0000 Subject: [PATCH 12/18] Temp ppa override --- files/patched-icehouse | 4 ++++ hooks/neutron_api_hooks.py | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 files/patched-icehouse diff --git a/files/patched-icehouse b/files/patched-icehouse new file mode 100644 index 00000000..c7bea34c --- /dev/null +++ b/files/patched-icehouse @@ -0,0 +1,4 @@ +[ /etc/apt/preferences.d/patched-icehouse ] +Package: * +Pin: release o=LP-PPA-sdn-charmers-cisco-vpp-testing +Pin-Priority: 990 diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index b79571e1..15b79ab3 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -9,6 +9,7 @@ from subprocess import ( from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, + charm_dir, config, is_relation_made, local_unit, @@ -143,6 +144,11 @@ def configure_https(): def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) + # XXX Remove me when patched nova and neutron are in the main ppa + configure_installation_source('ppa:sdn-charmers/cisco-vpp-testing') + apt_pin_file = charm_dir() + '/files/patched-icehouse' + import shutil + shutil.copyfile(apt_pin_file, '/etc/apt/preferences.d/patched-icehouse') apt_update() apt_install(determine_packages(config('openstack-origin')), From c8c7beb1e39d08607d0f39d8bebce0fd7f61117b Mon Sep 17 00:00:00 2001 From: Liam Young Date: Sun, 26 Jul 2015 14:59:38 +0100 Subject: [PATCH 13/18] Remove temporary ppa hack --- hooks/neutron_api_hooks.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 15b79ab3..8edc9b09 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -144,11 +144,6 @@ def configure_https(): def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) - # XXX Remove me when patched nova and neutron are in the main ppa - configure_installation_source('ppa:sdn-charmers/cisco-vpp-testing') - apt_pin_file = charm_dir() + '/files/patched-icehouse' - import shutil - shutil.copyfile(apt_pin_file, '/etc/apt/preferences.d/patched-icehouse') apt_update() apt_install(determine_packages(config('openstack-origin')), From 9d88d29605807cbacccde34f6ccfa4576c073bf6 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 29 Jul 2015 11:13:49 +0100 Subject: [PATCH 14/18] Add ability to except subordinate config in icehouse and juno. Other fixes from jamespages review comments --- config.yaml | 2 +- templates/icehouse/neutron.conf | 6 ++++++ templates/juno/neutron.conf | 6 ++++++ templates/kilo/neutron.conf | 20 -------------------- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/config.yaml b/config.yaml index 3affd361..76e52f3a 100644 --- a/config.yaml +++ b/config.yaml @@ -360,4 +360,4 @@ options: default: True description: | If True neutron-server will install neutron packages for the plugin - stipulated. + configured. diff --git a/templates/icehouse/neutron.conf b/templates/icehouse/neutron.conf index 08d14fc7..177eaea3 100644 --- a/templates/icehouse/neutron.conf +++ b/templates/icehouse/neutron.conf @@ -54,6 +54,12 @@ nova_admin_password = {{ admin_password }} nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0 {% endif -%} +{% if sections and 'DEFAULT' in sections -%} +{% for key, value in sections['DEFAULT'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} + [quotas] quota_driver = neutron.db.quota_db.DbQuotaDriver {% if neutron_security_groups -%} diff --git a/templates/juno/neutron.conf b/templates/juno/neutron.conf index 05d3e212..a4c97285 100644 --- a/templates/juno/neutron.conf +++ b/templates/juno/neutron.conf @@ -54,6 +54,12 @@ nova_admin_password = {{ admin_password }} nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0 {% endif -%} +{% if sections and 'DEFAULT' in sections -%} +{% for key, value in sections['DEFAULT'] -%} +{{ key }} = {{ value }} +{% endfor -%} +{% endif %} + [quotas] quota_driver = neutron.db.quota_db.DbQuotaDriver {% if neutron_security_groups -%} diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index bf62a467..5e067f00 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -83,11 +83,6 @@ quota_member = {{ quota_member }} quota_health_monitors = {{ quota_health_monitors }} quota_router = {{ quota_router }} quota_floatingip = {{ quota_floatingip }} -{% if sections and 'quotas' in sections -%} -{% for key, value in sections['quotas'] -%} -{{ key }} = {{ value }} -{% endfor -%} -{% endif %} [agent] root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf @@ -97,26 +92,11 @@ root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf {% include "parts/section-database" %} {% include "section-rabbitmq-oslo" %} -{% if sections and 'agent' in sections -%} -{% for key, value in sections['agent'] -%} -{{ key }} = {{ value }} -{% endfor -%} -{% endif %} [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 service_provider=FIREWALL:Iptables:neutron_fwaas.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default -{% if sections and 'service_providers' in sections -%} -{% for key, value in sections['service_providers'] -%} -{{ key }} = {{ value }} -{% endfor -%} -{% endif %} [oslo_concurrency] lock_path = $state_path/lock -{% if sections and 'oslo_concurrency' in sections -%} -{% for key, value in sections['oslo_concurrency'] -%} -{{ key }} = {{ value }} -{% endfor -%} -{% endif %} From b01f51dcbf854db5b173732e21702d42ff9a6038 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 12 Aug 2015 06:22:30 +0100 Subject: [PATCH 15/18] Remove leftover pin package --- files/patched-icehouse | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 files/patched-icehouse diff --git a/files/patched-icehouse b/files/patched-icehouse deleted file mode 100644 index c7bea34c..00000000 --- a/files/patched-icehouse +++ /dev/null @@ -1,4 +0,0 @@ -[ /etc/apt/preferences.d/patched-icehouse ] -Package: * -Pin: release o=LP-PPA-sdn-charmers-cisco-vpp-testing -Pin-Priority: 990 From 2c11941949b8c15beec3a9f97f95b1140abc561e Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 12 Aug 2015 11:14:00 +0100 Subject: [PATCH 16/18] Fix kilo template ordering --- templates/kilo/neutron.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index 5e067f00..ec54b395 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -57,14 +57,14 @@ nova_admin_password = {{ admin_password }} nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0 {% endif -%} -{% include "section-zeromq" %} - {% if sections and 'DEFAULT' in sections -%} {% for key, value in sections['DEFAULT'] -%} {{ key }} = {{ value }} {% endfor -%} {% endif %} +{% include "section-zeromq" %} + [quotas] quota_driver = neutron.db.quota_db.DbQuotaDriver {% if neutron_security_groups -%} From e78f7d5f7b119c7577e4b501b506c3c6c30da02b Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 12 Aug 2015 11:18:00 +0100 Subject: [PATCH 17/18] Fix lint and remove pointless comment from template --- hooks/neutron_api_hooks.py | 1 - templates/kilo/neutron.conf | 1 - 2 files changed, 2 deletions(-) diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 8edc9b09..b79571e1 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -9,7 +9,6 @@ from subprocess import ( from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, - charm_dir, config, is_relation_made, local_unit, diff --git a/templates/kilo/neutron.conf b/templates/kilo/neutron.conf index ec54b395..07a0ed88 100644 --- a/templates/kilo/neutron.conf +++ b/templates/kilo/neutron.conf @@ -29,7 +29,6 @@ bind_port = {{ neutron_bind_port }} bind_port = 9696 {% endif -%} -# {{ service_plugins }} {% if core_plugin -%} core_plugin = {{ core_plugin }} {% if service_plugins -%} From efffe3785f380e91259acf3f833daa25e28fd8bd Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 12 Aug 2015 11:35:59 +0100 Subject: [PATCH 18/18] Fix unit test --- unit_tests/test_neutron_api_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_tests/test_neutron_api_context.py b/unit_tests/test_neutron_api_context.py index a0ef6af4..3d12e482 100644 --- a/unit_tests/test_neutron_api_context.py +++ b/unit_tests/test_neutron_api_context.py @@ -447,7 +447,7 @@ class NeutronApiSDNContextTest(CharmTestCase): def test_init(self): napisdn_ctxt = context.NeutronApiSDNContext() self.assertEquals( - napisdn_ctxt.interface, + napisdn_ctxt.interfaces, 'neutron-plugin-api-subordinate' ) self.assertEquals(napisdn_ctxt.service, 'neutron-api')