mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-06-25 03:16:30 +00:00
Change handling with host files (#1223)
This commit is contained in:
parent
734fe3afde
commit
a2cf7ece70
@ -10,6 +10,7 @@ from ..coresys import CoreSys, CoreSysAttributes
|
|||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
AddonsError,
|
AddonsError,
|
||||||
AddonsNotSupportedError,
|
AddonsNotSupportedError,
|
||||||
|
CoreDNSError,
|
||||||
DockerAPIError,
|
DockerAPIError,
|
||||||
HomeAssistantAPIError,
|
HomeAssistantAPIError,
|
||||||
HostAppArmorError,
|
HostAppArmorError,
|
||||||
@ -74,6 +75,9 @@ class AddonManager(CoreSysAttributes):
|
|||||||
if tasks:
|
if tasks:
|
||||||
await asyncio.wait(tasks)
|
await asyncio.wait(tasks)
|
||||||
|
|
||||||
|
# Sync DNS
|
||||||
|
await self.sync_dns()
|
||||||
|
|
||||||
async def boot(self, stage: str) -> None:
|
async def boot(self, stage: str) -> None:
|
||||||
"""Boot add-ons with mode auto."""
|
"""Boot add-ons with mode auto."""
|
||||||
tasks = []
|
tasks = []
|
||||||
@ -299,3 +303,17 @@ class AddonManager(CoreSysAttributes):
|
|||||||
_LOGGER.error("Can't repair %s", addon.slug)
|
_LOGGER.error("Can't repair %s", addon.slug)
|
||||||
with suppress(AddonsError):
|
with suppress(AddonsError):
|
||||||
await self.uninstall(addon.slug)
|
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()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Init file for Hass.io add-ons."""
|
"""Init file for Hass.io add-ons."""
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from ipaddress import IPv4Address, ip_address
|
from ipaddress import IPv4Address
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path, PurePath
|
from pathlib import Path, PurePath
|
||||||
import re
|
import re
|
||||||
@ -81,8 +81,6 @@ class Addon(AddonModel):
|
|||||||
@property
|
@property
|
||||||
def ip_address(self) -> IPv4Address:
|
def ip_address(self) -> IPv4Address:
|
||||||
"""Return IP of Add-on instance."""
|
"""Return IP of Add-on instance."""
|
||||||
if not self.is_installed:
|
|
||||||
return ip_address("0.0.0.0")
|
|
||||||
return self.instance.ip_address
|
return self.instance.ip_address
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from ipaddress import IPv4Address, AddressValueError
|
from ipaddress import IPv4Address
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from string import Template
|
from string import Template
|
||||||
from typing import Awaitable, Dict, List, Optional
|
from typing import Awaitable, Dict, List, Optional
|
||||||
@ -81,8 +81,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
|
|
||||||
async def load(self) -> None:
|
async def load(self) -> None:
|
||||||
"""Load DNS setup."""
|
"""Load DNS setup."""
|
||||||
with suppress(CoreDNSError):
|
self._init_hosts()
|
||||||
self._import_hosts()
|
|
||||||
|
|
||||||
# Check CoreDNS state
|
# Check CoreDNS state
|
||||||
try:
|
try:
|
||||||
@ -181,13 +180,15 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.error("Can't start CoreDNS plugin")
|
_LOGGER.error("Can't start CoreDNS plugin")
|
||||||
raise CoreDNSError() from None
|
raise CoreDNSError() from None
|
||||||
|
|
||||||
def reset(self) -> None:
|
async def reset(self) -> None:
|
||||||
"""Reset Config / Hosts."""
|
"""Reset Config / Hosts."""
|
||||||
self.servers = DNS_SERVERS
|
self.servers = DNS_SERVERS
|
||||||
|
|
||||||
with suppress(OSError):
|
with suppress(OSError):
|
||||||
self.hosts.unlink()
|
self.hosts.unlink()
|
||||||
self._import_hosts()
|
self._init_hosts()
|
||||||
|
|
||||||
|
await self.sys_addons.sync_dns()
|
||||||
|
|
||||||
def _write_corefile(self) -> None:
|
def _write_corefile(self) -> None:
|
||||||
"""Write CoreDNS config."""
|
"""Write CoreDNS config."""
|
||||||
@ -207,43 +208,34 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.error("Can't update corefile: %s", err)
|
_LOGGER.error("Can't update corefile: %s", err)
|
||||||
raise CoreDNSError() from None
|
raise CoreDNSError() from None
|
||||||
|
|
||||||
def _import_hosts(self) -> None:
|
def _init_hosts(self) -> None:
|
||||||
"""Import hosts entry."""
|
"""Import hosts entry."""
|
||||||
# Generate Default
|
# Generate Default
|
||||||
if not self.hosts.exists():
|
self.add_host(
|
||||||
self.add_host(self.sys_docker.network.supervisor, ["hassio", "supervisor"])
|
self.sys_docker.network.supervisor, ["hassio", "supervisor"], write=False
|
||||||
self.add_host(
|
)
|
||||||
self.sys_docker.network.gateway, ["homeassistant", "home-assistant"]
|
self.add_host(
|
||||||
)
|
self.sys_docker.network.gateway,
|
||||||
return
|
["homeassistant", "home-assistant"],
|
||||||
|
write=False,
|
||||||
|
)
|
||||||
|
|
||||||
# Import Exists host table
|
def write_hosts(self) -> None:
|
||||||
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:
|
|
||||||
"""Write hosts from memory to file."""
|
"""Write hosts from memory to file."""
|
||||||
try:
|
try:
|
||||||
with self.hosts.open("w") as hosts:
|
with self.hosts.open("w") as hosts:
|
||||||
for address, hostnames in self._hosts.items():
|
for address, hostnames in self._hosts.items():
|
||||||
host = " ".join(hostnames)
|
host = " ".join(hostnames)
|
||||||
hosts.write(f"{address!s} {host}")
|
hosts.write(f"{address!s} {host}\n")
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
_LOGGER.error("Can't write hosts file: %s", err)
|
_LOGGER.error("Can't write hosts file: %s", err)
|
||||||
raise CoreDNSError() from None
|
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."""
|
"""Add a new host entry."""
|
||||||
|
if not ipv4 or ipv4 == IPv4Address("0.0.0.0"):
|
||||||
|
return
|
||||||
|
|
||||||
hostnames: List[str] = []
|
hostnames: List[str] = []
|
||||||
for name in names:
|
for name in names:
|
||||||
hostnames.append(name)
|
hostnames.append(name)
|
||||||
@ -252,10 +244,14 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
self._hosts[ipv4] = hostnames
|
self._hosts[ipv4] = hostnames
|
||||||
_LOGGER.debug("Add Host entry %s -> %s", ipv4, hostnames)
|
_LOGGER.debug("Add Host entry %s -> %s", ipv4, hostnames)
|
||||||
|
|
||||||
self._write_hosts()
|
if write:
|
||||||
|
self.write_hosts()
|
||||||
|
|
||||||
def delete_host(
|
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:
|
) -> None:
|
||||||
"""Remove a entry from hosts."""
|
"""Remove a entry from hosts."""
|
||||||
if host:
|
if host:
|
||||||
@ -270,7 +266,8 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
_LOGGER.debug("Remove Host entry %s", ipv4)
|
_LOGGER.debug("Remove Host entry %s", ipv4)
|
||||||
self._hosts.pop(ipv4, None)
|
self._hosts.pop(ipv4, None)
|
||||||
|
|
||||||
self._write_hosts()
|
if write:
|
||||||
|
self.write_hosts()
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("Can't remove Host entry: %s/%s", ipv4, host)
|
_LOGGER.warning("Can't remove Host entry: %s/%s", ipv4, host)
|
||||||
|
|
||||||
@ -336,7 +333,7 @@ class CoreDNS(JsonConfig, CoreSysAttributes):
|
|||||||
try:
|
try:
|
||||||
with RESOLV_CONF.open("w") as resolv:
|
with RESOLV_CONF.open("w") as resolv:
|
||||||
for line in resolv_lines:
|
for line in resolv_lines:
|
||||||
resolv.write(line)
|
resolv.write(f"{line}\n")
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
_LOGGER.error("Can't write local resolv: %s", err)
|
_LOGGER.error("Can't write local resolv: %s", err)
|
||||||
raise CoreDNSError() from None
|
raise CoreDNSError() from None
|
||||||
|
@ -228,7 +228,7 @@ class Tasks(CoreSysAttributes):
|
|||||||
|
|
||||||
if await self.sys_dns.is_fails():
|
if await self.sys_dns.is_fails():
|
||||||
_LOGGER.warning("CoreDNS plugin is in fails state / Reset config")
|
_LOGGER.warning("CoreDNS plugin is in fails state / Reset config")
|
||||||
self.sys_dns.reset()
|
await self.sys_dns.reset()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.sys_dns.start()
|
await self.sys_dns.start()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user