Merge lp:~hopem/charms/trusty/keystone/fix-db-migrate-race into lp:~openstack-charmers-archive/charms/trusty/keystone/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
Reviewer Review Type Date Requested Status
Liam Young (community) Approve
Review via email: mp+249904@code.launchpad.net
To post a comment you must log in.
Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_lint_check #2042 keystone-next for hopem mp249904
    LINT OK: passed

Build: http://10.245.162.77:8080/job/charm_lint_check/2042/

Revision history for this message
uosci-testing-bot (uosci-testing-bot) wrote :

charm_unit_test #1832 keystone-next for hopem mp249904
    UNIT OK: passed

Build: http://10.245.162.77:8080/job/charm_unit_test/1832/

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://10.245.162.77:8080/job/charm_amulet_test/1980/

Revision history for this message
Liam Young (gnuoy) wrote :

Approve

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'hooks/keystone_hooks.py'
--- hooks/keystone_hooks.py 2015-02-16 13:35:14 +0000
+++ hooks/keystone_hooks.py 2015-02-17 00:12:48 +0000
@@ -4,7 +4,6 @@
4import os4import os
5import stat5import stat
6import sys6import sys
7import time
87
9from subprocess import check_call8from subprocess import check_call
109
@@ -72,6 +71,7 @@
72 is_ssl_cert_master,71 is_ssl_cert_master,
73 is_db_ready,72 is_db_ready,
74 clear_ssl_synced_units,73 clear_ssl_synced_units,
74 is_db_initialised,
75)75)
7676
77from charmhelpers.contrib.hahelpers.cluster import (77from charmhelpers.contrib.hahelpers.cluster import (
@@ -198,17 +198,18 @@
198 level=INFO)198 level=INFO)
199 return199 return
200200
201 try:201 if not is_db_initialised():
202 migrate_database()202 log("Database not yet initialised - deferring identity-relation "
203 except Exception as exc:203 "updates", level=INFO)
204 log("Database initialisation failed (%s) - db not ready?" % (exc),204 return
205 level=WARNING)205
206 else:206 if is_elected_leader(CLUSTER_RES):
207 ensure_initial_admin(config)207 ensure_initial_admin(config)
208 log('Firing identity_changed hook for all related services.')208
209 for rid in relation_ids('identity-service'):209 log('Firing identity_changed hook for all related services.')
210 for unit in related_units(rid):210 for rid in relation_ids('identity-service'):
211 identity_changed(relation_id=rid, remote_unit=unit)211 for unit in related_units(rid):
212 identity_changed(relation_id=rid, remote_unit=unit)
212213
213214
214@synchronize_ca_if_changed(force=True)215@synchronize_ca_if_changed(force=True)
@@ -233,8 +234,10 @@
233 level=INFO)234 level=INFO)
234 return235 return
235236
237 migrate_database()
238
236 # Ensure any existing service entries are updated in the239 # Ensure any existing service entries are updated in the
237 # new database backend240 # new database backend. Also avoid duplicate db ready check.
238 update_all_identity_relation_units(check_db_ready=False)241 update_all_identity_relation_units(check_db_ready=False)
239242
240243
@@ -247,9 +250,15 @@
247 else:250 else:
248 CONFIGS.write(KEYSTONE_CONF)251 CONFIGS.write(KEYSTONE_CONF)
249 if is_elected_leader(CLUSTER_RES):252 if is_elected_leader(CLUSTER_RES):
253 if not is_db_ready(use_current_context=True):
254 log('Allowed_units list provided and this unit not present',
255 level=INFO)
256 return
257
258 migrate_database()
250 # Ensure any existing service entries are updated in the259 # Ensure any existing service entries are updated in the
251 # new database backend260 # new database backend. Also avoid duplicate db ready check.
252 update_all_identity_relation_units()261 update_all_identity_relation_units(check_db_ready=False)
253262
254263
255@hooks.hook('identity-service-relation-changed')264@hooks.hook('identity-service-relation-changed')
@@ -265,6 +274,11 @@
265 "ready - deferring until db ready", level=WARNING)274 "ready - deferring until db ready", level=WARNING)
266 return275 return
267276
277 if not is_db_initialised():
278 log("Database not yet initialised - deferring identity-relation "
279 "updates", level=INFO)
280 return
281
268 add_service_to_keystone(relation_id, remote_unit)282 add_service_to_keystone(relation_id, remote_unit)
269 settings = relation_get(rid=relation_id, unit=remote_unit)283 settings = relation_get(rid=relation_id, unit=remote_unit)
270 service = settings.get('service', None)284 service = settings.get('service', None)
@@ -394,7 +408,7 @@
394 # NOTE(jamespage) re-echo passwords for peer storage408 # NOTE(jamespage) re-echo passwords for peer storage
395 echo_whitelist, overrides = \409 echo_whitelist, overrides = \
396 apply_echo_filters(settings, ['_passwd', 'identity-service:',410 apply_echo_filters(settings, ['_passwd', 'identity-service:',
397 'ssl-cert-master'])411 'ssl-cert-master', 'db-initialised'])
398 log("Peer echo overrides: %s" % (overrides), level=DEBUG)412 log("Peer echo overrides: %s" % (overrides), level=DEBUG)
399 relation_set(**overrides)413 relation_set(**overrides)
400 if echo_whitelist:414 if echo_whitelist:
@@ -487,15 +501,8 @@
487501
488 clustered = relation_get('clustered')502 clustered = relation_get('clustered')
489 if clustered and is_elected_leader(CLUSTER_RES):503 if clustered and is_elected_leader(CLUSTER_RES):
490 if not is_db_ready():
491 log('Allowed_units list provided and this unit not present',
492 level=INFO)
493 return
494
495 ensure_initial_admin(config)
496 log('Cluster configured, notifying other services and updating '504 log('Cluster configured, notifying other services and updating '
497 'keystone endpoint configuration')505 'keystone endpoint configuration')
498
499 update_all_identity_relation_units()506 update_all_identity_relation_units()
500507
501508
@@ -546,7 +553,6 @@
546 if is_elected_leader(CLUSTER_RES):553 if is_elected_leader(CLUSTER_RES):
547 log('Cluster leader - ensuring endpoint configuration is up to '554 log('Cluster leader - ensuring endpoint configuration is up to '
548 'date', level=DEBUG)555 'date', level=DEBUG)
549 time.sleep(10)
550 update_all_identity_relation_units()556 update_all_identity_relation_units()
551557
552558
553559
=== modified file 'hooks/keystone_utils.py'
--- hooks/keystone_utils.py 2015-02-16 14:48:02 +0000
+++ hooks/keystone_utils.py 2015-02-17 00:12:48 +0000
@@ -314,7 +314,32 @@
314 configs.write_all()314 configs.write_all()
315315
316 if is_elected_leader(CLUSTER_RES):316 if is_elected_leader(CLUSTER_RES):
317 migrate_database()317 if is_db_ready():
318 migrate_database()
319 else:
320 log("Database not ready - deferring to shared-db relation",
321 level=INFO)
322 return
323
324
325def set_db_initialised():
326 for rid in relation_ids('cluster'):
327 relation_set(relation_settings={'db-initialised': 'True'},
328 relation_id=rid)
329
330
331def is_db_initialised():
332 for rid in relation_ids('cluster'):
333 units = related_units(rid) + [local_unit()]
334 for unit in units:
335 db_initialised = relation_get(attribute='db-initialised',
336 unit=unit, rid=rid)
337 if db_initialised:
338 log("Database is initialised", level=DEBUG)
339 return True
340
341 log("Database is NOT initialised", level=DEBUG)
342 return False
318343
319344
320def migrate_database():345def migrate_database():
@@ -328,10 +353,11 @@
328 subprocess.check_output(cmd)353 subprocess.check_output(cmd)
329 service_start('keystone')354 service_start('keystone')
330 time.sleep(10)355 time.sleep(10)
331356 set_db_initialised()
332357
333# OLD358# OLD
334359
360
335def get_local_endpoint():361def get_local_endpoint():
336 """Returns the URL for the local end-point bypassing haproxy/ssl"""362 """Returns the URL for the local end-point bypassing haproxy/ssl"""
337 if config('prefer-ipv6'):363 if config('prefer-ipv6'):
338364
=== modified file 'unit_tests/test_keystone_hooks.py'
--- unit_tests/test_keystone_hooks.py 2015-02-05 17:48:25 +0000
+++ unit_tests/test_keystone_hooks.py 2015-02-17 00:12:48 +0000
@@ -63,7 +63,6 @@
63 'execd_preinstall',63 'execd_preinstall',
64 'mkdir',64 'mkdir',
65 'os',65 'os',
66 'time',
67 # ip66 # ip
68 'get_iface_for_address',67 'get_iface_for_address',
69 'get_netmask_for_address',68 'get_netmask_for_address',
@@ -203,6 +202,7 @@
203 configs.write = MagicMock()202 configs.write = MagicMock()
204 hooks.pgsql_db_changed()203 hooks.pgsql_db_changed()
205204
205 @patch.object(hooks, 'is_db_initialised')
206 @patch.object(hooks, 'is_db_ready')206 @patch.object(hooks, 'is_db_ready')
207 @patch('keystone_utils.log')207 @patch('keystone_utils.log')
208 @patch('keystone_utils.ensure_ssl_cert_master')208 @patch('keystone_utils.ensure_ssl_cert_master')
@@ -210,7 +210,9 @@
210 @patch.object(hooks, 'identity_changed')210 @patch.object(hooks, 'identity_changed')
211 def test_db_changed_allowed(self, identity_changed, configs,211 def test_db_changed_allowed(self, identity_changed, configs,
212 mock_ensure_ssl_cert_master,212 mock_ensure_ssl_cert_master,
213 mock_log, mock_is_db_ready):213 mock_log, mock_is_db_ready,
214 mock_is_db_initialised):
215 mock_is_db_initialised.return_value = True
214 mock_is_db_ready.return_value = True216 mock_is_db_ready.return_value = True
215 mock_ensure_ssl_cert_master.return_value = False217 mock_ensure_ssl_cert_master.return_value = False
216 self.relation_ids.return_value = ['identity-service:0']218 self.relation_ids.return_value = ['identity-service:0']
@@ -247,12 +249,14 @@
247249
248 @patch('keystone_utils.log')250 @patch('keystone_utils.log')
249 @patch('keystone_utils.ensure_ssl_cert_master')251 @patch('keystone_utils.ensure_ssl_cert_master')
252 @patch.object(hooks, 'is_db_initialised')
250 @patch.object(hooks, 'is_db_ready')253 @patch.object(hooks, 'is_db_ready')
251 @patch.object(hooks, 'CONFIGS')254 @patch.object(hooks, 'CONFIGS')
252 @patch.object(hooks, 'identity_changed')255 @patch.object(hooks, 'identity_changed')
253 def test_postgresql_db_changed(self, identity_changed, configs,256 def test_postgresql_db_changed(self, identity_changed, configs,
254 mock_is_db_ready,257 mock_is_db_ready, mock_is_db_initialised,
255 mock_ensure_ssl_cert_master, mock_log):258 mock_ensure_ssl_cert_master, mock_log):
259 mock_is_db_initialised.return_value = True
256 mock_is_db_ready.return_value = True260 mock_is_db_ready.return_value = True
257 mock_ensure_ssl_cert_master.return_value = False261 mock_ensure_ssl_cert_master.return_value = False
258 self.relation_ids.return_value = ['identity-service:0']262 self.relation_ids.return_value = ['identity-service:0']
@@ -269,6 +273,7 @@
269273
270 @patch('keystone_utils.log')274 @patch('keystone_utils.log')
271 @patch('keystone_utils.ensure_ssl_cert_master')275 @patch('keystone_utils.ensure_ssl_cert_master')
276 @patch.object(hooks, 'is_db_initialised')
272 @patch.object(hooks, 'is_db_ready')277 @patch.object(hooks, 'is_db_ready')
273 @patch.object(hooks, 'peer_units')278 @patch.object(hooks, 'peer_units')
274 @patch.object(hooks, 'ensure_permissions')279 @patch.object(hooks, 'ensure_permissions')
@@ -283,8 +288,9 @@
283 self, configure_https, identity_changed,288 self, configure_https, identity_changed,
284 configs, get_homedir, ensure_user, cluster_joined,289 configs, get_homedir, ensure_user, cluster_joined,
285 admin_relation_changed, ensure_permissions, mock_peer_units,290 admin_relation_changed, ensure_permissions, mock_peer_units,
286 mock_is_db_ready,291 mock_is_db_ready, mock_is_db_initialised,
287 mock_ensure_ssl_cert_master, mock_log):292 mock_ensure_ssl_cert_master, mock_log):
293 mock_is_db_initialised.return_value = True
288 mock_is_db_ready.return_value = True294 mock_is_db_ready.return_value = True
289 self.openstack_upgrade_available.return_value = False295 self.openstack_upgrade_available.return_value = False
290 self.is_elected_leader.return_value = True296 self.is_elected_leader.return_value = True
@@ -302,7 +308,6 @@
302 configure_https.assert_called_with()308 configure_https.assert_called_with()
303 self.assertTrue(configs.write_all.called)309 self.assertTrue(configs.write_all.called)
304310
305 self.migrate_database.assert_called_with()
306 self.assertTrue(self.ensure_initial_admin.called)311 self.assertTrue(self.ensure_initial_admin.called)
307 self.log.assert_called_with(312 self.log.assert_called_with(
308 'Firing identity_changed hook for all related services.')313 'Firing identity_changed hook for all related services.')
@@ -343,6 +348,7 @@
343348
344 @patch('keystone_utils.log')349 @patch('keystone_utils.log')
345 @patch('keystone_utils.ensure_ssl_cert_master')350 @patch('keystone_utils.ensure_ssl_cert_master')
351 @patch.object(hooks, 'is_db_initialised')
346 @patch.object(hooks, 'is_db_ready')352 @patch.object(hooks, 'is_db_ready')
347 @patch.object(hooks, 'peer_units')353 @patch.object(hooks, 'peer_units')
348 @patch.object(hooks, 'ensure_permissions')354 @patch.object(hooks, 'ensure_permissions')
@@ -361,9 +367,11 @@
361 ensure_permissions,367 ensure_permissions,
362 mock_peer_units,368 mock_peer_units,
363 mock_is_db_ready,369 mock_is_db_ready,
370 mock_is_db_initialised,
364 mock_ensure_ssl_cert_master,371 mock_ensure_ssl_cert_master,
365 mock_log):372 mock_log):
366 mock_is_db_ready.return_value = True373 mock_is_db_ready.return_value = True
374 mock_is_db_initialised.return_value = True
367 self.openstack_upgrade_available.return_value = True375 self.openstack_upgrade_available.return_value = True
368 self.is_elected_leader.return_value = True376 self.is_elected_leader.return_value = True
369 # avoid having to mock syncer377 # avoid having to mock syncer
@@ -382,7 +390,6 @@
382 configure_https.assert_called_with()390 configure_https.assert_called_with()
383 self.assertTrue(configs.write_all.called)391 self.assertTrue(configs.write_all.called)
384392
385 self.migrate_database.assert_called_with()
386 self.assertTrue(self.ensure_initial_admin.called)393 self.assertTrue(self.ensure_initial_admin.called)
387 self.log.assert_called_with(394 self.log.assert_called_with(
388 'Firing identity_changed hook for all related services.')395 'Firing identity_changed hook for all related services.')
@@ -391,6 +398,7 @@
391 remote_unit='unit/0')398 remote_unit='unit/0')
392 admin_relation_changed.assert_called_with('identity-service:0')399 admin_relation_changed.assert_called_with('identity-service:0')
393400
401 @patch.object(hooks, 'is_db_initialised')
394 @patch.object(hooks, 'is_db_ready')402 @patch.object(hooks, 'is_db_ready')
395 @patch('keystone_utils.log')403 @patch('keystone_utils.log')
396 @patch('keystone_utils.ensure_ssl_cert_master')404 @patch('keystone_utils.ensure_ssl_cert_master')
@@ -398,7 +406,9 @@
398 @patch.object(hooks, 'send_notifications')406 @patch.object(hooks, 'send_notifications')
399 def test_identity_changed_leader(self, mock_send_notifications,407 def test_identity_changed_leader(self, mock_send_notifications,
400 mock_hashlib, mock_ensure_ssl_cert_master,408 mock_hashlib, mock_ensure_ssl_cert_master,
401 mock_log, mock_is_db_ready):409 mock_log, mock_is_db_ready,
410 mock_is_db_initialised):
411 mock_is_db_initialised.return_value = True
402 mock_is_db_ready.return_value = True412 mock_is_db_ready.return_value = True
403 mock_ensure_ssl_cert_master.return_value = False413 mock_ensure_ssl_cert_master.return_value = False
404 hooks.identity_changed(414 hooks.identity_changed(
@@ -557,13 +567,16 @@
557 @patch('keystone_utils.log')567 @patch('keystone_utils.log')
558 @patch('keystone_utils.ensure_ssl_cert_master')568 @patch('keystone_utils.ensure_ssl_cert_master')
559 @patch.object(hooks, 'is_db_ready')569 @patch.object(hooks, 'is_db_ready')
570 @patch.object(hooks, 'is_db_initialised')
560 @patch.object(hooks, 'identity_changed')571 @patch.object(hooks, 'identity_changed')
561 @patch.object(hooks, 'CONFIGS')572 @patch.object(hooks, 'CONFIGS')
562 def test_ha_relation_changed_clustered_leader(self, configs,573 def test_ha_relation_changed_clustered_leader(self, configs,
563 identity_changed,574 identity_changed,
575 mock_is_db_initialised,
564 mock_is_db_ready,576 mock_is_db_ready,
565 mock_ensure_ssl_cert_master,577 mock_ensure_ssl_cert_master,
566 mock_log):578 mock_log):
579 mock_is_db_initialised.return_value = True
567 mock_is_db_ready.return_value = True580 mock_is_db_ready.return_value = True
568 mock_ensure_ssl_cert_master.return_value = False581 mock_ensure_ssl_cert_master.return_value = False
569 self.relation_get.return_value = True582 self.relation_get.return_value = True
@@ -610,6 +623,8 @@
610 cmd = ['a2dissite', 'openstack_https_frontend']623 cmd = ['a2dissite', 'openstack_https_frontend']
611 self.check_call.assert_called_with(cmd)624 self.check_call.assert_called_with(cmd)
612625
626 @patch.object(hooks, 'is_db_ready')
627 @patch.object(hooks, 'is_db_initialised')
613 @patch('keystone_utils.log')628 @patch('keystone_utils.log')
614 @patch('keystone_utils.relation_ids')629 @patch('keystone_utils.relation_ids')
615 @patch('keystone_utils.is_elected_leader')630 @patch('keystone_utils.is_elected_leader')
@@ -623,7 +638,11 @@
623 mock_ensure_ssl_cert_master,638 mock_ensure_ssl_cert_master,
624 mock_is_elected_leader,639 mock_is_elected_leader,
625 mock_relation_ids,640 mock_relation_ids,
626 mock_log):641 mock_log,
642 mock_is_db_ready,
643 mock_is_db_initialised):
644 mock_is_db_initialised.return_value = True
645 mock_is_db_ready.return_value = True
627 mock_is_elected_leader.return_value = False646 mock_is_elected_leader.return_value = False
628 mock_relation_ids.return_value = []647 mock_relation_ids.return_value = []
629 mock_ensure_ssl_cert_master.return_value = True648 mock_ensure_ssl_cert_master.return_value = True

Subscribers

People subscribed via source and target branches