From e4ccc3d7f23d8b5cf6e2cdfbe67536a7a8d841b7 Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Mon, 21 Sep 2015 19:35:41 +0000 Subject: [PATCH] Action-managed openstack upgrade support --- actions.yaml | 4 ++ actions/openstack-upgrade | 1 + actions/openstack_upgrade.py | 38 ++++++++++++++ config.yaml | 10 ++++ hooks/heat_relations.py | 5 +- unit_tests/__init__.py | 1 + unit_tests/test_actions_openstack_upgrade.py | 54 ++++++++++++++++++++ unit_tests/test_heat_relations.py | 10 ++++ 8 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 actions.yaml create mode 120000 actions/openstack-upgrade create mode 100755 actions/openstack_upgrade.py create mode 100644 unit_tests/test_actions_openstack_upgrade.py diff --git a/actions.yaml b/actions.yaml new file mode 100644 index 0000000..9ece090 --- /dev/null +++ b/actions.yaml @@ -0,0 +1,4 @@ +openstack-upgrade: + description: + Perform openstack upgrades. Config option action-managed-upgrade must be + set to True. diff --git a/actions/openstack-upgrade b/actions/openstack-upgrade new file mode 120000 index 0000000..6179301 --- /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 0000000..6c2fc9b --- /dev/null +++ b/actions/openstack_upgrade.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +import sys + +sys.path.append('hooks/') + +from charmhelpers.contrib.openstack.utils import ( + do_action_openstack_upgrade, +) + +from heat_relations import config_changed + +from heat_utils import ( + do_openstack_upgrade, + register_configs +) + + +CONFIGS = register_configs() + + +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('heat-common', + do_openstack_upgrade, + CONFIGS)): + config_changed() + +if __name__ == '__main__': + openstack_upgrade() diff --git a/config.yaml b/config.yaml index d7dcece..c40f29a 100644 --- a/config.yaml +++ b/config.yaml @@ -85,3 +85,13 @@ options: create the following public endpoints for ceilometer: . https://ceilometer.example.com:8777/ + 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/heat_relations.py b/hooks/heat_relations.py index d2ad10d..0fdbdf9 100755 --- a/hooks/heat_relations.py +++ b/hooks/heat_relations.py @@ -87,8 +87,9 @@ def install(): @hooks.hook('config-changed') @restart_on_change(restart_map()) def config_changed(): - if openstack_upgrade_available('heat-common'): - do_openstack_upgrade(CONFIGS) + if not config('action-managed-upgrade'): + if openstack_upgrade_available('heat-common'): + do_openstack_upgrade(CONFIGS) CONFIGS.write_all() configure_https() diff --git a/unit_tests/__init__.py b/unit_tests/__init__.py index 415b211..d6289f0 100644 --- a/unit_tests/__init__.py +++ b/unit_tests/__init__.py @@ -1,2 +1,3 @@ import sys +sys.path.append('actions/') sys.path.append('hooks/') diff --git a/unit_tests/test_actions_openstack_upgrade.py b/unit_tests/test_actions_openstack_upgrade.py new file mode 100644 index 0000000..c516bc6 --- /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'] = 'heat' + +with patch('heat_utils.register_configs') as register_configs: + import openstack_upgrade + +from test_utils import ( + CharmTestCase +) + +TO_PATCH = [ + 'config_changed', + 'do_openstack_upgrade', + 'register_configs', +] + + +class TestHeatUpgradeActions(CharmTestCase): + + def setUp(self): + super(TestHeatUpgradeActions, 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.config_changed.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.config_changed.called) diff --git a/unit_tests/test_heat_relations.py b/unit_tests/test_heat_relations.py index 85d3ca3..ebdf7e5 100644 --- a/unit_tests/test_heat_relations.py +++ b/unit_tests/test_heat_relations.py @@ -76,6 +76,16 @@ class HeatRelationTests(CharmTestCase): relations.config_changed() self.assertTrue(self.do_openstack_upgrade.called) + @patch.object(relations, 'configure_https') + def test_config_changed_with_openstack_upgrade_action(self, + mock_configure_https): + self.openstack_upgrade_available.return_value = True + self.test_config.set('action-managed-upgrade', True) + + relations.config_changed() + + self.assertFalse(self.do_openstack_upgrade.called) + def test_db_joined(self): self.unit_get.return_value = 'heat.foohost.com' relations.db_joined()