# import uvloop from hailtop.config import DeployConfig from gear import configure_logging from .utils import parse_cpu, parse_image_tag from .semaphore import NullWeightedSemaphore, WeightedSemaphore from .log_store import LogStore from .google_storage import GCS # uvloop.install() configure_logging() log = logging.getLogger('batch2-agent') docker = aiodocker.Docker() MAX_IDLE_TIME_WITH_PODS = 60 * 2 # seconds MAX_IDLE_TIME_WITHOUT_PODS = 60 * 1 # seconds class Error: def __init__(self, reason, msg): self.reason = reason self.message = msg def to_dict(self): return { 'reason': self.reason, 'message': self.message }
async def start(self, path, started, session): log = logging.getLogger(f'Server({path})') log.info('starting') container, stream = None, None try: try: session_id = pathlib.Path(path).name container_name = f'{self.lektor_image}-{session_id}' session_address = self.session_address(session_id, container_name) labels = flatten_options(self.lektor_labels(session_id), 'traefik') session = { **session, 'edit_url': session_address, } if 'creation_time' in session: session['creation_time'] = str(session['creation_time'].timestamp()) session.pop('parked_time', None) labels.update(flatten_options(session, self.LABEL_PREFIX)) docker = aiodocker.Docker() container = await docker.containers.run( name=container_name, config=dict( HostConfig=dict( AutoRemove=self.auto_remove, NetworkMode=await self.network_mode, VolumesFrom=[ self.server_container, ], ), Cmd=[ '--project', f'{path}', 'server', '--host', '0.0.0.0', ], Labels=labels, Image=self.lektor_image, ), ) stream = container.log(stdout=True, stderr=True, follow=True) async for line in stream: logging.debug(line.strip()) if line.strip().startswith('Finished prune'): break else: raise RuntimeError('early process end') except Exception as exc: log.error('failed') started.set_exception(exc) if container is not None: await asyncio.gather( container.kill(), return_exceptions=True, ) else: log.info('started') started.set_result(session_address) self.serves[path][0] = container.kill finally: if stream is not None: await asyncio.gather( stream.aclose(), return_exceptions=True, ) finally: log.info('start ended')
def __init__(self, username=None, password=None): self._auth = AsyncDocker.create_auth(username, password) if username else None self.client = aiodocker.Docker()
async def pull_images(images, force_pull): async_docker = aiodocker.Docker() tasks = [pull_image(image, async_docker, force_pull) for image in images] await asyncio.wait(tasks) await async_docker.close()
def __init__(self, hass, config): """Initialize the Docker API.""" self._hass = hass self._config = config self._containers = {} self._tasks = {} self._info = {} self._event_create = {} self._event_destroy = {} _LOGGER.debug("Helper version: %s", VERSION) self._interval = config[CONF_SCAN_INTERVAL].seconds self._loop = asyncio.get_event_loop() try: # Try to fix unix:// to unix:/// (3 are required by aiodocker) url = self._config[CONF_URL] if ( url is not None and url.find("unix://") == 0 and url.find("unix:///") == -1 ): url = url.replace("unix://", "unix:///") # Do some debugging logging for TCP/TLS if url is not None: _LOGGER.debug("Docker URL is '%s'", url) # Check for TLS if it is not unix if url.find("tcp:") == 0 or url.find("http:") == 0: tlsverify = os.environ.get("DOCKER_TLS_VERIFY", None) certpath = os.environ.get("DOCKER_CERT_PATH", None) if tlsverify is None: _LOGGER.debug( "Docker environment 'DOCKER_TLS_VERIFY' is NOT set" ) else: _LOGGER.debug( "Docker environment set 'DOCKER_TLS_VERIFY=%s'", tlsverify ) if certpath is None: _LOGGER.debug( "Docker environment 'DOCKER_CERT_PATH' is NOT set" ) else: _LOGGER.debug( "Docker environment set 'DOCKER_CERT_PATH=%s'", certpath ) if self._config[CONF_CERTPATH]: _LOGGER.debug( "Docker CertPath set '%s', setting environment variables DOCKER_TLS_VERIFY/DOCKER_CERT_PATH", self._config[CONF_CERTPATH], ) os.environ["DOCKER_TLS_VERIFY"] = "1" os.environ["DOCKER_CERT_PATH"] = self._config[CONF_CERTPATH] self._api = aiodocker.Docker(url=url) except Exception as err: _LOGGER.error("Can not connect to Docker API (%s)", str(err), exc_info=True) return version = self._loop.run_until_complete(self._api.version()) _LOGGER.debug("Docker version: %s", version.get("Version", None)) # Start task to monitor events of create/delete/start/stop self._tasks["events"] = self._loop.create_task(self._run_docker_events()) # Start task to monitor total/running containers self._tasks["info"] = self._loop.create_task(self._run_docker_info()) # Get the list of containers to monitor containers = self._loop.run_until_complete(self._api.containers.list(all=True)) for container in containers or []: # Determine name from Docker API, it contains an array with a slash cname = container._container["Names"][0][1:] # We will monitor all containers, including excluded ones. # This is needed to get total CPU/Memory usage. _LOGGER.debug("%s: Container Monitored", cname) # Create our Docker Container API self._containers[cname] = DockerContainerAPI( self._api, cname, self._interval ) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self._monitor_stop) for component in COMPONENTS: load_platform( self._hass, component, DOMAIN, {CONF_NAME: self._config[CONF_NAME]}, self._config, )
def aclient(self): if self._aclient is None: self._aclient = aiodocker.Docker() return self._aclient
async def docker(): docker = aiodocker.Docker() try: yield docker finally: await docker.close()
async def docker_async_client(): client = aiodocker.Docker() try: yield client finally: await client.close()
def __init__(self, hass, config, startCount=0): """Initialize the Docker API.""" self._hass = hass self._config = config self._instance = config[CONF_NAME] self._containers = {} self._tasks = {} self._info = {} self._event_create = {} self._event_destroy = {} self._dockerStopped = False self._subscribers = [] _LOGGER.debug("[%s]: Helper version: %s", self._instance, VERSION) self._interval = config[CONF_SCAN_INTERVAL].seconds self._loop = asyncio.get_event_loop() try: # Try to fix unix:// to unix:/// (3 are required by aiodocker) url = self._config[CONF_URL] if (url is not None and url.find("unix://") == 0 and url.find("unix:///") == -1): url = url.replace("unix://", "unix:///") # When we reconnect with tcp, we should delay - docker is maybe not fully ready if startCount > 0 and url.find("unix:") != 0: time.sleep(5) # Do some debugging logging for TCP/TLS if url is not None: _LOGGER.debug("%s: Docker URL is '%s'", self._instance, url) # Check for TLS if it is not unix if url.find("tcp:") == 0 or url.find("http:") == 0: tlsverify = os.environ.get("DOCKER_TLS_VERIFY", None) certpath = os.environ.get("DOCKER_CERT_PATH", None) if tlsverify is None: _LOGGER.debug( "[%s]: Docker environment 'DOCKER_TLS_VERIFY' is NOT set", self._instance, ) else: _LOGGER.debug( "[%s]: Docker environment set 'DOCKER_TLS_VERIFY=%s'", self._instance, tlsverify, ) if certpath is None: _LOGGER.debug( "[%s]: Docker environment 'DOCKER_CERT_PATH' is NOT set", self._instance, ) else: _LOGGER.debug( "[%s]: Docker environment set 'DOCKER_CERT_PATH=%s'", self._instance, certpath, ) if self._config[CONF_CERTPATH]: _LOGGER.debug( "[%s]: Docker CertPath set '%s', setting environment variables DOCKER_TLS_VERIFY/DOCKER_CERT_PATH", self._instance, self._config[CONF_CERTPATH], ) os.environ["DOCKER_TLS_VERIFY"] = "1" os.environ["DOCKER_CERT_PATH"] = self._config[ CONF_CERTPATH] self._api = aiodocker.Docker(url=url) except Exception as err: _LOGGER.error( "[%s]: Can not connect to Docker API (%s)", self._instance, str(err), exc_info=True, ) return versionInfo = self._loop.run_until_complete(self._api.version()) version = versionInfo.get("Version", None) # Compare version with 19.03 when memory calculation has changed self._version1904 = None if version is not None: if tuple(map(int, (version.split(".")))) > tuple( map(int, ("19.03".split(".")))): self._version1904 = True else: self._version1904 = False _LOGGER.debug("[%s]: Docker version: %s (%s)", self._instance, version, self._version1904) # Start task to monitor events of create/delete/start/stop self._tasks["events"] = self._loop.create_task( self._run_docker_events()) # Start task to monitor total/running containers self._tasks["info"] = self._loop.create_task(self._run_docker_info()) # Get the list of containers to monitor containers = self._loop.run_until_complete( self._api.containers.list(all=True)) for container in containers or []: # Determine name from Docker API, it contains an array with a slash cname = container._container["Names"][0][1:] # We will monitor all containers, including excluded ones. # This is needed to get total CPU/Memory usage. _LOGGER.debug("[%s] %s: Container Monitored", self._instance, cname) # Create our Docker Container API self._containers[cname] = DockerContainerAPI( self._config, self._api, cname, version1904=self._version1904, ) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self._monitor_stop) for component in COMPONENTS: load_platform( self._hass, component, DOMAIN, {CONF_NAME: self._instance}, self._config, )