diff options
Diffstat (limited to 'charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py')
-rwxr-xr-x | charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py b/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py new file mode 100755 index 0000000..a0b013c --- /dev/null +++ b/charms/trusty/neutron-contrail/hooks/neutron_contrail_hooks.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python + +from subprocess import CalledProcessError +import sys + +from apt_pkg import version_compare +import json +import uuid +import yaml + +from charmhelpers.core.hookenv import ( + Hooks, + UnregisteredHookError, + config, + is_leader, + leader_get, + leader_set, + log, + relation_get, + relation_ids, + relation_set +) + +from charmhelpers.core.host import ( + restart_on_change, + service_restart +) + +from charmhelpers.fetch import ( + apt_install, + apt_upgrade, + configure_sources +) + +from neutron_contrail_utils import ( + CONTRAIL_VERSION, + OPENSTACK_VERSION, + configure_vrouter, + disable_vrouter_vgw, + dpkg_version, + drop_caches, + enable_vrouter_vgw, + fix_nodemgr, + fix_permissions, + fix_vrouter_scripts, + ifdown, + ifup, + modprobe, + provision_local_metadata, + provision_vrouter, + remove_juju_bridge, + units, + unprovision_local_metadata, + unprovision_vrouter, + write_barbican_auth_config, + write_nodemgr_config, + write_vnc_api_config, + write_vrouter_config, + write_vrouter_vgw_interfaces +) + +PACKAGES = [ "contrail-vrouter-dkms", "contrail-vrouter-agent", + "contrail-nova-driver", "contrail-utils", "python-jinja2", + "python-netifaces", "python-netaddr", "contrail-nodemgr" ] + +PACKAGES_LBAAS = [ "python-barbicanclient", "haproxy" ] + +hooks = Hooks() +config = config() + +def check_local_metadata(): + if not is_leader(): + return + + if not config.get("vrouter-provisioned"): + if leader_get("local-metadata-provisioned"): + # impossible to know if current hook is firing because + # relation or leader is being removed lp #1469731 + if not relation_ids("cluster"): + unprovision_local_metadata() + leader_set({"local-metadata-provisioned": ""}) + return + + if config["local-metadata-server"]: + if not leader_get("local-metadata-provisioned"): + provision_local_metadata() + leader_set({"local-metadata-provisioned": True}) + elif leader_get("local-metadata-provisioned"): + unprovision_local_metadata() + leader_set({"local-metadata-provisioned": ""}) + +def check_vrouter(): + # check relation dependencies + if config_get("contrail-api-ready") \ + and config_get("control-node-ready") \ + and config_get("identity-admin-ready"): + if not config_get("vrouter-provisioned"): + provision_vrouter() + config["vrouter-provisioned"] = True + elif config_get("vrouter-provisioned"): + unprovision_vrouter() + config["vrouter-provisioned"] = False + +@hooks.hook("config-changed") +def config_changed(): + configure_local_metadata() + configure_virtual_gateways() + write_config() + if not units("contrail-discovery") and not units("control-node"): + config["control-node-ready"] = True if config.get("discovery-server-ip") \ + else False + if not units("contrail-api"): + config["contrail-api-ready"] = True if config.get("contrail-api-ip") \ + else False + check_vrouter() + check_local_metadata() + +def config_get(key): + try: + return config[key] + except KeyError: + return None + +def configure_local_metadata(): + if config["local-metadata-server"]: + if "local-metadata-secret" not in config: + # generate secret + secret = str(uuid.uuid4()) + config["local-metadata-secret"] = secret + settings = { "metadata-shared-secret": secret } + # inform relations + for rid in relation_ids("neutron-plugin"): + relation_set(relation_id=rid, relation_settings=settings) + else: + if "local-metadata-secret" in config: + # remove secret + del config["local-metadata-secret"] + settings = { "metadata-shared-secret": None } + # inform relations + for rid in relation_ids("neutron-plugin"): + relation_set(relation_id=rid, relation_settings=settings) + +def configure_virtual_gateways(): + gateways = config.get("virtual-gateways") + previous_gateways = config_get("virtual-gateways-prev") + if gateways != previous_gateways: + # create/destroy virtual gateway interfaces according to new value + interfaces = { gateway["interface"]: set(gateway["subnets"]) + for gateway in yaml.safe_load(gateways) } \ + if gateways else {} + previous_interfaces = { gateway["interface"]: set(gateway["subnets"]) + for gateway in yaml.safe_load(previous_gateways) } \ + if previous_gateways else {} + ifaces = [ interface for interface, subnets in previous_interfaces.iteritems() + if interface not in interfaces + or subnets != interfaces[interface] ] + if ifaces: + ifdown(ifaces) + + write_vrouter_vgw_interfaces() + + ifaces = [ interface for interface, subnets in interfaces.iteritems() + if interface not in previous_interfaces + or subnets != previous_interfaces[interface] ] + if ifaces: + ifup(ifaces) + + if interfaces: + enable_vrouter_vgw() + else: + disable_vrouter_vgw() + + config["virtual-gateways-prev"] = gateways + +@hooks.hook("contrail-api-relation-departed") +@hooks.hook("contrail-api-relation-broken") +def contrail_api_departed(): + if not units("contrail-api") and not config.get("contrail-api-ip"): + config["contrail-api-ready"] = False + check_vrouter() + check_local_metadata() + write_vnc_api_config() + +@hooks.hook("contrail-api-relation-changed") +def contrail_api_changed(): + if not relation_get("port"): + log("Relation not ready") + return + write_vnc_api_config() + config["contrail-api-ready"] = True + check_vrouter() + check_local_metadata() + +@hooks.hook("contrail-discovery-relation-changed") +def contrail_discovery_changed(): + if not relation_get("port"): + log("Relation not ready") + return + contrail_discovery_relation() + config["control-node-ready"] = True + check_vrouter() + check_local_metadata() + +@hooks.hook("contrail-discovery-relation-departed") +@hooks.hook("contrail-discovery-relation-broken") +def contrail_discovery_departed(): + if not units("contrail-discovery") \ + and not units("control-node") \ + and not config.get("discovery-server-ip"): + config["control-node-ready"] = False + check_vrouter() + check_local_metadata() + contrail_discovery_relation() + +@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"], + "/etc/contrail/contrail-vrouter-nodemgr.conf": ["contrail-vrouter-nodemgr"]}) +def contrail_discovery_relation(): + write_vrouter_config() + write_nodemgr_config() + +@hooks.hook("control-node-relation-departed") +@hooks.hook("control-node-relation-broken") +def control_node_departed(): + if not units("control-node") \ + and not units("contrail-discovery") \ + and not config.get("discovery-server-ip"): + config["control-node-ready"] = False + check_vrouter() + check_local_metadata() + control_node_relation() + +@hooks.hook("control-node-relation-joined") +def control_node_joined(): + control_node_relation() + config["control-node-ready"] = True + check_vrouter() + check_local_metadata() + +@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"]}) +def control_node_relation(): + write_vrouter_config() + +@hooks.hook("identity-admin-relation-changed") +def identity_admin_changed(): + if not relation_get("service_hostname"): + log("Relation not ready") + return + write_vnc_api_config() + if version_compare(CONTRAIL_VERSION, "3.0.2.0-34") >= 0: + write_barbican_auth_config() + config["identity-admin-ready"] = True + check_vrouter() + check_local_metadata() + +@hooks.hook("identity-admin-relation-departed") +@hooks.hook("identity-admin-relation-broken") +def identity_admin_departed(): + if not units("identity-admin"): + config["identity-admin-ready"] = False + check_vrouter() + check_local_metadata() + write_vnc_api_config() + if version_compare(CONTRAIL_VERSION, "3.0.2.0-34") >= 0: + write_barbican_auth_config() + +@hooks.hook() +def install(): + configure_sources(True, "install-sources", "install-keys") + apt_upgrade(fatal=True, dist=True) + fix_vrouter_scripts() # bug in 2.0+20141015.1 packages + apt_install(PACKAGES, fatal=True) + + contrail_version = dpkg_version("contrail-vrouter-agent") + openstack_version = dpkg_version("nova-compute") + if version_compare(contrail_version, "3.0.2.0-34") >= 0 \ + and version_compare(openstack_version, "2:12.0.0") >= 0: + # install lbaas packages + apt_install(PACKAGES_LBAAS, fatal=True) + + fix_permissions() + fix_nodemgr() + if config.get("remove-juju-bridge"): + remove_juju_bridge() + try: + modprobe("vrouter") + except CalledProcessError: + log("vrouter kernel module failed to load, clearing pagecache and retrying") + drop_caches() + modprobe("vrouter") + modprobe("vrouter", True, True) + configure_vrouter() + service_restart("nova-compute") + +@hooks.hook("neutron-metadata-relation-changed") +def neutron_metadata_changed(): + if not relation_get("shared-secret"): + log("Relation not ready") + return + neutron_metadata_relation() + +@hooks.hook("neutron-metadata-relation-departed") +@hooks.hook("neutron-metadata-relation-broken") +@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"]}) +def neutron_metadata_relation(): + write_vrouter_config() + +@hooks.hook("neutron-plugin-relation-joined") +def neutron_plugin_joined(): + # create plugin config + section = [] + if version_compare(OPENSTACK_VERSION, "1:2015.1~") < 0: + if version_compare(OPENSTACK_VERSION, "1:2014.2") >= 0: + section.append(("network_api_class", "nova_contrail_vif.contrailvif.ContrailNetworkAPI")) + else: + section.append(("libvirt_vif_driver", "nova_contrail_vif.contrailvif.VRouterVIFDriver")) + section.append(("firewall_driver", "nova.virt.firewall.NoopFirewallDriver")) + conf = { + "nova-compute": { + "/etc/nova/nova.conf": { + "sections": { + "DEFAULT": section + } + } + } + } + relation_set(subordinate_configuration=json.dumps(conf)) + + if config["local-metadata-server"]: + settings = { "metadata-shared-secret": config["local-metadata-secret"] } + relation_set(relation_settings=settings) + +def main(): + try: + hooks.execute(sys.argv) + except UnregisteredHookError as e: + log("Unknown hook {} - skipping.".format(e)) + +@hooks.hook("upgrade-charm") +def upgrade_charm(): + write_vrouter_config() + write_vnc_api_config() + write_nodemgr_config() + service_restart("supervisor-vrouter") + +@restart_on_change({"/etc/contrail/contrail-vrouter-agent.conf": ["contrail-vrouter-agent"], + "/etc/contrail/contrail-vrouter-nodemgr.conf": ["contrail-vrouter-nodemgr"]}) +def write_config(): + write_vrouter_config() + write_vnc_api_config() + write_nodemgr_config() + +if __name__ == "__main__": + main() |