Exemplo n.º 1
0
# 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
        }
Exemplo n.º 2
0
 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')
Exemplo n.º 3
0
 def __init__(self, username=None, password=None):
     self._auth = AsyncDocker.create_auth(username,
                                          password) if username else None
     self.client = aiodocker.Docker()
Exemplo n.º 4
0
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()
Exemplo n.º 5
0
    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,
            )
Exemplo n.º 6
0
    def aclient(self):
        if self._aclient is None:
            self._aclient = aiodocker.Docker()

        return self._aclient
Exemplo n.º 7
0
async def docker():
    docker = aiodocker.Docker()
    try:
        yield docker
    finally:
        await docker.close()
Exemplo n.º 8
0
async def docker_async_client():
    client = aiodocker.Docker()
    try:
        yield client
    finally:
        await client.close()
Exemplo n.º 9
0
    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,
            )