supervisor/hassio/docker/network.py
Pascal Vizeli c0e3ccdb83
Improve gdbus error handling (#1252)
* Improve gdbus error handling

* Fix logging type

* Detect no dbus

* Fix issue with complex

* Update hassio/dbus/__init__.py

Co-Authored-By: Franck Nijhof <frenck@frenck.nl>

* Update hassio/dbus/hostname.py

Co-Authored-By: Franck Nijhof <frenck@frenck.nl>

* Update hassio/dbus/rauc.py

Co-Authored-By: Franck Nijhof <frenck@frenck.nl>

* Update hassio/dbus/systemd.py

Co-Authored-By: Franck Nijhof <frenck@frenck.nl>

* Fix black
2019-08-22 12:48:02 +02:00

110 lines
3.2 KiB
Python

"""Internal network manager for Hass.io."""
from ipaddress import IPv4Address
import logging
from typing import List, Optional
import docker
from ..const import DOCKER_NETWORK, DOCKER_NETWORK_MASK, DOCKER_NETWORK_RANGE
from ..exceptions import DockerAPIError
_LOGGER: logging.Logger = logging.getLogger(__name__)
class DockerNetwork:
"""Internal Hass.io Network.
This class is not AsyncIO safe!
"""
def __init__(self, docker_client: docker.DockerClient):
"""Initialize internal Hass.io network."""
self.docker: docker.DockerClient = docker_client
self.network: docker.models.networks.Network = self._get_network()
@property
def name(self) -> str:
"""Return name of network."""
return DOCKER_NETWORK
@property
def containers(self) -> List[docker.models.containers.Container]:
"""Return of connected containers from network."""
return self.network.containers
@property
def gateway(self) -> IPv4Address:
"""Return gateway of the network."""
return DOCKER_NETWORK_MASK[1]
@property
def supervisor(self) -> IPv4Address:
"""Return supervisor of the network."""
return DOCKER_NETWORK_MASK[2]
@property
def dns(self) -> IPv4Address:
"""Return dns of the network."""
return DOCKER_NETWORK_MASK[3]
def _get_network(self) -> docker.models.networks.Network:
"""Get HassIO network."""
try:
return self.docker.networks.get(DOCKER_NETWORK)
except docker.errors.NotFound:
_LOGGER.info("Can't find Hass.io network, create new network")
ipam_pool = docker.types.IPAMPool(
subnet=str(DOCKER_NETWORK_MASK),
gateway=str(self.gateway),
iprange=str(DOCKER_NETWORK_RANGE),
)
ipam_config = docker.types.IPAMConfig(pool_configs=[ipam_pool])
return self.docker.networks.create(
DOCKER_NETWORK,
driver="bridge",
ipam=ipam_config,
enable_ipv6=False,
options={"com.docker.network.bridge.name": DOCKER_NETWORK},
)
def attach_container(
self,
container: docker.models.containers.Container,
alias: Optional[List[str]] = None,
ipv4: Optional[IPv4Address] = None,
) -> None:
"""Attach container to Hass.io network.
Need run inside executor.
"""
ipv4 = str(ipv4) if ipv4 else None
try:
self.network.connect(container, aliases=alias, ipv4_address=ipv4)
except docker.errors.APIError as err:
_LOGGER.error("Can't link container to hassio-net: %s", err)
raise DockerAPIError() from None
self.network.reload()
def detach_default_bridge(
self, container: docker.models.containers.Container
) -> None:
"""Detach default Docker bridge.
Need run inside executor.
"""
try:
default_network = self.docker.networks.get("bridge")
default_network.disconnect(container)
except docker.errors.NotFound:
return
except docker.errors.APIError as err:
_LOGGER.warning("Can't disconnect container from default: %s", err)
raise DockerAPIError() from None