Change handling with host files (#1223)

This commit is contained in:
Pascal Vizeli 2019-08-16 12:47:32 +02:00 committed by GitHub
parent 734fe3afde
commit a2cf7ece70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 37 deletions

View File

@ -10,6 +10,7 @@ from ..coresys import CoreSys, CoreSysAttributes
from ..exceptions import (
AddonsError,
AddonsNotSupportedError,
CoreDNSError,
DockerAPIError,
HomeAssistantAPIError,
HostAppArmorError,
@ -74,6 +75,9 @@ class AddonManager(CoreSysAttributes):
if tasks:
await asyncio.wait(tasks)
# Sync DNS
await self.sync_dns()
async def boot(self, stage: str) -> None:
"""Boot add-ons with mode auto."""
tasks = []
@ -299,3 +303,17 @@ class AddonManager(CoreSysAttributes):
_LOGGER.error("Can't repair %s", addon.slug)
with suppress(AddonsError):
await self.uninstall(addon.slug)
async def sync_dns(self) -> None:
"""Sync add-ons DNS names."""
# Update hosts
for addon in self.installed:
if not await addon.is_running():
continue
self.sys_dns.add_host(
ipv4=addon.ip_address, names=[addon.hostname], write=False
)
# Write hosts files
with suppress(CoreDNSError):
self.sys_dns.write_hosts()

View File

@ -1,7 +1,7 @@
"""Init file for Hass.io add-ons."""
from contextlib import suppress
from copy import deepcopy
from ipaddress import IPv4Address, ip_address
from ipaddress import IPv4Address
import logging
from pathlib import Path, PurePath
import re
@ -81,8 +81,6 @@ class Addon(AddonModel):
@property
def ip_address(self) -> IPv4Address:
"""Return IP of Add-on instance."""
if not self.is_installed:
return ip_address("0.0.0.0")
return self.instance.ip_address
@property

View File

@ -2,7 +2,7 @@
import asyncio
import logging
from contextlib import suppress
from ipaddress import IPv4Address, AddressValueError
from ipaddress import IPv4Address
from pathlib import Path
from string import Template
from typing import Awaitable, Dict, List, Optional
@ -81,8 +81,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
async def load(self) -> None:
"""Load DNS setup."""
with suppress(CoreDNSError):
self._import_hosts()
self._init_hosts()
# Check CoreDNS state
try:
@ -181,13 +180,15 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.error("Can't start CoreDNS plugin")
raise CoreDNSError() from None
def reset(self) -> None:
async def reset(self) -> None:
"""Reset Config / Hosts."""
self.servers = DNS_SERVERS
with suppress(OSError):
self.hosts.unlink()
self._import_hosts()
self._init_hosts()
await self.sys_addons.sync_dns()
def _write_corefile(self) -> None:
"""Write CoreDNS config."""
@ -207,43 +208,34 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.error("Can't update corefile: %s", err)
raise CoreDNSError() from None
def _import_hosts(self) -> None:
def _init_hosts(self) -> None:
"""Import hosts entry."""
# Generate Default
if not self.hosts.exists():
self.add_host(self.sys_docker.network.supervisor, ["hassio", "supervisor"])
self.add_host(
self.sys_docker.network.gateway, ["homeassistant", "home-assistant"]
)
return
self.add_host(
self.sys_docker.network.supervisor, ["hassio", "supervisor"], write=False
)
self.add_host(
self.sys_docker.network.gateway,
["homeassistant", "home-assistant"],
write=False,
)
# Import Exists host table
try:
with self.hosts.open("r") as hosts:
for line in hosts.readlines():
try:
data = line.split(" ")
self._hosts[IPv4Address(data[0])] = data[1:]
except AddressValueError:
_LOGGER.warning("Fails to read %s", line)
except OSError as err:
_LOGGER.error("Can't read hosts file: %s", err)
raise CoreDNSError() from None
def _write_hosts(self) -> None:
def write_hosts(self) -> None:
"""Write hosts from memory to file."""
try:
with self.hosts.open("w") as hosts:
for address, hostnames in self._hosts.items():
host = " ".join(hostnames)
hosts.write(f"{address!s} {host}")
hosts.write(f"{address!s} {host}\n")
except OSError as err:
_LOGGER.error("Can't write hosts file: %s", err)
raise CoreDNSError() from None
def add_host(self, ipv4: IPv4Address, names: List[str]) -> None:
def add_host(self, ipv4: IPv4Address, names: List[str], write: bool = True) -> None:
"""Add a new host entry."""
if not ipv4 or ipv4 == IPv4Address("0.0.0.0"):
return
hostnames: List[str] = []
for name in names:
hostnames.append(name)
@ -252,10 +244,14 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
self._hosts[ipv4] = hostnames
_LOGGER.debug("Add Host entry %s -> %s", ipv4, hostnames)
self._write_hosts()
if write:
self.write_hosts()
def delete_host(
self, ipv4: Optional[IPv4Address] = None, host: Optional[str] = None
self,
ipv4: Optional[IPv4Address] = None,
host: Optional[str] = None,
write: bool = True,
) -> None:
"""Remove a entry from hosts."""
if host:
@ -270,7 +266,8 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
_LOGGER.debug("Remove Host entry %s", ipv4)
self._hosts.pop(ipv4, None)
self._write_hosts()
if write:
self.write_hosts()
else:
_LOGGER.warning("Can't remove Host entry: %s/%s", ipv4, host)
@ -336,7 +333,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
try:
with RESOLV_CONF.open("w") as resolv:
for line in resolv_lines:
resolv.write(line)
resolv.write(f"{line}\n")
except OSError as err:
_LOGGER.error("Can't write local resolv: %s", err)
raise CoreDNSError() from None

View File

@ -228,7 +228,7 @@ class Tasks(CoreSysAttributes):
if await self.sys_dns.is_fails():
_LOGGER.warning("CoreDNS plugin is in fails state / Reset config")
self.sys_dns.reset()
await self.sys_dns.reset()
try:
await self.sys_dns.start()