diff --git a/hooks/neutron_api_context.py b/hooks/neutron_api_context.py index 63b979e5..18cde174 100644 --- a/hooks/neutron_api_context.py +++ b/hooks/neutron_api_context.py @@ -750,6 +750,19 @@ class NeutronApiSDNContext(context.SubordinateConfigContext): return None return ctxt.get(templ_key) == self.defaults[interface_key]['value'] + def is_allowed(self, templ_key): + """Check whether specified key is allowed on the relation. + + :param templ_key: Key to lookup + :type templ_key: str + :returns: True or False + :rtype: bool + """ + for interface_key in self.defaults: + if self.defaults[interface_key]['templ_key'] == templ_key: + return True + return False + def __call__(self): ctxt = super(NeutronApiSDNContext, self).__call__() for rid in relation_ids('neutron-plugin-api-subordinate'): diff --git a/hooks/neutron_api_hooks.py b/hooks/neutron_api_hooks.py index 80ed42e2..ee54c7dd 100755 --- a/hooks/neutron_api_hooks.py +++ b/hooks/neutron_api_hooks.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json import os import sys import uuid @@ -65,44 +66,46 @@ from charmhelpers.contrib.openstack.utils import ( ) from neutron_api_utils import ( - additional_install_locations, ADMIN_POLICY, - API_PASTE_INI, + CLUSTER_RES, + NEUTRON_CONF, + additional_install_locations, api_port, assess_status, - CLUSTER_RES, + check_local_db_actions_complete, determine_packages, determine_ports, do_openstack_upgrade, dvr_router_present, force_etcd_restart, is_api_ready, + is_db_initialised, l3ha_router_present, + manage_plugin, migrate_neutron_database, - NEUTRON_CONF, neutron_ready, + pause_unit_helper, register_configs, + remove_old_packages, restart_map, + resume_unit_helper, services, setup_ipv6, - check_local_db_actions_complete, - pause_unit_helper, - resume_unit_helper, - remove_old_packages, - is_db_initialised, ) from neutron_api_context import ( + EtcdContext, + IdentityServiceContext, + NeutronApiSDNContext, + NeutronCCContext, get_dns_domain, get_dvr, - get_l3ha, get_l2population, + get_l3ha, get_overlay_network_type, - IdentityServiceContext, - is_qos_requested_and_valid, - is_vlan_trunking_requested_and_valid, is_nfg_logging_enabled, is_nsg_logging_enabled, - EtcdContext, + is_qos_requested_and_valid, + is_vlan_trunking_requested_and_valid, ) from charmhelpers.contrib.hahelpers.cluster import ( @@ -320,6 +323,8 @@ def config_changed(): identity_joined(rid=r_id) for r_id in relation_ids('ha'): ha_joined(relation_id=r_id) + for r_id in relation_ids('neutron-plugin-api-subordinate'): + neutron_plugin_api_subordinate_relation_joined(relid=r_id) [cluster_joined(rid) for rid in relation_ids('cluster')] @@ -608,17 +613,20 @@ def neutron_plugin_api_subordinate_relation_joined(relid=None): relation_data = {'neutron-api-ready': 'no'} if is_api_ready(CONFIGS): relation_data['neutron-api-ready'] = "yes" + if not manage_plugin(): + neutron_cc_ctxt = NeutronCCContext()() + plugin_instance = NeutronApiSDNContext() + neutron_config_data = { + k: v for k, v in neutron_cc_ctxt.items() + if plugin_instance.is_allowed(k)} + if neutron_config_data: + relation_data['neutron_config_data'] = json.dumps( + neutron_config_data) relation_set(relation_id=relid, **relation_data) # there is no race condition with the neutron service restart # as juju propagates the changes done in relation_set only after # the hook exists - CONFIGS.write(API_PASTE_INI) - - -@hooks.hook('neutron-plugin-api-subordinate-relation-changed') -@restart_on_change(restart_map(), stopstart=True) -def neutron_plugin_api_relation_changed(): CONFIGS.write_all() diff --git a/unit_tests/test_neutron_api_context.py b/unit_tests/test_neutron_api_context.py index 6a989112..009a03b5 100644 --- a/unit_tests/test_neutron_api_context.py +++ b/unit_tests/test_neutron_api_context.py @@ -1196,6 +1196,11 @@ class NeutronApiSDNContextTest(CharmTestCase): {'sections': {}}, ) + def test_is_allowed(self): + napisdn_instance = context.NeutronApiSDNContext() + self.assertTrue(napisdn_instance.is_allowed('core_plugin')) + self.assertFalse(napisdn_instance.is_allowed('non_existent_key')) + class NeutronApiSDNConfigFileContextTest(CharmTestCase): diff --git a/unit_tests/test_neutron_api_hooks.py b/unit_tests/test_neutron_api_hooks.py index 61f24293..f1edca58 100644 --- a/unit_tests/test_neutron_api_hooks.py +++ b/unit_tests/test_neutron_api_hooks.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json import sys from mock import MagicMock, patch, call @@ -198,6 +199,8 @@ class NeutronAPIHooksTests(CharmTestCase): _id_rel_joined = self.patch('identity_joined') _id_cluster_joined = self.patch('cluster_joined') _id_ha_joined = self.patch('ha_joined') + _n_plugin_api_sub_rel_joined = self.patch( + 'neutron_plugin_api_subordinate_relation_joined') self._call_hook('config-changed') self.assertTrue(_n_api_rel_joined.called) self.assertTrue(_n_plugin_api_rel_joined.called) @@ -208,6 +211,7 @@ class NeutronAPIHooksTests(CharmTestCase): self.assertTrue(self.CONFIGS.write_all.called) self.assertTrue(self.do_openstack_upgrade.called) self.assertTrue(self.apt_install.called) + _n_plugin_api_sub_rel_joined.assert_called() def test_config_changed_nodvr_disprouters(self): self.neutron_ready.return_value = True @@ -934,3 +938,27 @@ class NeutronAPIHooksTests(CharmTestCase): def test_infoblox_peer_departed(self): self._call_hook('infoblox-neutron-relation-departed') self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF)) + + @patch.object(hooks, 'NeutronApiSDNContext') + @patch.object(hooks, 'NeutronCCContext') + @patch.object(hooks, 'manage_plugin') + def test_neutron_plugin_api_subordinate_relation( + self, _manage_plugin, _NeutronCCContext, _NeutronApiSDNContext): + _manage_plugin.return_value = True + self._call_hook('neutron-plugin-api-subordinate-relation-joined') + self.relation_set.assert_called_once_with( + **{'neutron-api-ready': 'no'}, relation_id=None) + self.CONFIGS.write_all.assert_called_once_with() + self.relation_set.reset_mock() + _manage_plugin.return_value = False + ncc_instance = _NeutronCCContext.return_value + ncc_instance.return_value = {'core_plugin': 'aPlugin'} + napisdn_instance = _NeutronApiSDNContext.return_value + napisdn_instance.is_allowed.return_value = True + self._call_hook('neutron-plugin-api-subordinate-relation-changed') + hooks.neutron_plugin_api_subordinate_relation_joined() + self.relation_set.assert_called_with( + **{'neutron-api-ready': 'no', + 'neutron_config_data': json.dumps({'core_plugin': 'aPlugin'})}, + relation_id=None) + self.CONFIGS.write_all.assert_called_with()