Merge lp:~hopem/charms/trusty/keystone/fix-db-migrate-race into lp:~openstack-charmers-archive/charms/trusty/keystone/next
- Trusty Tahr (14.04)
- fix-db-migrate-race
- Merge into next
Proposed by
Edward Hope-Morley
Status: | Merged |
---|---|
Merged at revision: | 121 |
Proposed branch: | lp:~hopem/charms/trusty/keystone/fix-db-migrate-race |
Merge into: | lp:~openstack-charmers-archive/charms/trusty/keystone/next |
Diff against target: |
334 lines (+84/-33) 3 files modified
hooks/keystone_hooks.py (+29/-23) hooks/keystone_utils.py (+28/-2) unit_tests/test_keystone_hooks.py (+27/-8) |
To merge this branch: | bzr merge lp:~hopem/charms/trusty/keystone/fix-db-migrate-race |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Liam Young (community) | Approve | ||
Review via email: mp+249904@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_unit_test #1832 keystone-next for hopem mp249904
UNIT OK: passed
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote : | # |
charm_amulet_test #1980 keystone-next for hopem mp249904
AMULET OK: passed
Build: http://
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'hooks/keystone_hooks.py' |
2 | --- hooks/keystone_hooks.py 2015-02-16 13:35:14 +0000 |
3 | +++ hooks/keystone_hooks.py 2015-02-17 00:12:48 +0000 |
4 | @@ -4,7 +4,6 @@ |
5 | import os |
6 | import stat |
7 | import sys |
8 | -import time |
9 | |
10 | from subprocess import check_call |
11 | |
12 | @@ -72,6 +71,7 @@ |
13 | is_ssl_cert_master, |
14 | is_db_ready, |
15 | clear_ssl_synced_units, |
16 | + is_db_initialised, |
17 | ) |
18 | |
19 | from charmhelpers.contrib.hahelpers.cluster import ( |
20 | @@ -198,17 +198,18 @@ |
21 | level=INFO) |
22 | return |
23 | |
24 | - try: |
25 | - migrate_database() |
26 | - except Exception as exc: |
27 | - log("Database initialisation failed (%s) - db not ready?" % (exc), |
28 | - level=WARNING) |
29 | - else: |
30 | + if not is_db_initialised(): |
31 | + log("Database not yet initialised - deferring identity-relation " |
32 | + "updates", level=INFO) |
33 | + return |
34 | + |
35 | + if is_elected_leader(CLUSTER_RES): |
36 | ensure_initial_admin(config) |
37 | - log('Firing identity_changed hook for all related services.') |
38 | - for rid in relation_ids('identity-service'): |
39 | - for unit in related_units(rid): |
40 | - identity_changed(relation_id=rid, remote_unit=unit) |
41 | + |
42 | + log('Firing identity_changed hook for all related services.') |
43 | + for rid in relation_ids('identity-service'): |
44 | + for unit in related_units(rid): |
45 | + identity_changed(relation_id=rid, remote_unit=unit) |
46 | |
47 | |
48 | @synchronize_ca_if_changed(force=True) |
49 | @@ -233,8 +234,10 @@ |
50 | level=INFO) |
51 | return |
52 | |
53 | + migrate_database() |
54 | + |
55 | # Ensure any existing service entries are updated in the |
56 | - # new database backend |
57 | + # new database backend. Also avoid duplicate db ready check. |
58 | update_all_identity_relation_units(check_db_ready=False) |
59 | |
60 | |
61 | @@ -247,9 +250,15 @@ |
62 | else: |
63 | CONFIGS.write(KEYSTONE_CONF) |
64 | if is_elected_leader(CLUSTER_RES): |
65 | + if not is_db_ready(use_current_context=True): |
66 | + log('Allowed_units list provided and this unit not present', |
67 | + level=INFO) |
68 | + return |
69 | + |
70 | + migrate_database() |
71 | # Ensure any existing service entries are updated in the |
72 | - # new database backend |
73 | - update_all_identity_relation_units() |
74 | + # new database backend. Also avoid duplicate db ready check. |
75 | + update_all_identity_relation_units(check_db_ready=False) |
76 | |
77 | |
78 | @hooks.hook('identity-service-relation-changed') |
79 | @@ -265,6 +274,11 @@ |
80 | "ready - deferring until db ready", level=WARNING) |
81 | return |
82 | |
83 | + if not is_db_initialised(): |
84 | + log("Database not yet initialised - deferring identity-relation " |
85 | + "updates", level=INFO) |
86 | + return |
87 | + |
88 | add_service_to_keystone(relation_id, remote_unit) |
89 | settings = relation_get(rid=relation_id, unit=remote_unit) |
90 | service = settings.get('service', None) |
91 | @@ -394,7 +408,7 @@ |
92 | # NOTE(jamespage) re-echo passwords for peer storage |
93 | echo_whitelist, overrides = \ |
94 | apply_echo_filters(settings, ['_passwd', 'identity-service:', |
95 | - 'ssl-cert-master']) |
96 | + 'ssl-cert-master', 'db-initialised']) |
97 | log("Peer echo overrides: %s" % (overrides), level=DEBUG) |
98 | relation_set(**overrides) |
99 | if echo_whitelist: |
100 | @@ -487,15 +501,8 @@ |
101 | |
102 | clustered = relation_get('clustered') |
103 | if clustered and is_elected_leader(CLUSTER_RES): |
104 | - if not is_db_ready(): |
105 | - log('Allowed_units list provided and this unit not present', |
106 | - level=INFO) |
107 | - return |
108 | - |
109 | - ensure_initial_admin(config) |
110 | log('Cluster configured, notifying other services and updating ' |
111 | 'keystone endpoint configuration') |
112 | - |
113 | update_all_identity_relation_units() |
114 | |
115 | |
116 | @@ -546,7 +553,6 @@ |
117 | if is_elected_leader(CLUSTER_RES): |
118 | log('Cluster leader - ensuring endpoint configuration is up to ' |
119 | 'date', level=DEBUG) |
120 | - time.sleep(10) |
121 | update_all_identity_relation_units() |
122 | |
123 | |
124 | |
125 | === modified file 'hooks/keystone_utils.py' |
126 | --- hooks/keystone_utils.py 2015-02-16 14:48:02 +0000 |
127 | +++ hooks/keystone_utils.py 2015-02-17 00:12:48 +0000 |
128 | @@ -314,7 +314,32 @@ |
129 | configs.write_all() |
130 | |
131 | if is_elected_leader(CLUSTER_RES): |
132 | - migrate_database() |
133 | + if is_db_ready(): |
134 | + migrate_database() |
135 | + else: |
136 | + log("Database not ready - deferring to shared-db relation", |
137 | + level=INFO) |
138 | + return |
139 | + |
140 | + |
141 | +def set_db_initialised(): |
142 | + for rid in relation_ids('cluster'): |
143 | + relation_set(relation_settings={'db-initialised': 'True'}, |
144 | + relation_id=rid) |
145 | + |
146 | + |
147 | +def is_db_initialised(): |
148 | + for rid in relation_ids('cluster'): |
149 | + units = related_units(rid) + [local_unit()] |
150 | + for unit in units: |
151 | + db_initialised = relation_get(attribute='db-initialised', |
152 | + unit=unit, rid=rid) |
153 | + if db_initialised: |
154 | + log("Database is initialised", level=DEBUG) |
155 | + return True |
156 | + |
157 | + log("Database is NOT initialised", level=DEBUG) |
158 | + return False |
159 | |
160 | |
161 | def migrate_database(): |
162 | @@ -328,10 +353,11 @@ |
163 | subprocess.check_output(cmd) |
164 | service_start('keystone') |
165 | time.sleep(10) |
166 | - |
167 | + set_db_initialised() |
168 | |
169 | # OLD |
170 | |
171 | + |
172 | def get_local_endpoint(): |
173 | """Returns the URL for the local end-point bypassing haproxy/ssl""" |
174 | if config('prefer-ipv6'): |
175 | |
176 | === modified file 'unit_tests/test_keystone_hooks.py' |
177 | --- unit_tests/test_keystone_hooks.py 2015-02-05 17:48:25 +0000 |
178 | +++ unit_tests/test_keystone_hooks.py 2015-02-17 00:12:48 +0000 |
179 | @@ -63,7 +63,6 @@ |
180 | 'execd_preinstall', |
181 | 'mkdir', |
182 | 'os', |
183 | - 'time', |
184 | # ip |
185 | 'get_iface_for_address', |
186 | 'get_netmask_for_address', |
187 | @@ -203,6 +202,7 @@ |
188 | configs.write = MagicMock() |
189 | hooks.pgsql_db_changed() |
190 | |
191 | + @patch.object(hooks, 'is_db_initialised') |
192 | @patch.object(hooks, 'is_db_ready') |
193 | @patch('keystone_utils.log') |
194 | @patch('keystone_utils.ensure_ssl_cert_master') |
195 | @@ -210,7 +210,9 @@ |
196 | @patch.object(hooks, 'identity_changed') |
197 | def test_db_changed_allowed(self, identity_changed, configs, |
198 | mock_ensure_ssl_cert_master, |
199 | - mock_log, mock_is_db_ready): |
200 | + mock_log, mock_is_db_ready, |
201 | + mock_is_db_initialised): |
202 | + mock_is_db_initialised.return_value = True |
203 | mock_is_db_ready.return_value = True |
204 | mock_ensure_ssl_cert_master.return_value = False |
205 | self.relation_ids.return_value = ['identity-service:0'] |
206 | @@ -247,12 +249,14 @@ |
207 | |
208 | @patch('keystone_utils.log') |
209 | @patch('keystone_utils.ensure_ssl_cert_master') |
210 | + @patch.object(hooks, 'is_db_initialised') |
211 | @patch.object(hooks, 'is_db_ready') |
212 | @patch.object(hooks, 'CONFIGS') |
213 | @patch.object(hooks, 'identity_changed') |
214 | def test_postgresql_db_changed(self, identity_changed, configs, |
215 | - mock_is_db_ready, |
216 | + mock_is_db_ready, mock_is_db_initialised, |
217 | mock_ensure_ssl_cert_master, mock_log): |
218 | + mock_is_db_initialised.return_value = True |
219 | mock_is_db_ready.return_value = True |
220 | mock_ensure_ssl_cert_master.return_value = False |
221 | self.relation_ids.return_value = ['identity-service:0'] |
222 | @@ -269,6 +273,7 @@ |
223 | |
224 | @patch('keystone_utils.log') |
225 | @patch('keystone_utils.ensure_ssl_cert_master') |
226 | + @patch.object(hooks, 'is_db_initialised') |
227 | @patch.object(hooks, 'is_db_ready') |
228 | @patch.object(hooks, 'peer_units') |
229 | @patch.object(hooks, 'ensure_permissions') |
230 | @@ -283,8 +288,9 @@ |
231 | self, configure_https, identity_changed, |
232 | configs, get_homedir, ensure_user, cluster_joined, |
233 | admin_relation_changed, ensure_permissions, mock_peer_units, |
234 | - mock_is_db_ready, |
235 | + mock_is_db_ready, mock_is_db_initialised, |
236 | mock_ensure_ssl_cert_master, mock_log): |
237 | + mock_is_db_initialised.return_value = True |
238 | mock_is_db_ready.return_value = True |
239 | self.openstack_upgrade_available.return_value = False |
240 | self.is_elected_leader.return_value = True |
241 | @@ -302,7 +308,6 @@ |
242 | configure_https.assert_called_with() |
243 | self.assertTrue(configs.write_all.called) |
244 | |
245 | - self.migrate_database.assert_called_with() |
246 | self.assertTrue(self.ensure_initial_admin.called) |
247 | self.log.assert_called_with( |
248 | 'Firing identity_changed hook for all related services.') |
249 | @@ -343,6 +348,7 @@ |
250 | |
251 | @patch('keystone_utils.log') |
252 | @patch('keystone_utils.ensure_ssl_cert_master') |
253 | + @patch.object(hooks, 'is_db_initialised') |
254 | @patch.object(hooks, 'is_db_ready') |
255 | @patch.object(hooks, 'peer_units') |
256 | @patch.object(hooks, 'ensure_permissions') |
257 | @@ -361,9 +367,11 @@ |
258 | ensure_permissions, |
259 | mock_peer_units, |
260 | mock_is_db_ready, |
261 | + mock_is_db_initialised, |
262 | mock_ensure_ssl_cert_master, |
263 | mock_log): |
264 | mock_is_db_ready.return_value = True |
265 | + mock_is_db_initialised.return_value = True |
266 | self.openstack_upgrade_available.return_value = True |
267 | self.is_elected_leader.return_value = True |
268 | # avoid having to mock syncer |
269 | @@ -382,7 +390,6 @@ |
270 | configure_https.assert_called_with() |
271 | self.assertTrue(configs.write_all.called) |
272 | |
273 | - self.migrate_database.assert_called_with() |
274 | self.assertTrue(self.ensure_initial_admin.called) |
275 | self.log.assert_called_with( |
276 | 'Firing identity_changed hook for all related services.') |
277 | @@ -391,6 +398,7 @@ |
278 | remote_unit='unit/0') |
279 | admin_relation_changed.assert_called_with('identity-service:0') |
280 | |
281 | + @patch.object(hooks, 'is_db_initialised') |
282 | @patch.object(hooks, 'is_db_ready') |
283 | @patch('keystone_utils.log') |
284 | @patch('keystone_utils.ensure_ssl_cert_master') |
285 | @@ -398,7 +406,9 @@ |
286 | @patch.object(hooks, 'send_notifications') |
287 | def test_identity_changed_leader(self, mock_send_notifications, |
288 | mock_hashlib, mock_ensure_ssl_cert_master, |
289 | - mock_log, mock_is_db_ready): |
290 | + mock_log, mock_is_db_ready, |
291 | + mock_is_db_initialised): |
292 | + mock_is_db_initialised.return_value = True |
293 | mock_is_db_ready.return_value = True |
294 | mock_ensure_ssl_cert_master.return_value = False |
295 | hooks.identity_changed( |
296 | @@ -557,13 +567,16 @@ |
297 | @patch('keystone_utils.log') |
298 | @patch('keystone_utils.ensure_ssl_cert_master') |
299 | @patch.object(hooks, 'is_db_ready') |
300 | + @patch.object(hooks, 'is_db_initialised') |
301 | @patch.object(hooks, 'identity_changed') |
302 | @patch.object(hooks, 'CONFIGS') |
303 | def test_ha_relation_changed_clustered_leader(self, configs, |
304 | identity_changed, |
305 | + mock_is_db_initialised, |
306 | mock_is_db_ready, |
307 | mock_ensure_ssl_cert_master, |
308 | mock_log): |
309 | + mock_is_db_initialised.return_value = True |
310 | mock_is_db_ready.return_value = True |
311 | mock_ensure_ssl_cert_master.return_value = False |
312 | self.relation_get.return_value = True |
313 | @@ -610,6 +623,8 @@ |
314 | cmd = ['a2dissite', 'openstack_https_frontend'] |
315 | self.check_call.assert_called_with(cmd) |
316 | |
317 | + @patch.object(hooks, 'is_db_ready') |
318 | + @patch.object(hooks, 'is_db_initialised') |
319 | @patch('keystone_utils.log') |
320 | @patch('keystone_utils.relation_ids') |
321 | @patch('keystone_utils.is_elected_leader') |
322 | @@ -623,7 +638,11 @@ |
323 | mock_ensure_ssl_cert_master, |
324 | mock_is_elected_leader, |
325 | mock_relation_ids, |
326 | - mock_log): |
327 | + mock_log, |
328 | + mock_is_db_ready, |
329 | + mock_is_db_initialised): |
330 | + mock_is_db_initialised.return_value = True |
331 | + mock_is_db_ready.return_value = True |
332 | mock_is_elected_leader.return_value = False |
333 | mock_relation_ids.return_value = [] |
334 | mock_ensure_ssl_cert_master.return_value = True |
charm_lint_check #2042 keystone-next for hopem mp249904
LINT OK: passed
Build: http:// 10.245. 162.77: 8080/job/ charm_lint_ check/2042/