From 92ebe2f094d1d3cfe0281c42a6167ddfdaf4304e Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 14 Sep 2015 13:33:41 -0700 Subject: [PATCH 1/9] Action managed OpenStack upgrade --- actions.yaml | 2 + config.yaml | 10 ++++ hooks/charmhelpers/contrib/openstack/utils.py | 51 +++++++++++++++++++ hooks/neutron_hooks.py | 2 +- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/actions.yaml b/actions.yaml index 40828caa..05cef6ca 100644 --- a/actions.yaml +++ b/actions.yaml @@ -1,2 +1,4 @@ git-reinstall: description: Reinstall quantum-gateway from the openstack-origin-git repositories. +openstack-upgrade: + description: Perform openstack upgrades. Config option action-managed-upgrade must be set to True. diff --git a/config.yaml b/config.yaml index 048c86e4..00bd6aea 100644 --- a/config.yaml +++ b/config.yaml @@ -216,3 +216,13 @@ options: description: | Default multicast port number that will be used to communicate between HA Cluster nodes. + action-managed-upgrade: + type: boolean + default: False + description: | + If True enables openstack upgrades for this charm via juju actions. + You will still need to set openstack-origin to the new repository but + instead of an upgrade running automatically across all units, it will + wait for you to execute the openstack-upgrade action for this charm on + each unit. If False it will revert to existing behavior of upgrading + all units on config change. diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/hooks/charmhelpers/contrib/openstack/utils.py index c98c5c9e..2f5280e6 100644 --- a/hooks/charmhelpers/contrib/openstack/utils.py +++ b/hooks/charmhelpers/contrib/openstack/utils.py @@ -25,6 +25,7 @@ import sys import re import six +import traceback import yaml from charmhelpers.contrib.network import ip @@ -34,6 +35,8 @@ from charmhelpers.core import ( ) from charmhelpers.core.hookenv import ( + action_fail, + action_set, config, log as juju_log, charm_dir, @@ -114,6 +117,7 @@ SWIFT_CODENAMES = OrderedDict([ ('2.2.1', 'kilo'), ('2.2.2', 'kilo'), ('2.3.0', 'liberty'), + ('2.4.0', 'liberty'), ]) # >= Liberty version->codename mapping @@ -142,6 +146,9 @@ PACKAGE_CODENAMES = { 'glance-common': OrderedDict([ ('11.0.0', 'liberty'), ]), + 'openstack-dashboard': OrderedDict([ + ('8.0.0', 'liberty'), + ]), } DEFAULT_LOOPBACK_SIZE = '5G' @@ -745,3 +752,47 @@ def git_yaml_value(projects_yaml, key): return projects[key] return None + + +def do_action_openstack_upgrade(package, upgrade_callback, configs): + """Perform action-managed OpenStack upgrade. + + Upgrades packages to the configured openstack-origin version and sets + the corresponding action status as a result. + + If the charm was installed from source we cannot upgrade it. + For backwards compatibility a config flag (action-managed-upgrade) must + be set for this code to run, otherwise a full service level upgrade will + fire on config-changed. + + @param package: package name for determining if upgrade available + @param upgrade_callback: function callback to charm's upgrade function + @param configs: templating object derived from OSConfigRenderer class + + @return: True if upgrade successful; False if upgrade failed or skipped + """ + ret = False + + if git_install_requested(): + action_set({'outcome': 'installed from source, skipped upgrade.'}) + else: + if openstack_upgrade_available(package): + if config('action-managed-upgrade'): + juju_log('Upgrading OpenStack release') + + try: + upgrade_callback(configs=configs) + action_set({'outcome': 'success, upgrade completed.'}) + ret = True + except: + action_set({'outcome': 'upgrade failed, see traceback.'}) + action_set({'traceback': traceback.format_exc()}) + action_fail('do_openstack_upgrade resulted in an ' + 'unexpected error') + else: + action_set({'outcome': 'action-managed-upgrade config is ' + 'False, skipped upgrade.'}) + else: + action_set({'outcome': 'no upgrade available.'}) + + return ret diff --git a/hooks/neutron_hooks.py b/hooks/neutron_hooks.py index d63ba213..63db4040 100755 --- a/hooks/neutron_hooks.py +++ b/hooks/neutron_hooks.py @@ -102,7 +102,7 @@ def config_changed(): if config_value_changed('openstack-origin-git'): git_install(config('openstack-origin-git')) CONFIGS.write_all() - else: + elif not config('action-managed-upgrade'): if openstack_upgrade_available(get_common_package()): do_openstack_upgrade() CONFIGS.write_all() From 73fa88cbe4abbc8eea65af9e3d1cf73133ce86ce Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 14 Sep 2015 13:34:33 -0700 Subject: [PATCH 2/9] Action managed OpenStack upgrade --- actions/openstack-upgrade | 1 + actions/openstack_upgrade.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 120000 actions/openstack-upgrade create mode 100755 actions/openstack_upgrade.py diff --git a/actions/openstack-upgrade b/actions/openstack-upgrade new file mode 120000 index 00000000..61793013 --- /dev/null +++ b/actions/openstack-upgrade @@ -0,0 +1 @@ +openstack_upgrade.py \ No newline at end of file diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py new file mode 100755 index 00000000..b327e57b --- /dev/null +++ b/actions/openstack_upgrade.py @@ -0,0 +1,35 @@ +#!/usr/bin/python +import sys + +sys.path.append('hooks/') + +from charmhelpers.contrib.openstack.utils import ( + do_action_openstack_upgrade, +) + +from neutron_utils import ( + do_openstack_upgrade, + register_configs, + get_common_package, +) + + +CONFIGS = register_configs() + + +def openstack_upgrade(): + """Upgrade packages to config-set Openstack version. + + If the charm was installed from source we cannot upgrade it. + For backwards compatibility a config flag must be set for this + code to run, otherwise a full service level upgrade will fire + on config-changed.""" + + if (do_action_openstack_upgrade(get_common_package, + do_openstack_upgrade, + CONFIGS)): + CONFIGS.write_all() + + +if __name__ == '__main__': + openstack_upgrade() From 3d6fe797c3ad5b993e356d00e537c1c224e792dc Mon Sep 17 00:00:00 2001 From: David Ames Date: Tue, 15 Sep 2015 12:17:38 -0700 Subject: [PATCH 3/9] Add tests for action managed upgrade --- unit_tests/test_actions_openstack_upgrade.py | 54 ++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 unit_tests/test_actions_openstack_upgrade.py diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py new file mode 100644 index 00000000..5ef08549 --- /dev/null +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -0,0 +1,54 @@ +from mock import patch +import os + +os.environ['JUJU_UNIT_NAME'] = 'neutron-gateway' + +with patch('neutron_utils.register_configs') as register_configs: + import openstack_upgrade + +from test_utils import ( + CharmTestCase +) + +TO_PATCH = [ + 'do_openstack_upgrade', + 'register_configs', + 'CONFIGS' +] + + +class TestNeutronGWUpgradeActions(CharmTestCase): + + def setUp(self): + super(TestNeutronGWUpgradeActions, self).setUp(openstack_upgrade, + TO_PATCH) + + @patch('charmhelpers.contrib.openstack.utils.config') + @patch('charmhelpers.contrib.openstack.utils.action_set') + @patch('charmhelpers.contrib.openstack.utils.git_install_requested') + @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') + def test_openstack_upgrade_true(self, upgrade_avail, git_requested, + action_set, config): + git_requested.return_value = False + upgrade_avail.return_value = True + config.return_value = True + + openstack_upgrade.openstack_upgrade() + + self.assertTrue(self.do_openstack_upgrade.called) + self.assertTrue(self.CONFIGS.write_all.called) + + @patch('charmhelpers.contrib.openstack.utils.config') + @patch('charmhelpers.contrib.openstack.utils.action_set') + @patch('charmhelpers.contrib.openstack.utils.git_install_requested') + @patch('charmhelpers.contrib.openstack.utils.openstack_upgrade_available') + def test_openstack_upgrade_false(self, upgrade_avail, git_requested, + action_set, config): + git_requested.return_value = False + upgrade_avail.return_value = True + config.return_value = False + + openstack_upgrade.openstack_upgrade() + + self.assertFalse(self.do_openstack_upgrade.called) + self.assertFalse(self.CONFIGS.write_all.called) From 88528acfe312587b9cd564ebb122b38db9506dae Mon Sep 17 00:00:00 2001 From: David Ames Date: Tue, 15 Sep 2015 13:43:05 -0700 Subject: [PATCH 4/9] Get result of get_common_package --- actions/openstack_upgrade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py index b327e57b..5af1111e 100755 --- a/actions/openstack_upgrade.py +++ b/actions/openstack_upgrade.py @@ -25,7 +25,7 @@ def openstack_upgrade(): code to run, otherwise a full service level upgrade will fire on config-changed.""" - if (do_action_openstack_upgrade(get_common_package, + if (do_action_openstack_upgrade(get_common_package(), do_openstack_upgrade, CONFIGS)): CONFIGS.write_all() From 076d38017179de59f0fee10f96645afa281676c3 Mon Sep 17 00:00:00 2001 From: David Ames Date: Tue, 15 Sep 2015 14:09:40 -0700 Subject: [PATCH 5/9] Pass configs to do_openstack_upgrade --- actions/openstack_upgrade.py | 7 +++---- hooks/neutron_hooks.py | 3 +-- hooks/neutron_utils.py | 3 ++- unit_tests/test_actions_openstack_upgrade.py | 3 --- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py index 5af1111e..5da7a874 100755 --- a/actions/openstack_upgrade.py +++ b/actions/openstack_upgrade.py @@ -25,10 +25,9 @@ def openstack_upgrade(): code to run, otherwise a full service level upgrade will fire on config-changed.""" - if (do_action_openstack_upgrade(get_common_package(), - do_openstack_upgrade, - CONFIGS)): - CONFIGS.write_all() + do_action_openstack_upgrade(get_common_package(), + do_openstack_upgrade, + CONFIGS) if __name__ == '__main__': diff --git a/hooks/neutron_hooks.py b/hooks/neutron_hooks.py index 63db4040..2b91ed71 100755 --- a/hooks/neutron_hooks.py +++ b/hooks/neutron_hooks.py @@ -104,8 +104,7 @@ def config_changed(): CONFIGS.write_all() elif not config('action-managed-upgrade'): if openstack_upgrade_available(get_common_package()): - do_openstack_upgrade() - CONFIGS.write_all() + do_openstack_upgrade(CONFIGS) update_nrpe_config() diff --git a/hooks/neutron_utils.py b/hooks/neutron_utils.py index b8056599..265f7e73 100644 --- a/hooks/neutron_utils.py +++ b/hooks/neutron_utils.py @@ -645,7 +645,7 @@ def services(): return list(set(_services)) -def do_openstack_upgrade(): +def do_openstack_upgrade(configs): """ Perform an upgrade. Takes care of upgrading packages, rewriting configs, database migrations and potentially any other post-upgrade @@ -665,6 +665,7 @@ def do_openstack_upgrade(): fatal=True, dist=True) apt_install(get_early_packages(), fatal=True) apt_install(get_packages(), fatal=True) + configs.write_all() def configure_ovs(): diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py index 5ef08549..ac08c6ec 100644 --- a/unit_tests/test_actions_openstack_upgrade.py +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -13,7 +13,6 @@ from test_utils import ( TO_PATCH = [ 'do_openstack_upgrade', 'register_configs', - 'CONFIGS' ] @@ -36,7 +35,6 @@ class TestNeutronGWUpgradeActions(CharmTestCase): openstack_upgrade.openstack_upgrade() self.assertTrue(self.do_openstack_upgrade.called) - self.assertTrue(self.CONFIGS.write_all.called) @patch('charmhelpers.contrib.openstack.utils.config') @patch('charmhelpers.contrib.openstack.utils.action_set') @@ -51,4 +49,3 @@ class TestNeutronGWUpgradeActions(CharmTestCase): openstack_upgrade.openstack_upgrade() self.assertFalse(self.do_openstack_upgrade.called) - self.assertFalse(self.CONFIGS.write_all.called) From 3ccb2021361b724edce273994b5a95710bfcf2b4 Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 21 Sep 2015 11:25:31 -0700 Subject: [PATCH 6/9] Specifically call config_changed which has the restart_on_change decorator --- actions/openstack_upgrade.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py index 5da7a874..16994904 100755 --- a/actions/openstack_upgrade.py +++ b/actions/openstack_upgrade.py @@ -13,6 +13,7 @@ from neutron_utils import ( get_common_package, ) +from neutron_hooks import config_changed CONFIGS = register_configs() @@ -25,9 +26,10 @@ def openstack_upgrade(): code to run, otherwise a full service level upgrade will fire on config-changed.""" - do_action_openstack_upgrade(get_common_package(), + if do_action_openstack_upgrade(get_common_package(), do_openstack_upgrade, - CONFIGS) + CONFIGS): + config_changed() if __name__ == '__main__': From ee552f63df07b84f891ab1343dd206c67566da41 Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 21 Sep 2015 11:29:00 -0700 Subject: [PATCH 7/9] Lint fix --- actions/openstack_upgrade.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py index 16994904..af36c777 100755 --- a/actions/openstack_upgrade.py +++ b/actions/openstack_upgrade.py @@ -27,8 +27,8 @@ def openstack_upgrade(): on config-changed.""" if do_action_openstack_upgrade(get_common_package(), - do_openstack_upgrade, - CONFIGS): + do_openstack_upgrade, + CONFIGS): config_changed() From b010be86f94b92f92e9a7104ee43679a7a8e7b04 Mon Sep 17 00:00:00 2001 From: David Ames Date: Mon, 21 Sep 2015 11:49:31 -0700 Subject: [PATCH 8/9] Fix unit tests --- unit_tests/test_actions_openstack_upgrade.py | 3 +++ unit_tests/test_neutron_utils.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py index ac08c6ec..4294eb2e 100644 --- a/unit_tests/test_actions_openstack_upgrade.py +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -13,6 +13,7 @@ from test_utils import ( TO_PATCH = [ 'do_openstack_upgrade', 'register_configs', + 'config_changed', ] @@ -35,6 +36,7 @@ class TestNeutronGWUpgradeActions(CharmTestCase): openstack_upgrade.openstack_upgrade() self.assertTrue(self.do_openstack_upgrade.called) + self.assertTrue(self.config_changed.called) @patch('charmhelpers.contrib.openstack.utils.config') @patch('charmhelpers.contrib.openstack.utils.action_set') @@ -49,3 +51,4 @@ class TestNeutronGWUpgradeActions(CharmTestCase): openstack_upgrade.openstack_upgrade() self.assertFalse(self.do_openstack_upgrade.called) + self.assertFalse(self.config_changed.called) diff --git a/unit_tests/test_neutron_utils.py b/unit_tests/test_neutron_utils.py index acb571ca..79db5d76 100644 --- a/unit_tests/test_neutron_utils.py +++ b/unit_tests/test_neutron_utils.py @@ -233,7 +233,8 @@ class TestQuantumUtils(CharmTestCase): self.test_config.set('openstack-origin', 'cloud:precise-havana') self.test_config.set('plugin', 'ovs') self.get_os_codename_install_source.return_value = 'havana' - neutron_utils.do_openstack_upgrade() + configs = neutron_utils.register_configs() + neutron_utils.do_openstack_upgrade(configs) self.assertTrue(self.log.called) self.apt_update.assert_called_with(fatal=True) dpkg_opts = [ From 356754c94ecee2320c92bd4a456977c2a34b2cb2 Mon Sep 17 00:00:00 2001 From: David Ames Date: Wed, 23 Sep 2015 07:40:07 -0700 Subject: [PATCH 9/9] Do not use register_configs import CONFIGS directly --- actions/openstack_upgrade.py | 8 ++++---- unit_tests/test_actions_openstack_upgrade.py | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py index af36c777..7f3a4041 100755 --- a/actions/openstack_upgrade.py +++ b/actions/openstack_upgrade.py @@ -9,13 +9,13 @@ from charmhelpers.contrib.openstack.utils import ( from neutron_utils import ( do_openstack_upgrade, - register_configs, get_common_package, ) -from neutron_hooks import config_changed - -CONFIGS = register_configs() +from neutron_hooks import ( + config_changed, + CONFIGS, +) def openstack_upgrade(): diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py index 4294eb2e..3d417332 100644 --- a/unit_tests/test_actions_openstack_upgrade.py +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -12,7 +12,6 @@ from test_utils import ( TO_PATCH = [ 'do_openstack_upgrade', - 'register_configs', 'config_changed', ]