diff --git a/.bzrignore b/.bzrignore index 421e2bda..66484d6f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,3 +1,5 @@ bin .coverage tags +.tox +.testrepository diff --git a/.testr.conf b/.testr.conf new file mode 100644 index 00000000..801646bb --- /dev/null +++ b/.testr.conf @@ -0,0 +1,8 @@ +[DEFAULT] +test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ + OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ + OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ + ${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION + +test_id_option=--load-list $IDFILE +test_list_option=--list diff --git a/hooks/neutron_contexts.py b/hooks/neutron_contexts.py index 4d449952..e73776d8 100644 --- a/hooks/neutron_contexts.py +++ b/hooks/neutron_contexts.py @@ -89,9 +89,8 @@ def remap_plugin(plugin): def core_plugin(): plugin = remap_plugin(config('plugin')) - if (get_os_codename_install_source(config('openstack-origin')) - >= 'icehouse' - and plugin == OVS): + if (get_os_codename_install_source(config('openstack-origin')) >= + 'icehouse' and plugin == OVS): return NEUTRON_ML2_PLUGIN else: return CORE_PLUGIN[networking_name()][plugin] diff --git a/hooks/neutron_hooks.py b/hooks/neutron_hooks.py index d4d8c75e..2a036bb9 100755 --- a/hooks/neutron_hooks.py +++ b/hooks/neutron_hooks.py @@ -315,7 +315,7 @@ def update_nrpe_config(): shortname="netns", description='Network Namespace check {%s}' % current_unit, check_cmd='check_status_file.py -f /var/lib/nagios/netns-check.txt' - ) + ) nrpe_setup.write() diff --git a/hooks/neutron_utils.py b/hooks/neutron_utils.py index 25cc5069..04222492 100644 --- a/hooks/neutron_utils.py +++ b/hooks/neutron_utils.py @@ -567,22 +567,46 @@ CONFIG_FILES = { }, } +SERVICE_RENAMES = {} -def register_configs(): - ''' Register config files with their respective contexts. ''' - release = get_os_codename_install_source(config('openstack-origin')) - configs = templating.OSConfigRenderer(templates_dir=TEMPLATES, - openstack_release=release) - plugin = remap_plugin(config('plugin')) - name = networking_name() +def remap_service(service_name): + ''' + Remap service names based on openstack release to deal + with changes to packaging + + :param service_name: name of service to remap + :returns: remapped service name or original value + ''' + source = get_os_codename_install_source(config('openstack-origin')) + for rename_source in SERVICE_RENAMES: + if (source >= rename_source and + service_name in SERVICE_RENAMES[rename_source]): + service_name = SERVICE_RENAMES[rename_source][service_name] + return service_name + + +def resolve_config_files(name, plugin, release): + ''' + Resolve configuration files and contexts + + :param name: neutron or quantum + :param plugin: shortname of plugin e.g. ovs + :param release: openstack release codename + :returns: dict of configuration files, contexts + and associated services + ''' + config_files = deepcopy(CONFIG_FILES) if plugin == 'ovs': # NOTE: deal with switch to ML2 plugin for >= icehouse - drop_config = NEUTRON_ML2_PLUGIN_CONF + drop_config = [NEUTRON_ML2_PLUGIN_CONF] if release >= 'icehouse': - drop_config = NEUTRON_OVS_PLUGIN_CONF - if drop_config in CONFIG_FILES[name][plugin]: - CONFIG_FILES[name][plugin].pop(drop_config) + # ovs -> ml2 + drop_config = [NEUTRON_OVS_PLUGIN_CONF] + + for _config in drop_config: + if _config in config_files[name][plugin]: + config_files[name][plugin].pop(_config) if is_relation_made('amqp-nova'): amqp_nova_ctxt = context.AMQPContext( @@ -593,11 +617,22 @@ def register_configs(): amqp_nova_ctxt = context.AMQPContext( ssl_dir=NOVA_CONF_DIR, rel_name='amqp') - CONFIG_FILES[name][plugin][NOVA_CONF][ + config_files[name][plugin][NOVA_CONF][ 'hook_contexts'].append(amqp_nova_ctxt) - for conf in CONFIG_FILES[name][plugin]: + return config_files + + +def register_configs(): + ''' Register config files with their respective contexts. ''' + release = get_os_codename_install_source(config('openstack-origin')) + plugin = remap_plugin(config('plugin')) + name = networking_name() + config_files = resolve_config_files(name, plugin, release) + configs = templating.OSConfigRenderer(templates_dir=TEMPLATES, + openstack_release=release) + for conf in config_files[name][plugin]: configs.register(conf, - CONFIG_FILES[name][plugin][conf]['hook_contexts']) + config_files[name][plugin][conf]['hook_contexts']) return configs @@ -619,15 +654,17 @@ def restart_map(): :returns: dict: A dictionary mapping config file to lists of services that should be restarted when file changes. ''' - _map = {} - plugin = config('plugin') + release = get_os_codename_install_source(config('openstack-origin')) + plugin = remap_plugin(config('plugin')) name = networking_name() - for f, ctxt in CONFIG_FILES[name][plugin].iteritems(): - svcs = [] + config_files = resolve_config_files(name, plugin, release) + _map = {} + for f, ctxt in config_files[name][plugin].iteritems(): + svcs = set() for svc in ctxt['services']: - svcs.append(svc) + svcs.add(remap_service(svc)) if svcs: - _map[f] = svcs + _map[f] = list(svcs) return _map diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..2cc5f64a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. +PyYAML>=3.1.0 +simplejson>=2.2.0 +netifaces>=0.10.4 +netaddr>=0.7.12,!=0.7.16 +Jinja2>=2.6 # BSD License (3 clause) +six>=1.9.0 +dnspython>=1.12.0 +psutil>=1.1.1,<2.0.0 +python-neutronclient>=2.6.0 diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000..3af44d73 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,8 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. +coverage>=3.6 +mock>=1.2 +flake8>=2.2.4,<=2.4.1 +os-testr>=0.4.1 +charm-tools diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..8278f3dc --- /dev/null +++ b/tox.ini @@ -0,0 +1,29 @@ +[tox] +envlist = pep8,py27 +skipsdist = True + +[testenv] +setenv = VIRTUAL_ENV={envdir} + PYTHONHASHSEED=0 +install_command = + pip install --allow-unverified python-apt {opts} {packages} +commands = ostestr {posargs} + +[testenv:py27] +basepython = python2.7 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +[testenv:pep8] +basepython = python2.7 +deps = -r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt +commands = flake8 {posargs} hooks unit_tests tests actions + charm proof + +[testenv:venv] +commands = {posargs} + +[flake8] +ignore = E402,E226 +exclude = hooks/charmhelpers diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py index 4c31893f..df10613e 100644 --- a/unit_tests/test_actions_openstack_upgrade.py +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -14,6 +14,7 @@ with patch('charmhelpers.core.hookenv.status_set'): TO_PATCH = [ 'do_openstack_upgrade', 'config_changed', + 'get_common_package', ] diff --git a/unit_tests/test_neutron_contexts.py b/unit_tests/test_neutron_contexts.py index 100de7f7..ad24050c 100644 --- a/unit_tests/test_neutron_contexts.py +++ b/unit_tests/test_neutron_contexts.py @@ -55,7 +55,7 @@ class TestL3AgentContext(CharmTestCase): self.config.side_effect = self.test_config.get @patch('neutron_contexts.NeutronAPIContext') - def test_no_ext_netid(self, _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') diff --git a/unit_tests/test_neutron_utils.py b/unit_tests/test_neutron_utils.py index d33bee05..70609535 100644 --- a/unit_tests/test_neutron_utils.py +++ b/unit_tests/test_neutron_utils.py @@ -1,4 +1,4 @@ -from mock import MagicMock, call, patch +from mock import MagicMock, call, patch, ANY import collections import charmhelpers.contrib.openstack.templating as templating @@ -287,11 +287,7 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.NEUTRON_OVS_PLUGIN_CONF, neutron_utils.EXT_PORT_CONF] for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['neutron'][neutron_utils.OVS][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_register_configs_ovs_odl(self): self.config.side_effect = self.test_config.get @@ -306,12 +302,7 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.NEUTRON_L3_AGENT_CONF, neutron_utils.EXT_PORT_CONF] for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['neutron'] - [neutron_utils.OVS_ODL][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_register_configs_amqp_nova(self): self.config.return_value = 'ovs' @@ -325,11 +316,7 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.NEUTRON_OVS_PLUGIN_CONF, neutron_utils.EXT_PORT_CONF] for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['neutron'][neutron_utils.OVS][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_restart_map_ovs(self): self.config.return_value = 'ovs' @@ -411,11 +398,7 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.NOVA_CONF, neutron_utils.NEUTRON_CONF] for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['neutron'][neutron_utils.NVP][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_register_configs_nsx(self): self.config.return_value = 'nsx' @@ -425,11 +408,7 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.NOVA_CONF, neutron_utils.NEUTRON_CONF] for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['neutron'][neutron_utils.NSX][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_stop_services_nvp(self): self.config.return_value = 'nvp' @@ -482,13 +461,8 @@ class TestQuantumUtils(CharmTestCase): neutron_utils.QUANTUM_L3_AGENT_CONF, neutron_utils.QUANTUM_OVS_PLUGIN_CONF, neutron_utils.EXT_PORT_CONF] - print configs.register.mock_calls for conf in confs: - configs.register.assert_any_call( - conf, - neutron_utils.CONFIG_FILES['quantum'][neutron_utils.OVS][conf] - ['hook_contexts'] - ) + configs.register.assert_any_call(conf, ANY) def test_get_common_package_quantum(self): self.get_os_codename_package.return_value = 'folsom'