diff --git a/.bzrignore b/.bzrignore index a2c7a097..421e2bda 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,2 +1,3 @@ bin .coverage +tags diff --git a/Makefile b/Makefile index 29cc596e..c2bddd9b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PYTHON := /usr/bin/env python lint: - @flake8 --exclude hooks/charmhelpers hooks unit_tests tests + @flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests @charm proof unit_test: @@ -24,7 +24,9 @@ test: # raise_status() messages to stderr: # https://bugs.launchpad.net/amulet/+bug/1320357 @juju test -v -p AMULET_HTTP_PROXY --timeout 900 \ - 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse + 00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse \ + 16-basic-trusty-icehouse-git 17-basic-trusty-juno \ + 18-basic-trusty-juno-git publish: lint unit_test bzr push lp:charms/quantum-gateway diff --git a/README.md b/README.md index afade695..22debdba 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,94 @@ OpenStack upstream documentation recomments a MTU value of 1400: Note that this option was added in Havana and will be ignored in older releases. +Deploying from source +===================== + +The minimum openstack-origin-git config required to deploy from source is: + + openstack-origin-git: + "repositories: + - {name: requirements, + repository: 'git://git.openstack.org/openstack/requirements', + branch: stable/juno} + - {name: neutron, + repository: 'git://git.openstack.org/openstack/neutron', + branch: stable/juno}" + +Note that there are only two 'name' values the charm knows about: 'requirements' +and 'neutron'. These repositories must correspond to these 'name' values. +Additionally, the requirements repository must be specified first and the +neutron repository must be specified last. All other repostories are installed +in the order in which they are specified. + +The following is a full list of current tip repos (may not be up-to-date): + + openstack-origin-git: + "repositories: + - {name: requirements, + repository: 'git://git.openstack.org/openstack/requirements', + branch: master} + - {name: oslo-concurrency, + repository: 'git://git.openstack.org/openstack/oslo.concurrency', + branch: master} + - {name: oslo-config, + repository: 'git://git.openstack.org/openstack/oslo.config', + branch: master} + - {name: oslo-context, + repository: 'git://git.openstack.org/openstack/oslo.context.git', + branch: master} + - {name: oslo-db, + repository: 'git://git.openstack.org/openstack/oslo.db', + branch: master} + - {name: oslo-i18n, + repository: 'git://git.openstack.org/openstack/oslo.i18n', + branch: master} + - {name: oslo-messaging, + repository: 'git://git.openstack.org/openstack/oslo.messaging.git', + branch: master} + - {name: oslo-middleware, + repository': 'git://git.openstack.org/openstack/oslo.middleware.git', + branch: master} + - {name: oslo-rootwrap', + repository: 'git://git.openstack.org/openstack/oslo.rootwrap.git', + branch: master} + - {name: oslo-serialization, + repository: 'git://git.openstack.org/openstack/oslo.serialization', + branch: master} + - {name: oslo-utils, + repository: 'git://git.openstack.org/openstack/oslo.utils', + branch: master} + - {name: pbr, + repository: 'git://git.openstack.org/openstack-dev/pbr', + branch: master} + - {name: stevedore, + repository: 'git://git.openstack.org/openstack/stevedore.git', + branch: 'master'} + - {name: python-keystoneclient, + repository: 'git://git.openstack.org/openstack/python-keystoneclient', + branch: master} + - {name: python-neutronclient, + repository: 'git://git.openstack.org/openstack/python-neutronclient.git', + branch: master} + - {name: python-novaclient, + repository': 'git://git.openstack.org/openstack/python-novaclient.git', + branch: master} + - {name: keystonemiddleware, + repository: 'git://git.openstack.org/openstack/keystonemiddleware', + branch: master} + - {name: neutron-fwaas, + repository': 'git://git.openstack.org/openstack/neutron-fwaas.git', + branch: master} + - {name: neutron-lbaas, + repository: 'git://git.openstack.org/openstack/neutron-lbaas.git', + branch: master} + - {name: neutron-vpnaas, + repository: 'git://git.openstack.org/openstack/neutron-vpnaas.git', + branch: master} + - {name: neutron, + repository: 'git://git.openstack.org/openstack/neutron', + branch: master}" + TODO ---- diff --git a/actions.yaml b/actions.yaml new file mode 100644 index 00000000..40828caa --- /dev/null +++ b/actions.yaml @@ -0,0 +1,2 @@ +git-reinstall: + description: Reinstall quantum-gateway from the openstack-origin-git repositories. diff --git a/actions/git-reinstall b/actions/git-reinstall new file mode 120000 index 00000000..ff684984 --- /dev/null +++ b/actions/git-reinstall @@ -0,0 +1 @@ +git_reinstall.py \ No newline at end of file diff --git a/actions/git_reinstall.py b/actions/git_reinstall.py new file mode 100755 index 00000000..2eab3a33 --- /dev/null +++ b/actions/git_reinstall.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +import sys +import traceback + +sys.path.append('hooks/') + +from charmhelpers.contrib.openstack.utils import ( + git_install_requested, +) + +from charmhelpers.core.hookenv import ( + action_set, + action_fail, + config, +) + +from quantum_utils import ( + git_install, +) + + +def git_reinstall(): + """Reinstall from source and restart services. + + If the openstack-origin-git config option was used to install openstack + from source git repositories, then this action can be used to reinstall + from updated git repositories, followed by a restart of services.""" + if not git_install_requested(): + action_fail('openstack-origin-git is not configured') + return + + try: + git_install(config('openstack-origin-git')) + except: + action_set({'traceback': traceback.format_exc()}) + action_fail('git-reinstall resulted in an unexpected error') + + +if __name__ == '__main__': + git_reinstall() diff --git a/config.yaml b/config.yaml index 6bf27e47..abff70d5 100644 --- a/config.yaml +++ b/config.yaml @@ -37,6 +37,22 @@ options: - deb http://my.archive.com/ubuntu main|KEYID . Note that quantum/neutron is only supported >= Folsom. + + Note that when openstack-origin-git is specified, openstack + specific packages will be installed from source rather than + from the openstack-origin repository. + openstack-origin-git: + default: + type: string + description: | + Specifies a YAML-formatted dictionary listing the git + repositories and branches from which to install OpenStack and + its dependencies. + + Note that the installed config files will be determined based on + the OpenStack release of the openstack-origin option. + + For more details see README.md. run-internal-router: type: string default: all diff --git a/hooks/charmhelpers/contrib/openstack/context.py b/hooks/charmhelpers/contrib/openstack/context.py index 45e65790..dd51bfbb 100644 --- a/hooks/charmhelpers/contrib/openstack/context.py +++ b/hooks/charmhelpers/contrib/openstack/context.py @@ -320,14 +320,15 @@ def db_ssl(rdata, ctxt, ssl_dir): class IdentityServiceContext(OSContextGenerator): - interfaces = ['identity-service'] - def __init__(self, service=None, service_user=None): + def __init__(self, service=None, service_user=None, rel_name='identity-service'): self.service = service self.service_user = service_user + self.rel_name = rel_name + self.interfaces = [self.rel_name] def __call__(self): - log('Generating template context for identity-service', level=DEBUG) + log('Generating template context for ' + self.rel_name, level=DEBUG) ctxt = {} if self.service and self.service_user: @@ -341,7 +342,7 @@ class IdentityServiceContext(OSContextGenerator): ctxt['signing_dir'] = cachedir - for rid in relation_ids('identity-service'): + for rid in relation_ids(self.rel_name): for unit in related_units(rid): rdata = relation_get(rid=rid, unit=unit) serv_host = rdata.get('service_host') diff --git a/hooks/charmhelpers/contrib/openstack/templates/git.upstart b/hooks/charmhelpers/contrib/openstack/templates/git.upstart index da94ad12..62af9204 100644 --- a/hooks/charmhelpers/contrib/openstack/templates/git.upstart +++ b/hooks/charmhelpers/contrib/openstack/templates/git.upstart @@ -9,5 +9,7 @@ respawn exec start-stop-daemon --start --chuid {{ user_name }} \ --chdir {{ start_dir }} --name {{ process_name }} \ --exec {{ executable_name }} -- \ + {% for config_file in config_files -%} --config-file={{ config_file }} \ + {% endfor -%} --log-file={{ log_file }} diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/hooks/charmhelpers/contrib/openstack/utils.py index 78c5e2df..5a12c9d6 100644 --- a/hooks/charmhelpers/contrib/openstack/utils.py +++ b/hooks/charmhelpers/contrib/openstack/utils.py @@ -510,8 +510,10 @@ def git_clone_and_install(projects_yaml, core_project): repository: 'git://git.openstack.org/openstack/requirements.git', branch: 'stable/icehouse'} directory: /mnt/openstack-git + http_proxy: http://squid.internal:3128 + https_proxy: https://squid.internal:3128 - The directory key is optional. + The directory, http_proxy, and https_proxy keys are optional. """ global requirements_dir parent_dir = '/mnt/openstack-git' @@ -522,6 +524,12 @@ def git_clone_and_install(projects_yaml, core_project): projects = yaml.load(projects_yaml) _git_validate_projects_yaml(projects, core_project) + if 'http_proxy' in projects.keys(): + os.environ['http_proxy'] = projects['http_proxy'] + + if 'https_proxy' in projects.keys(): + os.environ['https_proxy'] = projects['https_proxy'] + if 'directory' in projects.keys(): parent_dir = projects['directory'] diff --git a/hooks/charmhelpers/core/hookenv.py b/hooks/charmhelpers/core/hookenv.py index 715dd4c5..86f805f1 100644 --- a/hooks/charmhelpers/core/hookenv.py +++ b/hooks/charmhelpers/core/hookenv.py @@ -20,11 +20,13 @@ # Authors: # Charm Helpers Developers +from __future__ import print_function import os import json import yaml import subprocess import sys +import errno from subprocess import CalledProcessError import six @@ -87,7 +89,18 @@ def log(message, level=None): if not isinstance(message, six.string_types): message = repr(message) command += [message] - subprocess.call(command) + # Missing juju-log should not cause failures in unit tests + # Send log output to stderr + try: + subprocess.call(command) + except OSError as e: + if e.errno == errno.ENOENT: + if level: + message = "{}: {}".format(level, message) + message = "juju-log: {}".format(message) + print(message, file=sys.stderr) + else: + raise class Serializable(UserDict): diff --git a/hooks/quantum_hooks.py b/hooks/quantum_hooks.py index 61e81f7a..f01de3fd 100755 --- a/hooks/quantum_hooks.py +++ b/hooks/quantum_hooks.py @@ -30,6 +30,7 @@ from charmhelpers.contrib.hahelpers.apache import( install_ca_cert ) from charmhelpers.contrib.openstack.utils import ( + config_value_changed, configure_installation_source, openstack_upgrade_available, os_requires_version, @@ -50,6 +51,8 @@ from quantum_utils import ( get_early_packages, get_common_package, get_topics, + git_install, + git_install_requested, valid_plugin, configure_ovs, stop_services, @@ -82,6 +85,7 @@ def install(): fatal=True) apt_install(filter_installed_packages(get_packages()), fatal=True) + git_install(config('openstack-origin-git')) else: log('Please provide a valid plugin config', level=ERROR) sys.exit(1) @@ -94,8 +98,15 @@ def install(): @restart_on_change(restart_map()) def config_changed(): global CONFIGS - if openstack_upgrade_available(get_common_package()): - CONFIGS = do_openstack_upgrade() + if git_install_requested(): + if config_value_changed('openstack-origin-git'): + git_install(config('openstack-origin-git')) + CONFIGS.write_all() + else: + if openstack_upgrade_available(get_common_package()): + do_openstack_upgrade() + CONFIGS.write_all() + update_nrpe_config() sysctl_dict = config('sysctl') @@ -120,10 +131,11 @@ def config_changed(): log('Please provide a valid plugin config', level=ERROR) sys.exit(1) if config('plugin') == 'n1kv': - if config('enable-l3-agent'): - apt_install(filter_installed_packages('neutron-l3-agent')) - else: - apt_purge('neutron-l3-agent') + if not git_install_requested(): + if config('enable-l3-agent'): + apt_install(filter_installed_packages('neutron-l3-agent')) + else: + apt_purge('neutron-l3-agent') # Setup legacy ha configurations update_legacy_ha_files() diff --git a/hooks/quantum_utils.py b/hooks/quantum_utils.py index d96475b8..3dd8fa1b 100644 --- a/hooks/quantum_utils.py +++ b/hooks/quantum_utils.py @@ -1,14 +1,20 @@ import os +import shutil import subprocess from shutil import copy2 from charmhelpers.core.host import ( + adduser, + add_group, + add_user_to_group, + lsb_release, mkdir, service_running, service_stop, service_restart, - lsb_release, + write_file, ) from charmhelpers.core.hookenv import ( + charm_dir, log, DEBUG, INFO, @@ -18,6 +24,7 @@ from charmhelpers.core.hookenv import ( unit_private_ip, is_relation_made, ) +from charmhelpers.core.templating import render from charmhelpers.fetch import ( apt_upgrade, apt_update, @@ -32,6 +39,9 @@ from charmhelpers.contrib.openstack.utils import ( configure_installation_source, get_os_codename_install_source, get_os_codename_package, + git_install_requested, + git_clone_and_install, + git_src_dir, get_hostname ) @@ -174,6 +184,39 @@ LEGACY_FILES_MAP = { LEGACY_RES_MAP = ['res_monitor'] L3HA_PACKAGES = ['keepalived'] +BASE_GIT_PACKAGES = [ + 'dnsmasq', + 'libxml2-dev', + 'libxslt1-dev', + 'python-dev', + 'python-pip', + 'python-setuptools', + 'zlib1g-dev', +] + +# ubuntu packages that should not be installed when deploying from git +GIT_PACKAGE_BLACKLIST = [ + 'nova-api-metadata', + 'neutron-common', + 'neutron-dhcp-agent', + 'neutron-l3-agent', + 'neutron-lbaas-agent', + 'neutron-metadata-agent', + 'neutron-metering-agent', + 'neutron-plugin-cisco', + 'neutron-plugin-metering-agent', + 'neutron-plugin-openvswitch-agent', + 'neutron-plugin-vpn-agent', + 'neutron-vpn-agent', + 'python-neutron-fwaas', + 'python-oslo.config', + 'quantum-common', + 'quantum-dhcp-agent', + 'quantum-l3-agent', + 'quantum-metadata-agent', + 'quantum-plugin-openvswitch-agent', +] + def get_early_packages(): '''Return a list of package for pre-install based on configured plugin''' @@ -204,6 +247,15 @@ def get_packages(): if source >= 'kilo': packages.append('python-neutron-fwaas') packages.extend(determine_l3ha_packages()) + + if git_install_requested(): + packages = list(set(packages)) + packages.extend(BASE_GIT_PACKAGES) + # don't include packages that will be installed from git + for p in GIT_PACKAGE_BLACKLIST: + if p in packages: + packages.remove(p) + return packages @@ -612,12 +664,6 @@ def do_openstack_upgrade(): apt_install(get_early_packages(), fatal=True) apt_install(get_packages(), fatal=True) - # set CONFIGS to load templates from new release - configs = register_configs() - configs.write_all() - [service_restart(s) for s in services()] - return configs - def configure_ovs(): if config('plugin') == OVS: @@ -760,3 +806,526 @@ def get_topics(): topics.append('q-agent-notifier-dvr-update') topics.append('q-agent-notifier-l2population-update') return topics + + +def git_install(projects_yaml): + """Perform setup, and install git repos specified in yaml parameter.""" + if git_install_requested(): + git_pre_install() + git_clone_and_install(projects_yaml, core_project='neutron') + git_post_install(projects_yaml) + + +def git_pre_install(): + """Perform pre-install setup.""" + dirs = [ + '/etc/neutron', + '/etc/neutron/rootwrap.d', + '/etc/neutron/plugins', + '/etc/nova', + '/var/lib/neutron', + '/var/lib/neutron/lock', + '/var/log/neutron', + ] + + logs = [ + '/var/log/neutron/bigswitch-agent.log', + '/var/log/neutron/dhcp-agent.log', + '/var/log/neutron/l3-agent.log', + '/var/log/neutron/lbaas-agent.log', + '/var/log/neutron/ibm-agent.log', + '/var/log/neutron/linuxbridge-agent.log', + '/var/log/neutron/metadata-agent.log', + '/var/log/neutron/metering_agent.log', + '/var/log/neutron/mlnx-agent.log', + '/var/log/neutron/nec-agent.log', + '/var/log/neutron/nvsd-agent.log', + '/var/log/neutron/openflow-agent.log', + '/var/log/neutron/openvswitch-agent.log', + '/var/log/neutron/ovs-cleanup.log', + '/var/log/neutron/ryu-agent.log', + '/var/log/neutron/server.log', + '/var/log/neutron/sriov-agent.log', + '/var/log/neutron/vpn_agent.log', + ] + + adduser('neutron', shell='/bin/bash', system_user=True) + add_group('neutron', system_group=True) + add_user_to_group('neutron', 'neutron') + + for d in dirs: + mkdir(d, owner='neutron', group='neutron', perms=0700, force=False) + + for l in logs: + write_file(l, '', owner='neutron', group='neutron', perms=0644) + + +def git_post_install(projects_yaml): + """Perform post-install setup.""" + src_etc = os.path.join(git_src_dir(projects_yaml, 'neutron'), 'etc') + etc_configs = { + 'api-paste': { + 'src': os.path.join(src_etc, 'api-paste.ini'), + 'dest': '/etc/neutron/api-paste.ini', + }, + 'dhcp_agent': { + 'src': os.path.join(src_etc, 'dhcp_agent.ini'), + 'dest': '/etc/neutron/dhcp_agent.ini', + }, + 'fwaas_driver': { + 'src': os.path.join(src_etc, 'fwaas_driver.ini'), + 'dest': '/etc/neutron/fwaas_driver.ini', + }, + 'l3_agent': { + 'src': os.path.join(src_etc, 'l3_agent.ini'), + 'dest': '/etc/neutron/l3_agent.ini', + }, + 'lbaas_agent': { + 'src': os.path.join(src_etc, 'lbaas_agent.ini'), + 'dest': '/etc/neutron/lbaas_agent.ini', + }, + 'metadata_agent': { + 'src': os.path.join(src_etc, 'metadata_agent.ini'), + 'dest': '/etc/neutron/metadata_agent.ini', + }, + 'metering_agent': { + 'src': os.path.join(src_etc, 'metering_agent.ini'), + 'dest': '/etc/neutron/metering_agent.ini', + }, + 'policy': { + 'src': os.path.join(src_etc, 'policy.json'), + 'dest': '/etc/neutron/policy.json', + }, + 'rootwrap': { + 'src': os.path.join(src_etc, 'rootwrap.conf'), + 'dest': '/etc/neutron/rootwrap.conf', + }, + 'vpn_agent': { + 'src': os.path.join(src_etc, 'vpn_agent.ini'), + 'dest': '/etc/neutron/vpn_agent.ini', + }, + } + + for conf, files in etc_configs.iteritems(): + if os.path.exists(files['src']): + shutil.copyfile(files['src'], files['dest']) + + src_plugins = os.path.join(src_etc, 'neutron/plugins') + plugins_configs = { + 'bigswitch': { + 'src': os.path.join(src_plugins, 'bigswitch'), + 'dest': '/etc/neutron/plugins/bigswitch', + }, + 'brocade': { + 'src': os.path.join(src_plugins, 'brocade'), + 'dest': '/etc/neutron/plugins/brocade', + }, + 'cisco': { + 'src': os.path.join(src_plugins, 'cisco'), + 'dest': '/etc/neutron/plugins/cisco', + }, + 'hyperv': { + 'src': os.path.join(src_plugins, 'hyperv'), + 'dest': '/etc/neutron/plugins/hyperv', + }, + 'ibm': { + 'src': os.path.join(src_plugins, 'ibm'), + 'dest': '/etc/neutron/plugins/ibm', + }, + 'metaplugin': { + 'src': os.path.join(src_plugins, 'metaplugin'), + 'dest': '/etc/neutron/plugins/metaplugin', + }, + 'midonet': { + 'src': os.path.join(src_plugins, 'midonet'), + 'dest': '/etc/neutron/plugins/midonet', + }, + 'ml2': { + 'src': os.path.join(src_plugins, 'ml2'), + 'dest': '/etc/neutron/plugins/ml2', + }, + 'mlnx': { + 'src': os.path.join(src_plugins, 'mlnx'), + 'dest': '/etc/neutron/plugins/mlnx', + }, + 'nec': { + 'src': os.path.join(src_plugins, 'nec'), + 'dest': '/etc/neutron/plugins/nec', + }, + 'nuage': { + 'src': os.path.join(src_plugins, 'nuage'), + 'dest': '/etc/neutron/plugins/nuage', + }, + 'oneconvergence': { + 'src': os.path.join(src_plugins, 'oneconvergence'), + 'dest': '/etc/neutron/plugins/oneconvergence', + }, + 'opencontrail': { + 'src': os.path.join(src_plugins, 'opencontrail'), + 'dest': '/etc/neutron/plugins/opencontrail', + }, + 'plumgrid': { + 'src': os.path.join(src_plugins, 'plumgrid'), + 'dest': '/etc/neutron/plugins/plumgrid', + }, + 'ryu': { + 'src': os.path.join(src_plugins, 'ryu'), + 'dest': '/etc/neutron/plugins/ryu', + }, + 'vmware': { + 'src': os.path.join(src_plugins, 'vmware'), + 'dest': '/etc/neutron/plugins/vmware', + }, + } + + for conf, dirs in plugins_configs.iteritems(): + if os.path.exists(dirs['src']): + if os.path.exists(dirs['dest']): + shutil.rmtree(dirs['dest']) + shutil.copytree(dirs['src'], dirs['dest']) + + src_rootwrap = os.path.join(src_etc, 'neutron/rootwrap.d') + rootwrap_configs = { + 'debug-filters': { + 'src': os.path.join(src_rootwrap, 'debug.filters'), + 'dest': '/etc/neutron/rootwrap.d/debug.filters', + }, + 'dhcp-filters': { + 'src': os.path.join(src_rootwrap, 'dhcp.filters'), + 'dest': '/etc/neutron/rootwrap.d/dhcp.filters', + }, + 'ipset-firewall-filters': { + 'src': os.path.join(src_rootwrap, 'ipset-firewall.filters'), + 'dest': '/etc/neutron/rootwrap.d/ipset-firewall.filters', + }, + 'iptables-firewall-filters': { + 'src': os.path.join(src_rootwrap, 'iptables-firewall.filters'), + 'dest': '/etc/neutron/rootwrap.d/iptables-firewall.filters', + }, + 'l3-filters': { + 'src': os.path.join(src_rootwrap, 'l3.filters'), + 'dest': '/etc/neutron/rootwrap.d/l3.filters', + }, + 'lbaas-haproxy': { + 'src': os.path.join(src_rootwrap, 'lbaas-haproxy.filters'), + 'dest': '/etc/neutron/rootwrap.d/lbaas-haproxy.filters', + }, + 'linuxbridge-plugin': { + 'src': os.path.join(src_rootwrap, 'linuxbridge-plugin.filters'), + 'dest': '/etc/neutron/rootwrap.d/linuxbridge-plugin.filters', + }, + 'nec-plugin': { + 'src': os.path.join(src_rootwrap, 'nec-plugin.filters'), + 'dest': '/etc/neutron/rootwrap.d/nec-plugin.filters', + }, + 'openvswitch-plugin': { + 'src': os.path.join(src_rootwrap, 'openvswitch-plugin.filters'), + 'dest': '/etc/neutron/rootwrap.d/openvswitch-plugin.filters', + }, + 'ryu-plugin': { + 'src': os.path.join(src_rootwrap, 'ryu-plugin.filters'), + 'dest': '/etc/neutron/rootwrap.d/ryu-plugin.filters', + }, + 'vpnaas': { + 'src': os.path.join(src_rootwrap, 'vpnaas.filters'), + 'dest': '/etc/neutron/rootwrap.d/vpnaas.filters', + }, + } + + for conf, files in rootwrap_configs.iteritems(): + if os.path.exists(files['src']): + shutil.copyfile(files['src'], files['dest']) + + symlinks = [ + {'src': '/usr/local/bin/neutron-rootwrap', + 'link': '/usr/bin/neutron-rootwrap'}, + ] + + for s in symlinks: + if os.path.lexists(s['link']): + os.remove(s['link']) + os.symlink(s['src'], s['link']) + + render('neutron_sudoers', + '/etc/sudoers.d/neutron_sudoers', {}, perms=0o440) + render('cron.d/neutron-dhcp-agent-netns-cleanup', + '/etc/cron.d/neutron-dhcp-agent-netns-cleanup', {}, perms=0o755) + render('cron.d/neutron-l3-agent-netns-cleanup', + '/etc/cron.d/neutron-l3-agent-netns-cleanup', {}, perms=0o755) + render('cron.d/neutron-lbaas-agent-netns-cleanup', + '/etc/cron.d/neutron-lbaas-agent-netns-cleanup', {}, perms=0o755) + + service_name = 'quantum-gateway' + user_name = 'neutron' + neutron_api_context = { + 'service_description': 'Neutron API server', + 'service_name': service_name, + 'process_name': 'neutron-server', + } + neutron_dhcp_agent_context = { + 'service_description': 'Neutron DHCP Agent', + 'service_name': service_name, + 'process_name': 'neutron-dhcp-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/dhcp_agent.ini'], + 'log_file': '/var/log/neutron/dhcp-agent.log', + } + neutron_l3_agent_context = { + 'service_description': 'Neutron L3 Agent', + 'service_name': service_name, + 'process_name': 'neutron-l3-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/l3_agent.ini', + '/etc/neutron/fwaas_driver.ini'], + 'log_file': '/var/log/neutron/l3-agent.log', + } + neutron_lbaas_agent_context = { + 'service_description': 'Neutron LBaaS Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-lbaas-agent', + 'executable_name': '/usr/local/bin/neutron-lbaas-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/lbaas_agent.ini'], + 'log_file': '/var/log/neutron/lbaas-agent.log', + } + neutron_metadata_agent_context = { + 'service_description': 'Neutron Metadata Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-metadata-agent', + 'executable_name': '/usr/local/bin/neutron-metadata-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/metadata_agent.ini'], + 'log_file': '/var/log/neutron/metadata-agent.log', + } + neutron_metering_agent_context = { + 'service_description': 'Neutron Metering Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-metering-agent', + 'executable_name': '/usr/local/bin/neutron-metering-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/metering_agent.ini'], + 'log_file': '/var/log/neutron/metering-agent.log', + } + neutron_ovs_cleanup_context = { + 'service_description': 'Neutron OVS cleanup', + 'service_name': service_name, + 'process_name': 'neutron-ovs-cleanup', + 'config_file': '/etc/neutron/neutron.conf', + 'log_file': '/var/log/neutron/ovs-cleanup.log', + } + neutron_plugin_bigswitch_context = { + 'service_description': 'Neutron BigSwitch Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-restproxy-agent', + 'executable_name': '/usr/local/bin/neutron-restproxy-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/bigswitch/restproxy.ini'], + 'log_file': '/var/log/neutron/bigswitch-agent.log', + } + neutron_plugin_ibm_context = { + 'service_description': 'Neutron IBM SDN Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ibm-agent', + 'executable_name': '/usr/local/bin/neutron-ibm-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini'], + 'log_file': '/var/log/neutron/ibm-agent.log', + } + neutron_plugin_linuxbridge_context = { + 'service_description': 'Neutron Linux Bridge Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-linuxbridge-agent', + 'executable_name': '/usr/local/bin/neutron-linuxbridge-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf.ini'], + 'log_file': '/var/log/neutron/linuxbridge-agent.log', + } + neutron_plugin_mlnx_context = { + 'service_description': 'Neutron MLNX Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-mlnx-agent', + 'executable_name': '/usr/local/bin/neutron-mlnx-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/mlnx/mlnx_conf.ini'], + 'log_file': '/var/log/neutron/mlnx-agent.log', + } + neutron_plugin_nec_context = { + 'service_description': 'Neutron NEC Plugin Agent', + 'service_name': service_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-nec-agent', + 'executable_name': '/usr/local/bin/neutron-nec-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/nec/nec.ini'], + 'log_file': '/var/log/neutron/nec-agent.log', + } + neutron_plugin_oneconvergence_context = { + 'service_description': 'Neutron One Convergence Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-nvsd-agent', + 'executable_name': '/usr/local/bin/neutron-nvsd-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/oneconvergence/nvsdplugin.ini'], + 'log_file': '/var/log/neutron/nvsd-agent.log', + } + neutron_plugin_openflow_context = { + 'service_description': 'Neutron OpenFlow Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ofagent-agent', + 'executable_name': '/usr/local/bin/neutron-ofagent-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf_ofa.ini'], + 'log_file': '/var/log/neutron/openflow-agent.log', + } + neutron_plugin_openvswitch_context = { + 'service_description': 'Neutron OpenvSwitch Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-openvswitch-agent', + 'executable_name': '/usr/local/bin/neutron-openvswitch-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf.ini'], + 'log_file': '/var/log/neutron/openvswitch-agent.log', + } + neutron_plugin_ryu_context = { + 'service_description': 'Neutron RYU Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ryu-agent', + 'executable_name': '/usr/local/bin/neutron-ryu-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ryu/ryu.ini'], + 'log_file': '/var/log/neutron/ryu-agent.log', + } + neutron_plugin_sriov_context = { + 'service_description': 'Neutron SRIOV SDN Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-sriov-nic-agent', + 'executable_name': '/usr/local/bin/neutron-sriov-nic-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf_sriov'], + 'log_file': '/var/log/neutron/sriov-agent.log', + } + neutron_vpn_agent_context = { + 'service_description': 'Neutron VPN Agent', + 'service_name': service_name, + 'process_name': 'neutron-vpn-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/vpn_agent.ini', + '/etc/neutron/l3_agent.ini', + '/etc/neutron/fwaas_driver.ini'], + 'log_file': '/var/log/neutron/vpn_agent.log', + } + + # NOTE(coreycb): Needs systemd support + templates_dir = 'hooks/charmhelpers/contrib/openstack/templates' + templates_dir = os.path.join(charm_dir(), templates_dir) + render('upstart/neutron-agent.upstart', + '/etc/init/neutron-dhcp-agent.conf', + neutron_dhcp_agent_context, perms=0o644) + render('upstart/neutron-agent.upstart', + '/etc/init/neutron-l3-agent.conf', + neutron_l3_agent_context, perms=0o644) + render('git.upstart', + '/etc/init/neutron-lbaas-agent.conf', + neutron_lbaas_agent_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-metadata-agent.conf', + neutron_metadata_agent_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-metering-agent.conf', + neutron_metering_agent_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-ovs-cleanup.conf', + neutron_ovs_cleanup_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-bigswitch-agent.conf', + neutron_plugin_bigswitch_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-ibm-agent.conf', + neutron_plugin_ibm_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-linuxbridge-agent.conf', + neutron_plugin_linuxbridge_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-mlnx-agent.conf', + neutron_plugin_mlnx_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-nec-agent.conf', + neutron_plugin_nec_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-oneconvergence-agent.conf', + neutron_plugin_oneconvergence_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-openflow-agent.conf', + neutron_plugin_openflow_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-openvswitch-agent.conf', + neutron_plugin_openvswitch_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-ryu-agent.conf', + neutron_plugin_ryu_context, perms=0o644, + templates_dir=templates_dir) + render('git.upstart', + '/etc/init/neutron-plugin-sriov-agent.conf', + neutron_plugin_sriov_context, perms=0o644, + templates_dir=templates_dir) + render('upstart/neutron-server.upstart', + '/etc/init/neutron-server.conf', + neutron_api_context, perms=0o644) + render('upstart/neutron-agent.upstart', + '/etc/init/neutron-vpn-agent.conf', + neutron_vpn_agent_context, perms=0o644) + + service_restart('neutron-dhcp-agent') + service_restart('neutron-l3-agent') + service_restart('neutron-lbaas-agent') + service_restart('neutron-metadata-agent') + service_restart('neutron-metering-agent') + service_restart('neutron-ovs-cleanup') + service_restart('neutron-plugin-bigswitch') + service_restart('neutron-plugin-ibm-agent') + service_restart('neutron-plugin-linuxbridge-agent') + service_restart('neutron-plugin-mlnx-agent') + service_restart('neutron-plugin-nec-agent') + service_restart('neutron-plugin-oneconvergence-agent') + service_restart('neutron-plugin-openflow-agent') + service_restart('neutron-plugin-openvswitch-agent') + service_restart('neutron-plugin-ryu-agent') + service_restart('neutron-plugin-sriov-agent') + service_restart('neutron-server') + service_restart('neutron-vpn-agent') diff --git a/templates/cron.d/neutron-dhcp-agent-netns-cleanup b/templates/cron.d/neutron-dhcp-agent-netns-cleanup new file mode 100644 index 00000000..f42d71e2 --- /dev/null +++ b/templates/cron.d/neutron-dhcp-agent-netns-cleanup @@ -0,0 +1,4 @@ +# vim: set filetype=crontab: +# Periodically cleans Neutron's network namespaces on behalf of the Neutron +# DHCP agent. +30 * * * * neutron if [ -x /usr/local/bin/neutron-netns-cleanup ] ; then /usr/local/bin/neutron-netns-cleanup --config-file=/etc/neutron/neutron.conf --config-file=/etc/neutron/dhcp_agent.ini >/dev/null 2>&1; fi diff --git a/templates/cron.d/neutron-l3-agent-netns-cleanup b/templates/cron.d/neutron-l3-agent-netns-cleanup new file mode 100644 index 00000000..f13bfb11 --- /dev/null +++ b/templates/cron.d/neutron-l3-agent-netns-cleanup @@ -0,0 +1,4 @@ +# vim: set filetype=crontab: +# Periodically cleans Neutron's network namespaces on behalf of the Neutron +# L3 agent. +0 * * * * neutron if [ -x /usr/local/bin/neutron-netns-cleanup ] ; then /usr/local/bin/neutron-netns-cleanup --config-file=/etc/neutron/neutron.conf --config-file=/etc/neutron/l3_agent.ini >/dev/null 2>&1; fi diff --git a/templates/cron.d/neutron-lbaas-agent-netns-cleanup b/templates/cron.d/neutron-lbaas-agent-netns-cleanup new file mode 100644 index 00000000..6ffaa7cf --- /dev/null +++ b/templates/cron.d/neutron-lbaas-agent-netns-cleanup @@ -0,0 +1,4 @@ +# vim: set filetype=crontab: +# Periodically cleans Neutron's network namespaces on behalf of the Neutron +# L3 agent. +0 * * * * neutron if [ -x /usr/local/bin/neutron-netns-cleanup ] ; then /usr/local/bin/neutron-netns-cleanup --config-file=/etc/neutron/neutron.conf --config-file=/etc/neutron/lbaas_agent.ini >/dev/null 2>&1; fi diff --git a/templates/neutron_sudoers b/templates/neutron_sudoers new file mode 100644 index 00000000..d6fec647 --- /dev/null +++ b/templates/neutron_sudoers @@ -0,0 +1,4 @@ +Defaults:neutron !requiretty + +neutron ALL = (root) NOPASSWD: /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf * + diff --git a/templates/upstart/neutron-agent.upstart b/templates/upstart/neutron-agent.upstart new file mode 100644 index 00000000..3853caa4 --- /dev/null +++ b/templates/upstart/neutron-agent.upstart @@ -0,0 +1,25 @@ +description "{{ service_description }}" +author "Juju {{ service_name }} Charm " + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +chdir /var/run + +pre-start script + mkdir -p /var/run/neutron + chown neutron:root /var/run/neutron + # Check to see if openvswitch plugin in use by checking + # status of cleanup upstart configuration + if status neutron-ovs-cleanup; then + start wait-for-state WAIT_FOR=neutron-ovs-cleanup WAIT_STATE=running WAITER={{ process_name }} + fi +end script + +exec start-stop-daemon --start --chuid neutron --exec /usr/local/bin/{{ process_name }} -- \ + {% for config_file in config_files -%} + --config-file={{ config_file }} \ + {% endfor -%} + --log-file={{ log_file }} diff --git a/templates/upstart/neutron-ovs-cleanup.upstart b/templates/upstart/neutron-ovs-cleanup.upstart new file mode 100644 index 00000000..fa2c2149 --- /dev/null +++ b/templates/upstart/neutron-ovs-cleanup.upstart @@ -0,0 +1,13 @@ +description "{{ service_description }}" +author "Juju {{ service_name }} Charm " + +start on started openvswitch-switch +stop on runlevel [!2345] + +pre-start script + [ ! -x /usr/local/bin/{{ process_name }} ] && exit 0 + start-stop-daemon --start --chuid neutron \ + --exec /usr/local/bin/{{ process_name }} -- \ + --log-file {{ log_file }} \ + --config-file {{ config_file }} --verbose +end script diff --git a/templates/upstart/neutron-server.upstart b/templates/upstart/neutron-server.upstart new file mode 100644 index 00000000..2d2c73a2 --- /dev/null +++ b/templates/upstart/neutron-server.upstart @@ -0,0 +1,22 @@ +description "{{ service_description }}" +author "Juju {{ service_name }} Charm " + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +chdir /var/run + +pre-start script + mkdir -p /var/run/neutron + chown neutron:root /var/run/neutron +end script + +script + [ -r /etc/default/{{ process_name }} ] && . /etc/default/{{ process_name }} + [ -r "$NEUTRON_PLUGIN_CONFIG" ] && CONF_ARG="--config-file $NEUTRON_PLUGIN_CONFIG" + exec start-stop-daemon --start --chuid neutron --exec /usr/local/bin/neutron-server -- \ + --config-file /etc/neutron/neutron.conf \ + --log-file /var/log/neutron/server.log $CONF_ARG +end script diff --git a/tests/12-basic-precise-grizzly b/tests/12-basic-precise-grizzly deleted file mode 100755 index 29c358b9..00000000 --- a/tests/12-basic-precise-grizzly +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/python - -"""Amulet tests on a basic quantum-gateway deployment on precise-grizzly.""" - -from basic_deployment import QuantumGatewayBasicDeployment - -if __name__ == '__main__': - deployment = QuantumGatewayBasicDeployment(series='precise', - openstack='cloud:precise-grizzly', - source='cloud:precise-updates/grizzly') - deployment.run_tests() diff --git a/tests/13-basic-precise-havana b/tests/13-basic-precise-havana deleted file mode 100755 index 285fc333..00000000 --- a/tests/13-basic-precise-havana +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/python - -"""Amulet tests on a basic quantum-gateway deployment on precise-havana.""" - -from basic_deployment import QuantumGatewayBasicDeployment - -if __name__ == '__main__': - deployment = QuantumGatewayBasicDeployment(series='precise', - openstack='cloud:precise-havana', - source='cloud:precise-updates/havana') - deployment.run_tests() diff --git a/tests/16-basic-trusty-icehouse-git b/tests/16-basic-trusty-icehouse-git new file mode 100755 index 00000000..a24daec0 --- /dev/null +++ b/tests/16-basic-trusty-icehouse-git @@ -0,0 +1,9 @@ +#!/usr/bin/python + +"""Amulet tests on a basic quantum-gateway git deployment on trusty-icehouse.""" + +from basic_deployment import QuantumGatewayBasicDeployment + +if __name__ == '__main__': + deployment = QuantumGatewayBasicDeployment(series='trusty', git=True) + deployment.run_tests() diff --git a/tests/17-basic-trusty-juno b/tests/17-basic-trusty-juno new file mode 100755 index 00000000..525ffb5c --- /dev/null +++ b/tests/17-basic-trusty-juno @@ -0,0 +1,11 @@ +#!/usr/bin/python + +"""Amulet tests on a basic quantum-gateway deployment on trusty-juno.""" + +from basic_deployment import QuantumGatewayBasicDeployment + +if __name__ == '__main__': + deployment = QuantumGatewayBasicDeployment(series='trusty', + openstack='cloud:trusty-juno', + source='cloud:trusty-updates/juno') + deployment.run_tests() diff --git a/tests/18-basic-trusty-juno-git b/tests/18-basic-trusty-juno-git new file mode 100755 index 00000000..92e3c194 --- /dev/null +++ b/tests/18-basic-trusty-juno-git @@ -0,0 +1,12 @@ +#!/usr/bin/python + +"""Amulet tests on a basic quantum-gateway git deployment on trusty-juno.""" + +from basic_deployment import QuantumGatewayBasicDeployment + +if __name__ == '__main__': + deployment = QuantumGatewayBasicDeployment(series='trusty', + openstack='cloud:trusty-juno', + source='cloud:trusty-updates/juno', + git=True) + deployment.run_tests() diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py index 9e771a68..ced1909a 100644 --- a/tests/basic_deployment.py +++ b/tests/basic_deployment.py @@ -2,6 +2,7 @@ import amulet import time +import yaml try: from quantumclient.v2_0 import client as neutronclient except ImportError: @@ -18,16 +19,18 @@ from charmhelpers.contrib.openstack.amulet.utils import ( ) # Use DEBUG to turn on debug logging -u = OpenStackAmuletUtils(ERROR) +u = OpenStackAmuletUtils(DEBUG) class QuantumGatewayBasicDeployment(OpenStackAmuletDeployment): """Amulet tests on a basic quantum-gateway deployment.""" - def __init__(self, series, openstack=None, source=None, stable=False): + def __init__(self, series, openstack=None, source=None, git=False, + stable=False): """Deploy the entire test environment.""" super(QuantumGatewayBasicDeployment, self).__init__(series, openstack, source, stable) + self.git = git self._add_services() self._add_relations() self._configure_services() @@ -64,11 +67,29 @@ class QuantumGatewayBasicDeployment(OpenStackAmuletDeployment): def _configure_services(self): """Configure all of the services.""" + quantum_gateway_config = {} + if self.git: + branch = 'stable/' + self._get_openstack_release_string() + openstack_origin_git = { + 'repositories': [ + {'name': 'requirements', + 'repository': 'git://git.openstack.org/openstack/requirements', + 'branch': branch}, + {'name': 'neutron', + 'repository': 'git://git.openstack.org/openstack/neutron', + 'branch': branch}, + ], + 'directory': '/mnt/openstack-git', + 'http_proxy': 'http://squid.internal:3128', + 'https_proxy': 'https://squid.internal:3128', + } + quantum_gateway_config['openstack-origin-git'] = yaml.dump(openstack_origin_git) keystone_config = {'admin-password': 'openstack', 'admin-token': 'ubuntutesting'} nova_cc_config = {'network-manager': 'Quantum', 'quantum-security-groups': 'yes'} - configs = {'keystone': keystone_config, + configs = {'quantum-gateway': quantum_gateway_config, + 'keystone': keystone_config, 'nova-cloud-controller': nova_cc_config} super(QuantumGatewayBasicDeployment, self)._configure_services(configs) @@ -269,7 +290,7 @@ class QuantumGatewayBasicDeployment(OpenStackAmuletDeployment): self.d.configure('quantum-gateway', {'debug': 'True'}) - time = 20 + time = 40 for s in services: if not u.service_restarted(self.quantum_gateway_sentry, s, conf, pgrep_full=True, sleep_time=time): @@ -388,101 +409,6 @@ class QuantumGatewayBasicDeployment(OpenStackAmuletDeployment): message = "ml2 config error: {}".format(ret) amulet.raise_status(amulet.FAIL, msg=message) - def test_api_paste_config(self): - """Verify the data in the api paste config file.""" - unit = self.quantum_gateway_sentry - if self._get_openstack_release() >= self.precise_havana: - conf = '/etc/neutron/api-paste.ini' - expected = { - 'composite:neutron': { - 'use': 'egg:Paste#urlmap', - '/': 'neutronversions', - '/v2.0': 'neutronapi_v2_0' - }, - 'filter:keystonecontext': { - 'paste.filter_factory': 'neutron.auth:' - 'NeutronKeystoneContext.factory' - }, - 'filter:authtoken': { - 'paste.filter_factory': 'keystoneclient.middleware.' - 'auth_token:filter_factory' - }, - 'filter:extensions': { - 'paste.filter_factory': 'neutron.api.extensions:' - 'plugin_aware_extension_middleware_' - 'factory' - }, - 'app:neutronversions': { - 'paste.app_factory': 'neutron.api.versions:Versions.factory' - }, - 'app:neutronapiapp_v2_0': { - 'paste.app_factory': 'neutron.api.v2.router:APIRouter.' - 'factory' - } - } - if self._get_openstack_release() == self.precise_havana: - expected_additional = { - 'composite:neutronapi_v2_0': { - 'use': 'call:neutron.auth:pipeline_factory', - 'noauth': 'extensions neutronapiapp_v2_0', - 'keystone': 'authtoken keystonecontext extensions ' - 'neutronapiapp_v2_0' - } - } - else: - expected_additional = { - 'composite:neutronapi_v2_0': { - 'use': 'call:neutron.auth:pipeline_factory', - 'noauth': 'request_id catch_errors extensions ' - 'neutronapiapp_v2_0', - 'keystone': 'request_id catch_errors authtoken ' - 'keystonecontext extensions ' - 'neutronapiapp_v2_0' - } - } - expected = dict(expected.items() + expected_additional.items()) - else: - conf = '/etc/quantum/api-paste.ini' - expected = { - 'composite:quantum': { - 'use': 'egg:Paste#urlmap', - '/': 'quantumversions', - '/v2.0': 'quantumapi_v2_0' - }, - 'composite:quantumapi_v2_0': { - 'use': 'call:quantum.auth:pipeline_factory', - 'noauth': 'extensions quantumapiapp_v2_0', - 'keystone': 'authtoken keystonecontext extensions ' - 'quantumapiapp_v2_0', - }, - 'filter:keystonecontext': { - 'paste.filter_factory': 'quantum.auth:' - 'QuantumKeystoneContext.factory' - }, - 'filter:authtoken': { - 'paste.filter_factory': 'keystoneclient.middleware.' - 'auth_token:filter_factory' - }, - 'filter:extensions': { - 'paste.filter_factory': 'quantum.api.extensions:' - 'plugin_aware_extension_middleware_' - 'factory' - }, - 'app:quantumversions': { - 'paste.app_factory': 'quantum.api.versions:Versions.factory' - }, - 'app:quantumapiapp_v2_0': { - 'paste.app_factory': 'quantum.api.v2.router:APIRouter.' - 'factory' - } - } - - for section, pairs in expected.iteritems(): - ret = u.validate_config_data(unit, conf, section, pairs) - if ret: - message = "api paste config error: {}".format(ret) - amulet.raise_status(amulet.FAIL, msg=message) - def test_dhcp_agent_config(self): """Verify the data in the dhcp agent config file.""" unit = self.quantum_gateway_sentry diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py index f80aab3d..c9fd5a96 100644 --- a/unit_tests/__init__.py +++ b/unit_tests/__init__.py @@ -1,2 +1,4 @@ import sys + +sys.path.append('actions') sys.path.append('hooks') diff --git a/unit_tests/test_actions_git_reinstall.py b/unit_tests/test_actions_git_reinstall.py new file mode 100644 index 00000000..e38fb6b7 --- /dev/null +++ b/unit_tests/test_actions_git_reinstall.py @@ -0,0 +1,85 @@ +from mock import patch + +with patch('charmhelpers.core.hookenv.config') as config: + config.return_value = 'neutron' + import quantum_utils as utils # noqa + +import git_reinstall + +from test_utils import ( + CharmTestCase +) + +TO_PATCH = [ + 'config', +] + + +openstack_origin_git = \ + """repositories: + - {name: requirements, + repository: 'git://git.openstack.org/openstack/requirements', + branch: stable/juno} + - {name: neutron, + repository: 'git://git.openstack.org/openstack/neutron', + branch: stable/juno}""" + + +class TestNeutronAPIActions(CharmTestCase): + + def setUp(self): + super(TestNeutronAPIActions, self).setUp(git_reinstall, TO_PATCH) + self.config.side_effect = self.test_config.get + + @patch.object(git_reinstall, 'action_set') + @patch.object(git_reinstall, 'action_fail') + @patch.object(git_reinstall, 'git_install') + def test_git_reinstall(self, git_install, action_fail, action_set): + self.test_config.set('openstack-origin-git', openstack_origin_git) + + git_reinstall.git_reinstall() + + git_install.assert_called_with(openstack_origin_git) + self.assertTrue(git_install.called) + self.assertFalse(action_set.called) + self.assertFalse(action_fail.called) + + @patch.object(git_reinstall, 'action_set') + @patch.object(git_reinstall, 'action_fail') + @patch.object(git_reinstall, 'git_install') + @patch('charmhelpers.contrib.openstack.utils.config') + def test_git_reinstall_not_configured(self, _config, git_install, + action_fail, action_set): + _config.return_value = None + + git_reinstall.git_reinstall() + + msg = 'openstack-origin-git is not configured' + action_fail.assert_called_with(msg) + self.assertFalse(git_install.called) + self.assertFalse(action_set.called) + + @patch.object(git_reinstall, 'action_set') + @patch.object(git_reinstall, 'action_fail') + @patch.object(git_reinstall, 'git_install') + @patch('charmhelpers.contrib.openstack.utils.config') + def test_git_reinstall_exception(self, _config, git_install, + action_fail, action_set): + _config.return_value = openstack_origin_git + e = OSError('something bad happened') + git_install.side_effect = e + traceback = ( + "Traceback (most recent call last):\n" + " File \"actions/git_reinstall.py\", line 33, in git_reinstall\n" + " git_install(config(\'openstack-origin-git\'))\n" + " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 964, in __call__\n" # noqa + " return _mock_self._mock_call(*args, **kwargs)\n" + " File \"/usr/lib/python2.7/dist-packages/mock.py\", line 1019, in _mock_call\n" # noqa + " raise effect\n" + "OSError: something bad happened\n") + + git_reinstall.git_reinstall() + + msg = 'git-reinstall resulted in an unexpected error' + action_fail.assert_called_with(msg) + action_set.assert_called_with({'traceback': traceback}) diff --git a/unit_tests/test_quantum_hooks.py b/unit_tests/test_quantum_hooks.py index dc5d5d50..a530352e 100644 --- a/unit_tests/test_quantum_hooks.py +++ b/unit_tests/test_quantum_hooks.py @@ -1,4 +1,5 @@ from mock import MagicMock, patch, call +import yaml import charmhelpers.core.hookenv as hookenv hookenv.config = MagicMock() import quantum_utils as utils @@ -23,6 +24,7 @@ TO_PATCH = [ 'filter_installed_packages', 'get_early_packages', 'get_packages', + 'git_install', 'log', 'do_openstack_upgrade', 'openstack_upgrade_available', @@ -103,9 +105,46 @@ class TestQuantumHooks(CharmTestCase): self.assertTrue(self.log.called) _exit.assert_called_with(1) - def test_config_changed(self): + @patch.object(utils, 'git_install_requested') + def test_install_hook_git(self, git_requested): + git_requested.return_value = True + self.valid_plugin.return_value = True + _pkgs = ['foo', 'bar'] + self.filter_installed_packages.return_value = _pkgs + repo = 'cloud:trusty-juno' + openstack_origin_git = { + 'repositories': [ + {'name': 'requirements', + 'repository': 'git://git.openstack.org/openstack/requirements', # noqa + 'branch': 'stable/juno'}, + {'name': 'neutron', + 'repository': 'git://git.openstack.org/openstack/neutron', + 'branch': 'stable/juno'} + ], + 'directory': '/mnt/openstack-git', + } + projects_yaml = yaml.dump(openstack_origin_git) + self.test_config.set('openstack-origin', repo) + self.test_config.set('openstack-origin-git', projects_yaml) + self._call_hook('install') + self.configure_installation_source.assert_called_with( + 'cloud:trusty-juno' + ) + self.apt_update.assert_called_with(fatal=True) + self.apt_install.assert_has_calls([ + call(_pkgs, fatal=True), + call(_pkgs, fatal=True), + ]) + self.assertTrue(self.get_early_packages.called) + self.assertTrue(self.get_packages.called) + self.git_install.assert_called_with(projects_yaml) + self.assertTrue(self.execd_preinstall.called) + + @patch.object(hooks, 'git_install_requested') + def test_config_changed(self, git_requested): def mock_relids(rel): return ['relid'] + git_requested.return_value = False self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}') self.openstack_upgrade_available.return_value = True self.valid_plugin.return_value = True @@ -125,14 +164,18 @@ class TestQuantumHooks(CharmTestCase): self.assertTrue(_zmq_joined.called) self.create_sysctl.assert_called() - def test_config_changed_upgrade(self): + @patch.object(hooks, 'git_install_requested') + def test_config_changed_upgrade(self, git_requested): + git_requested.return_value = False self.openstack_upgrade_available.return_value = True self.valid_plugin.return_value = True self._call_hook('config-changed') self.assertTrue(self.do_openstack_upgrade.called) self.assertTrue(self.configure_ovs.called) - def test_config_changed_n1kv(self): + @patch.object(hooks, 'git_install_requested') + def test_config_changed_n1kv(self, git_requested): + git_requested.return_value = False self.openstack_upgrade_available.return_value = False self.valid_plugin.return_value = True self.filter_installed_packages.side_effect = lambda p: p @@ -144,12 +187,56 @@ class TestQuantumHooks(CharmTestCase): self.apt_purge.assert_called_with('neutron-l3-agent') @patch('sys.exit') - def test_config_changed_invalid_plugin(self, _exit): + @patch.object(hooks, 'git_install_requested') + def test_config_changed_invalid_plugin(self, git_requested, _exit): + git_requested.return_value = False self.valid_plugin.return_value = False self._call_hook('config-changed') self.assertTrue(self.log.called) _exit.assert_called_with(1) + @patch.object(hooks, 'git_install_requested') + @patch.object(hooks, 'config_value_changed') + def test_config_changed_git(self, config_val_changed, git_requested): + def mock_relids(rel): + return ['relid'] + git_requested.return_value = True + self.test_config.set('sysctl', '{ kernel.max_pid: "1337"}') + self.openstack_upgrade_available.return_value = True + self.valid_plugin.return_value = True + self.relation_ids.side_effect = mock_relids + _db_joined = self.patch('db_joined') + _pgsql_db_joined = self.patch('pgsql_db_joined') + _amqp_joined = self.patch('amqp_joined') + _amqp_nova_joined = self.patch('amqp_nova_joined') + _zmq_joined = self.patch('zeromq_configuration_relation_joined') + repo = 'cloud:trusty-juno' + openstack_origin_git = { + 'repositories': [ + {'name': 'requirements', + 'repository': + 'git://git.openstack.org/openstack/requirements', + 'branch': 'stable/juno'}, + {'name': 'neutron', + 'repository': 'git://git.openstack.org/openstack/neutron', + 'branch': 'stable/juno'} + ], + 'directory': '/mnt/openstack-git', + } + projects_yaml = yaml.dump(openstack_origin_git) + self.test_config.set('openstack-origin', repo) + self.test_config.set('openstack-origin-git', projects_yaml) + self._call_hook('config-changed') + self.git_install.assert_called_with(projects_yaml) + self.assertFalse(self.do_openstack_upgrade.called) + self.assertTrue(self.configure_ovs.called) + self.assertTrue(_db_joined.called) + self.assertTrue(_pgsql_db_joined.called) + self.assertTrue(_amqp_joined.called) + self.assertTrue(_amqp_nova_joined.called) + self.assertTrue(_zmq_joined.called) + self.create_sysctl.assert_called() + def test_upgrade_charm(self): _install = self.patch('install') _config_changed = self.patch('config_changed') diff --git a/unit_tests/test_quantum_utils.py b/unit_tests/test_quantum_utils.py index 7fa472c6..5ad5f00b 100644 --- a/unit_tests/test_quantum_utils.py +++ b/unit_tests/test_quantum_utils.py @@ -49,6 +49,15 @@ TO_PATCH = [ 'NeutronAPIContext', ] +openstack_origin_git = \ + """repositories: + - {name: requirements, + repository: 'git://git.openstack.org/openstack/requirements', + branch: stable/juno} + - {name: neutron, + repository: 'git://git.openstack.org/openstack/neutron', + branch: stable/juno}""" + class TestQuantumUtils(CharmTestCase): @@ -110,36 +119,48 @@ class TestQuantumUtils(CharmTestCase): self.assertEquals(quantum_utils.get_early_packages(), []) - def test_get_packages_ovs(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_ovs(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'havana' self.assertNotEqual(quantum_utils.get_packages(), []) - def test_get_packages_ovs_icehouse(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_ovs_icehouse(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'icehouse' self.assertTrue('neutron-vpn-agent' in quantum_utils.get_packages()) self.assertFalse('neutron-l3-agent' in quantum_utils.get_packages()) - def test_get_packages_ovs_juno_utopic(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_ovs_juno_utopic(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'juno' self._set_distrib_codename('utopic') self.assertFalse('neutron-vpn-agent' in quantum_utils.get_packages()) self.assertTrue('neutron-l3-agent' in quantum_utils.get_packages()) - def test_get_packages_ovs_juno_trusty(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_ovs_juno_trusty(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'juno' self.assertTrue('neutron-vpn-agent' in quantum_utils.get_packages()) self.assertFalse('neutron-l3-agent' in quantum_utils.get_packages()) - def test_get_packages_ovs_kilo(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_ovs_kilo(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'kilo' self.assertTrue('python-neutron-fwaas' in quantum_utils.get_packages()) - def test_get_packages_l3ha(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_get_packages_l3ha(self, git_requested): + git_requested.return_value = False self.config.return_value = 'ovs' self.get_os_codename_install_source.return_value = 'juno' self.assertTrue('keepalived' in quantum_utils.get_packages()) @@ -204,7 +225,9 @@ class TestQuantumUtils(CharmTestCase): # Not called since we have a bogus bridge in data-ports self.assertFalse(self.add_bridge_port.called) - def test_do_openstack_upgrade(self): + @patch.object(quantum_utils, 'git_install_requested') + def test_do_openstack_upgrade(self, git_requested): + git_requested.return_value = False self.config.side_effect = self.test_config.get self.is_relation_made.return_value = False self.test_config.set('openstack-origin', 'cloud:precise-havana') @@ -671,3 +694,453 @@ class TestQuantumAgentReallocation(CharmTestCase): self.assertTrue(self.log.called) assert not dummy_client.remove_router_from_l3_agent.called assert not dummy_client.remove_network_from_dhcp_agent.called + + @patch.object(quantum_utils, 'git_install_requested') + @patch.object(quantum_utils, 'git_clone_and_install') + @patch.object(quantum_utils, 'git_post_install') + @patch.object(quantum_utils, 'git_pre_install') + def test_git_install(self, git_pre, git_post, git_clone_and_install, + git_requested): + projects_yaml = openstack_origin_git + git_requested.return_value = True + quantum_utils.git_install(projects_yaml) + self.assertTrue(git_pre.called) + git_clone_and_install.assert_called_with(openstack_origin_git, + core_project='neutron') + self.assertTrue(git_post.called) + + @patch.object(quantum_utils, 'mkdir') + @patch.object(quantum_utils, 'write_file') + @patch.object(quantum_utils, 'add_user_to_group') + @patch.object(quantum_utils, 'add_group') + @patch.object(quantum_utils, 'adduser') + def test_git_pre_install(self, adduser, add_group, add_user_to_group, + write_file, mkdir): + quantum_utils.git_pre_install() + adduser.assert_called_with('neutron', shell='/bin/bash', + system_user=True) + add_group.assert_called_with('neutron', system_group=True) + add_user_to_group.assert_called_with('neutron', 'neutron') + expected = [ + call('/etc/neutron', owner='neutron', + group='neutron', perms=0700, force=False), + call('/etc/neutron/rootwrap.d', owner='neutron', + group='neutron', perms=0700, force=False), + call('/etc/neutron/plugins', owner='neutron', + group='neutron', perms=0700, force=False), + call('/etc/nova', owner='neutron', + group='neutron', perms=0700, force=False), + call('/var/lib/neutron', owner='neutron', + group='neutron', perms=0700, force=False), + call('/var/lib/neutron/lock', owner='neutron', + group='neutron', perms=0700, force=False), + call('/var/log/neutron', owner='neutron', + group='neutron', perms=0700, force=False), + ] + self.assertEquals(mkdir.call_args_list, expected) + expected = [ + call('/var/log/neutron/bigswitch-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/dhcp-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/l3-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/lbaas-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/ibm-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/linuxbridge-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/metadata-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/metering_agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/mlnx-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/nec-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/nvsd-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/openflow-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/openvswitch-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/ovs-cleanup.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/ryu-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/server.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/sriov-agent.log', '', owner='neutron', + group='neutron', perms=0644), + call('/var/log/neutron/vpn_agent.log', '', owner='neutron', + group='neutron', perms=0644), + ] + self.assertEquals(write_file.call_args_list, expected) + + @patch.object(quantum_utils, 'git_src_dir') + @patch.object(quantum_utils, 'render') + @patch('os.path.join') + @patch('os.path.exists') + @patch('os.symlink') + @patch('shutil.rmtree') + @patch('shutil.copyfile') + @patch('shutil.copytree') + def test_git_post_install(self, copytree, copyfile, rmtree, symlink, + exists, join, render, git_src_dir): + projects_yaml = openstack_origin_git + join.return_value = 'joined-string' + quantum_utils.git_post_install(projects_yaml) + expected = [ + call('joined-string', '/etc/neutron/api-paste.ini'), + call('joined-string', '/etc/neutron/dhcp_agent.ini'), + call('joined-string', '/etc/neutron/fwaas_driver.ini'), + call('joined-string', '/etc/neutron/l3_agent.ini'), + call('joined-string', '/etc/neutron/lbaas_agent.ini'), + call('joined-string', '/etc/neutron/metadata_agent.ini'), + call('joined-string', '/etc/neutron/metering_agent.ini'), + call('joined-string', '/etc/neutron/policy.json'), + call('joined-string', '/etc/neutron/rootwrap.conf'), + call('joined-string', '/etc/neutron/vpn_agent.ini'), + ] + copyfile.assert_has_calls(expected, any_order=True) + expected = [ + call('joined-string', '/etc/neutron/plugins/bigswitch'), + call('joined-string', '/etc/neutron/plugins/brocade'), + call('joined-string', '/etc/neutron/plugins/cisco'), + call('joined-string', '/etc/neutron/plugins/hyperv'), + call('joined-string', '/etc/neutron/plugins/ibm'), + call('joined-string', '/etc/neutron/plugins/metaplugin'), + call('joined-string', '/etc/neutron/plugins/midonet'), + call('joined-string', '/etc/neutron/plugins/ml2'), + call('joined-string', '/etc/neutron/plugins/mlnx'), + call('joined-string', '/etc/neutron/plugins/nec'), + call('joined-string', '/etc/neutron/plugins/nuage'), + call('joined-string', '/etc/neutron/plugins/oneconvergence'), + call('joined-string', '/etc/neutron/plugins/opencontrail'), + call('joined-string', '/etc/neutron/plugins/plumgrid'), + call('joined-string', '/etc/neutron/plugins/ryu'), + call('joined-string', '/etc/neutron/plugins/vmware'), + ] + copytree.assert_has_calls(expected, any_order=True) + expected = [ + call('joined-string', + '/etc/neutron/rootwrap.d/dhcp.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/ipset-firewall.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/iptables-firewall.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/l3.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/lbaas-haproxy.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/linuxbridge-plugin.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/nec-plugin.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/openvswitch-plugin.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/ryu-plugin.filters'), + call('joined-string', + '/etc/neutron/rootwrap.d/vpnaas.filters'), + ] + copyfile.assert_has_calls(expected, any_order=True) + expected = [ + call('/usr/local/bin/neutron-rootwrap', + '/usr/bin/neutron-rootwrap'), + ] + symlink.assert_has_calls(expected) + service_name = 'quantum-gateway' + user_name = 'neutron' + neutron_api_context = { + 'service_description': 'Neutron API server', + 'charm_name': 'neutron-api', + 'process_name': 'neutron-server', + } + neutron_dhcp_agent_context = { + 'service_description': 'Neutron DHCP Agent', + 'service_name': service_name, + 'process_name': 'neutron-dhcp-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/dhcp_agent.ini'], + 'log_file': '/var/log/neutron/dhcp-agent.log', + } + neutron_l3_agent_context = { + 'service_description': 'Neutron L3 Agent', + 'service_name': service_name, + 'process_name': 'neutron-l3-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/l3_agent.ini', + '/etc/neutron/fwaas_driver.ini'], + 'log_file': '/var/log/neutron/l3-agent.log', + } + neutron_lbaas_agent_context = { + 'service_description': 'Neutron LBaaS Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-lbaas-agent', + 'executable_name': '/usr/local/bin/neutron-lbaas-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/lbaas_agent.ini'], + 'log_file': '/var/log/neutron/lbaas-agent.log', + } + neutron_metadata_agent_context = { + 'service_description': 'Neutron Metadata Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-metadata-agent', + 'executable_name': '/usr/local/bin/neutron-metadata-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/metadata_agent.ini'], + 'log_file': '/var/log/neutron/metadata-agent.log', + } + neutron_metering_agent_context = { + 'service_description': 'Neutron Metering Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-metering-agent', + 'executable_name': '/usr/local/bin/neutron-metering-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/metering_agent.ini'], + 'log_file': '/var/log/neutron/metering-agent.log', + } + neutron_ovs_cleanup_context = { + 'service_description': 'Neutron OVS cleanup', + 'service_name': service_name, + 'process_name': 'neutron-ovs-cleanup', + 'config_file': '/etc/neutron/neutron.conf', + 'log_file': '/var/log/neutron/ovs-cleanup.log', + } + neutron_plugin_bigswitch_context = { + 'service_description': 'Neutron BigSwitch Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-restproxy-agent', + 'executable_name': '/usr/local/bin/neutron-restproxy-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/bigswitch/restproxy.ini'], + 'log_file': '/var/log/neutron/bigswitch-agent.log', + } + neutron_plugin_ibm_context = { + 'service_description': 'Neutron IBM SDN Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ibm-agent', + 'executable_name': '/usr/local/bin/neutron-ibm-agent', + 'config_files': + ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini'], + 'log_file': '/var/log/neutron/ibm-agent.log', + } + neutron_plugin_linuxbridge_context = { + 'service_description': 'Neutron Linux Bridge Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-linuxbridge-agent', + 'executable_name': '/usr/local/bin/neutron-linuxbridge-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf.ini'], + 'log_file': '/var/log/neutron/linuxbridge-agent.log', + } + neutron_plugin_mlnx_context = { + 'service_description': 'Neutron MLNX Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-mlnx-agent', + 'executable_name': '/usr/local/bin/neutron-mlnx-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/mlnx/mlnx_conf.ini'], + 'log_file': '/var/log/neutron/mlnx-agent.log', + } + neutron_plugin_nec_context = { + 'service_description': 'Neutron NEC Plugin Agent', + 'service_name': service_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-nec-agent', + 'executable_name': '/usr/local/bin/neutron-nec-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/nec/nec.ini'], + 'log_file': '/var/log/neutron/nec-agent.log', + } + neutron_plugin_oneconvergence_context = { + 'service_description': 'Neutron One Convergence Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-nvsd-agent', + 'executable_name': '/usr/local/bin/neutron-nvsd-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/oneconvergence/nvsdplugin.ini'], + 'log_file': '/var/log/neutron/nvsd-agent.log', + } + neutron_plugin_openflow_context = { + 'service_description': 'Neutron OpenFlow Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ofagent-agent', + 'executable_name': '/usr/local/bin/neutron-ofagent-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf_ofa.ini'], + 'log_file': '/var/log/neutron/openflow-agent.log', + } + neutron_plugin_openvswitch_context = { + 'service_description': 'Neutron OpenvSwitch Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-openvswitch-agent', + 'executable_name': '/usr/local/bin/neutron-openvswitch-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf.ini'], + 'log_file': '/var/log/neutron/openvswitch-agent.log', + } + neutron_plugin_ryu_context = { + 'service_description': 'Neutron RYU Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-ryu-agent', + 'executable_name': '/usr/local/bin/neutron-ryu-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ryu/ryu.ini'], + 'log_file': '/var/log/neutron/ryu-agent.log', + } + neutron_plugin_sriov_context = { + 'service_description': 'Neutron SRIOV SDN Plugin Agent', + 'service_name': service_name, + 'user_name': user_name, + 'start_dir': '/var/lib/neutron', + 'process_name': 'neutron-sriov-nic-agent', + 'executable_name': '/usr/local/bin/neutron-sriov-nic-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/plugins/ml2/ml2_conf_sriov'], + 'log_file': '/var/log/neutron/sriov-agent.log', + } + neutron_api_context = { + 'service_description': 'Neutron API server', + 'service_name': service_name, + 'process_name': 'neutron-server', + } + neutron_vpn_agent_context = { + 'service_description': 'Neutron VPN Agent', + 'service_name': service_name, + 'process_name': 'neutron-vpn-agent', + 'config_files': ['/etc/neutron/neutron.conf', + '/etc/neutron/vpn_agent.ini', + '/etc/neutron/l3_agent.ini', + '/etc/neutron/fwaas_driver.ini'], + 'log_file': '/var/log/neutron/vpn_agent.log', + } + expected = [ + call('neutron_sudoers', + '/etc/sudoers.d/neutron_sudoers', + {}, perms=0o440), + call('cron.d/neutron-dhcp-agent-netns-cleanup', + '/etc/cron.d/neutron-dhcp-agent-netns-cleanup', + {}, perms=0o755), + call('cron.d/neutron-l3-agent-netns-cleanup', + '/etc/cron.d/neutron-l3-agent-netns-cleanup', + {}, perms=0o755), + call('cron.d/neutron-lbaas-agent-netns-cleanup', + '/etc/cron.d/neutron-lbaas-agent-netns-cleanup', + {}, perms=0o755), + call('upstart/neutron-agent.upstart', + '/etc/init/neutron-dhcp-agent.conf', + neutron_dhcp_agent_context, perms=0o644), + call('upstart/neutron-agent.upstart', + '/etc/init/neutron-l3-agent.conf', + neutron_l3_agent_context, perms=0o644), + call('git.upstart', + '/etc/init/neutron-lbaas-agent.conf', + neutron_lbaas_agent_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-metadata-agent.conf', + neutron_metadata_agent_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-metering-agent.conf', + neutron_metering_agent_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-ovs-cleanup.conf', + neutron_ovs_cleanup_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-bigswitch-agent.conf', + neutron_plugin_bigswitch_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-ibm-agent.conf', + neutron_plugin_ibm_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-linuxbridge-agent.conf', + neutron_plugin_linuxbridge_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-mlnx-agent.conf', + neutron_plugin_mlnx_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-nec-agent.conf', + neutron_plugin_nec_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-oneconvergence-agent.conf', + neutron_plugin_oneconvergence_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-openflow-agent.conf', + neutron_plugin_openflow_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-openvswitch-agent.conf', + neutron_plugin_openvswitch_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-ryu-agent.conf', + neutron_plugin_ryu_context, perms=0o644, + templates_dir='joined-string'), + call('git.upstart', + '/etc/init/neutron-plugin-sriov-agent.conf', + neutron_plugin_sriov_context, perms=0o644, + templates_dir='joined-string'), + call('upstart/neutron-server.upstart', + '/etc/init/neutron-server.conf', + neutron_api_context, perms=0o644), + call('upstart/neutron-agent.upstart', + '/etc/init/neutron-vpn-agent.conf', + neutron_vpn_agent_context, perms=0o644), + ] + self.assertEquals(render.call_args_list, expected) + expected = [ + call('neutron-dhcp-agent'), + call('neutron-l3-agent'), + call('neutron-lbaas-agent'), + call('neutron-metadata-agent'), + call('neutron-metering-agent'), + call('neutron-ovs-cleanup'), + call('neutron-plugin-bigswitch'), + call('neutron-plugin-ibm-agent'), + call('neutron-plugin-linuxbridge-agent'), + call('neutron-plugin-mlnx-agent'), + call('neutron-plugin-nec-agent'), + call('neutron-plugin-oneconvergence-agent'), + call('neutron-plugin-openflow-agent'), + call('neutron-plugin-openvswitch-agent'), + call('neutron-plugin-ryu-agent'), + call('neutron-plugin-sriov-agent'), + call('neutron-server'), + call('neutron-vpn-agent'), + ] + self.assertEquals(self.service_restart.call_args_list, expected)