aboutsummaryrefslogtreecommitdiffstats
path: root/moon_interface/moon_interface/containers.py
blob: 4f93d742508c521fee4b44d671ce9c70a5fb3786 (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
# Copyright 2017 Open Platform for NFV Project, Inc. and its contributors
# This software is distributed under the terms and conditions of the 'Apache-2.0'
# license which can be found in the file 'LICENSE' in this package distribution
# or at 'http://www.apache.org/licenses/LICENSE-2.0'.

import docker
import logging
import re
import requests
import time
from python_moonutilities import configuration, exceptions

__version__ = "0.1.0"

LOG = logging.getLogger("moon.interface.container")


class DockerManager:

    def __init__(self):
        docker_conf = configuration.get_configuration("docker")['docker']
        self.docker = docker.DockerClient(base_url=docker_conf['url'])

    def create_container(self, data):
        """Create the container through the docker client

        :param data: {
            "name": "authz",
            "hostname": "authz123456789",
            "port": {
                "PrivatePort": 8090,
                "Type": "tcp",
                "IP": "0.0.0.0",
                "PublicPort": 8090
            },
            "keystone_project_id": "keystone_project_id1",
            "pdp_id": "123456789",
            "container_name": "wukongsun/moon_authz:v4.1"
        }
        :return: container output
        """
        output = self.docker.containers.run(
            image=data.get("container_name"),
            hostname=data.get("hostname", data.get("name"))[:63],
            name=data.get("name"),
            network='moon',
            ports={'{}/{}'.format(
                data.get("port").get("PrivatePort"),
                data.get("port").get("Type")
            ): int(data.get("port").get("PrivatePort"))},
            environment={
                "UUID": data.get("hostname"),
                "BIND": data.get("port").get("IP"),
                "TYPE": data.get("plugin_name"),
                "PORT": data.get("port").get("PrivatePort"),
                "PDP_ID": data.get("pdp_id"),
                "META_RULE_ID": data.get("meta_rule_id"),
                "KEYSTONE_PROJECT_ID": data.get("keystone_project_id"),
            },
            detach=True
        )
        try:
            req = requests.head("http://{}:{}/".format(data.get("hostname"), data.get("port").get("PublicPort")))
        except requests.exceptions.ConnectionError:
            pass
        else:
            if req.status_code != 200:
                raise exceptions.DockerError("Container {} is not running!".format(data.get("hostname")))
            output.ip = "0.0.0.0"
            return output

        # Note: host is not reachable through hostname so trying to find th IP address
        res = output.exec_run("ip addr")
        find = re.findall("inet (\d+\.\d+\.\d+\.\d+)", res.decode("utf-8"))
        ip = "127.0.0.1"
        for ip in find:
            if ip.startswith("127"):
                continue
            break
        cpt = 0
        while True:
            try:
                req = requests.head("http://{}:{}/".format(ip, data.get("port").get("PublicPort")))
            except requests.exceptions.ConnectionError:
                pass
            else:
                if req.status_code not in (200, 201):
                    LOG.error("url={}".format("http://{}:{}/".format(ip, data.get("port").get("PublicPort"))))
                    LOG.error("req={}".format(req))
                    raise exceptions.DockerError("Container {} is not running!".format(data.get("hostname")))
                output.ip = ip
                return output
            finally:
                cpt += 1
                time.sleep(0.1)
                if cpt > 20:
                    break
        output.ip = ip
        return output

    def delete_container(self, uuid):
        raise NotImplementedError