Merge lp:~corey.bryant/charm-helpers/action-managed-upgrade into lp:charm-helpers

Proposed by Corey Bryant on 2015-09-14
Status: Merged
Merged at revision: 452
Proposed branch: lp:~corey.bryant/charm-helpers/action-managed-upgrade
Merge into: lp:charm-helpers
Diff against target: 198 lines (+167/-0)
2 files modified
charmhelpers/contrib/openstack/utils.py (+47/-0)
tests/contrib/openstack/test_openstack_utils.py (+120/-0)
To merge this branch: bzr merge lp:~corey.bryant/charm-helpers/action-managed-upgrade
Reviewer Review Type Date Requested Status
James Page 2015-09-14 Approve on 2015-09-16
Review via email: mp+270998@code.launchpad.net
To post a comment you must log in.
453. By Corey Bryant on 2015-09-14

call upgrade_callback

454. By Corey Bryant on 2015-09-15

unit tests for do_action_openstack_upgrade()

455. By Corey Bryant on 2015-09-15

more unit test updates

456. By Corey Bryant on 2015-09-15

Merge charm-helpers trunk

James Page (james-page) wrote :

Corey

This all looks OK to me, but it currently conflicts with head of charm-helpers due to the landing of the service status work.

Please can you rebase, and then +1

review: Approve
457. By Corey Bryant on 2015-09-16

Drop action-managed upgrade code temporarily for merge

458. By Corey Bryant on 2015-09-16

Sync charm-helpers trunk

459. By Corey Bryant on 2015-09-16

Add action-managed upgrade code after merge

460. By Corey Bryant on 2015-09-16

Fix up test_openstack_upgrade_traceback()

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmhelpers/contrib/openstack/utils.py'
2--- charmhelpers/contrib/openstack/utils.py 2015-09-15 17:52:15 +0000
3+++ charmhelpers/contrib/openstack/utils.py 2015-09-16 15:03:29 +0000
4@@ -25,6 +25,7 @@
5 import re
6
7 import six
8+import traceback
9 import yaml
10
11 from charmhelpers.contrib.network import ip
12@@ -34,6 +35,8 @@
13 )
14
15 from charmhelpers.core.hookenv import (
16+ action_fail,
17+ action_set,
18 config,
19 log as juju_log,
20 charm_dir,
21@@ -921,3 +924,47 @@
22 for i in incomplete_relations:
23 incomplete_context_data[i] = configs.get_incomplete_context_data(required_interfaces[i])
24 return incomplete_context_data
25+
26+
27+def do_action_openstack_upgrade(package, upgrade_callback, configs):
28+ """Perform action-managed OpenStack upgrade.
29+
30+ Upgrades packages to the configured openstack-origin version and sets
31+ the corresponding action status as a result.
32+
33+ If the charm was installed from source we cannot upgrade it.
34+ For backwards compatibility a config flag (action-managed-upgrade) must
35+ be set for this code to run, otherwise a full service level upgrade will
36+ fire on config-changed.
37+
38+ @param package: package name for determining if upgrade available
39+ @param upgrade_callback: function callback to charm's upgrade function
40+ @param configs: templating object derived from OSConfigRenderer class
41+
42+ @return: True if upgrade successful; False if upgrade failed or skipped
43+ """
44+ ret = False
45+
46+ if git_install_requested():
47+ action_set({'outcome': 'installed from source, skipped upgrade.'})
48+ else:
49+ if openstack_upgrade_available(package):
50+ if config('action-managed-upgrade'):
51+ juju_log('Upgrading OpenStack release')
52+
53+ try:
54+ upgrade_callback(configs=configs)
55+ action_set({'outcome': 'success, upgrade completed.'})
56+ ret = True
57+ except:
58+ action_set({'outcome': 'upgrade failed, see traceback.'})
59+ action_set({'traceback': traceback.format_exc()})
60+ action_fail('do_openstack_upgrade resulted in an '
61+ 'unexpected error')
62+ else:
63+ action_set({'outcome': 'action-managed-upgrade config is '
64+ 'False, skipped upgrade.'})
65+ else:
66+ action_set({'outcome': 'no upgrade available.'})
67+
68+ return ret
69
70=== modified file 'tests/contrib/openstack/test_openstack_utils.py'
71--- tests/contrib/openstack/test_openstack_utils.py 2015-09-15 17:52:15 +0000
72+++ tests/contrib/openstack/test_openstack_utils.py 2015-09-16 15:03:29 +0000
73@@ -943,5 +943,125 @@
74 "incomplete relations: message, "
75 "identity")
76
77+ @patch.object(openstack, 'action_set')
78+ @patch.object(openstack, 'action_fail')
79+ @patch.object(openstack, 'openstack_upgrade_available')
80+ @patch('charmhelpers.contrib.openstack.utils.config')
81+ def test_openstack_upgrade(self, config, openstack_upgrade_available,
82+ action_fail, action_set):
83+ def do_openstack_upgrade(configs):
84+ pass
85+
86+ openstack_upgrade_available.return_value = True
87+
88+ # openstack-origin-git=None, action-managed-upgrade=True
89+ config.side_effect = [None, True]
90+
91+ openstack.do_action_openstack_upgrade('package-xyz',
92+ do_openstack_upgrade,
93+ None)
94+
95+ self.assertTrue(openstack_upgrade_available.called)
96+ msg = ('success, upgrade completed.')
97+ action_set.assert_called_with({'outcome': msg})
98+ self.assertFalse(action_fail.called)
99+
100+ @patch.object(openstack, 'action_set')
101+ @patch.object(openstack, 'action_fail')
102+ @patch.object(openstack, 'openstack_upgrade_available')
103+ @patch('charmhelpers.contrib.openstack.utils.config')
104+ def test_openstack_upgrade_git(self, config, openstack_upgrade_available,
105+ action_fail, action_set):
106+ def do_openstack_upgrade(configs):
107+ pass
108+
109+ openstack_upgrade_available.return_value = True
110+
111+ # openstack-origin-git=xyz
112+ config.side_effect = ['openstack-origin-git: xyz']
113+
114+ openstack.do_action_openstack_upgrade('package-xyz',
115+ do_openstack_upgrade,
116+ None)
117+
118+ self.assertFalse(openstack_upgrade_available.called)
119+ msg = ('installed from source, skipped upgrade.')
120+ action_set.assert_called_with({'outcome': msg})
121+ self.assertFalse(action_fail.called)
122+
123+ @patch.object(openstack, 'action_set')
124+ @patch.object(openstack, 'action_fail')
125+ @patch.object(openstack, 'openstack_upgrade_available')
126+ @patch('charmhelpers.contrib.openstack.utils.config')
127+ def test_openstack_upgrade_not_avail(self, config,
128+ openstack_upgrade_available,
129+ action_fail, action_set):
130+ def do_openstack_upgrade(configs):
131+ pass
132+
133+ openstack_upgrade_available.return_value = False
134+
135+ # openstack-origin-git=None
136+ config.side_effect = [None]
137+
138+ openstack.do_action_openstack_upgrade('package-xyz',
139+ do_openstack_upgrade,
140+ None)
141+
142+ self.assertTrue(openstack_upgrade_available.called)
143+ msg = ('no upgrade available.')
144+ action_set.assert_called_with({'outcome': msg})
145+ self.assertFalse(action_fail.called)
146+
147+ @patch.object(openstack, 'action_set')
148+ @patch.object(openstack, 'action_fail')
149+ @patch.object(openstack, 'openstack_upgrade_available')
150+ @patch('charmhelpers.contrib.openstack.utils.config')
151+ def test_openstack_upgrade_config_false(self, config,
152+ openstack_upgrade_available,
153+ action_fail, action_set):
154+ def do_openstack_upgrade(configs):
155+ pass
156+
157+ openstack_upgrade_available.return_value = True
158+
159+ # openstack-origin-git=None, action-managed-upgrade=False
160+ config.side_effect = [None, False]
161+
162+ openstack.do_action_openstack_upgrade('package-xyz',
163+ do_openstack_upgrade,
164+ None)
165+
166+ self.assertTrue(openstack_upgrade_available.called)
167+ msg = ('action-managed-upgrade config is False, skipped upgrade.')
168+ action_set.assert_called_with({'outcome': msg})
169+ self.assertFalse(action_fail.called)
170+
171+ @patch.object(openstack, 'action_set')
172+ @patch.object(openstack, 'action_fail')
173+ @patch.object(openstack, 'openstack_upgrade_available')
174+ @patch('traceback.format_exc')
175+ @patch('charmhelpers.contrib.openstack.utils.config')
176+ def test_openstack_upgrade_traceback(self, config, traceback,
177+ openstack_upgrade_available,
178+ action_fail, action_set):
179+ def do_openstack_upgrade(configs):
180+ oops() # noqa
181+
182+ openstack_upgrade_available.return_value = True
183+
184+ # openstack-origin-git=None, action-managed-upgrade=False
185+ config.side_effect = [None, True]
186+
187+ openstack.do_action_openstack_upgrade('package-xyz',
188+ do_openstack_upgrade,
189+ None)
190+
191+ self.assertTrue(openstack_upgrade_available.called)
192+ msg = 'do_openstack_upgrade resulted in an unexpected error'
193+ action_fail.assert_called_with(msg)
194+ self.assertTrue(action_set.called)
195+ self.assertTrue(traceback.called)
196+
197 if __name__ == '__main__':
198 unittest.main()

Subscribers

People subscribed via source and target branches