aboutsummaryrefslogtreecommitdiffstats
path: root/charms/trusty/contrail-control/hooks/contrail_control_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'charms/trusty/contrail-control/hooks/contrail_control_utils.py')
-rw-r--r--charms/trusty/contrail-control/hooks/contrail_control_utils.py249
1 files changed, 249 insertions, 0 deletions
diff --git a/charms/trusty/contrail-control/hooks/contrail_control_utils.py b/charms/trusty/contrail-control/hooks/contrail_control_utils.py
new file mode 100644
index 0000000..fad2d11
--- /dev/null
+++ b/charms/trusty/contrail-control/hooks/contrail_control_utils.py
@@ -0,0 +1,249 @@
+import functools
+import os
+import pwd
+import shutil
+from socket import gethostbyname, gethostname
+from subprocess import (
+ CalledProcessError,
+ check_call,
+ check_output
+)
+from time import sleep, time
+
+import apt_pkg
+from apt_pkg import version_compare
+import json
+
+from charmhelpers.core.hookenv import (
+ local_unit,
+ log,
+ related_units,
+ relation_get,
+ relation_ids,
+ relation_type,
+ remote_unit,
+ unit_get
+)
+from charmhelpers.core.host import service_restart
+from charmhelpers.core.templating import render
+
+apt_pkg.init()
+
+def dpkg_version(pkg):
+ try:
+ return check_output(["dpkg-query", "-f", "${Version}\\n", "-W", pkg]).rstrip()
+ except CalledProcessError:
+ return None
+
+CONTRAIL_VERSION = dpkg_version("contrail-control")
+
+def retry(f=None, timeout=10, delay=2):
+ """Retry decorator.
+
+ Provides a decorator that can be used to retry a function if it raises
+ an exception.
+
+ :param timeout: timeout in seconds (default 10)
+ :param delay: retry delay in seconds (default 2)
+
+ Examples::
+
+ # retry fetch_url function
+ @retry
+ def fetch_url():
+ # fetch url
+
+ # retry fetch_url function for 60 secs
+ @retry(timeout=60)
+ def fetch_url():
+ # fetch url
+ """
+ if not f:
+ return functools.partial(retry, timeout=timeout, delay=delay)
+ @functools.wraps(f)
+ def func(*args, **kwargs):
+ start = time()
+ error = None
+ while True:
+ try:
+ return f(*args, **kwargs)
+ except Exception as e:
+ error = e
+ elapsed = time() - start
+ if elapsed >= timeout:
+ raise error
+ remaining = timeout - elapsed
+ if delay <= remaining:
+ sleep(delay)
+ else:
+ sleep(remaining)
+ raise error
+ return func
+
+def contrail_api_ctx():
+ ctxs = [ { "api_server": gethostbyname(relation_get("private-address", unit, rid)),
+ "api_port": port }
+ for rid in relation_ids("contrail-api")
+ for unit, port in
+ ((unit, relation_get("port", unit, rid)) for unit in related_units(rid))
+ if port ]
+ return ctxs[0] if ctxs else {}
+
+def contrail_ctx():
+ return { "host_ip": gethostbyname(unit_get("private-address")) }
+
+def contrail_discovery_ctx():
+ ctxs = [ { "discovery_server": vip if vip \
+ else gethostbyname(relation_get("private-address", unit, rid)),
+ "discovery_port": port }
+ for rid in relation_ids("contrail-discovery")
+ for unit, port, vip in
+ ((unit, relation_get("port", unit, rid), relation_get("vip", unit, rid))
+ for unit in related_units(rid))
+ if port ]
+ return ctxs[0] if ctxs else {}
+
+def contrail_ifmap_ctx():
+ ctxs = []
+ unit = local_unit()
+ for rid in relation_ids("contrail-ifmap"):
+ for u in related_units(rid):
+ creds = relation_get("creds", u, rid)
+ if creds:
+ creds = json.loads(creds)
+ if unit in creds:
+ cs = creds[unit]
+ ctx = {}
+ ctx["ifmap_user"] = cs["username"]
+ ctx["ifmap_password"] = cs["password"]
+ ctxs.append(ctx)
+ return ctxs[0] if ctxs else {}
+
+@retry(timeout=300)
+def contrail_provision_control(hostname, ip, router_asn, api_ip, api_port, op,
+ user, password, tenant):
+ check_call(["contrail-provision-control",
+ "--host_name", hostname,
+ "--host_ip", ip,
+ "--router_asn", str(router_asn),
+ "--api_server_ip", api_ip,
+ "--api_server_port", str(api_port),
+ "--oper", op,
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant_name", tenant])
+
+def fix_nodemgr():
+ # add files missing from contrail-nodemgr package
+ shutil.copy("files/contrail-nodemgr-control.ini",
+ "/etc/contrail/supervisord_control_files")
+ pw = pwd.getpwnam("contrail")
+ os.chown("/etc/contrail/supervisord_control_files/contrail-nodemgr-control.ini",
+ pw.pw_uid, pw.pw_gid)
+ shutil.copy("files/contrail-control-nodemgr", "/etc/init.d")
+ os.chmod("/etc/init.d/contrail-control-nodemgr", 0755)
+
+ # fake ntp status when inside a container
+ if is_container():
+ shutil.copy("files/ntpq-nodemgr", "/usr/local/bin/ntpq")
+
+ service_restart("supervisor-control")
+
+def fix_permissions():
+ os.chmod("/etc/contrail", 0755)
+ os.chown("/etc/contrail", 0, 0)
+
+def identity_admin_ctx():
+ ctxs = [ { "auth_host": gethostbyname(hostname),
+ "auth_port": relation_get("service_port", unit, rid) }
+ for rid in relation_ids("identity-admin")
+ for unit, hostname in
+ ((unit, relation_get("service_hostname", unit, rid)) for unit in related_units(rid))
+ if hostname ]
+ return ctxs[0] if ctxs else {}
+
+def is_container():
+ """Return boolean determining if inside container"""
+ try:
+ check_call(["running-in-container"])
+ return True
+ except CalledProcessError:
+ return False
+
+def provision_control():
+ hostname = gethostname()
+ ip = gethostbyname(unit_get("private-address"))
+ api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)),
+ port)
+ for rid in relation_ids("contrail-api")
+ for unit, port in
+ ((unit, relation_get("port", unit, rid)) for unit in related_units(rid))
+ if port ][0]
+ user, password, tenant = [ (relation_get("service_username", unit, rid),
+ relation_get("service_password", unit, rid),
+ relation_get("service_tenant_name", unit, rid))
+ for rid in relation_ids("identity-admin")
+ for unit in related_units(rid)
+ if relation_get("service_hostname", unit, rid) ][0]
+ log("Provisioning control {}".format(ip))
+ contrail_provision_control(hostname, ip, 64512, api_ip, api_port, "add",
+ user, password, tenant)
+
+def units(relation):
+ """Return a list of units for the specified relation"""
+ return [ unit for rid in relation_ids(relation)
+ for unit in related_units(rid) ]
+
+def unprovision_control():
+ if not remote_unit():
+ return
+ hostname = gethostname()
+ ip = gethostbyname(unit_get("private-address"))
+ relation = relation_type()
+ api_ip = None
+ api_port = None
+ if relation == "contrail-api":
+ api_ip = gethostbyname(relation_get("private-address"))
+ api_port = relation_get("port")
+ else:
+ api_ip, api_port = [ (gethostbyname(relation_get("private-address", unit, rid)),
+ relation_get("port", unit, rid))
+ for rid in relation_ids("contrail-api")
+ for unit in related_units(rid) ][0]
+ user = None
+ password = None
+ tenant = None
+ if relation == "identity-admin":
+ user = relation_get("service_username")
+ password = relation_get("service_password")
+ tenant = relation_get("service_tenant_name")
+ else:
+ user, password, tenant = [ (relation_get("service_username", unit, rid),
+ relation_get("service_password", unit, rid),
+ relation_get("service_tenant_name", unit, rid))
+ for rid in relation_ids("identity-admin")
+ for unit in related_units(rid) ][0]
+ log("Unprovisioning control {}".format(ip))
+ contrail_provision_control(hostname, ip, 64512, api_ip, api_port, "del",
+ user, password, tenant)
+
+def write_control_config():
+ ctx = {}
+ ctx.update(contrail_ctx())
+ ctx.update(contrail_discovery_ctx())
+ ctx.update(contrail_ifmap_ctx())
+ target = "/etc/contrail/contrail-control.conf" \
+ if version_compare(CONTRAIL_VERSION, "2.0") >= 0 \
+ else "/etc/contrail/control-node.conf"
+ render("control-node.conf", target, ctx, "root", "contrail", 0440)
+
+def write_nodemgr_config():
+ ctx = contrail_discovery_ctx()
+ render("contrail-control-nodemgr.conf",
+ "/etc/contrail/contrail-control-nodemgr.conf", ctx)
+
+def write_vnc_api_config():
+ ctx = {}
+ ctx.update(contrail_api_ctx())
+ ctx.update(identity_admin_ctx())
+ render("vnc_api_lib.ini", "/etc/contrail/vnc_api_lib.ini", ctx)