From 80dccdd02b3ef76e28a1b1f7118570f760e403be Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Wed, 7 Oct 2015 12:20:36 -0400 Subject: [PATCH] Action-managed upgrade support. --- actions.yaml | 4 ++ actions/openstack_upgrade.py | 37 +++++++++++++ config.yaml | 11 +++- hooks/keystone_hooks.py | 2 +- unit_tests/test_actions_openstack_upgrade.py | 56 ++++++++++++++++++++ unit_tests/test_keystone_hooks.py | 31 +++++++++++ 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 actions/openstack_upgrade.py create mode 100644 unit_tests/test_actions_openstack_upgrade.py diff --git a/actions.yaml b/actions.yaml index 81ec284a..81bbd5b5 100644 --- a/actions.yaml +++ b/actions.yaml @@ -11,3 +11,7 @@ resume: Resume keystone services. If the keystone deployment is clustered using the hacluster charm, the corresponding hacluster unit on the node must be resumed as well. +openstack-upgrade: + description: | + Perform openstack upgrades. Config option action-managed-upgrade must be + set to True. diff --git a/actions/openstack_upgrade.py b/actions/openstack_upgrade.py new file mode 100644 index 00000000..301e414a --- /dev/null +++ b/actions/openstack_upgrade.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +import sys + +sys.path.append('hooks/') + +from charmhelpers.contrib.openstack.utils import ( + do_action_openstack_upgrade, +) + +from keystone_hooks import ( + config_changed, + CONFIGS, +) + +from keystone_utils import ( + do_openstack_upgrade, +) + + +def openstack_upgrade(): + """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.""" + + if (do_action_openstack_upgrade('keystone', + do_openstack_upgrade, + CONFIGS)): + config_changed() + +if __name__ == '__main__': + openstack_upgrade() diff --git a/config.yaml b/config.yaml index 9b4c4d26..b00c2f0e 100644 --- a/config.yaml +++ b/config.yaml @@ -298,4 +298,13 @@ options: description: | A comma-separated list of nagios servicegroups. If left empty, the nagios_context will be used as the servicegroup - + 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/keystone_hooks.py b/hooks/keystone_hooks.py index 66e564d6..3153f356 100755 --- a/hooks/keystone_hooks.py +++ b/hooks/keystone_hooks.py @@ -153,7 +153,7 @@ def config_changed(): if config_value_changed('openstack-origin-git'): status_set('maintenance', 'Running Git install') git_install(config('openstack-origin-git')) - else: + elif not config('action-managed-upgrade'): if openstack_upgrade_available('keystone'): status_set('maintenance', 'Running openstack upgrade') do_openstack_upgrade(configs=CONFIGS) diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py new file mode 100644 index 00000000..58a54904 --- /dev/null +++ b/unit_tests/test_actions_openstack_upgrade.py @@ -0,0 +1,56 @@ +from mock import patch +import os + +os.environ['JUJU_UNIT_NAME'] = 'keystone' + +with patch('keystone_utils.register_configs') as register_configs: + import openstack_upgrade + import keystone_hooks as hooks + +from test_utils import ( + CharmTestCase +) + +TO_PATCH = [ + 'config_changed', + 'do_openstack_upgrade', +] + + +class TestCinderUpgradeActions(CharmTestCase): + + def setUp(self): + super(TestCinderUpgradeActions, self).setUp(openstack_upgrade, + TO_PATCH) + + @patch.object(hooks, 'register_configs') + @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, reg_configs): + 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.config_changed.called) + + @patch.object(hooks, 'register_configs') + @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, reg_configs): + 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.config_changed.called) diff --git a/unit_tests/test_keystone_hooks.py b/unit_tests/test_keystone_hooks.py index ff01c956..70ade2e1 100644 --- a/unit_tests/test_keystone_hooks.py +++ b/unit_tests/test_keystone_hooks.py @@ -540,6 +540,37 @@ class KeystoneRelationTests(CharmTestCase): self.assertFalse(self.openstack_upgrade_available.called) self.assertFalse(self.do_openstack_upgrade.called) + @patch.object(hooks, 'git_install_requested') + @patch.object(hooks, 'config_value_changed') + @patch.object(hooks, 'ensure_ssl_dir') + @patch.object(hooks, 'configure_https') + @patch.object(hooks, 'is_pki_enabled') + @patch.object(hooks, 'is_ssl_cert_master') + @patch.object(hooks, 'peer_units') + @patch.object(unison, 'get_homedir') + @patch.object(unison, 'ensure_user') + @patch('keystone_utils.ensure_ssl_cert_master') + def test_config_changed_with_openstack_upgrade_action(self, + ensure_ssl_cert, + ensure_user, + get_home, + peer_units, is_ssl, + is_pki, config_https, + ensure_ssl_dir, + config_value_changed, + git_requested): + ensure_ssl_cert.return_value = False + is_pki.return_value = False + peer_units.return_value = [] + + git_requested.return_value = False + self.openstack_upgrade_available.return_value = True + self.test_config.set('action-managed-upgrade', True) + + hooks.config_changed() + + self.assertFalse(self.do_openstack_upgrade.called) + @patch('keystone_utils.log') @patch('keystone_utils.ensure_ssl_cert_master') @patch.object(hooks, 'hashlib')