mirror of
https://github.com/home-assistant/core.git
synced 2025-08-01 09:38:21 +00:00
Properly cleanup ONVIF events to prevent log flooding on setup errors (#149603)
This commit is contained in:
parent
b67e85e8da
commit
aaec243bf4
@ -1,7 +1,7 @@
|
|||||||
"""The ONVIF integration."""
|
"""The ONVIF integration."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import suppress
|
from contextlib import AsyncExitStack, suppress
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -45,50 +45,56 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
device = ONVIFDevice(hass, entry)
|
device = ONVIFDevice(hass, entry)
|
||||||
|
|
||||||
try:
|
async with AsyncExitStack() as stack:
|
||||||
await device.async_setup()
|
# Register cleanup callback for device
|
||||||
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
@stack.push_async_callback
|
||||||
await async_populate_snapshot_auth(hass, device, entry)
|
async def _cleanup():
|
||||||
except (TimeoutError, aiohttp.ClientError) as err:
|
await _async_stop_device(hass, device)
|
||||||
await device.device.close()
|
|
||||||
raise ConfigEntryNotReady(
|
|
||||||
f"Could not connect to camera {device.device.host}:{device.device.port}: {err}"
|
|
||||||
) from err
|
|
||||||
except Fault as err:
|
|
||||||
await device.device.close()
|
|
||||||
if is_auth_error(err):
|
|
||||||
raise ConfigEntryAuthFailed(
|
|
||||||
f"Auth Failed: {stringify_onvif_error(err)}"
|
|
||||||
) from err
|
|
||||||
raise ConfigEntryNotReady(
|
|
||||||
f"Could not connect to camera: {stringify_onvif_error(err)}"
|
|
||||||
) from err
|
|
||||||
except ONVIFError as err:
|
|
||||||
await device.device.close()
|
|
||||||
raise ConfigEntryNotReady(
|
|
||||||
f"Could not setup camera {device.device.host}:{device.device.port}: {stringify_onvif_error(err)}"
|
|
||||||
) from err
|
|
||||||
except TransportError as err:
|
|
||||||
await device.device.close()
|
|
||||||
stringified_onvif_error = stringify_onvif_error(err)
|
|
||||||
if err.status_code in (
|
|
||||||
HTTPStatus.UNAUTHORIZED.value,
|
|
||||||
HTTPStatus.FORBIDDEN.value,
|
|
||||||
):
|
|
||||||
raise ConfigEntryAuthFailed(
|
|
||||||
f"Auth Failed: {stringified_onvif_error}"
|
|
||||||
) from err
|
|
||||||
raise ConfigEntryNotReady(
|
|
||||||
f"Could not setup camera {device.device.host}:{device.device.port}: {stringified_onvif_error}"
|
|
||||||
) from err
|
|
||||||
except asyncio.CancelledError as err:
|
|
||||||
# After https://github.com/agronholm/anyio/issues/374 is resolved
|
|
||||||
# this may be able to be removed
|
|
||||||
await device.device.close()
|
|
||||||
raise ConfigEntryNotReady(f"Setup was unexpectedly canceled: {err}") from err
|
|
||||||
|
|
||||||
if not device.available:
|
try:
|
||||||
raise ConfigEntryNotReady
|
await device.async_setup()
|
||||||
|
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
||||||
|
await async_populate_snapshot_auth(hass, device, entry)
|
||||||
|
except (TimeoutError, aiohttp.ClientError) as err:
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not connect to camera {device.device.host}:{device.device.port}: {err}"
|
||||||
|
) from err
|
||||||
|
except Fault as err:
|
||||||
|
if is_auth_error(err):
|
||||||
|
raise ConfigEntryAuthFailed(
|
||||||
|
f"Auth Failed: {stringify_onvif_error(err)}"
|
||||||
|
) from err
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not connect to camera: {stringify_onvif_error(err)}"
|
||||||
|
) from err
|
||||||
|
except ONVIFError as err:
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not setup camera {device.device.host}:{device.device.port}: {stringify_onvif_error(err)}"
|
||||||
|
) from err
|
||||||
|
except TransportError as err:
|
||||||
|
stringified_onvif_error = stringify_onvif_error(err)
|
||||||
|
if err.status_code in (
|
||||||
|
HTTPStatus.UNAUTHORIZED.value,
|
||||||
|
HTTPStatus.FORBIDDEN.value,
|
||||||
|
):
|
||||||
|
raise ConfigEntryAuthFailed(
|
||||||
|
f"Auth Failed: {stringified_onvif_error}"
|
||||||
|
) from err
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Could not setup camera {device.device.host}:{device.device.port}: {stringified_onvif_error}"
|
||||||
|
) from err
|
||||||
|
except asyncio.CancelledError as err:
|
||||||
|
# After https://github.com/agronholm/anyio/issues/374 is resolved
|
||||||
|
# this may be able to be removed
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Setup was unexpectedly canceled: {err}"
|
||||||
|
) from err
|
||||||
|
|
||||||
|
if not device.available:
|
||||||
|
raise ConfigEntryNotReady
|
||||||
|
|
||||||
|
# If we get here, setup was successful - prevent cleanup
|
||||||
|
stack.pop_all()
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.unique_id] = device
|
hass.data[DOMAIN][entry.unique_id] = device
|
||||||
|
|
||||||
@ -111,17 +117,20 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def _async_stop_device(hass: HomeAssistant, device: ONVIFDevice) -> None:
|
||||||
"""Unload a config entry."""
|
"""Stop the ONVIF device."""
|
||||||
|
|
||||||
device: ONVIFDevice = hass.data[DOMAIN][entry.unique_id]
|
|
||||||
|
|
||||||
if device.capabilities.events and device.events.started:
|
if device.capabilities.events and device.events.started:
|
||||||
try:
|
try:
|
||||||
await device.events.async_stop()
|
await device.events.async_stop()
|
||||||
except (TimeoutError, ONVIFError, Fault, aiohttp.ClientError, TransportError):
|
except (TimeoutError, ONVIFError, Fault, aiohttp.ClientError, TransportError):
|
||||||
LOGGER.warning("Error while stopping events: %s", device.name)
|
LOGGER.warning("Error while stopping events: %s", device.name)
|
||||||
|
await device.device.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
"""Unload a config entry."""
|
||||||
|
device: ONVIFDevice = hass.data[DOMAIN][entry.unique_id]
|
||||||
|
await _async_stop_device(hass, device)
|
||||||
return await hass.config_entries.async_unload_platforms(entry, device.platforms)
|
return await hass.config_entries.async_unload_platforms(entry, device.platforms)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user