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 import voluptuous as vol
from homeassistant.auth.const import GROUP_ID_ADMIN from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components import panel_custom, persistent_notification from homeassistant.components import panel_custom
from homeassistant.components.homeassistant import ( from homeassistant.components.homeassistant import async_set_stop_handler
SERVICE_CHECK_CONFIG,
SHUTDOWN_SERVICES,
)
import homeassistant.config as conf_util
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_MANUFACTURER, ATTR_MANUFACTURER,
ATTR_NAME, ATTR_NAME,
EVENT_CORE_CONFIG_UPDATE, EVENT_CORE_CONFIG_UPDATE,
HASSIO_USER_NAME, HASSIO_USER_NAME,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
Platform, Platform,
) )
from homeassistant.core import ( from homeassistant.core import (
CALLBACK_TYPE, CALLBACK_TYPE,
DOMAIN as HASS_DOMAIN,
HassJob, HassJob,
HomeAssistant, HomeAssistant,
ServiceCall, ServiceCall,
@ -39,11 +32,7 @@ from homeassistant.core import (
callback, callback,
) )
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import ( from homeassistant.helpers import config_validation as cv, device_registry as dr
config_validation as cv,
device_registry as dr,
recorder,
)
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.event import async_call_later from homeassistant.helpers.event import async_call_later
@ -573,53 +562,15 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa:
# Fetch data # Fetch data
await update_info_data() await update_info_data()
async def async_handle_core_service(call: ServiceCall) -> None: async def _async_stop(hass: HomeAssistant, restart: bool) -> None:
"""Service handler for handling core services.""" """Stop or restart home assistant."""
if call.service in SHUTDOWN_SERVICES and recorder.async_migration_in_progress( if restart:
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:
await hassio.restart_homeassistant() await hassio.restart_homeassistant()
else:
await hassio.stop_homeassistant()
# Mock core services # Set a custom handler for the homeassistant.restart and homeassistant.stop services
for service in ( async_set_stop_handler(hass, _async_stop)
SERVICE_HOMEASSISTANT_STOP,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_CHECK_CONFIG,
):
hass.services.async_register(HASS_DOMAIN, service, async_handle_core_service)
# Init discovery Hass.io feature # Init discovery Hass.io feature
async_setup_discovery_view(hass, hassio) async_setup_discovery_view(hass, hassio)

View file

@ -1,7 +1,9 @@
"""Integration providing core pieces of infrastructure.""" """Integration providing core pieces of infrastructure."""
import asyncio import asyncio
from collections.abc import Callable, Coroutine
import itertools as it import itertools as it
import logging import logging
from typing import Any
import voluptuous as vol import voluptuous as vol
@ -14,8 +16,6 @@ from homeassistant.const import (
ATTR_LATITUDE, ATTR_LATITUDE,
ATTR_LONGITUDE, ATTR_LONGITUDE,
RESTART_EXIT_CODE, RESTART_EXIT_CODE,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_RELOAD, SERVICE_RELOAD,
SERVICE_SAVE_PERSISTENT_STATES, SERVICE_SAVE_PERSISTENT_STATES,
SERVICE_TOGGLE, SERVICE_TOGGLE,
@ -34,7 +34,13 @@ from homeassistant.helpers.service import (
from homeassistant.helpers.template import async_load_custom_templates from homeassistant.helpers.template import async_load_custom_templates
from homeassistant.helpers.typing import ConfigType 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 from .exposed_entities import ExposedEntities
ATTR_ENTRY_ID = "entry_id" 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: async def async_handle_core_service(call: ha.ServiceCall) -> None:
"""Service handler for handling core services.""" """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( if call.service in SHUTDOWN_SERVICES and recorder.async_migration_in_progress(
hass hass
): ):
@ -161,8 +169,8 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
) )
if call.service == SERVICE_HOMEASSISTANT_STOP: if call.service == SERVICE_HOMEASSISTANT_STOP:
# Track trask in hass.data. No need to cleanup, we're stopping. stop_handler = hass.data[DATA_STOP_HANDLER]
hass.data["homeassistant_stop"] = asyncio.create_task(hass.async_stop()) await stop_handler(hass, False)
return return
errors = await conf_util.async_check_ha_config_file(hass) 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: if call.service == SERVICE_HOMEASSISTANT_RESTART:
# Track trask in hass.data. No need to cleanup, we're stopping. stop_handler = hass.data[DATA_STOP_HANDLER]
hass.data["homeassistant_stop"] = asyncio.create_task( await stop_handler(hass, True)
hass.async_stop(RESTART_EXIT_CODE)
)
async def async_handle_update_service(call: ha.ServiceCall) -> None: async def async_handle_update_service(call: ha.ServiceCall) -> None:
"""Service handler for updating an entity.""" """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) exposed_entities = ExposedEntities(hass)
await exposed_entities.async_initialize() await exposed_entities.async_initialize()
hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities
async_set_stop_handler(hass, _async_stop)
return True 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.""" """Constants for the Homeassistant integration."""
from typing import Final
import homeassistant.core as ha import homeassistant.core as ha
DOMAIN = ha.DOMAIN DOMAIN = ha.DOMAIN
DATA_EXPOSED_ENTITIES = f"{DOMAIN}.exposed_entites" 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" COMPRESSED_STATE_LAST_UPDATED = "lu"
# #### SERVICES #### # #### SERVICES ####
SERVICE_HOMEASSISTANT_STOP: Final = "stop"
SERVICE_HOMEASSISTANT_RESTART: Final = "restart"
SERVICE_TURN_ON: Final = "turn_on" SERVICE_TURN_ON: Final = "turn_on"
SERVICE_TURN_OFF: Final = "turn_off" SERVICE_TURN_OFF: Final = "turn_off"
SERVICE_TOGGLE: Final = "toggle" SERVICE_TOGGLE: Final = "toggle"

View file

@ -692,6 +692,7 @@ async def test_service_calls_core(
hassio_env, hass: HomeAssistant, aioclient_mock: AiohttpClientMocker hassio_env, hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None: ) -> None:
"""Call core service and check the API calls behind that.""" """Call core service and check the API calls behind that."""
assert await async_setup_component(hass, "homeassistant", {})
assert await async_setup_component(hass, "hassio", {}) assert await async_setup_component(hass, "hassio", {})
aioclient_mock.post("http://127.0.0.1/homeassistant/restart", json={"result": "ok"}) 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 ( from homeassistant.components.homeassistant import (
ATTR_ENTRY_ID, ATTR_ENTRY_ID,
SERVICE_CHECK_CONFIG, SERVICE_CHECK_CONFIG,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_RELOAD_ALL, SERVICE_RELOAD_ALL,
SERVICE_RELOAD_CORE_CONFIG, SERVICE_RELOAD_CORE_CONFIG,
SERVICE_RELOAD_CUSTOM_TEMPLATES, SERVICE_RELOAD_CUSTOM_TEMPLATES,
@ -22,8 +24,6 @@ from homeassistant.const import (
ENTITY_MATCH_ALL, ENTITY_MATCH_ALL,
ENTITY_MATCH_NONE, ENTITY_MATCH_NONE,
EVENT_CORE_CONFIG_UPDATE, EVENT_CORE_CONFIG_UPDATE,
SERVICE_HOMEASSISTANT_RESTART,
SERVICE_HOMEASSISTANT_STOP,
SERVICE_SAVE_PERSISTENT_STATES, SERVICE_SAVE_PERSISTENT_STATES,
SERVICE_TOGGLE, SERVICE_TOGGLE,
SERVICE_TURN_OFF, SERVICE_TURN_OFF,