Provide workaround for missing/disabled/broken IPv6 (#37887)

pull/37888/head
J. Nick Koston 2020-07-15 08:26:40 -10:00 committed by GitHub
parent 53d6f4948e
commit abe3e3094e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 7 deletions

View File

@ -9,6 +9,7 @@ from zeroconf import (
DNSPointer,
DNSRecord,
InterfaceChoice,
IPVersion,
NonUniqueNameException,
ServiceBrowser,
ServiceInfo,
@ -42,7 +43,9 @@ ZEROCONF_TYPE = "_home-assistant._tcp.local."
HOMEKIT_TYPE = "_hap._tcp.local."
CONF_DEFAULT_INTERFACE = "default_interface"
CONF_IPV6 = "ipv6"
DEFAULT_DEFAULT_INTERFACE = False
DEFAULT_IPV6 = True
HOMEKIT_PROPERTIES = "properties"
HOMEKIT_PAIRED_STATUS_FLAG = "sf"
@ -54,7 +57,8 @@ CONFIG_SCHEMA = vol.Schema(
{
vol.Optional(
CONF_DEFAULT_INTERFACE, default=DEFAULT_DEFAULT_INTERFACE
): cv.boolean
): cv.boolean,
vol.Optional(CONF_IPV6, default=DEFAULT_IPV6): cv.boolean,
}
)
},
@ -68,11 +72,17 @@ async def async_get_instance(hass):
return await hass.async_add_executor_job(_get_instance, hass)
def _get_instance(hass, default_interface=False):
def _get_instance(hass, default_interface=False, ipv6=True):
"""Create an instance."""
logging.getLogger("zeroconf").setLevel(logging.NOTSET)
args = [InterfaceChoice.Default] if default_interface else []
zeroconf = HaZeroconf(*args)
zc_args = {}
if default_interface:
zc_args["interfaces"] = InterfaceChoice.Default
if not ipv6:
zc_args["ip_version"] = IPVersion.V4Only
zeroconf = HaZeroconf(**zc_args)
def stop_zeroconf(_):
"""Stop Zeroconf."""
@ -115,8 +125,13 @@ class HaZeroconf(Zeroconf):
def setup(hass, config):
"""Set up Zeroconf and make Home Assistant discoverable."""
zc_config = config.get(DOMAIN, {})
zeroconf = hass.data[DOMAIN] = _get_instance(
hass, config.get(DOMAIN, {}).get(CONF_DEFAULT_INTERFACE)
hass,
default_interface=zc_config.get(
CONF_DEFAULT_INTERFACE, DEFAULT_DEFAULT_INTERFACE
),
ipv6=zc_config.get(CONF_IPV6, DEFAULT_IPV6),
)
# Get instance UUID

View File

@ -1,9 +1,9 @@
"""Test Zeroconf component setup process."""
import pytest
from zeroconf import InterfaceChoice, ServiceInfo, ServiceStateChange
from zeroconf import InterfaceChoice, IPVersion, ServiceInfo, ServiceStateChange
from homeassistant.components import zeroconf
from homeassistant.components.zeroconf import CONF_DEFAULT_INTERFACE
from homeassistant.components.zeroconf import CONF_DEFAULT_INTERFACE, CONF_IPV6
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.generated import zeroconf as zc_gen
from homeassistant.setup import async_setup_component
@ -114,6 +114,43 @@ async def test_setup_without_default_interface(hass, mock_zeroconf):
assert mock_zeroconf.called_with()
async def test_setup_without_ipv6(hass, mock_zeroconf):
"""Test without ipv6."""
with patch.object(hass.config_entries.flow, "async_init"), patch.object(
zeroconf, "HaServiceBrowser", side_effect=service_update_mock
):
mock_zeroconf.get_service_info.side_effect = get_service_info_mock
assert await async_setup_component(
hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {CONF_IPV6: False}}
)
assert mock_zeroconf.called_with(ip_version=IPVersion.V4Only)
async def test_setup_with_ipv6(hass, mock_zeroconf):
"""Test without ipv6."""
with patch.object(hass.config_entries.flow, "async_init"), patch.object(
zeroconf, "HaServiceBrowser", side_effect=service_update_mock
):
mock_zeroconf.get_service_info.side_effect = get_service_info_mock
assert await async_setup_component(
hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {CONF_IPV6: True}}
)
assert mock_zeroconf.called_with()
async def test_setup_with_ipv6_default(hass, mock_zeroconf):
"""Test without ipv6 as default."""
with patch.object(hass.config_entries.flow, "async_init"), patch.object(
zeroconf, "HaServiceBrowser", side_effect=service_update_mock
):
mock_zeroconf.get_service_info.side_effect = get_service_info_mock
assert await async_setup_component(hass, zeroconf.DOMAIN, {zeroconf.DOMAIN: {}})
assert mock_zeroconf.called_with()
async def test_homekit_match_partial_space(hass, mock_zeroconf):
"""Test configured options for a device are loaded via config entry."""
with patch.dict(