charm-neutron-api/hooks/neutron_api_hooks.py

287 lines
9.2 KiB
Python
Executable File

#!/usr/bin/python
import sys
from charmhelpers.core.hookenv import (
Hooks,
UnregisteredHookError,
config,
is_relation_made,
log,
ERROR,
relation_get,
relation_ids,
relation_set,
related_units,
open_port,
unit_get,
)
from charmhelpers.core.host import (
restart_on_change
)
from charmhelpers.fetch import (
apt_install, apt_update
)
from charmhelpers.contrib.openstack.utils import (
configure_installation_source,
openstack_upgrade_available,
)
from charmhelpers.contrib.openstack.neutron import (
network_manager,
neutron_plugin_attribute,
)
from neutron_api_utils import (
determine_endpoints,
determine_packages,
determine_ports,
register_configs,
restart_map,
NEUTRON_CONF,
api_port,
keystone_ca_cert_b64,
CLUSTER_RES,
)
from charmhelpers.contrib.hahelpers.cluster import (
canonical_url,
eligible_leader,
get_hacluster_config,
is_leader,
)
from charmhelpers.payload.execd import execd_preinstall
hooks = Hooks()
CONFIGS = register_configs()
@hooks.hook()
def install():
execd_preinstall()
configure_installation_source(config('openstack-origin'))
apt_update()
apt_install(determine_packages(), fatal=True)
[open_port(port) for port in determine_ports()]
@hooks.hook('config-changed')
@restart_on_change(restart_map(), stopstart=True)
def config_changed():
global CONFIGS
CONFIGS.write_all()
for r_id in relation_ids('neutron-api'):
neutron_api_relation_joined(rid=r_id)
for r_id in relation_ids('neutron-plugin-api'):
neutron_plugin_api_relation_joined(rid=r_id)
@hooks.hook('amqp-relation-joined')
def amqp_joined(relation_id=None):
relation_set(relation_id=relation_id,
username=config('rabbit-user'), vhost=config('rabbit-vhost'))
@hooks.hook('amqp-relation-changed')
@hooks.hook('amqp-relation-departed')
@restart_on_change(restart_map())
def amqp_changed():
if 'amqp' not in CONFIGS.complete_contexts():
log('amqp relation incomplete. Peer not ready?')
return
CONFIGS.write(NEUTRON_CONF)
@hooks.hook('shared-db-relation-joined')
def db_joined():
if is_relation_made('pgsql-nova-db') or \
is_relation_made('pgsql-db'):
# error, postgresql is used
e = ('Attempting to associate a mysql database when there is already '
'associated a postgresql one')
log(e, level=ERROR)
raise Exception(e)
relation_set(database=config('database'),
username=config('database-user'),
hostname=unit_get('private-address'))
@hooks.hook('pgsql-db-relation-joined')
def pgsql_neutron_db_joined():
if is_relation_made('shared-db'):
# raise error
e = ('Attempting to associate a postgresql database'
' when there is already associated a mysql one')
log(e, level=ERROR)
raise Exception(e)
relation_set(database=config('database'))
@hooks.hook('shared-db-relation-changed')
@restart_on_change(restart_map())
def db_changed():
if 'shared-db' not in CONFIGS.complete_contexts():
log('shared-db relation incomplete. Peer not ready?')
return
CONFIGS.write_all()
@hooks.hook('pgsql-db-relation-changed')
@restart_on_change(restart_map())
def postgresql_neutron_db_changed():
if network_manager() in ['neutron', 'quantum']:
plugin = config('neutron-plugin')
# DB config might have been moved to main neutron.conf in H?
CONFIGS.write(neutron_plugin_attribute(plugin, 'config'))
@hooks.hook('amqp-relation-broken',
'identity-service-relation-broken',
'shared-db-relation-broken',
'pgsql-db-relation-broken')
def relation_broken():
CONFIGS.write_all()
@hooks.hook('upgrade-charm')
def upgrade_charm():
for r_id in relation_ids('amqp'):
amqp_joined(relation_id=r_id)
for r_id in relation_ids('identity-service'):
identity_joined(rid=r_id)
@hooks.hook('identity-service-relation-joined')
def identity_joined(rid=None):
base_url = canonical_url(CONFIGS)
relation_set(relation_id=rid, **determine_endpoints(base_url))
@hooks.hook('identity-service-relation-changed')
@restart_on_change(restart_map())
def identity_changed():
if 'identity-service' not in CONFIGS.complete_contexts():
log('identity-service relation incomplete. Peer not ready?')
return
CONFIGS.write(NEUTRON_CONF)
for r_id in relation_ids('neutron-api'):
neutron_api_relation_joined(rid=r_id)
def _get_keystone_info():
keystone_info = {}
for lrid in relation_ids('identity-service'):
for unit in related_units(lrid):
rdata = relation_get(rid=lrid, unit=unit)
keystone_info['service_protocol'] = rdata.get('service_protocol')
keystone_info['service_host'] = rdata.get('service_host')
keystone_info['service_port'] = rdata.get('service_port')
keystone_info['service_tenant'] = rdata.get('service_tenant')
keystone_info['service_username'] = rdata.get('service_username')
keystone_info['service_password'] = rdata.get('service_password')
keystone_info['auth_url'] = "%s://%s:%s/v2.0" % (keystone_info['service_protocol'],
keystone_info['service_host'],
keystone_info['service_port'])
return keystone_info
@hooks.hook('neutron-api-relation-joined')
def neutron_api_relation_joined(rid=None):
manager = network_manager()
base_url = canonical_url(CONFIGS)
neutron_url = '%s:%s' % (base_url, api_port('neutron-server'))
relation_data = {
'network_manager': manager,
'default_floating_pool': config('neutron-external-network'),
'external_network': config('neutron-external-network'),
manager + '_plugin': config('neutron-plugin'),
manager + '_url': neutron_url,
}
if config('neutron-security-groups'):
relation_data[manager + '_security_groups'] = "yes"
else:
relation_data[manager + '_security_groups'] = "no"
keystone_info = _get_keystone_info()
if is_relation_made('identity-service') and keystone_info:
relation_data.update({
manager + '_admin_tenant_name': keystone_info['service_tenant'],
manager + '_admin_username': keystone_info['service_username'],
manager + '_admin_password': keystone_info['service_password'],
manager + '_admin_auth_url': keystone_info['auth_url'],
})
relation_set(relation_id=rid, **relation_data)
# Nova-cc may have grabbed the quantum endpoint so kick identity-service relation to
# register that its here
for r_id in relation_ids('identity-service'):
identity_joined(rid=r_id)
@hooks.hook('neutron-api-relation-changed')
@restart_on_change(restart_map())
def neutron_api_relation_changed():
CONFIGS.write(NEUTRON_CONF)
@hooks.hook('neutron-plugin-api-relation-joined')
def neutron_plugin_api_relation_joined(rid=None):
relation_data = {
'neutron_security_groups': config('neutron-security-groups')
}
relation_set(relation_id=rid, **relation_data)
@hooks.hook('cluster-relation-changed',
'cluster-relation-departed')
@restart_on_change(restart_map(), stopstart=True)
def cluster_changed():
CONFIGS.write_all()
@hooks.hook('ha-relation-joined')
def ha_joined():
config = get_hacluster_config()
resources = {
'res_neutron_vip': 'ocf:heartbeat:IPaddr2',
'res_neutron_haproxy': 'lsb:haproxy',
}
vip_params = 'params ip="%s" cidr_netmask="%s" nic="%s"' % \
(config['vip'], config['vip_cidr'], config['vip_iface'])
resource_params = {
'res_neutron_vip': vip_params,
'res_neutron_haproxy': 'op monitor interval="5s"'
}
init_services = {
'res_neutron_haproxy': 'haproxy'
}
clones = {
'cl_nova_haproxy': 'res_neutron_haproxy'
}
relation_set(init_services=init_services,
corosync_bindiface=config['ha-bindiface'],
corosync_mcastport=config['ha-mcastport'],
resources=resources,
resource_params=resource_params,
clones=clones)
@hooks.hook('ha-relation-changed')
def ha_changed():
clustered = relation_get('clustered')
if not clustered or clustered in [None, 'None', '']:
log('ha_changed: hacluster subordinate not fully clustered.')
return
if not is_leader(CLUSTER_RES):
log('ha_changed: hacluster complete but we are not leader.')
return
log('Cluster configured, notifying other services and updating '
'keystone endpoint configuration')
for rid in relation_ids('identity-service'):
identity_joined(rid=rid)
for rid in relation_ids('neutron-api'):
neutron_api_relation_joined(rid=rid)
def main():
try:
hooks.execute(sys.argv)
except UnregisteredHookError as e:
log('Unknown hook {} - skipping.'.format(e))
if __name__ == '__main__':
main()