Add stats sensors for core and supervisor (#89455)
* Add stats sensors for core and supervisor * Update homeassistant/components/hassio/__init__.py
This commit is contained in:
parent
3a4ce260b4
commit
4f29e1e180
9 changed files with 295 additions and 13 deletions
|
@ -115,11 +115,13 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
|
||||
|
||||
DATA_CORE_INFO = "hassio_core_info"
|
||||
DATA_CORE_STATS = "hassio_core_stats"
|
||||
DATA_HOST_INFO = "hassio_host_info"
|
||||
DATA_STORE = "hassio_store"
|
||||
DATA_INFO = "hassio_info"
|
||||
DATA_OS_INFO = "hassio_os_info"
|
||||
DATA_SUPERVISOR_INFO = "hassio_supervisor_info"
|
||||
DATA_SUPERVISOR_STATS = "hassio_supervisor_stats"
|
||||
DATA_ADDONS_CHANGELOGS = "hassio_addons_changelogs"
|
||||
DATA_ADDONS_INFO = "hassio_addons_info"
|
||||
DATA_ADDONS_STATS = "hassio_addons_stats"
|
||||
|
@ -301,6 +303,26 @@ def get_addons_stats(hass):
|
|||
return hass.data.get(DATA_ADDONS_STATS)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_core_stats(hass):
|
||||
"""Return core stats.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
return hass.data.get(DATA_CORE_STATS)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_supervisor_stats(hass):
|
||||
"""Return supervisor stats.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
return hass.data.get(DATA_SUPERVISOR_STATS)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def get_addons_changelogs(hass):
|
||||
|
@ -747,8 +769,14 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
if self.is_hass_os:
|
||||
new_data[DATA_KEY_OS] = get_os_info(self.hass)
|
||||
|
||||
new_data[DATA_KEY_CORE] = get_core_info(self.hass)
|
||||
new_data[DATA_KEY_SUPERVISOR] = supervisor_info
|
||||
new_data[DATA_KEY_CORE] = {
|
||||
**(get_core_info(self.hass) or {}),
|
||||
**get_core_stats(self.hass),
|
||||
}
|
||||
new_data[DATA_KEY_SUPERVISOR] = {
|
||||
**supervisor_info,
|
||||
**get_supervisor_stats(self.hass),
|
||||
}
|
||||
|
||||
# If this is the initial refresh, register all addons and return the dict
|
||||
if not self.data:
|
||||
|
@ -805,12 +833,16 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
(
|
||||
self.hass.data[DATA_INFO],
|
||||
self.hass.data[DATA_CORE_INFO],
|
||||
self.hass.data[DATA_CORE_STATS],
|
||||
self.hass.data[DATA_SUPERVISOR_INFO],
|
||||
self.hass.data[DATA_SUPERVISOR_STATS],
|
||||
self.hass.data[DATA_OS_INFO],
|
||||
) = await asyncio.gather(
|
||||
self.hassio.get_info(),
|
||||
self.hassio.get_core_info(),
|
||||
self.hassio.get_core_stats(),
|
||||
self.hassio.get_supervisor_info(),
|
||||
self.hassio.get_supervisor_stats(),
|
||||
self.hassio.get_os_info(),
|
||||
)
|
||||
|
||||
|
|
|
@ -319,6 +319,14 @@ class HassIO:
|
|||
"""
|
||||
return self.send_command(f"/addons/{addon}/info", method="get")
|
||||
|
||||
@api_data
|
||||
def get_core_stats(self):
|
||||
"""Return stats for the core.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/core/stats", method="get")
|
||||
|
||||
@api_data
|
||||
def get_addon_stats(self, addon):
|
||||
"""Return stats for an Add-on.
|
||||
|
@ -327,6 +335,14 @@ class HassIO:
|
|||
"""
|
||||
return self.send_command(f"/addons/{addon}/stats", method="get")
|
||||
|
||||
@api_data
|
||||
def get_supervisor_stats(self):
|
||||
"""Return stats for the supervisor.
|
||||
|
||||
This method returns a coroutine.
|
||||
"""
|
||||
return self.send_command("/supervisor/stats", method="get")
|
||||
|
||||
def get_addon_changelog(self, addon):
|
||||
"""Return changelog for an Add-on.
|
||||
|
||||
|
|
|
@ -18,9 +18,16 @@ from .const import (
|
|||
ATTR_VERSION,
|
||||
ATTR_VERSION_LATEST,
|
||||
DATA_KEY_ADDONS,
|
||||
DATA_KEY_CORE,
|
||||
DATA_KEY_OS,
|
||||
DATA_KEY_SUPERVISOR,
|
||||
)
|
||||
from .entity import (
|
||||
HassioAddonEntity,
|
||||
HassioCoreEntity,
|
||||
HassioOSEntity,
|
||||
HassioSupervisorEntity,
|
||||
)
|
||||
from .entity import HassioAddonEntity, HassioOSEntity
|
||||
|
||||
COMMON_ENTITY_DESCRIPTIONS = (
|
||||
SensorEntityDescription(
|
||||
|
@ -35,7 +42,7 @@ COMMON_ENTITY_DESCRIPTIONS = (
|
|||
),
|
||||
)
|
||||
|
||||
ADDON_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS + (
|
||||
STATS_ENTITY_DESCRIPTIONS = (
|
||||
SensorEntityDescription(
|
||||
entity_registry_enabled_default=False,
|
||||
key=ATTR_CPU_PERCENT,
|
||||
|
@ -54,7 +61,10 @@ ADDON_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS + (
|
|||
),
|
||||
)
|
||||
|
||||
ADDON_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS + STATS_ENTITY_DESCRIPTIONS
|
||||
CORE_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||
OS_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS
|
||||
SUPERVISOR_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -65,7 +75,9 @@ async def async_setup_entry(
|
|||
"""Sensor set up for Hass.io config entry."""
|
||||
coordinator = hass.data[ADDONS_COORDINATOR]
|
||||
|
||||
entities: list[HassioOSSensor | HassioAddonSensor] = []
|
||||
entities: list[
|
||||
HassioOSSensor | HassioAddonSensor | CoreSensor | SupervisorSensor
|
||||
] = []
|
||||
|
||||
for addon in coordinator.data[DATA_KEY_ADDONS].values():
|
||||
for entity_description in ADDON_ENTITY_DESCRIPTIONS:
|
||||
|
@ -77,6 +89,22 @@ async def async_setup_entry(
|
|||
)
|
||||
)
|
||||
|
||||
for entity_description in CORE_ENTITY_DESCRIPTIONS:
|
||||
entities.append(
|
||||
CoreSensor(
|
||||
coordinator=coordinator,
|
||||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
|
||||
for entity_description in SUPERVISOR_ENTITY_DESCRIPTIONS:
|
||||
entities.append(
|
||||
SupervisorSensor(
|
||||
coordinator=coordinator,
|
||||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
|
||||
if coordinator.is_hass_os:
|
||||
for entity_description in OS_ENTITY_DESCRIPTIONS:
|
||||
entities.append(
|
||||
|
@ -107,3 +135,21 @@ class HassioOSSensor(HassioOSEntity, SensorEntity):
|
|||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[DATA_KEY_OS][self.entity_description.key]
|
||||
|
||||
|
||||
class CoreSensor(HassioCoreEntity, SensorEntity):
|
||||
"""Sensor to track a core attribute."""
|
||||
|
||||
@property
|
||||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[DATA_KEY_CORE][self.entity_description.key]
|
||||
|
||||
|
||||
class SupervisorSensor(HassioSupervisorEntity, SensorEntity):
|
||||
"""Sensor to track a supervisor attribute."""
|
||||
|
||||
@property
|
||||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[DATA_KEY_SUPERVISOR][self.entity_description.key]
|
||||
|
|
|
@ -120,6 +120,38 @@ def mock_all(aioclient_mock, request):
|
|||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="")
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/addons/test/info",
|
||||
|
|
|
@ -125,6 +125,38 @@ def mock_all(aioclient_mock, request):
|
|||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="")
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/addons/test/info",
|
||||
|
|
|
@ -226,6 +226,34 @@ async def test_api_addon_stats(
|
|||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_core_stats(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Add-on stats."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={"result": "ok", "data": {"memory_percent": 0.01}},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_core_stats()
|
||||
assert data["memory_percent"] == 0.01
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_supervisor_stats(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
"""Test setup with API Add-on stats."""
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={"result": "ok", "data": {"memory_percent": 0.01}},
|
||||
)
|
||||
|
||||
data = await hassio_handler.get_supervisor_stats()
|
||||
assert data["memory_percent"] == 0.01
|
||||
assert aioclient_mock.call_count == 1
|
||||
|
||||
|
||||
async def test_api_discovery_message(
|
||||
hassio_handler: HassIO, aioclient_mock: AiohttpClientMocker
|
||||
) -> None:
|
||||
|
|
|
@ -124,6 +124,38 @@ def mock_all(aioclient_mock, request, os_info):
|
|||
],
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/addons/test/stats",
|
||||
json={
|
||||
|
@ -210,7 +242,7 @@ async def test_setup_api_ping(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert hass.components.hassio.get_core_info()["version_latest"] == "1.0.0"
|
||||
assert hass.components.hassio.is_hassio()
|
||||
|
||||
|
@ -254,7 +286,7 @@ async def test_setup_api_push_api_data(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
||||
assert aioclient_mock.mock_calls[1][2]["watchdog"]
|
||||
|
@ -273,7 +305,7 @@ async def test_setup_api_push_api_data_server_host(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[1][2]["port"] == 9999
|
||||
assert not aioclient_mock.mock_calls[1][2]["watchdog"]
|
||||
|
@ -290,7 +322,7 @@ async def test_setup_api_push_api_data_default(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
||||
refresh_token = aioclient_mock.mock_calls[1][2]["refresh_token"]
|
||||
|
@ -370,7 +402,7 @@ async def test_setup_api_existing_hassio_user(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert not aioclient_mock.mock_calls[1][2]["ssl"]
|
||||
assert aioclient_mock.mock_calls[1][2]["port"] == 8123
|
||||
assert aioclient_mock.mock_calls[1][2]["refresh_token"] == token.token
|
||||
|
@ -387,7 +419,7 @@ async def test_setup_core_push_timezone(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert aioclient_mock.mock_calls[2][2]["timezone"] == "testzone"
|
||||
|
||||
with patch("homeassistant.util.dt.set_default_time_zone"):
|
||||
|
@ -407,7 +439,7 @@ async def test_setup_hassio_no_additional_data(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert aioclient_mock.mock_calls[-1][3]["Authorization"] == "Bearer 123456"
|
||||
|
||||
|
||||
|
@ -822,7 +854,7 @@ async def test_setup_hardware_integration(
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert result
|
||||
assert aioclient_mock.call_count == 16
|
||||
assert aioclient_mock.call_count == 18
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
|
|
|
@ -113,6 +113,38 @@ def mock_all(aioclient_mock, request):
|
|||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="")
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/addons/test/info",
|
||||
|
|
|
@ -127,6 +127,38 @@ def mock_all(aioclient_mock, request):
|
|||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/core/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/supervisor/stats",
|
||||
json={
|
||||
"result": "ok",
|
||||
"data": {
|
||||
"cpu_percent": 0.99,
|
||||
"memory_usage": 182611968,
|
||||
"memory_limit": 3977146368,
|
||||
"memory_percent": 4.59,
|
||||
"network_rx": 362570232,
|
||||
"network_tx": 82374138,
|
||||
"blk_read": 46010945536,
|
||||
"blk_write": 15051526144,
|
||||
},
|
||||
},
|
||||
)
|
||||
aioclient_mock.get("http://127.0.0.1/addons/test/changelog", text="")
|
||||
aioclient_mock.get(
|
||||
"http://127.0.0.1/addons/test/info",
|
||||
|
|
Loading…
Add table
Reference in a new issue