Add container arch to system info (#147372)

This commit is contained in:
Stefan Agner
2025-06-24 09:52:21 +02:00
committed by GitHub
parent 121239bcf7
commit e5d19baf3e
14 changed files with 99 additions and 118 deletions

View File

@@ -12,7 +12,6 @@ import re
import struct
from typing import Any, NamedTuple
import aiofiles
from aiohasupervisor import SupervisorError
import voluptuous as vol
@@ -239,12 +238,6 @@ def _is_32_bit() -> bool:
return size * 8 == 32
async def _get_arch() -> str:
async with aiofiles.open("/etc/apk/arch") as arch_file:
raw_arch = await arch_file.read()
return {"x86": "i386"}.get(raw_arch, raw_arch)
class APIEndpointSettings(NamedTuple):
"""Settings for API endpoint."""
@@ -566,8 +559,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_config_entry_first_refresh()
hass.data[ADDONS_COORDINATOR] = coordinator
arch = await _get_arch()
def deprecated_setup_issue() -> None:
os_info = get_os_info(hass)
info = get_info(hass)
@@ -575,6 +566,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return
is_haos = info.get("hassos") is not None
board = os_info.get("board")
arch = info.get("arch", "unknown")
unsupported_board = board in {"tinker", "odroid-xu4", "rpi2"}
unsupported_os_on_board = board in {"rpi3", "rpi4"}
if is_haos and (unsupported_board or unsupported_os_on_board):

View File

@@ -7,7 +7,6 @@ import logging
import struct
from typing import Any
import aiofiles
import voluptuous as vol
from homeassistant import config as conf_util, core_config
@@ -18,6 +17,7 @@ from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_LATITUDE,
ATTR_LONGITUDE,
EVENT_HOMEASSISTANT_STARTED,
RESTART_EXIT_CODE,
SERVICE_RELOAD,
SERVICE_SAVE_PERSISTENT_STATES,
@@ -26,6 +26,7 @@ from homeassistant.const import (
SERVICE_TURN_ON,
)
from homeassistant.core import (
Event,
HomeAssistant,
ServiceCall,
ServiceResponse,
@@ -101,12 +102,6 @@ def _is_32_bit() -> bool:
return size * 8 == 32
async def _get_arch() -> str:
async with aiofiles.open("/etc/apk/arch") as arch_file:
raw_arch = (await arch_file.read()).strip()
return {"x86": "i386", "x86_64": "amd64"}.get(raw_arch, raw_arch)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901
"""Set up general services related to Home Assistant."""
@@ -411,45 +406,50 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa:
hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities
async_set_stop_handler(hass, _async_stop)
info = await async_get_system_info(hass)
async def _async_check_deprecation(event: Event) -> None:
"""Check and create deprecation issues after startup."""
info = await async_get_system_info(hass)
installation_type = info["installation_type"][15:]
if installation_type in {"Core", "Container"}:
deprecated_method = installation_type == "Core"
bit32 = _is_32_bit()
arch = info["arch"]
if bit32 and installation_type == "Container":
arch = await _get_arch()
ir.async_create_issue(
hass,
DOMAIN,
"deprecated_container",
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_container",
translation_placeholders={"arch": arch},
)
deprecated_architecture = bit32 and installation_type != "Container"
if deprecated_method or deprecated_architecture:
issue_id = "deprecated"
if deprecated_method:
issue_id += "_method"
if deprecated_architecture:
issue_id += "_architecture"
ir.async_create_issue(
hass,
DOMAIN,
issue_id,
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key=issue_id,
translation_placeholders={
"installation_type": installation_type,
"arch": arch,
},
)
installation_type = info["installation_type"][15:]
if installation_type in {"Core", "Container"}:
deprecated_method = installation_type == "Core"
bit32 = _is_32_bit()
arch = info["arch"]
if bit32 and installation_type == "Container":
arch = info.get("container_arch", arch)
ir.async_create_issue(
hass,
DOMAIN,
"deprecated_container",
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_container",
translation_placeholders={"arch": arch},
)
deprecated_architecture = bit32 and installation_type != "Container"
if deprecated_method or deprecated_architecture:
issue_id = "deprecated"
if deprecated_method:
issue_id += "_method"
if deprecated_architecture:
issue_id += "_architecture"
ir.async_create_issue(
hass,
DOMAIN,
issue_id,
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key=issue_id,
translation_placeholders={
"installation_type": installation_type,
"arch": arch,
},
)
# Delay deprecation check to make sure installation method is determined correctly
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, _async_check_deprecation)
return True

View File

@@ -124,6 +124,7 @@
"info": {
"arch": "CPU architecture",
"config_dir": "Configuration directory",
"container_arch": "Container architecture",
"dev": "Development",
"docker": "Docker",
"hassio": "Supervisor",

View File

@@ -27,6 +27,7 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
"dev": info.get("dev"),
"hassio": info.get("hassio"),
"docker": info.get("docker"),
"container_arch": info.get("container_arch"),
"user": info.get("user"),
"virtualenv": info.get("virtualenv"),
"python_version": info.get("python_version"),

View File

@@ -21,6 +21,7 @@ from .singleton import singleton
_LOGGER = logging.getLogger(__name__)
_DATA_MAC_VER = "system_info_mac_ver"
_DATA_CONTAINER_ARCH = "system_info_container_arch"
@singleton(_DATA_MAC_VER)
@@ -29,6 +30,22 @@ async def async_get_mac_ver(hass: HomeAssistant) -> str:
return (await hass.async_add_executor_job(platform.mac_ver))[0]
@singleton(_DATA_CONTAINER_ARCH)
async def async_get_container_arch(hass: HomeAssistant) -> str:
"""Return the container architecture."""
def _read_arch_file() -> str:
"""Read the architecture from /etc/apk/arch."""
with open("/etc/apk/arch", encoding="utf-8") as arch_file:
return arch_file.read().strip()
try:
raw_arch = await hass.async_add_executor_job(_read_arch_file)
except FileNotFoundError:
return "unknown"
return {"x86": "i386", "x86_64": "amd64"}.get(raw_arch, raw_arch)
# Cache the result of getuser() because it can call getpwuid() which
# can do blocking I/O to look up the username in /etc/passwd.
cached_get_user = cache(getuser)
@@ -79,6 +96,7 @@ async def async_get_system_info(hass: HomeAssistant) -> dict[str, Any]:
if info_object["docker"]:
if info_object["user"] == "root" and is_official_image():
info_object["installation_type"] = "Home Assistant Container"
info_object["container_arch"] = await async_get_container_arch(hass)
else:
info_object["installation_type"] = "Unsupported Third Party Container"

View File

@@ -3,7 +3,6 @@
aiodhcpwatcher==1.2.0
aiodiscover==2.7.0
aiodns==3.5.0
aiofiles==24.1.0
aiohasupervisor==0.3.1
aiohttp-asyncmdnsresolver==0.1.1
aiohttp-fast-zlib==0.3.0
@@ -201,6 +200,14 @@ tenacity!=8.4.0
# TypeError: 'Timeout' object does not support the context manager protocol
async-timeout==4.0.3
# aiofiles keeps getting downgraded by custom components
# causing newer methods to not be available and breaking
# some integrations at startup
# https://github.com/home-assistant/core/issues/127529
# https://github.com/home-assistant/core/issues/122508
# https://github.com/home-assistant/core/issues/118004
aiofiles>=24.1.0
# multidict < 6.4.0 has memory leaks
# https://github.com/aio-libs/multidict/issues/1134
# https://github.com/aio-libs/multidict/issues/1131