Merge lp:~1chb1n/openstack-mojo-specs/mojo-openstack-specs-juju-wait-for-workload-status into lp:openstack-mojo-specs

Proposed by Ryan Beisner on 2016-03-07
Status: Merged
Merged at revision: 251
Proposed branch: lp:~1chb1n/openstack-mojo-specs/mojo-openstack-specs-juju-wait-for-workload-status
Merge into: lp:openstack-mojo-specs
Diff against target: 295 lines (+62/-24)
12 files modified
helper/bundles/baremetal7.yaml (+0/-1)
helper/bundles/full.yaml (+0/-1)
helper/bundles/full_ssl.yaml (+0/-1)
helper/bundles/full_vrrpha.yaml (+0/-1)
helper/bundles/ha.yaml (+0/-1)
helper/bundles/haphase2.yaml (+0/-1)
helper/bundles/minimal.yaml (+0/-1)
helper/bundles/next-ha.yaml (+0/-1)
helper/bundles/ssl-everywhere.yaml (+0/-1)
helper/tests/check_juju.py (+2/-2)
helper/utils/juju_wait.py (+53/-12)
helper/utils/mojo_utils.py (+7/-1)
To merge this branch: bzr merge lp:~1chb1n/openstack-mojo-specs/mojo-openstack-specs-juju-wait-for-workload-status
Reviewer Review Type Date Requested Status
James Page 2016-03-07 Approve on 2016-03-08
Review via email: mp+288302@code.launchpad.net

Commit Message

Refresh with a fork of juju-wait which enables workload status blocking. If a unit is in a blocked state, keep waiting.
  From: https://code.launchpad.net/~1chb1n/juju-wait/workload-status
  Re: https://bugs.launchpad.net/juju-wait/+bug/1553312

Remove neutron-gateway:mysql shared-db relation from bundles
  Re: https://github.com/openstack/charm-neutron-gateway/commit/00f0edc70d68ce846db928ec2304d79fc6d1a5ae

Description of the Change

Refresh with a fork of juju-wait which enables workload status blocking. If a unit is in a blocked state, keep waiting.
  From: https://code.launchpad.net/~1chb1n/juju-wait/workload-status
  Re: https://bugs.launchpad.net/juju-wait/+bug/1553312

Remove neutron-gateway:mysql shared-db relation from bundles
  Re: https://github.com/openstack/charm-neutron-gateway/commit/00f0edc70d68ce846db928ec2304d79fc6d1a5ae

To post a comment you must log in.

charm_lint_check #1877 mojo-openstack-specs for 1chb1n mp288302
    LINT OK: passed

Build: http://10.245.162.36:8080/job/charm_lint_check/1877/

charm_lint_check #1878 mojo-openstack-specs for 1chb1n mp288302
    LINT FAIL: lint-test failed

LINT Results (max last 2 lines):
make: *** [lint] Error 1
ERROR:root:Make target returned non-zero.

Full lint test output: http://paste.ubuntu.com/15321958/
Build: http://10.245.162.36:8080/job/charm_lint_check/1878/

254. By Ryan Beisner on 2016-03-07

Lint cleanup

charm_lint_check #1879 mojo-openstack-specs for 1chb1n mp288302
    LINT OK: passed

Build: http://10.245.162.36:8080/job/charm_lint_check/1879/

James Page (james-page) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'helper/bundles/baremetal7.yaml'
2--- helper/bundles/baremetal7.yaml 2016-01-22 15:43:03 +0000
3+++ helper/bundles/baremetal7.yaml 2016-03-07 17:17:39 +0000
4@@ -152,7 +152,6 @@
5 - [ cinder, keystone ]
6 - [ cinder, cinder-ceph ]
7 - [ cinder-ceph, ceph ]
8- - [ neutron-gateway, mysql ]
9 - [ neutron-gateway, nova-cloud-controller ]
10 - [ openstack-dashboard, keystone ]
11 - [ swift-proxy, keystone ]
12
13=== modified file 'helper/bundles/full.yaml'
14--- helper/bundles/full.yaml 2016-01-22 17:10:00 +0000
15+++ helper/bundles/full.yaml 2016-03-07 17:17:39 +0000
16@@ -113,7 +113,6 @@
17 - [ cinder, nova-cloud-controller ]
18 - [ cinder, keystone ]
19 - [ cinder, ceph ]
20- - [ neutron-gateway, mysql ]
21 - [ neutron-gateway, nova-cloud-controller ]
22 - [ openstack-dashboard, keystone ]
23 - [ swift-proxy, keystone ]
24
25=== modified file 'helper/bundles/full_ssl.yaml'
26--- helper/bundles/full_ssl.yaml 2015-08-05 08:40:27 +0000
27+++ helper/bundles/full_ssl.yaml 2016-03-07 17:17:39 +0000
28@@ -117,7 +117,6 @@
29 - [ cinder, nova-cloud-controller ]
30 - [ cinder, keystone ]
31 - [ cinder, ceph ]
32- - [ neutron-gateway, mysql ]
33 - [ neutron-gateway, nova-cloud-controller ]
34 - [ openstack-dashboard, keystone ]
35 - [ swift-proxy, keystone ]
36
37=== modified file 'helper/bundles/full_vrrpha.yaml'
38--- helper/bundles/full_vrrpha.yaml 2015-11-16 15:07:13 +0000
39+++ helper/bundles/full_vrrpha.yaml 2016-03-07 17:17:39 +0000
40@@ -64,7 +64,6 @@
41 - [ cinder, rabbitmq-server ]
42 - [ cinder, nova-cloud-controller ]
43 - [ cinder, keystone ]
44- - [ neutron-gateway, mysql ]
45 - [ neutron-gateway, nova-cloud-controller ]
46 - [ openstack-dashboard, keystone ]
47 openstack-singlerabbit:
48
49=== modified file 'helper/bundles/ha.yaml'
50--- helper/bundles/ha.yaml 2016-01-20 10:57:18 +0000
51+++ helper/bundles/ha.yaml 2016-03-07 17:17:39 +0000
52@@ -196,7 +196,6 @@
53 - [ cinder, keystone ]
54 - [ cinder, cinder-ceph ]
55 - [ cinder-ceph, ceph ]
56- - [ neutron-gateway, mysql ]
57 - [ neutron-gateway, nova-cloud-controller ]
58 - [ openstack-dashboard, keystone ]
59 - [ swift-proxy, keystone ]
60
61=== modified file 'helper/bundles/haphase2.yaml'
62--- helper/bundles/haphase2.yaml 2015-10-21 20:53:34 +0000
63+++ helper/bundles/haphase2.yaml 2016-03-07 17:17:39 +0000
64@@ -152,7 +152,6 @@
65 - [ nova-compute, mysql ]
66 - [ glance, mysql ]
67 - [ cinder, mysql ]
68- - [ neutron-gateway, mysql ]
69 openstack-mysql-database:
70 inherits:
71 - openstack-services
72
73=== modified file 'helper/bundles/minimal.yaml'
74--- helper/bundles/minimal.yaml 2015-08-05 08:40:27 +0000
75+++ helper/bundles/minimal.yaml 2016-03-07 17:17:39 +0000
76@@ -61,7 +61,6 @@
77 - [ cinder, rabbitmq-server ]
78 - [ cinder, nova-cloud-controller ]
79 - [ cinder, keystone ]
80- - [ neutron-gateway, mysql ]
81 - [ neutron-gateway, nova-cloud-controller ]
82 openstack-singlerabbit:
83 openstack-singlerabbit:
84
85=== modified file 'helper/bundles/next-ha.yaml'
86--- helper/bundles/next-ha.yaml 2015-08-05 08:40:27 +0000
87+++ helper/bundles/next-ha.yaml 2016-03-07 17:17:39 +0000
88@@ -173,7 +173,6 @@
89 - [ cinder, nova-cloud-controller ]
90 - [ cinder, keystone ]
91 - [ cinder, ceph ]
92- - [ neutron-gateway, mysql ]
93 - [ neutron-gateway, nova-cloud-controller ]
94 - [ openstack-dashboard, keystone ]
95 - [ swift-proxy, keystone ]
96
97=== modified file 'helper/bundles/ssl-everywhere.yaml'
98--- helper/bundles/ssl-everywhere.yaml 2014-12-18 10:28:32 +0000
99+++ helper/bundles/ssl-everywhere.yaml 2016-03-07 17:17:39 +0000
100@@ -117,7 +117,6 @@
101 - [ cinder, nova-cloud-controller ]
102 - [ cinder, keystone ]
103 - [ cinder, ceph ]
104- - [ neutron-gateway, mysql ]
105 - [ neutron-gateway, rabbitmq-server ]
106 - [ neutron-gateway, nova-cloud-controller ]
107 - [ openstack-dashboard, keystone ]
108
109=== modified file 'helper/tests/check_juju.py'
110--- helper/tests/check_juju.py 2015-11-02 11:31:41 +0000
111+++ helper/tests/check_juju.py 2016-03-07 17:17:39 +0000
112@@ -1,6 +1,6 @@
113 #!/usr/bin/python
114 import sys
115-from utils.juju_wait import wait
116+from utils.mojo_utils import juju_wait_finished
117
118 if __name__ == '__main__':
119- sys.exit(wait())
120+ sys.exit(juju_wait_finished())
121
122=== modified file 'helper/utils/juju_wait.py'
123--- helper/utils/juju_wait.py 2015-11-02 11:31:41 +0000
124+++ helper/utils/juju_wait.py 2016-03-07 17:17:39 +0000
125@@ -1,5 +1,10 @@
126 #!/usr/bin/python3
127
128+# NOTE(beisner): this is a fork of juju-wait which enables workload
129+# status blocking. ie. If a unit is in a blocked state, keep waiting.
130+# From: https://code.launchpad.net/~1chb1n/juju-wait/workload-status
131+# Re: https://bugs.launchpad.net/juju-wait/+bug/1553312
132+
133 # This file is part of juju-wait, a juju plugin to wait for environment
134 # steady state.
135 #
136@@ -82,7 +87,6 @@
137 # using the environment variable.
138 env = os.environ.copy()
139 env['TZ'] = 'UTC'
140- env['JUJU_CLI_VERSION'] = '1'
141 json_status = run_or_die(['juju', 'status', '--format=json'], env=env)
142 if json_status is None:
143 return None
144@@ -107,6 +111,14 @@
145 # still due to be run.
146 IDLE_CONFIRMATION = timedelta(seconds=15)
147
148+# If all units have one of the following workload status values,
149+# consider them ready. Not all charms use workload the status feature.
150+# Those that do not will be represented by the 'unknown' value and
151+# workload status will be ignored. For charms that do, wait for an
152+# 'active' workload status value. FYI: blocked, waiting, maintenance
153+# values indicate not-ready workload states.
154+WORKLOAD_OK_STATES = ['active', 'unknown']
155+
156
157 def wait_cmd(args=sys.argv[1:]):
158 description = dedent("""\
159@@ -126,6 +138,9 @@
160 action='store_true', default=False)
161 parser.add_argument('-v', '--verbose', dest='verbose',
162 action='store_true', default=False)
163+ parser.add_argument('-w', '--workload', dest='wait_for_workload',
164+ help='Wait for unit workload status active state',
165+ action='store_true', default=False)
166 args = parser.parse_args(args)
167
168 # Parser did not exit, so continue.
169@@ -138,7 +153,7 @@
170 else:
171 log.setLevel(logging.INFO)
172 try:
173- wait(log)
174+ wait(log, args.wait_for_workload)
175 return 0
176 except JujuWaitException as x:
177 return x.args[0]
178@@ -153,7 +168,7 @@
179 'logging-config=juju=WARNING;unit=INFO'])
180
181
182-def wait(log=None):
183+def wait(log=None, wait_for_workload=False):
184 if log is None:
185 log = logging.getLogger()
186
187@@ -181,32 +196,50 @@
188 # logs sniffed because they are running Juju 1.23 or earlier.
189 ready_units = {}
190
191- # Flattened agent status for all units and subordinates that
192- # provide it. Note that 'agent status' is only available in
193+ # Flattened agent and workload status for all units and subordinates
194+ # that provide it. Note that 'agent status' is only available in
195 # Juju 1.24 and later. This is easily confused with 'agent state'
196 # which is available in earlier versions of Juju.
197+ workload_status = {}
198 agent_status = {}
199 agent_version = {}
200 for sname, service in status.get('services', {}).items():
201 for uname, unit in service.get('units', {}).items():
202 all_units.add(uname)
203 agent_version[uname] = unit.get('agent-version')
204- if 'agent-status' in unit:
205+ if ('workload-status' in unit and
206+ 'current' in unit['workload-status']):
207+ workload_status[uname] = unit['workload-status']
208+
209+ if 'agent-status' in unit and unit['agent-status'] != {}:
210 agent_status[uname] = unit['agent-status']
211 else:
212 ready_units[uname] = unit # Schedule for sniffing.
213 for subname, sub in unit.get('subordinates', {}).items():
214+ if ('workload-status' in sub and
215+ 'current' in sub['workload-status']):
216+ workload_status[subname] = sub['workload-status']
217+
218 agent_version[subname] = sub.get('agent-version')
219- if 'agent-status' in sub:
220+ if 'agent-status' in sub and unit['agent-status'] != {}:
221 agent_status[subname] = sub['agent-status']
222 else:
223 ready_units[subname] = sub # Schedule for sniffing.
224
225+ for uname, wstatus in sorted(workload_status.items()):
226+ current = wstatus['current']
227+ since = parse_ts(wstatus['since'])
228+ if current not in WORKLOAD_OK_STATES and wait_for_workload:
229+ logging.debug('{} workload status is {} since '
230+ '{}Z'.format(uname, current, since))
231+ ready = False
232+
233 for uname, astatus in sorted(agent_status.items()):
234 current = astatus['current']
235 since = parse_ts(astatus['since'])
236- logging.debug('{} is {} since {}Z'.format(uname, current, since))
237 if current != 'idle':
238+ logging.debug('{} agent status is {} since '
239+ '{}Z'.format(uname, current, since))
240 ready = False
241
242 # Log storage to compare with prev_logs.
243@@ -228,6 +261,11 @@
244 logging.debug('{} is {}'.format(uname, agent_state))
245 ready = False
246 elif ready:
247+ # We only start grabbing the logs once all the units
248+ # are in a suitable lifecycle state. If we don't do this,
249+ # we risk attempting to grab logs from units or subordinates
250+ # that are not yet ready to respond, or have disappeared
251+ # since we last checked the environment status.
252 if not logging_reset:
253 reset_logging()
254 logging_reset = True
255@@ -248,9 +286,9 @@
256 for uname, version in agent_version.items():
257 sname = uname.split('/', 1)[0]
258 services.add(sname)
259- if (sname not in services_with_leader and version
260- and (LooseVersion(version) >= LooseVersion('1.23')
261- or get_is_leader(uname) is True)):
262+ if (sname not in services_with_leader and version and
263+ (LooseVersion(version) <= LooseVersion('1.23') or
264+ get_is_leader(uname) is True)):
265 services_with_leader.add(sname)
266 logging.debug('{} is lead by {}'.format(sname, uname))
267 for sname in services:
268@@ -283,4 +321,7 @@
269 # Most installations will be using the setuptools generated
270 # launchers.
271 script = os.path.basename(sys.argv[0])
272- sys.exit(wait_cmd())
273+ if script == 'juju-wait':
274+ sys.exit(wait_cmd())
275+ else:
276+ raise RuntimeError('Unknown script {}'.format(script))
277
278=== modified file 'helper/utils/mojo_utils.py'
279--- helper/utils/mojo_utils.py 2016-03-07 10:37:26 +0000
280+++ helper/utils/mojo_utils.py 2016-03-07 17:17:39 +0000
281@@ -481,7 +481,13 @@
282
283
284 def juju_wait_finished():
285- juju_wait.wait()
286+ """Use juju-wait from local utils path to block until all service
287+ units quiesce and satisfy workload status ready state."""
288+ log = logging.getLogger()
289+ log.setLevel(logging.DEBUG)
290+ logging.info('Calling juju-wait')
291+ juju_wait.wait(log, wait_for_workload=True)
292+ logging.debug('End of juju-wait')
293
294
295 def dict_to_yaml(dict_data):

Subscribers

People subscribed via source and target branches