From d5e9cebd14dd452c4ed0eb0fdf41b634b109bc22 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Sat, 21 Mar 2015 10:25:07 +0000 Subject: [PATCH] Overall refresh to current install from source approach --- Makefile | 7 +- README.md | 166 +++++++++--------- actions.yaml | 2 + actions/git-reinstall | 1 + actions/git_reinstall.py | 40 +++++ ...pers-sync.yaml => charm-helpers-hooks.yaml | 3 +- charm-helpers-tests.yaml | 3 +- config.yaml | 12 +- hooks/neutron_ovs_hooks.py | 9 + hooks/neutron_ovs_utils.py | 17 +- tests/16-basic-trusty-icehouse-git | 9 + ...basic-trusty-juno => 17-basic-trusty-juno} | 0 tests/18-basic-trusty-juno-git | 12 ++ tests/basic_deployment.py | 24 ++- unit_tests/__init__.py | 2 + unit_tests/test_actions_git_reinstall.py | 85 +++++++++ 16 files changed, 279 insertions(+), 113 deletions(-) create mode 100644 actions.yaml create mode 120000 actions/git-reinstall create mode 100755 actions/git_reinstall.py rename charm-helpers-sync.yaml => charm-helpers-hooks.yaml (76%) create mode 100755 tests/16-basic-trusty-icehouse-git rename tests/{16-basic-trusty-juno => 17-basic-trusty-juno} (100%) create mode 100755 tests/18-basic-trusty-juno-git create mode 100644 unit_tests/test_actions_git_reinstall.py diff --git a/Makefile b/Makefile index db4e2c25..6ca58a67 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: @@ -15,7 +15,7 @@ bin/charm_helpers_sync.py: > bin/charm_helpers_sync.py sync: bin/charm_helpers_sync.py - @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-sync.yaml + @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-hooks.yaml @$(PYTHON) bin/charm_helpers_sync.py -c charm-helpers-tests.yaml test: @@ -25,7 +25,8 @@ test: # 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 \ - 16-basic-trusty-juno + 16-basic-trusty-icehouse-git 17-basic-trusty-juno \ + 18-basic-trusty-juno-git publish: lint unit_test bzr push lp:charms/neutron-openvswitch diff --git a/README.md b/README.md index b4022f6a..05d08869 100644 --- a/README.md +++ b/README.md @@ -44,95 +44,87 @@ These compute nodes could then be accessed by cloud users via use of host aggreg # Deploying from source -The minimal openstack-origin-git config required to deploy from source is: +The minimum openstack-origin-git config required to deploy from source is: openstack-origin-git: - "{'neutron': - {'repository': 'git://git.openstack.org/openstack/neutron.git', - 'branch': 'stable/icehouse'}}" + "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}" -If you specify a 'requirements' repository, it will be used to update the -requirements.txt files of all other git repos that it applies to, before -they are installed: +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: - "{'requirements': - {'repository': 'git://git.openstack.org/openstack/requirements.git', - 'branch': 'master'}, - 'neutron': - {'repository': 'git://git.openstack.org/openstack/neutron.git', - 'branch': 'master'}}" - -Note that there are only two key values the charm knows about for the outermost -dictionary: 'neutron' and 'requirements'. These repositories must correspond to -these keys. If the requirements repository is specified, it will be installed -first. The neutron repository is always installed last. All other repostories -will be installed in between. - -NOTE(coreycb): The following is temporary to keep track of the full list of -current tip repos (may not be up-to-date). - - openstack-origin-git: - "{'requirements': - {'repository': 'git://git.openstack.org/openstack/requirements.git', - 'branch': 'master'}, - 'neutron-fwaas': - {'repository': 'git://git.openstack.org/openstack/neutron-fwaas.git', - 'branch': 'master'}, - 'neutron-lbaas': - {'repository: 'git://git.openstack.org/openstack/neutron-lbaas.git', - 'branch': 'master'}, - 'neutron-vpnaas': - {'repository: 'git://git.openstack.org/openstack/neutron-vpnaas.git', - 'branch': 'master'}, - 'keystonemiddleware: - {'repository': 'git://git.openstack.org/openstack/keystonemiddleware.git', - 'branch: 'master'}, - 'oslo-concurrency': - {'repository': 'git://git.openstack.org/openstack/oslo.concurrency.git', - 'branch: 'master'}, - 'oslo-config': - {'repository': 'git://git.openstack.org/openstack/oslo.config.git', - 'branch: 'master'}, - 'oslo-context': - {'repository': 'git://git.openstack.org/openstack/oslo.context.git', - 'branch: 'master'}, - 'oslo-db': - {'repository': 'git://git.openstack.org/openstack/oslo.db.git', - 'branch: 'master'}, - 'oslo-i18n': - {'repository': 'git://git.openstack.org/openstack/oslo.i18n.git', - 'branch: 'master'}, - 'oslo-messaging': - {'repository': 'git://git.openstack.org/openstack/oslo.messaging.git', - 'branch: 'master'}, - 'oslo-middleware: - {'repository': 'git://git.openstack.org/openstack/oslo.middleware.git', - 'branch': 'master'}, - 'oslo-rootwrap': - {'repository': 'git://git.openstack.org/openstack/oslo.rootwrap.git', - 'branch: 'master'}, - 'oslo-serialization': - {'repository': 'git://git.openstack.org/openstack/oslo.serialization.git', - 'branch: 'master'}, - 'oslo-utils': - {'repository': 'git://git.openstack.org/openstack/oslo.utils.git', - 'branch: 'master'}, - 'pbr': - {'repository': 'git://git.openstack.org/openstack-dev/pbr.git', - 'branch: 'master'}, - 'python-keystoneclient': - {'repository': 'git://git.openstack.org/openstack/python-keystoneclient.git', - 'branch: 'master'}, - 'python-neutronclient': - {'repository': 'git://git.openstack.org/openstack/python-neutronclient.git', - 'branch: 'master'}, - 'python-novaclient': - {'repository': 'git://git.openstack.org/openstack/python-novaclient.git', - 'branch: 'master'}, - 'stevedore': - {'repository': 'git://git.openstack.org/openstack/stevedore.git', - 'branch: 'master'}, - 'neutron': - {'repository': 'git://git.openstack.org/openstack/neutron.git', - 'branch': 'master'}}" + "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}" diff --git a/actions.yaml b/actions.yaml new file mode 100644 index 00000000..02fbf59a --- /dev/null +++ b/actions.yaml @@ -0,0 +1,2 @@ +git-reinstall: + description: Reinstall neutron-openvswitch 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..849e6634 --- /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 neutron_ovs_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/charm-helpers-sync.yaml b/charm-helpers-hooks.yaml similarity index 76% rename from charm-helpers-sync.yaml rename to charm-helpers-hooks.yaml index e9b66fc7..9b5e79e9 100644 --- a/charm-helpers-sync.yaml +++ b/charm-helpers-hooks.yaml @@ -1,5 +1,4 @@ -#branch: lp:charm-helpers -branch: /home/corey/src/charms/git/charm-helpers +branch: lp:charm-helpers destination: hooks/charmhelpers include: - core diff --git a/charm-helpers-tests.yaml b/charm-helpers-tests.yaml index aaa21c31..48b12f6f 100644 --- a/charm-helpers-tests.yaml +++ b/charm-helpers-tests.yaml @@ -1,5 +1,4 @@ -#branch: lp:charm-helpers -branch: /home/corey/src/charms/git/charm-helpers +branch: lp:charm-helpers destination: tests/charmhelpers include: - contrib.amulet diff --git a/config.yaml b/config.yaml index 6a5ff908..501aff83 100644 --- a/config.yaml +++ b/config.yaml @@ -3,20 +3,16 @@ options: default: None type: string description: | - Specifies a YAML-formatted two-dimensional array listing the git - repositories and branches from which to install OpenStack and its - dependencies. + Specifies a YAML-formatted dictionary listing the git + repositories and branches from which to install OpenStack and + its dependencies. When openstack-origin-git is specified, openstack-specific packages will be installed from source rather than from the the nova-compute charm's openstack-origin repository. Note that the installed config files will be determined based on - the OpenStack release of the nova-compute charm's openstack-origin - option. - - Note also that this option is processed for the initial install - only. Setting this option after deployment is not supported. + the OpenStack release of the openstack-origin option. For more details see README.md. rabbit-user: diff --git a/hooks/neutron_ovs_hooks.py b/hooks/neutron_ovs_hooks.py index 61ce2e14..6e8264a7 100755 --- a/hooks/neutron_ovs_hooks.py +++ b/hooks/neutron_ovs_hooks.py @@ -2,6 +2,11 @@ import sys +from charmhelpers.contrib.openstack.utils import ( + config_value_changed, + git_install_requested, +) + from charmhelpers.core.hookenv import ( Hooks, UnregisteredHookError, @@ -51,6 +56,10 @@ def install(): def config_changed(): CONFIGS.write_all() + if git_install_requested() and + config_value_changed('openstack-origin-git'): + git_install(config('openstack-origin-git')) + @hooks.hook('amqp-relation-joined') def amqp_joined(relation_id=None): diff --git a/hooks/neutron_ovs_utils.py b/hooks/neutron_ovs_utils.py index 86e24127..cd96257b 100644 --- a/hooks/neutron_ovs_utils.py +++ b/hooks/neutron_ovs_utils.py @@ -6,6 +6,11 @@ from charmhelpers.contrib.openstack.neutron import neutron_plugin_attribute from copy import deepcopy from charmhelpers.contrib.openstack import context, templating +from charmhelpers.contrib.openstack.utils import ( + git_install_requested, + git_clone_and_install, + git_src_dir, +) from collections import OrderedDict from charmhelpers.contrib.openstack.utils import ( os_release, @@ -87,12 +92,12 @@ def restart_map(): return {k: v['services'] for k, v in resource_map().iteritems()} -def git_install(projects): +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(yaml.load(projects), core_project='neutron') - git_post_install() + git_clone_and_install(projects_yaml, core_project='neutron') + git_post_install(projects_yaml) def git_pre_install(): @@ -121,9 +126,9 @@ def git_pre_install(): write_file(l, '', owner='neutron', group='neutron', perms=0600) -def git_post_install(): +def git_post_install(projects_yaml): """Perform post-install setup.""" - src_etc = os.path.join(charm_dir(), '/mnt/openstack-git/neutron-api.git/etc') + src_etc = os.path.join(git_src_dir(projects_yaml, 'neutron'), 'etc') configs = { 'debug-filters': { 'src': os.path.join(src_etc, 'neutron/rootwrap.d/debug.filters'), @@ -175,10 +180,10 @@ def git_post_install(): 'log_file': '/var/log/neutron/ovs-cleanup.log', } + # NOTE(coreycb): Needs systemd support render('upstart/neutron-plugin-openvswitch-agent.upstart', '/etc/init/neutron-plugin-openvswitch-agent.conf', neutron_ovs_agent_context, perms=0o644) - render('upstart/neutron-ovs-cleanup.upstart', '/etc/init/neutron-ovs-cleanup.conf', neutron_ovs_cleanup_context, perms=0o644) diff --git a/tests/16-basic-trusty-icehouse-git b/tests/16-basic-trusty-icehouse-git new file mode 100755 index 00000000..de2fec89 --- /dev/null +++ b/tests/16-basic-trusty-icehouse-git @@ -0,0 +1,9 @@ +#!/usr/bin/python + +"""Amulet tests on a basic neutron-openvswitch git deployment on trusty-icehouse.""" + +from basic_deployment import NeutronOVSBasicDeployment + +if __name__ == '__main__': + deployment = NeutronOVSBasicDeployment(series='trusty', git=True) + deployment.run_tests() diff --git a/tests/16-basic-trusty-juno b/tests/17-basic-trusty-juno similarity index 100% rename from tests/16-basic-trusty-juno rename to tests/17-basic-trusty-juno diff --git a/tests/18-basic-trusty-juno-git b/tests/18-basic-trusty-juno-git new file mode 100755 index 00000000..618c9aa2 --- /dev/null +++ b/tests/18-basic-trusty-juno-git @@ -0,0 +1,12 @@ +#!/usr/bin/python + +"""Amulet tests on a basic neutron-openvswitch git deployment on trusty-juno.""" + +from basic_deployment import NeutronOVSBasicDeployment + +if __name__ == '__main__': + deployment = NeutronOVSBasicDeployment(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 b0e83403..34d2472c 100644 --- a/tests/basic_deployment.py +++ b/tests/basic_deployment.py @@ -2,6 +2,7 @@ import amulet import time +import yaml from charmhelpers.contrib.openstack.amulet.deployment import ( OpenStackAmuletDeployment @@ -24,10 +25,12 @@ u = OpenStackAmuletUtils(ERROR) class NeutronOVSBasicDeployment(OpenStackAmuletDeployment): """Amulet tests on a basic neutron-openvswtich 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(NeutronOVSBasicDeployment, self).__init__(series, openstack, source, stable) + self.git = git self._add_services() self._add_relations() self._configure_services() @@ -61,10 +64,21 @@ class NeutronOVSBasicDeployment(OpenStackAmuletDeployment): def _configure_services(self): """Configure all of the services.""" - neutron_ovs_config = {'openstack-origin-git': - "{'neutron':" - " {'repository': 'git://git.openstack.org/openstack/neutron.git'," - " 'branch': 'stable/icehouse'}}"} + neutron_ovs_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', + } + neutron_api_config['openstack-origin-git'] = yaml.dump(openstack_origin_git) configs = {'neutron-openvswitch': neutron_ovs_config} super(NeutronOVSBasicDeployment, self)._configure_services(configs) diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py index 415b2110..43aa3614 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..802e9f52 --- /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 neutron_ovs_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 TestNeutronOVSActions(CharmTestCase): + + def setUp(self): + super(TestNeutronOVSActions, 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})