117
129
check_call(['chmod', '-R', 'g+wrx', '/var/lib/keystone/'])
131
# Ensure unison can write to certs dir.
132
# FIXME: need to a better way around this e.g. move cert to it's own dir
133
# and give that unison permissions.
134
path = os.path.dirname(CA_CERT_PATH)
135
perms = int(oct(stat.S_IMODE(os.stat(path).st_mode) |
136
(stat.S_IWGRP | stat.S_IXGRP)), base=8)
137
ensure_permissions(path, group='keystone', perms=perms)
120
140
configure_https()
121
141
update_nrpe_config()
122
142
CONFIGS.write_all()
123
if eligible_leader(CLUSTER_RES):
125
ensure_initial_admin(config)
126
log('Firing identity_changed hook for all related services.')
127
# HTTPS may have been set - so fire all identity relations
129
for r_id in relation_ids('identity-service'):
130
for unit in relation_list(r_id):
131
identity_changed(relation_id=r_id,
144
# Update relations since SSL may have been configured. If we have peer
145
# units we can rely on the sync to do this in cluster relation.
146
if is_elected_leader(CLUSTER_RES) and not peer_units():
147
update_all_identity_relation_units()
134
149
for rid in relation_ids('identity-admin'):
135
150
admin_relation_changed(rid)
136
for rid in relation_ids('cluster'):
152
# Ensure sync request is sent out (needed for upgrade to ssl from non-ssl)
154
append_ssl_sync_request(settings)
156
for rid in relation_ids('cluster'):
157
relation_set(relation_id=rid, relation_settings=settings)
140
160
@hooks.hook('shared-db-relation-joined')
167
187
relation_set(database=config('database'))
190
def update_all_identity_relation_units():
194
except Exception as exc:
195
log("Database initialisation failed (%s) - db not ready?" % (exc),
198
ensure_initial_admin(config)
199
log('Firing identity_changed hook for all related services.')
200
for rid in relation_ids('identity-service'):
201
for unit in related_units(rid):
202
identity_changed(relation_id=rid, remote_unit=unit)
205
@synchronize_ca_if_changed(force=True)
206
def update_all_identity_relation_units_force_sync():
207
update_all_identity_relation_units()
170
210
@hooks.hook('shared-db-relation-changed')
171
211
@restart_on_change(restart_map())
212
@synchronize_ca_if_changed()
172
213
def db_changed():
173
214
if 'shared-db' not in CONFIGS.complete_contexts():
174
215
log('shared-db relation incomplete. Peer not ready?')
176
217
CONFIGS.write(KEYSTONE_CONF)
177
if eligible_leader(CLUSTER_RES):
218
if is_elected_leader(CLUSTER_RES):
178
219
# Bugs 1353135 & 1187508. Dbs can appear to be ready before the
179
220
# units acl entry has been added. So, if the db supports passing
180
221
# a list of permitted units then check if we're in the list.
182
223
if allowed_units and local_unit() not in allowed_units.split():
183
224
log('Allowed_units list provided and this unit not present')
186
ensure_initial_admin(config)
187
226
# Ensure any existing service entries are updated in the
188
227
# new database backend
189
for rid in relation_ids('identity-service'):
190
for unit in related_units(rid):
191
identity_changed(relation_id=rid, remote_unit=unit)
228
update_all_identity_relation_units()
194
231
@hooks.hook('pgsql-db-relation-changed')
195
232
@restart_on_change(restart_map())
233
@synchronize_ca_if_changed()
196
234
def pgsql_db_changed():
197
235
if 'pgsql-db' not in CONFIGS.complete_contexts():
198
236
log('pgsql-db relation incomplete. Peer not ready?')
200
238
CONFIGS.write(KEYSTONE_CONF)
201
if eligible_leader(CLUSTER_RES):
203
ensure_initial_admin(config)
239
if is_elected_leader(CLUSTER_RES):
204
240
# Ensure any existing service entries are updated in the
205
241
# new database backend
206
for rid in relation_ids('identity-service'):
207
for unit in related_units(rid):
208
identity_changed(relation_id=rid, remote_unit=unit)
242
update_all_identity_relation_units()
211
245
@hooks.hook('identity-service-relation-changed')
246
@synchronize_ca_if_changed()
212
247
def identity_changed(relation_id=None, remote_unit=None):
213
250
notifications = {}
214
if eligible_leader(CLUSTER_RES):
215
add_service_to_keystone(relation_id, remote_unit)
251
if is_elected_leader(CLUSTER_RES):
252
# Catch database not configured error and defer until db ready
253
from keystoneclient.apiclient.exceptions import InternalServerError
255
add_service_to_keystone(relation_id, remote_unit)
256
except InternalServerError as exc:
257
key = re.compile("'keystone\..+' doesn't exist")
258
if re.search(key, exc.message):
259
log("Keystone database not yet ready (InternalServerError "
260
"raised) - deferring until *-db relation completes.",
264
log("Unexpected exception occurred", level=ERROR)
218
267
settings = relation_get(rid=relation_id, unit=remote_unit)
219
268
service = settings.get('service', None)
241
290
send_notifications(notifications)
293
def append_ssl_sync_request(settings):
294
"""Add request to be synced to relation settings.
296
This will be consumed by cluster-relation-changed ssl master.
298
if (is_str_true(config('use-https')) or
299
is_str_true(config('https-service-endpoints'))):
300
unit = local_unit().replace('/', '-')
301
settings['ssl-sync-required-%s' % (unit)] = '1'
244
304
@hooks.hook('cluster-relation-joined')
245
def cluster_joined(relation_id=None):
305
def cluster_joined():
246
306
unison.ssh_authorized_peers(user=SSH_USER,
247
307
group='juju_keystone',
248
308
peer_interface='cluster',
249
309
ensure_local_user=True)
250
313
for addr_type in ADDRESS_TYPES:
251
314
address = get_address_in_network(
252
315
config('os-{}-network'.format(addr_type))
256
relation_id=relation_id,
257
relation_settings={'{}-address'.format(addr_type): address}
318
settings['{}-address'.format(addr_type)] = address
260
320
if config('prefer-ipv6'):
261
321
private_addr = get_ipv6_addr(exc_list=[config('vip')])[0]
262
relation_set(relation_id=relation_id,
263
relation_settings={'private-address': private_addr})
322
settings['private-address'] = private_addr
324
append_ssl_sync_request(settings)
326
relation_set(relation_settings=settings)
329
def apply_echo_filters(settings, echo_whitelist):
330
"""Filter settings to be peer_echo'ed.
332
We may have received some data that we don't want to re-echo so filter
333
out unwanted keys and provide overrides.
336
tuple(filtered list of keys to be echoed, overrides for keys omitted)
340
for key in settings.iterkeys():
341
for ekey in echo_whitelist:
343
if ekey == 'identity-service:':
344
auth_host = resolve_address(ADMIN)
345
service_host = resolve_address(PUBLIC)
346
if (key.endswith('auth_host') and
347
settings[key] != auth_host):
348
overrides[key] = auth_host
350
elif (key.endswith('service_host') and
351
settings[key] != service_host):
352
overrides[key] = service_host
357
return filtered, overrides
266
360
@hooks.hook('cluster-relation-changed',
267
361
'cluster-relation-departed')
268
362
@restart_on_change(restart_map(), stopstart=True)
269
363
def cluster_changed():
364
settings = relation_get()
270
365
# NOTE(jamespage) re-echo passwords for peer storage
271
peer_echo(includes=['_passwd', 'identity-service:'])
366
echo_whitelist, overrides = \
367
apply_echo_filters(settings, ['_passwd', 'identity-service:',
369
log("Peer echo overrides: %s" % (overrides), level=DEBUG)
370
relation_set(**overrides)
372
log("Peer echo whitelist: %s" % (echo_whitelist), level=DEBUG)
373
peer_echo(includes=echo_whitelist)
272
376
unison.ssh_authorized_peers(user=SSH_USER,
273
377
group='keystone',
274
378
peer_interface='cluster',
275
379
ensure_local_user=True)
278
for r_id in relation_ids('identity-service'):
279
for unit in relation_list(r_id):
280
identity_changed(relation_id=r_id,
282
for rid in relation_ids('identity-admin'):
283
admin_relation_changed(rid)
381
if is_elected_leader(CLUSTER_RES) or is_ssl_cert_master():
382
units = get_ssl_sync_request_units()
383
synced_units = relation_get(attribute='ssl-synced-units',
386
synced_units = json.loads(synced_units)
387
diff = set(units).symmetric_difference(set(synced_units))
389
if units and (not synced_units or diff):
390
log("New peers joined and need syncing - %s" %
391
(', '.join(units)), level=DEBUG)
392
update_all_identity_relation_units_force_sync()
394
update_all_identity_relation_units()
396
for rid in relation_ids('identity-admin'):
397
admin_relation_changed(rid)
286
402
@hooks.hook('ha-relation-joined')
339
455
@hooks.hook('ha-relation-changed')
340
456
@restart_on_change(restart_map())
457
@synchronize_ca_if_changed()
341
458
def ha_changed():
342
461
clustered = relation_get('clustered')
344
if (clustered is not None and
345
is_leader(CLUSTER_RES)):
462
if clustered and is_elected_leader(CLUSTER_RES):
346
463
ensure_initial_admin(config)
347
464
log('Cluster configured, notifying other services and updating '
348
465
'keystone endpoint configuration')
349
for rid in relation_ids('identity-service'):
350
for unit in related_units(rid):
351
identity_changed(relation_id=rid, remote_unit=unit)
467
update_all_identity_relation_units()
354
470
@hooks.hook('identity-admin-relation-changed')
384
501
@hooks.hook('upgrade-charm')
385
502
@restart_on_change(restart_map(), stopstart=True)
503
@synchronize_ca_if_changed()
386
504
def upgrade_charm():
387
505
apt_install(filter_installed_packages(determine_packages()))
388
506
unison.ssh_authorized_peers(user=SSH_USER,
389
507
group='keystone',
390
508
peer_interface='cluster',
391
509
ensure_local_user=True)
392
512
update_nrpe_config()
394
if eligible_leader(CLUSTER_RES):
395
log('Cluster leader - ensuring endpoint configuration'
514
if is_elected_leader(CLUSTER_RES):
515
log('Cluster leader - ensuring endpoint configuration is up to '
398
ensure_initial_admin(config)
399
# Deal with interface changes for icehouse
400
for r_id in relation_ids('identity-service'):
401
for unit in relation_list(r_id):
402
identity_changed(relation_id=r_id,
518
update_all_identity_relation_units()
407
521
@hooks.hook('nrpe-external-master-relation-joined',