Don't duplicate core services in hassio (#102593)

This commit is contained in:
Erik Montnemery 2023-10-23 20:26:56 +02:00 committed by GitHub
parent c555fe4462
commit 7a009ed6cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 73 deletions

View file

@ -13,25 +13,18 @@ from typing import Any, NamedTuple
import voluptuous as vol
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components import panel_custom, persistent_notification
from homeassistant.components.homeassistant import (
SERVICE_CHECK_CONFIG,
SHUTDOWN_SERVICES,
)
import homeassistant.config as conf_util
from homeassistant.components import panel_custom
from homeassistant.components.homeassistant import async_set_stop_handler
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_MANUFACTURER,
ATTR_NAME,
EVENT_CORE_CONFIG_UPDATE,
HASSIO_USER_NAME,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
Platform,
)
from homeassistant.core import (
CALLBACK_TYPE,
DOMAIN as HASS_DOMAIN,
HassJob,
HomeAssistant,
ServiceCall,
@ -39,11 +32,7 @@ from homeassistant.core import (
callback,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import (
config_validation as cv,
device_registry as dr,
recorder,
)
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.event import async_call_later
@ -573,53 +562,15 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa:
# Fetch data
await update_info_data()
async def async_handle_core_service(call: ServiceCall) -> None:
"""Service handler for handling core services."""
if call.service in SHUTDOWN_SERVICES and recorder.async_migration_in_progress(
hass
):
_LOGGER.error(
"The system cannot %s while a database upgrade is in progress",
call.service,
)
raise HomeAssistantError(
f"The system cannot {call.service} "
"while a database upgrade is in progress."
)
if call.service == SERVICE_HOMEASSISTANT_STOP:
await hassio.stop_homeassistant()
return
errors = await conf_util.async_check_ha_config_file(hass)
if errors:
_LOGGER.error(
"The system cannot %s because the configuration is not valid: %s",
call.service,
errors,
)
persistent_notification.async_create(
hass,
"Config error. See [the logs](/config/logs) for details.",
"Config validating",
f"{HASS_DOMAIN}.check_config",
)
raise HomeAssistantError(
f"The system cannot {call.service} "
f"because the configuration is not valid: {errors}"
)
if call.service == SERVICE_HOMEASSISTANT_RESTART:
async def _async_stop(hass: HomeAssistant, restart: bool) -> None:
"""Stop or restart home assistant."""
if restart:
await hassio.restart_homeassistant()
else:
await hassio.stop_homeassistant()
# Mock core services
for service in (
SERVICE_HOMEASSISTANT_STOP,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_CHECK_CONFIG,
):
hass.services.async_register(HASS_DOMAIN, service, async_handle_core_service)
# Set a custom handler for the homeassistant.restart and homeassistant.stop services
async_set_stop_handler(hass, _async_stop)
# Init discovery Hass.io feature
async_setup_discovery_view(hass, hassio)

View file

@ -1,7 +1,9 @@
"""Integration providing core pieces of infrastructure."""
import asyncio
from collections.abc import Callable, Coroutine
import itertools as it
import logging
from typing import Any
import voluptuous as vol
@ -14,8 +16,6 @@ from homeassistant.const import (
ATTR_LATITUDE,
ATTR_LONGITUDE,
RESTART_EXIT_CODE,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_RELOAD,
SERVICE_SAVE_PERSISTENT_STATES,
SERVICE_TOGGLE,
@ -34,7 +34,13 @@ from homeassistant.helpers.service import (
from homeassistant.helpers.template import async_load_custom_templates
from homeassistant.helpers.typing import ConfigType
from .const import DATA_EXPOSED_ENTITIES, DOMAIN
from .const import (
DATA_EXPOSED_ENTITIES,
DATA_STOP_HANDLER,
DOMAIN,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
)
from .exposed_entities import ExposedEntities
ATTR_ENTRY_ID = "entry_id"
@ -148,6 +154,8 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
async def async_handle_core_service(call: ha.ServiceCall) -> None:
"""Service handler for handling core services."""
stop_handler: Callable[[ha.HomeAssistant, bool], Coroutine[Any, Any, None]]
if call.service in SHUTDOWN_SERVICES and recorder.async_migration_in_progress(
hass
):
@ -161,8 +169,8 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
)
if call.service == SERVICE_HOMEASSISTANT_STOP:
# Track trask in hass.data. No need to cleanup, we're stopping.
hass.data["homeassistant_stop"] = asyncio.create_task(hass.async_stop())
stop_handler = hass.data[DATA_STOP_HANDLER]
await stop_handler(hass, False)
return
errors = await conf_util.async_check_ha_config_file(hass)
@ -185,10 +193,8 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
)
if call.service == SERVICE_HOMEASSISTANT_RESTART:
# Track trask in hass.data. No need to cleanup, we're stopping.
hass.data["homeassistant_stop"] = asyncio.create_task(
hass.async_stop(RESTART_EXIT_CODE)
)
stop_handler = hass.data[DATA_STOP_HANDLER]
await stop_handler(hass, True)
async def async_handle_update_service(call: ha.ServiceCall) -> None:
"""Service handler for updating an entity."""
@ -358,5 +364,22 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
exposed_entities = ExposedEntities(hass)
await exposed_entities.async_initialize()
hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities
async_set_stop_handler(hass, _async_stop)
return True
async def _async_stop(hass: ha.HomeAssistant, restart: bool):
"""Stop home assistant."""
exit_code = RESTART_EXIT_CODE if restart else 0
# Track trask in hass.data. No need to cleanup, we're stopping.
hass.data["homeassistant_stop"] = asyncio.create_task(hass.async_stop(exit_code))
@ha.callback
def async_set_stop_handler(
hass: ha.HomeAssistant,
stop_handler: Callable[[ha.HomeAssistant, bool], Coroutine[Any, Any, None]],
) -> None:
"""Set function which is called by the stop and restart services."""
hass.data[DATA_STOP_HANDLER] = stop_handler

View file

@ -1,6 +1,12 @@
"""Constants for the Homeassistant integration."""
from typing import Final
import homeassistant.core as ha
DOMAIN = ha.DOMAIN
DATA_EXPOSED_ENTITIES = f"{DOMAIN}.exposed_entites"
DATA_STOP_HANDLER = f"{DOMAIN}.stop_handler"
SERVICE_HOMEASSISTANT_STOP: Final = "stop"
SERVICE_HOMEASSISTANT_RESTART: Final = "restart"

View file

@ -1058,9 +1058,6 @@ COMPRESSED_STATE_LAST_CHANGED = "lc"
COMPRESSED_STATE_LAST_UPDATED = "lu"
# #### SERVICES ####
SERVICE_HOMEASSISTANT_STOP: Final = "stop"
SERVICE_HOMEASSISTANT_RESTART: Final = "restart"
SERVICE_TURN_ON: Final = "turn_on"
SERVICE_TURN_OFF: Final = "turn_off"
SERVICE_TOGGLE: Final = "toggle"

View file

@ -692,6 +692,7 @@ async def test_service_calls_core(
hassio_env, hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Call core service and check the API calls behind that."""
assert await async_setup_component(hass, "homeassistant", {})
assert await async_setup_component(hass, "hassio", {})
aioclient_mock.post("http://127.0.0.1/homeassistant/restart", json={"result": "ok"})

View file

@ -12,6 +12,8 @@ import homeassistant.components as comps
from homeassistant.components.homeassistant import (
ATTR_ENTRY_ID,
SERVICE_CHECK_CONFIG,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_RELOAD_ALL,
SERVICE_RELOAD_CORE_CONFIG,
SERVICE_RELOAD_CUSTOM_TEMPLATES,
@ -22,8 +24,6 @@ from homeassistant.const import (
ENTITY_MATCH_ALL,
ENTITY_MATCH_NONE,
EVENT_CORE_CONFIG_UPDATE,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_SAVE_PERSISTENT_STATES,
SERVICE_TOGGLE,
SERVICE_TURN_OFF,