aboutsummaryrefslogtreecommitdiffstats
path: root/charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py')
-rw-r--r--charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py503
1 files changed, 503 insertions, 0 deletions
diff --git a/charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py b/charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py
new file mode 100644
index 0000000..bb11693
--- /dev/null
+++ b/charms/trusty/contrail-configuration/hooks/contrail_configuration_utils.py
@@ -0,0 +1,503 @@
+from collections import OrderedDict
+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
+import urllib2
+
+from charmhelpers.core.hookenv import (
+ config,
+ leader_get,
+ log,
+ related_units,
+ relation_get,
+ relation_ids,
+ relation_type,
+ remote_unit,
+ unit_get
+)
+
+from charmhelpers.core.host import (
+ service_available,
+ service_restart,
+ service_stop
+)
+
+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-config")
+
+config = config()
+
+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 amqp_ctx():
+ ctxs = []
+ servers = OrderedDict()
+ for rid in relation_ids("amqp"):
+ for unit in related_units(rid):
+ password = relation_get("password", unit, rid)
+ if not password:
+ continue
+ ctxs.append({"rabbit_user": "contrail",
+ "rabbit_password": password,
+ "rabbit_vhost": "contrail"})
+ vip = relation_get("vip", unit, rid)
+ server = (vip if vip \
+ else gethostbyname(relation_get("hostname", unit, rid))) + ":5672"
+ servers[server] = None
+ ctx = ctxs[0] if ctxs else {}
+ ctx["rabbit_servers"] = servers.keys()
+ return ctx
+
+def analytics_api_ctx():
+ ctxs = [ { "analytics_server_ip": vip if vip \
+ else gethostbyname(relation_get("private-address", unit, rid)),
+ "analytics_server_port": port }
+ for rid in relation_ids("contrail-analytics-api")
+ 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 api_port():
+ return 8082
+
+def cassandra_ctx():
+ servers = [ gethostbyname(relation_get("private-address", unit, rid))
+ + ":" + (rpc_port if rpc_port else port)
+ for rid in relation_ids("cassandra")
+ for unit, rpc_port, port in
+ ((unit, relation_get("rpc_port", unit, rid), relation_get("port", unit, rid))
+ for unit in related_units(rid))
+ if rpc_port or port ] \
+ if config.get("cassandra-ready") else []
+ return { "cassandra_servers": servers }
+
+def cassandra_units():
+ """Return a list of cassandra units"""
+ return [ unit for rid in relation_ids("cassandra")
+ for unit in related_units(rid)
+ if relation_get("rpc_port", unit, rid) or relation_get("port", unit, rid) ]
+
+@retry(timeout=300, delay=10)
+def check_url(url):
+ try:
+ urllib2.urlopen(url)
+ except urllib2.HTTPError:
+ pass
+
+def contrail_ctx():
+ addr = gethostbyname(unit_get("private-address"))
+ return { "api_port": api_port(),
+ "ifmap_server": addr,
+ "disc_server": addr,
+ "disc_port": discovery_port() }
+
+def contrail_floating_ip_create(network, name):
+ 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("Creating floating ip pool {} for network {}".format(name, network))
+ check_call(["python", "/usr/share/contrail-utils/create_floating_pool.py",
+ "--public_vn_name", network,
+ "--floating_ip_pool_name", name,
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant", tenant])
+
+def contrail_floating_ip_deactivate(project, name):
+ 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("Deactivating floating ip pool {} for project {}".format(name, project))
+ check_call(["scripts/deactivate_floating_pool.py",
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant", tenant,
+ project, name])
+
+def contrail_floating_ip_delete(network, name):
+ 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("Deleting floating ip pool {} for network {}".format(name, network))
+ check_call(["scripts/delete_floating_pool.py",
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant", tenant,
+ network, name])
+
+def contrail_floating_ip_use(project, name):
+ 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("Activating floating ip pool {} for project {}".format(name, project))
+ check_call(["python", "/usr/share/contrail-utils/use_floating_pool.py",
+ "--project_name", project,
+ "--floating_ip_pool_name", name,
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant", tenant])
+
+def contrail_ifmap_ctx():
+ creds = []
+ cs = leader_get("ifmap-creds")
+ if cs:
+ cs = json.loads(cs)
+ for units in cs.itervalues():
+ for c in units.itervalues():
+ creds.append(c)
+ return { "ifmap_creds": creds }
+
+def discovery_port():
+ return 5998
+
+def fix_ifmap_server():
+ # disable ifmap-server upstart service
+ if service_available("ifmap-server"):
+ service_stop("ifmap-server")
+ with open("/etc/init/ifmap-server.override", "w") as conf:
+ conf.write("manual\n")
+
+ # use supervisord config
+ shutil.copy("files/ifmap.ini", "/etc/contrail/supervisord_config_files")
+ pw = pwd.getpwnam("contrail")
+ os.chown("/etc/contrail/supervisord_config_files/ifmap.ini", pw.pw_uid,
+ pw.pw_gid)
+ shutil.copy("files/ifmap", "/etc/init.d")
+ os.chmod("/etc/init.d/ifmap", 0755)
+
+def fix_nodemgr():
+ # add files missing from contrail-nodemgr package
+ shutil.copy("files/contrail-nodemgr-config.ini",
+ "/etc/contrail/supervisord_config_files")
+ pw = pwd.getpwnam("contrail")
+ os.chown("/etc/contrail/supervisord_config_files/contrail-nodemgr-config.ini",
+ pw.pw_uid, pw.pw_gid)
+ shutil.copy("files/contrail-config-nodemgr", "/etc/init.d")
+ os.chmod("/etc/init.d/contrail-config-nodemgr", 0755)
+
+ # fake ntp status when inside a container
+ if is_container():
+ shutil.copy("files/ntpq-nodemgr", "/usr/local/bin/ntpq")
+
+def fix_permissions():
+ os.chmod("/etc/contrail", 0755)
+ os.chown("/etc/contrail", 0, 0)
+
+def fix_scripts():
+ version = dpkg_version("contrail-config")
+ if version_compare(version, "2.01") >= 0:
+ # supervisord and init scripts need correcting on contrail 2.01+
+ for service in [ "contrail-api", "contrail-discovery" ]:
+ # remove hardcoded port
+ check_call(["sed", "-E", "-i", "-e",
+ "s/ --listen_port [^[:blank:]]+//",
+ "/etc/contrail/supervisord_config_files/{}.ini".format(service)])
+
+ # fix init script
+ check_call(["sed", "-i", "-e",
+ "s/`basename ${0}`$/\"`basename ${0}`:*\"/",
+ "/etc/init.d/{}".format(service)])
+
+def fix_services():
+ fix_permissions()
+ fix_ifmap_server()
+ fix_nodemgr()
+ fix_scripts()
+ service_restart("supervisor-config")
+
+def identity_admin_ctx():
+ ctxs = [ { "auth_host": gethostbyname(hostname),
+ "auth_port": relation_get("service_port", unit, rid),
+ "admin_user": relation_get("service_username", unit, rid),
+ "admin_password": relation_get("service_password", unit, rid),
+ "admin_tenant_name": relation_get("service_tenant_name", unit, rid),
+ "auth_region": relation_get("service_region", 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_configuration():
+ hostname = gethostname()
+ ip = gethostbyname(unit_get("private-address"))
+ 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 configuration {}".format(ip))
+ check_call(["contrail-provision-config",
+ "--host_name", hostname,
+ "--host_ip", ip,
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--oper", "add",
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant_name", tenant])
+
+def provision_metadata():
+ ip = [ gethostbyname(relation_get("private-address", unit, rid))
+ for rid in relation_ids("neutron-metadata")
+ for unit in related_units(rid) ][0]
+ user, password = [ (relation_get("service_username", unit, rid),
+ relation_get("service_password", 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 metadata service {}:8775".format(ip))
+ check_call(["contrail-provision-linklocal",
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--linklocal_service_name", "metadata",
+ "--linklocal_service_ip", "169.254.169.254",
+ "--linklocal_service_port", "80",
+ "--ipfabric_service_ip", ip,
+ "--ipfabric_service_port", "8775",
+ "--oper", "add",
+ "--admin_user", user,
+ "--admin_password", password])
+
+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_configuration():
+ if not remote_unit():
+ return
+ hostname = gethostname()
+ ip = gethostbyname(unit_get("private-address"))
+ relation = relation_type()
+ 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 configuration {}".format(ip))
+ check_call(["contrail-provision-config",
+ "--host_name", hostname,
+ "--host_ip", ip,
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--oper", "del",
+ "--admin_user", user,
+ "--admin_password", password,
+ "--admin_tenant_name", tenant])
+
+def unprovision_metadata():
+ if not remote_unit():
+ return
+ relation = relation_type()
+ ip = None
+ if relation == "neutron-metadata":
+ ip = gethostbyname(relation_get("private-address"))
+ else:
+ ip = [ gethostbyname(relation_get("private-address", unit, rid))
+ for rid in relation_ids("neutron-metadata")
+ for unit in related_units(rid) ][0]
+ user = None
+ password = None
+ if relation == "identity-admin":
+ user = relation_get("service_username")
+ password = relation_get("service_password")
+ else:
+ user, password = [ (relation_get("service_username", unit, rid),
+ relation_get("service_password", unit, rid))
+ for rid in relation_ids("identity-admin")
+ for unit in related_units(rid) ][0]
+ log("Unprovisioning metadata service {}:8775".format(ip))
+ check_call(["contrail-provision-linklocal",
+ "--api_server_ip", "127.0.0.1",
+ "--api_server_port", str(api_port()),
+ "--linklocal_service_name", "metadata",
+ "--linklocal_service_ip", "169.254.169.254",
+ "--linklocal_service_port", "80",
+ "--ipfabric_service_ip", ip,
+ "--ipfabric_service_port", "8775",
+ "--oper", "del",
+ "--admin_user", user,
+ "--admin_password", password])
+
+def write_barbican_auth_config():
+ ctx = identity_admin_ctx()
+ render("contrail-barbican-auth.conf",
+ "/etc/contrail/contrail-barbican-auth.conf", ctx, "root", "contrail",
+ 0440)
+
+def write_contrail_api_config():
+ ctx = {}
+ ctx.update(contrail_ctx())
+ ctx.update(cassandra_ctx())
+ ctx.update(zookeeper_ctx())
+ ctx.update(amqp_ctx())
+ ctx.update(identity_admin_ctx())
+ render("contrail-api.conf", "/etc/contrail/contrail-api.conf", ctx, "root",
+ "contrail", 0440)
+
+def write_contrail_schema_config():
+ ctx = {}
+ ctx.update(cassandra_ctx())
+ ctx.update(zookeeper_ctx())
+ ctx.update(identity_admin_ctx())
+ ctx.update(contrail_ctx())
+ if version_compare(CONTRAIL_VERSION, "3.0") >= 0:
+ ctx["rabbitmq"] = True
+ ctx.update(amqp_ctx())
+ render("contrail-schema.conf", "/etc/contrail/contrail-schema.conf",
+ ctx, "root", "contrail", 0440)
+
+def write_contrail_svc_monitor_config():
+ ctx = {}
+ ctx.update(contrail_ctx())
+ ctx.update(cassandra_ctx())
+ ctx.update(zookeeper_ctx())
+ ctx.update(amqp_ctx())
+ ctx.update(identity_admin_ctx())
+ ctx.update(analytics_api_ctx())
+ render("contrail-svc-monitor.conf",
+ "/etc/contrail/contrail-svc-monitor.conf", ctx, "root", "contrail",
+ 0440)
+
+def write_device_manager_config():
+ ctx = {}
+ ctx.update(contrail_ctx())
+ ctx.update(zookeeper_ctx())
+ ctx.update(cassandra_ctx())
+ ctx.update(amqp_ctx())
+ ctx.update(identity_admin_ctx())
+ render("contrail-device-manager.conf",
+ "/etc/contrail/contrail-device-manager.conf", ctx, "root",
+ "contrail", 0440)
+
+def write_discovery_config():
+ ctx = {}
+ ctx.update(zookeeper_ctx())
+ ctx.update(cassandra_ctx())
+ target = "/etc/contrail/contrail-discovery.conf" \
+ if version_compare(CONTRAIL_VERSION, "1.20~") >= 0 \
+ else "/etc/contrail/discovery.conf"
+ render("discovery.conf", target, ctx)
+
+def write_ifmap_config():
+ ctx = contrail_ifmap_ctx()
+ render("basicauthusers.properties",
+ "/etc/ifmap-server/basicauthusers.properties", ctx, "root",
+ "contrail", 0440)
+
+def write_nodemgr_config():
+ ctx = contrail_ctx()
+ render("contrail-config-nodemgr.conf",
+ "/etc/contrail/contrail-config-nodemgr.conf", ctx)
+
+def write_vnc_api_config():
+ ctx = {}
+ ctx.update(contrail_ctx())
+ ctx.update(identity_admin_ctx())
+ render("vnc_api_lib.ini", "/etc/contrail/vnc_api_lib.ini", ctx)
+
+def zookeeper_ctx():
+ return { "zk_servers": [ gethostbyname(relation_get("private-address", unit, rid))
+ + ":" + port
+ for rid in relation_ids("zookeeper")
+ for unit, port in
+ ((unit, relation_get("port", unit, rid)) for unit in related_units(rid))
+ if port ] }