Пример #1
0
class DockerController(object):
    def _load_config(self):
        with open('./config.yaml') as fh:
            config = yaml.load(fh)
        return config

    def __init__(self):
        config = self._load_config()

        self.REDIS_HOST = config['redis_host']
        self.PYWB_HOST = config['pywb_host']
        self.C_EXPIRE_TIME = config['container_expire_secs']
        self.Q_EXPIRE_TIME = config['queue_expire_secs']
        self.REMOVE_EXP_TIME = config['remove_expired_secs']
        self.VERSION = config['api_version']

        self.VNC_PORT = config['vnc_port']
        self.CMD_PORT = config['cmd_port']

        self.image_prefix = config['image_prefix']
        self.browsers = config['browsers']

        self.redis = redis.StrictRedis(host=self.REDIS_HOST)

        self.redis.setnx('next_client', '1')

        if os.path.exists('/var/run/docker.sock'):
            self.cli = Client(base_url='unix://var/run/docker.sock',
                              version=self.VERSION)
        else:
            kwargs = kwargs_from_env()
            kwargs['tls'].assert_hostname = False
            kwargs['version'] = self.VERSION
            self.cli = Client(**kwargs)

    def new_container(self, browser, env=None):
        tag = self.browsers.get(browser)

        # get default browser
        if not tag:
            tag = self.browsers['']

        container = self.cli.create_container(image=self.image_prefix + '/' + tag,
                                              ports=[self.VNC_PORT, self.CMD_PORT],
                                              environment=env,
                                             )
        id_ = container.get('Id')

        res = self.cli.start(container=id_,
                             port_bindings={self.VNC_PORT: None, self.CMD_PORT: None},
                             links={self.PYWB_HOST: self.PYWB_HOST,
                                    self.REDIS_HOST: self.REDIS_HOST},
                             volumes_from=['netcapsule_shared_data_1'],
                            )

        vnc_port = self.cli.port(id_, self.VNC_PORT)
        vnc_port = vnc_port[0]['HostPort']

        cmd_port = self.cli.port(id_, self.CMD_PORT)
        cmd_port = cmd_port[0]['HostPort']

        info = self.cli.inspect_container(id_)
        ip = info['NetworkSettings']['IPAddress']

        short_id = id_[:12]
        self.redis.hset('all_containers', short_id, ip)
        self.redis.setex('c:' + short_id, self.C_EXPIRE_TIME, 1)

        return vnc_port, cmd_port

    def remove_container(self, short_id, ip):
        print('REMOVING ' + short_id)
        try:
            self.cli.remove_container(short_id, force=True)
        except Exception as e:
            print(e)

        self.redis.hdel('all_containers', short_id)
        self.redis.delete('c:' + short_id)

        ip_keys = self.redis.keys(ip +':*')
        for key in ip_keys:
            self.redis.delete(key)

    def remove_all(self, check_expired=False):
        all_containers = self.redis.hgetall('all_containers')

        for short_id, ip in all_containers.iteritems():
            if check_expired:
                remove = not self.redis.get('c:' + short_id)
            else:
                remove = True

            if remove:
                self.remove_container(short_id, ip)

    def add_new_client(self):
        #client_id = base64.b64encode(os.urandom(27))
        #self.redis.rpush('q:clients', client_id)
        client_id = self.redis.incr('clients')
        self.redis.setex('q:' + str(client_id), self.Q_EXPIRE_TIME, 1)
        return client_id

    def am_i_next(self, client_id):
        next_client = int(self.redis.get('next_client'))

        # not next client
        if next_client != client_id:
            # if this client expired, delete it from queue
            if not self.redis.get('q:' + str(next_client)):
                print('skipping expired', next_client)
                self.redis.incr('next_client')

            # missed your number somehow, get a new one!
            if client_id < next_client:
                client_id = self.add_new_client()
            else:
                self.redis.expire('q:' + str(client_id), self.Q_EXPIRE_TIME)

            return client_id, client_id - next_client

        # not avail yet
        num_containers = self.redis.hlen('all_containers')
        if num_containers >= MAX_CONT:
            self.redis.expire('q:' + str(client_id), self.Q_EXPIRE_TIME)
            return client_id, client_id - next_client

        self.redis.incr('next_client')
        return client_id, -1
Пример #2
0
class DockerController(object):
    def _load_config(self):
        with open('./config.yaml') as fh:
            config = yaml.load(fh)
        return config

    def __init__(self):
        config = self._load_config()

        self.REDIS_HOST = config['redis_host']
        self.PYWB_HOST = config['pywb_host']
        self.EXPIRE_TIME = config['expire_secs']
        self.REMOVE_EXP_TIME = config['remove_expired_secs']
        self.VERSION = config['api_version']

        self.VNC_PORT = config['vnc_port']
        self.CMD_PORT = config['cmd_port']

        self.image_prefix = config['image_prefix']
        self.browsers = config['browsers']

        self.redis = redis.StrictRedis(host=self.REDIS_HOST)

        if os.path.exists('/var/run/docker.sock'):
            self.cli = Client(base_url='unix://var/run/docker.sock',
                              version=self.VERSION)
        else:
            kwargs = kwargs_from_env()
            kwargs['tls'].assert_hostname = False
            kwargs['version'] = self.VERSION
            self.cli = Client(**kwargs)

    def new_container(self, browser, env=None):
        tag = self.browsers.get(browser)

        # get default browser
        if not tag:
            tag = self.browsers['']

        container = self.cli.create_container(image=self.image_prefix + '/' + tag,
                                              ports=[self.VNC_PORT, self.CMD_PORT],
                                              environment=env)
        id_ = container.get('Id')

        res = self.cli.start(container=id_,
                             port_bindings={self.VNC_PORT: None, self.CMD_PORT: None},
                             links={self.PYWB_HOST: self.PYWB_HOST,
                                    self.REDIS_HOST: self.REDIS_HOST})

        vnc_port = self.cli.port(id_, self.VNC_PORT)
        vnc_port = vnc_port[0]['HostPort']

        cmd_port = self.cli.port(id_, self.CMD_PORT)
        cmd_port = cmd_port[0]['HostPort']

        info = self.cli.inspect_container(id_)
        ip = info['NetworkSettings']['IPAddress']

        short_id = id_[:12]
        self.redis.hset('all_containers', short_id, ip)
        self.redis.setex('c:' + short_id, self.EXPIRE_TIME, 1)

        return vnc_port, cmd_port

    def remove_container(self, short_id, ip):
        print('REMOVING ' + short_id)
        try:
            self.cli.remove_container(short_id, force=True)
        except Exception as e:
            print(e)

        self.redis.hdel('all_containers', short_id)
        self.redis.delete('c:' + short_id)

        ip_keys = self.redis.keys(ip +':*')
        for key in ip_keys:
            self.redis.delete(key)

    def remove_all(self, check_expired=False):
        all_containers = self.redis.hgetall('all_containers')

        for short_id, ip in all_containers.iteritems():
            if check_expired:
                remove = not self.redis.get('c:' + short_id)
            else:
                remove = True

            if remove:
                self.remove_container(short_id, ip)