aboutsummaryrefslogtreecommitdiffstats
path: root/contrail-analytics/hooks/common_utils.py
blob: 9208ba7d0e09486ddb271e6e501ff410656cb669 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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