1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2025-12-24 12:29:08 +00:00
Files
supervisor/supervisor/resolution/checks/dns_server_failure.py
Mike Degatano f3e2ccce43 Create issue for detected DNS server problem (#3578)
* Create issue for detected DNS server problem

* Validate behavior on restart as well

* tls:// not supported, remove check

* Move DNS server checks into resolution checks

* Revert all changes to plugins.dns

* Run DNS server checks if affected

* Mock aiodns query during all checks tests
2022-04-21 10:55:49 +02:00

84 lines
2.6 KiB
Python

"""Helpers to check DNS servers for failure."""
import asyncio
from datetime import timedelta
from typing import Optional
from aiodns import DNSResolver
from aiodns.error import DNSError
from supervisor.jobs.const import JobCondition, JobExecutionLimit
from supervisor.jobs.decorator import Job
from ...const import CoreState
from ...coresys import CoreSys
from ..const import DNS_CHECK_HOST, ContextType, IssueType
from .base import CheckBase
def setup(coresys: CoreSys) -> CheckBase:
"""Check setup function."""
return CheckDNSServerFailures(coresys)
class CheckDNSServerFailures(CheckBase):
"""CheckDNSServerFailures class for check."""
@Job(
conditions=[JobCondition.INTERNET_SYSTEM],
limit=JobExecutionLimit.THROTTLE,
throttle_period=timedelta(hours=24),
)
async def run_check(self) -> None:
"""Run check if not affected by issue."""
dns_servers = self.dns_servers
results = await asyncio.gather(
*[self._check_server(server) for server in dns_servers],
return_exceptions=True,
)
for i in (r for r in range(len(results)) if isinstance(results[r], DNSError)):
self.sys_resolution.create_issue(
IssueType.DNS_SERVER_FAILED,
ContextType.DNS_SERVER,
reference=dns_servers[i],
)
self.sys_capture_exception(results[i])
@Job(conditions=[JobCondition.INTERNET_SYSTEM])
async def approve_check(self, reference: Optional[str] = None) -> bool:
"""Approve check if it is affected by issue."""
if reference not in self.dns_servers:
return False
try:
await self._check_server(reference)
except DNSError:
return True
return False
async def _check_server(self, server: str):
"""Check a DNS server and report issues."""
ip_addr = server[6:] if server.startswith("dns://") else server
resolver = DNSResolver(nameservers=[ip_addr])
await resolver.query(DNS_CHECK_HOST, "A")
@property
def dns_servers(self) -> list[str]:
"""All user and system provided dns servers."""
return self.sys_plugins.dns.servers + self.sys_plugins.dns.locals
@property
def issue(self) -> IssueType:
"""Return a IssueType enum."""
return IssueType.DNS_SERVER_FAILED
@property
def context(self) -> ContextType:
"""Return a ContextType enum."""
return ContextType.DNS_SERVER
@property
def states(self) -> list[CoreState]:
"""Return a list of valid states when this check can run."""
return [CoreState.RUNNING]