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
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)