diff options
Diffstat (limited to 'contrail-analyticsdb/hooks/common_utils.py')
-rw-r--r-- | contrail-analyticsdb/hooks/common_utils.py | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/contrail-analyticsdb/hooks/common_utils.py b/contrail-analyticsdb/hooks/common_utils.py new file mode 100644 index 0000000..9208ba7 --- /dev/null +++ b/contrail-analyticsdb/hooks/common_utils.py @@ -0,0 +1,158 @@ +from base64 import b64decode +import os +from socket import gethostbyname, gethostname, gaierror +from subprocess import ( + CalledProcessError, + check_call, + check_output +) +import netifaces +import time +import platform +import json + +from charmhelpers.contrib.network.ip import get_address_in_network +from charmhelpers.core.hookenv import ( + config, + status_set, + log, + ERROR, + application_version_set, +) +from charmhelpers.core.host import write_file + +from docker_utils import ( + is_container_launched, + is_container_present, + apply_config_in_container, + get_docker_image_id, + load_docker_image, + launch_docker_image, + dpkg_version, + docker_exec, +) + +config = config() + + +def get_ip(): + network = config.get("control-network") + ip = get_address_in_network(network) if network else None + if not ip: + ip = _get_default_ip() + return ip + + +def _get_default_ip(): + if hasattr(netifaces, "gateways"): + iface = netifaces.gateways()["default"][netifaces.AF_INET][1] + else: + data = check_output("ip route | grep ^default", shell=True).split() + iface = data[data.index("dev") + 1] + return netifaces.ifaddresses(iface)[netifaces.AF_INET][0]["addr"] + + +def fix_hostname(): + hostname = gethostname() + try: + gethostbyname(hostname) + except gaierror: + ip = get_ip() + check_call(["sed", "-E", "-i", "-e", + ("/127.0.0.1[[:blank:]]+/a \\\n" + ip + " " + hostname), + "/etc/hosts"]) + + +def decode_cert(key): + val = config.get(key) + if not val: + return None + try: + return b64decode(val) + except Exception as e: + log("Couldn't decode certificate from config['{}']: {}".format( + key, str(e)), level=ERROR) + return None + + +def save_file(path, data): + if data: + fdir = os.path.dirname(path) + if not os.path.exists(fdir): + os.makedirs(fdir) + write_file(path, data, perms=0o400) + elif os.path.exists(path): + os.remove(path) + + +def update_services_status(name, services): + try: + output = docker_exec(name, "contrail-status") + except CalledProcessError as e: + log("Container is not ready to get contrail-status: " + str(e)) + status_set("waiting", "Waiting services to run in container") + return + + statuses = dict() + for line in output.splitlines()[1:]: + if len(line) == 0 or line.startswith("=="): + continue + lst = line.split() + if len(lst) < 2: + continue + srv = lst[0].split(":")[0] + statuses[srv] = (lst[1], " ".join(lst[2:])) + for srv in services: + if srv not in statuses: + status_set("waiting", srv + " is absent in the contrail-status") + return + status, desc = statuses.get(srv) + if status != "active": + workload = "waiting" if status == "initializing" else "blocked" + status_set(workload, "{} is not ready. Reason: {}" + .format(srv, desc)) + return + + status_set("active", "Unit is ready") + + +def check_run_prerequisites(name, config_name, update_config_func, services): + if is_container_launched(name): + check = True + if update_config_func: + update_config_func() + check = apply_config_in_container(name, config_name) + if check: + update_services_status(name, services) + return False + + if is_container_present(name): + status_set( + "blocked", + "Container is present but is not running. Run or remove it.") + return False + + image_id = get_docker_image_id(name) + if not image_id: + image_id = load_docker_image(name) + if not image_id: + status_set("waiting", "Awaiting for container resource") + return False + + return True + + +def run_container(name, pkg_to_check): + args = [] + if platform.linux_distribution()[2].strip() == "trusty": + args.append("--pid=host") + launch_docker_image(name, args) + + time.sleep(5) + version = dpkg_version(name, pkg_to_check) + application_version_set(version) + status_set("waiting", "Waiting services to run in container") + + +def json_loads(data, default=None): + return json.loads(data) if data else default |