aboutsummaryrefslogtreecommitdiffstats
path: root/contrail-openstack/hooks/contrail_openstack_hooks.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrail-openstack/hooks/contrail_openstack_hooks.py')
-rwxr-xr-xcontrail-openstack/hooks/contrail_openstack_hooks.py241
1 files changed, 241 insertions, 0 deletions
diff --git a/contrail-openstack/hooks/contrail_openstack_hooks.py b/contrail-openstack/hooks/contrail_openstack_hooks.py
new file mode 100755
index 0000000..b0d7ce4
--- /dev/null
+++ b/contrail-openstack/hooks/contrail_openstack_hooks.py
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+
+import json
+from subprocess import CalledProcessError, check_output
+import sys
+import uuid
+
+from charmhelpers.core.hookenv import (
+ Hooks,
+ UnregisteredHookError,
+ config,
+ log,
+ related_units,
+ relation_get,
+ relation_ids,
+ relation_set,
+ status_set,
+ leader_get,
+ leader_set,
+ is_leader,
+ application_version_set,
+)
+
+from charmhelpers.core.host import (
+ restart_on_change,
+)
+
+from charmhelpers.fetch import (
+ apt_install,
+ apt_update,
+ apt_upgrade,
+ configure_sources
+)
+
+from contrail_openstack_utils import (
+ write_configs,
+ update_service_ips,
+)
+
+NEUTRON_API_PACKAGES = ["neutron-plugin-contrail"]
+
+
+hooks = Hooks()
+config = config()
+
+
+@hooks.hook("install.real")
+def install():
+ status_set('maintenance', 'Installing...')
+ configure_sources(True, "install-sources", "install-keys")
+ apt_update(fatal=True)
+ apt_upgrade(fatal=True, dist=False)
+ status_set("blocked", "Missing relation to contrail-controller")
+
+
+@hooks.hook("config-changed")
+def config_changed():
+ if config.changed("install-sources") or config.changed("install-keys"):
+ configure_sources(True, "install-sources", "install-keys")
+ apt_update(fatal=True)
+ apt_upgrade(fatal=True, dist=False)
+
+ if is_leader():
+ _configure_metadata_shared_secret()
+
+
+@hooks.hook("leader-elected")
+def leader_elected():
+ _configure_metadata_shared_secret()
+ _notify_clients()
+
+
+@hooks.hook("leader-settings-changed")
+def leader_settings_changed():
+ _notify_clients()
+
+
+@hooks.hook("contrail-controller-relation-joined")
+def contrail_controller_joined():
+ if not is_leader():
+ return
+
+ data = _get_orchestrator_info()
+ relation_set(**data)
+
+
+@hooks.hook("contrail-controller-relation-changed")
+@restart_on_change({"/etc/neutron/plugins/opencontrail/ContrailPlugin.ini":
+ ["neutron-server"]})
+def contrail_controller_changed():
+ data = relation_get()
+
+ def _update_config(key, data_key):
+ if data_key in data:
+ val = data[data_key]
+ if val is not None:
+ config[key] = val
+ else:
+ config.pop(key, None)
+
+ _update_config("auth_info", "auth-info")
+ _update_config("ssl_ca", "ssl-ca")
+ _update_config("api_vip", "api-vip")
+ _update_config("api_ip", "private-address")
+ _update_config("api_port", "port")
+ config.save()
+ write_configs()
+
+ status_set("active", "Unit is ready")
+
+ # auth_info can affect endpoints
+ changed = update_service_ips()
+ if changed and is_leader():
+ data = _get_orchestrator_info()
+ for rid in relation_ids("contrail-controller"):
+ relation_set(relation_id=rid, **data)
+
+
+@hooks.hook("contrail-controller-relation-departed")
+@restart_on_change({"/etc/neutron/plugins/opencontrail/ContrailPlugin.ini":
+ ["neutron-server"]})
+def contrail_cotroller_departed():
+ units = [unit for rid in relation_ids("contrail-controller")
+ for unit in related_units(rid)]
+ if units:
+ return
+
+ for key in ["auth_info", "ssl_ca", "api_vip", "api_ip", "api_port"]:
+ config.pop(key, None)
+ config.save()
+ write_configs()
+ status_set("blocked", "Missing relation to contrail-controller")
+
+
+def _configure_metadata_shared_secret():
+ secret = leader_get("metadata-shared-secret")
+ if config["enable-metadata-server"] and not secret:
+ secret = str(uuid.uuid4())
+ elif not config["enable-metadata-server"] and secret:
+ secret = None
+ else:
+ return
+
+ leader_set(settings={"metadata-shared-secret": secret})
+
+
+def _notify_clients():
+ # notify clients
+ data = _get_orchestrator_info()
+ for rid in relation_ids("contrail-controller"):
+ relation_set(relation_id=rid, **data)
+ for rid in relation_ids("nova-compute"):
+ nova_compute_joined(rid)
+
+
+def _get_orchestrator_info():
+ info = {"cloud_orchestrator": "openstack"}
+
+ if config["enable-metadata-server"]:
+ info["metadata_shared_secret"] = leader_get("metadata-shared-secret")
+
+ def _add_to_info(key):
+ value = config.get(key)
+ if value:
+ info[key] = value
+
+ _add_to_info("compute_service_ip")
+ _add_to_info("image_service_ip")
+ _add_to_info("network_service_ip")
+ return {"orchestrator-info": json.dumps(info)}
+
+
+@hooks.hook("neutron-api-relation-joined")
+def neutron_api_joined():
+ apt_install(NEUTRON_API_PACKAGES, fatal=True)
+ try:
+ cmd = ["dpkg-query", "-f", "${Version}\\n",
+ "-W", "neutron-plugin-contrail"]
+ version = check_output(cmd).decode("UTF-8").rstrip()
+ application_version_set(version)
+ except CalledProcessError as e:
+ log("Couldn't detect installed application version: " + str(e))
+
+ # create plugin config
+ base = "neutron_plugin_contrail.plugins.opencontrail"
+ plugin = base + ".contrail_plugin.NeutronPluginContrailCoreV2"
+ service_plugins = base + ".loadbalancer.v2.plugin.LoadBalancerPluginV2"
+ extensions = [
+ "/usr/lib/python2.7/dist-packages/neutron_plugin_contrail/extensions",
+ "/usr/lib/python2.7/dist-packages/neutron_lbaas/extensions"]
+ conf = {
+ "neutron-api": {
+ "/etc/neutron/neutron.conf": {
+ "sections": {
+ "DEFAULT": [
+ ("api_extensions_path", ":".join(extensions))
+ ]
+ }
+ }
+ }
+ }
+ settings = {
+ "neutron-plugin": "contrail",
+ "core-plugin": plugin,
+ "neutron-plugin-config":
+ "/etc/neutron/plugins/opencontrail/ContrailPlugin.ini",
+ "service-plugins": service_plugins,
+ "quota-driver": base + ".quota.driver.QuotaDriver",
+ "subordinate_configuration": json.dumps(conf)}
+ relation_set(relation_settings=settings)
+
+
+@hooks.hook("nova-compute-relation-joined")
+def nova_compute_joined(rel_id=None):
+ # create plugin config
+ conf = {
+ "nova-compute": {
+ "/etc/nova/nova.conf": {
+ "sections": {
+ "DEFAULT": [
+ ("firewall_driver", "nova.virt.firewall.NoopFirewallDriver")
+ ]
+ }
+ }
+ }
+ }
+ settings = {
+ "metadata-shared-secret": leader_get("metadata-shared-secret"),
+ "subordinate_configuration": json.dumps(conf)}
+ relation_set(relation_id=rel_id, relation_settings=settings)
+
+
+def main():
+ try:
+ hooks.execute(sys.argv)
+ except UnregisteredHookError as e:
+ log("Unknown hook {} - skipping.".format(e))
+
+
+if __name__ == "__main__":
+ main()