Handle no enabled ipv4 addresses in the network integration (#63416)

This commit is contained in:
J. Nick Koston 2022-01-04 19:22:28 -10:00 committed by GitHub
parent 224f960050
commit e6e200f3c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 0 deletions

View file

@ -2,8 +2,10 @@
from __future__ import annotations from __future__ import annotations
from ipaddress import IPv4Address, IPv6Address, ip_interface from ipaddress import IPv4Address, IPv6Address, ip_interface
import logging
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -12,6 +14,8 @@ from .const import IPV4_BROADCAST_ADDR, PUBLIC_TARGET_IP
from .models import Adapter from .models import Adapter
from .network import Network, async_get_network from .network import Network, async_get_network
_LOGGER = logging.getLogger(__name__)
@bind_hass @bind_hass
async def async_get_adapters(hass: HomeAssistant) -> list[Adapter]: async def async_get_adapters(hass: HomeAssistant) -> list[Adapter]:
@ -32,6 +36,16 @@ async def async_get_source_ip(
all_ipv4s.extend([ipv4["address"] for ipv4 in ipv4s]) all_ipv4s.extend([ipv4["address"] for ipv4 in ipv4s])
source_ip = util.async_get_source_ip(target_ip) source_ip = util.async_get_source_ip(target_ip)
if not all_ipv4s:
_LOGGER.warning(
"Because the system does not have any enabled IPv4 addresses, source address detection may be inaccurate"
)
if source_ip is None:
raise HomeAssistantError(
"Could not determine source ip because the system does not have any enabled IPv4 addresses and creating a socket failed"
)
return source_ip
return source_ip if source_ip in all_ipv4s else all_ipv4s[0] return source_ip if source_ip in all_ipv4s else all_ipv4s[0]

View file

@ -3,6 +3,7 @@ from ipaddress import IPv4Address
from unittest.mock import MagicMock, Mock, patch from unittest.mock import MagicMock, Mock, patch
import ifaddr import ifaddr
import pytest
from homeassistant.components import network from homeassistant.components import network
from homeassistant.components.network.const import ( from homeassistant.components.network.const import (
@ -13,6 +14,7 @@ from homeassistant.components.network.const import (
STORAGE_KEY, STORAGE_KEY,
STORAGE_VERSION, STORAGE_VERSION,
) )
from homeassistant.exceptions import HomeAssistantError
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
_NO_LOOPBACK_IPADDR = "192.168.1.5" _NO_LOOPBACK_IPADDR = "192.168.1.5"
@ -602,3 +604,49 @@ async def test_async_get_ipv4_broadcast_addresses_multiple(hass, hass_storage):
IPv4Address("192.168.1.255"), IPv4Address("192.168.1.255"),
IPv4Address("169.254.255.255"), IPv4Address("169.254.255.255"),
} }
async def test_async_get_source_ip_no_enabled_addresses(hass, hass_storage, caplog):
"""Test getting the source ip address when all adapters are disabled."""
hass_storage[STORAGE_KEY] = {
"version": STORAGE_VERSION,
"key": STORAGE_KEY,
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
}
with patch(
"homeassistant.components.network.util.ifaddr.get_adapters",
return_value=[],
), patch(
"homeassistant.components.network.util.socket.socket",
return_value=_mock_socket(["192.168.1.5"]),
):
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
await hass.async_block_till_done()
assert await network.async_get_source_ip(hass, MDNS_TARGET_IP) == "192.168.1.5"
assert "source address detection may be inaccurate" in caplog.text
async def test_async_get_source_ip_cannot_be_determined_and_no_enabled_addresses(
hass, hass_storage, caplog
):
"""Test getting the source ip address when all adapters are disabled and getting it fails."""
hass_storage[STORAGE_KEY] = {
"version": STORAGE_VERSION,
"key": STORAGE_KEY,
"data": {ATTR_CONFIGURED_ADAPTERS: ["eth1"]},
}
with patch(
"homeassistant.components.network.util.ifaddr.get_adapters",
return_value=[],
), patch(
"homeassistant.components.network.util.socket.socket",
return_value=_mock_socket([None]),
):
assert not await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
await hass.async_block_till_done()
with pytest.raises(HomeAssistantError):
await network.async_get_source_ip(hass, MDNS_TARGET_IP)