5
from subprocess import check_call
6
from urlparse import urlparse
8
from charmhelpers.core.hookenv import (
10
UnregisteredHookError,
20
from charmhelpers.core.host import (
21
apt_install, apt_update, filter_installed_packages, restart_on_change
24
from charmhelpers.contrib.openstack.utils import (
25
configure_installation_source,
26
openstack_upgrade_available,
29
from nova_cc_utils import (
46
from misc_utils import (
51
from charmhelpers.contrib.hahelpers.cluster import (
59
CONFIGS = register_configs()
64
configure_installation_source(config('openstack-origin'))
66
apt_install(determine_packages(), fatal=True)
67
[open_port(port) for port in determine_ports()]
71
@restart_on_change(restart_map())
73
if openstack_upgrade_available('nova-common'):
74
do_openstack_upgrade()
77
# XXX configure quantum networking
80
@hooks.hook('amqp-relation-joined')
81
@restart_on_change(restart_map())
83
relation_set(username=config('rabbit-user'), vhost=config('rabbit-vhost'))
86
@hooks.hook('amqp-relation-changed')
87
@restart_on_change(restart_map())
89
if 'amqp' not in CONFIGS.complete_contexts():
90
log('amqp relation incomplete. Peer not ready?')
92
CONFIGS.write('/etc/nova/nova.conf')
94
CONFIGS.write('/etc/quantum/quantum.conf')
95
# XXX Configure quantum networking (after-restart!?)
98
@hooks.hook('shared-db-relation-joined')
100
relation_set(nova_database=config('database'),
101
nova_username=config('database-user'),
102
nova_hostname=unit_get('private-address'))
103
if quantum_enabled():
104
# request a database created for quantum if needed.
105
relation_set(quantum_database=config('database'),
106
quantum_username=config('database-user'),
107
quantum_hostname=unit_get('private-address'))
110
@hooks.hook('shared-db-relation-changed')
111
@restart_on_change(restart_map())
113
if 'shared-db' not in CONFIGS.complete_contexts():
114
log('shared-db relation incomplete. Peer not ready?')
116
CONFIGS.write('/etc/nova/nova.conf')
118
if quantum_enabled():
119
plugin = quantum_plugin()
120
CONFIGS.write(quantum_attribute(plugin, 'config'))
122
if eligible_leader(CLUSTER_RES):
126
@hooks.hook('image-service-relation-changed')
127
@restart_on_change(restart_map())
128
def image_service_changed():
129
if 'image-service' not in CONFIGS.complete_contexts():
130
log('image-service relation incomplete. Peer not ready?')
132
CONFIGS.write('/etc/nova/nova.conf')
133
# TODO: special case config flag for essex (strip protocol)
136
@hooks.hook('identity-service-relation-joined')
137
@restart_on_change(restart_map())
138
def identity_joined(rid=None):
139
relation_set(rid=rid, **determine_endpoints())
142
@hooks.hook('identity-service-relation-changed')
143
@restart_on_change(restart_map())
144
def identity_changed():
145
if 'identity-service' not in CONFIGS.complete_contexts():
146
log('identity-service relation incomplete. Peer not ready?')
148
CONFIGS.write('/etc/nova/api-paste.ini')
149
if quantum_enabled():
150
CONFIGS.write('/etc/quantum/api-paste.ini')
151
# XXX configure quantum networking
154
@hooks.hook('nova-volume-service-relation-joined',
155
'cinder-volume-service-relation-joined')
156
@restart_on_change(restart_map())
158
CONFIGS.write('/etc/nova/nova.conf')
159
# kick identity_joined() to publish possibly new nova-volume endpoint.
160
[identity_joined(rid) for rid in relation_ids('identity-service')]
164
'''Grab all KS auth token config from api-paste.ini, or return empty {}'''
165
ks_auth_host = auth_token_config('auth_host')
167
# if there is no auth_host set, identity-service changed hooks
168
# have not fired, yet.
171
'auth_host': ks_auth_host,
172
'auth_port': auth_token_config('auth_port'),
173
'service_port': auth_token_config('service_port'),
174
'service_username': auth_token_config('admin_user'),
175
'service_password': auth_token_config('admin_password'),
176
'service_tenant_name': auth_token_config('admin_tenant_name'),
177
'auth_uri': auth_token_config('auth_uri'),
182
@hooks.hook('cloud-compute-relation-joined')
183
def compute_joined(rid=None):
184
if not eligible_leader():
187
'network_manager': config('network-manager'),
188
'volume_service': volume_service(),
189
# (comment from bash vers) XXX Should point to VIP if clustered, or
190
# this may not even be needed.
191
'ec2_host': unit_get('private-address'),
194
ks_auth_config = _auth_config()
196
if quantum_enabled():
198
rel_settings.update(ks_auth_config)
199
rel_settings.update({
200
'quantum_plugin': quantum_plugin(),
201
'region': config('region'),
202
'quantum_security_groups': config('quantum_security_groups'),
205
ks_ca = keystone_ca_cert_b64()
206
if ks_auth_config and ks_ca:
207
rel_settings['ca_cert'] = ks_ca
208
relation_set(rid=rid, **rel_settings)
211
@hooks.hook('cloud-compute-relation-joined')
212
def compute_changed():
213
migration_auth = relation_get('migration_auth_type')
214
if migration_auth == 'ssh':
218
@hooks.hook('quantum-network-servicerelation-joined')
219
def quantum_joined(rid=None):
220
if not eligible_leader():
223
# XXX TODO: Need to add neutron/quantum compat. for pkg naming
224
required_pkg = filter_installed_packages(['quantum-server'])
226
apt_install(required_pkg)
228
url = canonical_url(CONFIGS) + ':9696'
231
'quantum_host': urlparse(url).hostname,
233
'quantum_port': 9696,
234
'quantum_plugin': config('quantum-plugin'),
235
'region': config('region')
238
# inform quantum about local keystone auth config
239
ks_auth_config = _auth_config()
240
rel_settings.update(ks_auth_config)
242
# must pass the keystone CA cert, if it exists.
243
ks_ca = keystone_ca_cert_b64()
244
if ks_auth_config and ks_ca:
245
rel_settings['ca_cert'] = ks_ca
247
relation_set(rid=rid, **rel_settings)
250
@hooks.hook('cluster-relation-changed',
251
'cluster-relation-departed')
252
@restart_on_change(restart_map())
253
def cluster_changed():
257
@hooks.hook('ha-relation-joined')
259
config = get_hacluster_config()
261
'res_nova_vip': 'ocf:heartbeat:IPaddr2',
262
'res_nova_haproxy': 'lsb:haproxy',
264
vip_params = 'params ip="%s" cidr_netmask="%s" nic="%s"' % \
265
(config['vip'], config['vip_cidr'], config['vip_iface'])
267
'res_nova_vip': vip_params,
268
'res_nova_haproxy': 'op monitor interval="5s"'
271
'res_nova_haproxy': 'haproxy'
274
'cl_nova_haproxy': 'res_nova_haproxy'
276
relation_set(init_services=init_services,
277
corosync_bindiface=config['ha-bindiface'],
278
corosync_mcastport=config['ha-mcastport'],
280
resource_params=resource_params,
284
@hooks.hook('ha-relation-changed')
286
if not relation_get('clustered'):
287
log('ha_changed: hacluster subordinate not fully clustered.')
289
if not is_leader(CLUSTER_RES):
290
log('ha_changed: hacluster complete but we are not leader.')
292
log('Cluster configured, notifying other services and updating '
293
'keystone endpoint configuration')
294
for rid in relation_ids('identity-service'):
295
identity_joined(rid=rid)
298
def configure_https():
300
Enables SSL API Apache config if appropriate and kicks identity-service
301
with any required api updates.
303
# need to write all to ensure changes to the entire request pipeline
304
# propagate (c-api, haprxy, apache)
306
if 'https' in CONFIGS.complete_contexts():
307
cmd = ['a2ensite', 'openstack_https_frontend']
310
cmd = ['a2dissite', 'openstack_https_frontend']
313
for rid in relation_ids('identity-service'):
314
identity_joined(rid=rid)
319
hooks.execute(sys.argv)
320
except UnregisteredHookError as e:
321
log('Unknown hook {} - skipping.'.format(e))
324
if __name__ == '__main__':