Don't duplicate core services in hassio (#102593)
This commit is contained in:
parent
c555fe4462
commit
7a009ed6cd
6 changed files with 51 additions and 73 deletions
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"})
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue