mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Make DHCP discovery aware of the network integration (#144767)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@ -7,6 +7,7 @@ from collections.abc import Callable
|
||||
from datetime import timedelta
|
||||
from fnmatch import translate
|
||||
from functools import lru_cache, partial
|
||||
from ipaddress import IPv4Address
|
||||
import itertools
|
||||
import logging
|
||||
import re
|
||||
@ -22,6 +23,7 @@ from aiodiscover.discovery import (
|
||||
from cached_ipaddress import cached_ip_addresses
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import network
|
||||
from homeassistant.components.device_tracker import (
|
||||
ATTR_HOST_NAME,
|
||||
ATTR_IP,
|
||||
@ -421,9 +423,33 @@ class DHCPWatcher(WatcherBase):
|
||||
response.ip_address, response.hostname, response.mac_address
|
||||
)
|
||||
|
||||
async def async_get_adapter_indexes(self) -> list[int] | None:
|
||||
"""Get the adapter indexes."""
|
||||
adapters = await network.async_get_adapters(self.hass)
|
||||
if network.async_only_default_interface_enabled(adapters):
|
||||
return None
|
||||
return [
|
||||
adapter["index"]
|
||||
for adapter in adapters
|
||||
if (
|
||||
adapter["enabled"]
|
||||
and adapter["index"] is not None
|
||||
and adapter["ipv4"]
|
||||
and (
|
||||
addresses := [IPv4Address(ip["address"]) for ip in adapter["ipv4"]]
|
||||
)
|
||||
and any(
|
||||
ip for ip in addresses if not ip.is_loopback and not ip.is_global
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
async def async_start(self) -> None:
|
||||
"""Start watching for dhcp packets."""
|
||||
self._unsub = await aiodhcpwatcher.async_start(self._async_process_dhcp_request)
|
||||
self._unsub = await aiodhcpwatcher.async_start(
|
||||
self._async_process_dhcp_request,
|
||||
await self.async_get_adapter_indexes(),
|
||||
)
|
||||
|
||||
|
||||
class RediscoveryWatcher(WatcherBase):
|
||||
|
@ -2,6 +2,7 @@
|
||||
"domain": "dhcp",
|
||||
"name": "DHCP Discovery",
|
||||
"codeowners": ["@bdraco"],
|
||||
"dependencies": ["network"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/dhcp",
|
||||
"integration_type": "system",
|
||||
"iot_class": "local_push",
|
||||
|
@ -157,6 +157,7 @@ async def _async_get_handle_dhcp_packet(
|
||||
hass,
|
||||
DHCPData(integration_matchers, set(), address_data),
|
||||
)
|
||||
|
||||
with patch("aiodhcpwatcher.async_start"):
|
||||
await dhcp_watcher.async_start()
|
||||
|
||||
@ -171,6 +172,53 @@ async def _async_get_handle_dhcp_packet(
|
||||
return cast("Callable[[Any], Awaitable[None]]", _async_handle_dhcp_packet)
|
||||
|
||||
|
||||
async def test_dhcp_start_using_multiple_interfaces(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test start using multiple interfaces."""
|
||||
|
||||
def _generate_mock_adapters():
|
||||
return [
|
||||
{
|
||||
"index": 1,
|
||||
"auto": False,
|
||||
"default": False,
|
||||
"enabled": True,
|
||||
"ipv4": [{"address": "192.168.0.1", "network_prefix": 24}],
|
||||
"ipv6": [],
|
||||
"name": "eth0",
|
||||
},
|
||||
{
|
||||
"index": 2,
|
||||
"auto": True,
|
||||
"default": True,
|
||||
"enabled": True,
|
||||
"ipv4": [{"address": "192.168.1.1", "network_prefix": 24}],
|
||||
"ipv6": [],
|
||||
"name": "eth1",
|
||||
},
|
||||
]
|
||||
|
||||
integration_matchers = dhcp.async_index_integration_matchers(
|
||||
[{"domain": "mock-domain", "hostname": "connect", "macaddress": "B8B7F1*"}]
|
||||
)
|
||||
dhcp_watcher = dhcp.DHCPWatcher(
|
||||
hass,
|
||||
DHCPData(integration_matchers, set(), {}),
|
||||
)
|
||||
|
||||
with (
|
||||
patch("aiodhcpwatcher.async_start") as mock_start,
|
||||
patch(
|
||||
"homeassistant.components.dhcp.network.async_get_adapters",
|
||||
return_value=_generate_mock_adapters(),
|
||||
),
|
||||
):
|
||||
await dhcp_watcher.async_start()
|
||||
|
||||
mock_start.assert_called_with(dhcp_watcher._async_process_dhcp_request, [1, 2])
|
||||
|
||||
|
||||
async def test_dhcp_match_hostname_and_macaddress(hass: HomeAssistant) -> None:
|
||||
"""Test matching based on hostname and macaddress."""
|
||||
integration_matchers = dhcp.async_index_integration_matchers(
|
||||
|
@ -22,6 +22,7 @@ async def test_subscribe_discovery(
|
||||
|
||||
async def mock_start(
|
||||
callback: Callable[[aiodhcpwatcher.DHCPRequest], None],
|
||||
if_indexes: list[int] | None = None,
|
||||
) -> None:
|
||||
"""Mock start."""
|
||||
nonlocal saved_callback
|
||||
|
@ -655,5 +655,5 @@ async def test_discovery_requirements_dhcp(hass: HomeAssistant) -> None:
|
||||
) as mock_process:
|
||||
await async_get_integration_with_requirements(hass, "comp")
|
||||
|
||||
assert len(mock_process.mock_calls) == 1 # dhcp does not depend on http
|
||||
assert len(mock_process.mock_calls) == 2 # dhcp does not depend on http
|
||||
assert mock_process.mock_calls[0][1][1] == dhcp.requirements
|
||||
|
Reference in New Issue
Block a user