Add Docker info & check (#1736)

* Add Docker info & check

* Add checks

* Fix logging

* fix lint
This commit is contained in:
Pascal Vizeli 2020-05-21 12:06:27 +02:00 committed by GitHub
parent c7b6b2ddb3
commit 8e043a01c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 2 deletions

1
API.md
View File

@ -789,6 +789,7 @@ return:
"supervisor": "version", "supervisor": "version",
"homeassistant": "version", "homeassistant": "version",
"hassos": "null|version", "hassos": "null|version",
"docker": "version",
"hostname": "name", "hostname": "name",
"machine": "type", "machine": "type",
"arch": "arch", "arch": "arch",

View File

@ -7,6 +7,7 @@ from aiohttp import web
from ..const import ( from ..const import (
ATTR_ARCH, ATTR_ARCH,
ATTR_CHANNEL, ATTR_CHANNEL,
ATTR_DOCKER,
ATTR_HASSOS, ATTR_HASSOS,
ATTR_HOMEASSISTANT, ATTR_HOMEASSISTANT,
ATTR_HOSTNAME, ATTR_HOSTNAME,
@ -32,6 +33,7 @@ class APIInfo(CoreSysAttributes):
ATTR_SUPERVISOR: self.sys_supervisor.version, ATTR_SUPERVISOR: self.sys_supervisor.version,
ATTR_HOMEASSISTANT: self.sys_homeassistant.version, ATTR_HOMEASSISTANT: self.sys_homeassistant.version,
ATTR_HASSOS: self.sys_hassos.version, ATTR_HASSOS: self.sys_hassos.version,
ATTR_DOCKER: self.sys_docker.info.version,
ATTR_HOSTNAME: self.sys_host.info.hostname, ATTR_HOSTNAME: self.sys_host.info.hostname,
ATTR_MACHINE: self.sys_machine, ATTR_MACHINE: self.sys_machine,
ATTR_ARCH: self.sys_arch.default, ATTR_ARCH: self.sys_arch.default,

View File

@ -76,6 +76,7 @@ ENV_SUPERVISOR_MACHINE = "SUPERVISOR_MACHINE"
REQUEST_FROM = "HASSIO_FROM" REQUEST_FROM = "HASSIO_FROM"
ATTR_DOCKER = "docker"
ATTR_SUPERVISOR = "supervisor" ATTR_SUPERVISOR = "supervisor"
ATTR_MACHINE = "machine" ATTR_MACHINE = "machine"
ATTR_MULTICAST = "multicast" ATTR_MULTICAST = "multicast"

View File

@ -31,16 +31,29 @@ class Core(CoreSysAttributes):
"""Connect Supervisor container.""" """Connect Supervisor container."""
await self.sys_supervisor.load() await self.sys_supervisor.load()
# Check if system is healthy # If a update is failed?
if self.sys_dev: if self.sys_dev:
self.sys_config.version = self.sys_supervisor.version self.sys_config.version = self.sys_supervisor.version
elif ( elif (
self.sys_config.version self.sys_config.version
and self.sys_config.version != self.sys_supervisor.version and self.sys_config.version != self.sys_supervisor.version
): ):
self.healthy = False
_LOGGER.critical("Update of Supervisor fails!")
# If local docker is supported?
if not self.sys_docker.info.supported_version:
self.healthy = False self.healthy = False
_LOGGER.critical( _LOGGER.critical(
"System running in a unhealthy state. Please update you OS!" "Docker version %s is not supported by Supervisor!",
self.sys_docker.info.version,
)
self.sys_docker.info.check_requirements()
# Check if system is healthy
if not self.healthy:
_LOGGER.critical(
"System running in a unhealthy state. Please update you OS or software!"
) )
async def setup(self): async def setup(self):

View File

@ -6,6 +6,7 @@ from typing import Any, Dict, Optional
import attr import attr
import docker import docker
from packaging import version as pkg_version
from ..const import SOCKET_DOCKER, DNS_SUFFIX from ..const import SOCKET_DOCKER, DNS_SUFFIX
from ..exceptions import DockerAPIError from ..exceptions import DockerAPIError
@ -13,6 +14,8 @@ from .network import DockerNetwork
_LOGGER: logging.Logger = logging.getLogger(__name__) _LOGGER: logging.Logger = logging.getLogger(__name__)
MIN_SUPPORTED_DOCKER = "19.03.0"
@attr.s(frozen=True) @attr.s(frozen=True)
class CommandReturn: class CommandReturn:
@ -22,6 +25,36 @@ class CommandReturn:
output: bytes = attr.ib() output: bytes = attr.ib()
@attr.s(frozen=True)
class DockerInfo:
"""Return docker information."""
version: str = attr.ib()
storage: str = attr.ib()
logging: str = attr.ib()
@staticmethod
def new(data: Dict[str, Any]):
"""Create a object from docker info."""
return DockerInfo(data["ServerVersion"], data["Driver"], data["LoggingDriver"])
@property
def supported_version(self) -> bool:
"""Return true, if docker version is supported."""
version_local = pkg_version.parse(self.version)
version_min = pkg_version.parse(MIN_SUPPORTED_DOCKER)
return version_local >= version_min
def check_requirements(self) -> None:
"""Show wrong configurations."""
if self.storage != "overlay2":
_LOGGER.error("Docker storage driver %s is not supported!", self.storage)
if self.logging != "journald":
_LOGGER.error("Docker logging driver %s is not supported!", self.logging)
class DockerAPI: class DockerAPI:
"""Docker Supervisor wrapper. """Docker Supervisor wrapper.
@ -34,6 +67,7 @@ class DockerAPI:
base_url="unix:/{}".format(str(SOCKET_DOCKER)), version="auto", timeout=900 base_url="unix:/{}".format(str(SOCKET_DOCKER)), version="auto", timeout=900
) )
self.network: DockerNetwork = DockerNetwork(self.docker) self.network: DockerNetwork = DockerNetwork(self.docker)
self._info: DockerInfo = DockerInfo.new(self.docker.info())
@property @property
def images(self) -> docker.models.images.ImageCollection: def images(self) -> docker.models.images.ImageCollection:
@ -50,6 +84,11 @@ class DockerAPI:
"""Return API containers.""" """Return API containers."""
return self.docker.api return self.docker.api
@property
def info(self) -> DockerInfo:
"""Return local docker info."""
return self._info
def run( def run(
self, self,
image: str, image: str,