Add more system information from Supervisor (#35560)

pull/35564/head^2
Franck Nijhof 2020-05-13 00:27:34 +02:00 committed by GitHub
parent 306f15723d
commit eddb5c6c3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 148 additions and 35 deletions

View File

@ -41,7 +41,8 @@ CONFIG_SCHEMA = vol.Schema(
)
DATA_HOMEASSISTANT_VERSION = "hassio_hass_version"
DATA_INFO = "hassio_info"
DATA_HOST_INFO = "hassio_host_info"
HASSIO_UPDATE_INTERVAL = timedelta(minutes=55)
SERVICE_ADDON_START = "addon_start"
@ -130,7 +131,29 @@ def get_homeassistant_version(hass):
Async friendly.
"""
return hass.data.get(DATA_HOMEASSISTANT_VERSION)
if DATA_INFO not in hass.data:
return None
return hass.data[DATA_INFO].get("homeassistant")
@callback
@bind_hass
def get_info(hass):
"""Return generic information from Supervisor.
Async friendly.
"""
return hass.data.get(DATA_INFO)
@callback
@bind_hass
def get_host_info(hass):
"""Return generic host information.
Async friendly.
"""
return hass.data.get(DATA_HOST_INFO)
@callback
@ -247,20 +270,20 @@ async def async_setup(hass, config):
DOMAIN, service, async_service_handler, schema=settings[1]
)
async def update_homeassistant_version(now):
"""Update last available Home Assistant version."""
async def update_info_data(now):
"""Update last available supervisor information."""
try:
data = await hassio.get_homeassistant_info()
hass.data[DATA_HOMEASSISTANT_VERSION] = data["last_version"]
hass.data[DATA_INFO] = await hassio.get_info()
hass.data[DATA_HOST_INFO] = await hassio.get_host_info()
except HassioAPIError as err:
_LOGGER.warning("Can't read last version: %s", err)
hass.helpers.event.async_track_point_in_utc_time(
update_homeassistant_version, utcnow() + HASSIO_UPDATE_INTERVAL
update_info_data, utcnow() + HASSIO_UPDATE_INTERVAL
)
# Fetch last version
await update_homeassistant_version(None)
await update_info_data(None)
async def async_handle_core_service(call):
"""Service handler for handling core services."""

View File

@ -68,12 +68,20 @@ class HassIO:
return self.send_command("/supervisor/ping", method="get", timeout=15)
@_api_data
def get_homeassistant_info(self):
"""Return data for Home Assistant.
def get_info(self):
"""Return generic Supervisor information.
This method return a coroutine.
"""
return self.send_command("/homeassistant/info", method="get")
return self.send_command("/info", method="get")
@_api_data
def get_host_info(self):
"""Return data for Host.
This method return a coroutine.
"""
return self.send_command("/host/info", method="get")
@_api_data
def get_addon_info(self, addon):

View File

@ -14,6 +14,7 @@ from .typing import HomeAssistantType
async def async_get_system_info(hass: HomeAssistantType) -> Dict:
"""Return info about the system."""
info_object = {
"installation_type": "Unknown",
"version": current_version,
"dev": "dev" in current_version,
"hassio": hass.components.hassio.is_hassio(),
@ -33,4 +34,26 @@ async def async_get_system_info(hass: HomeAssistantType) -> Dict:
elif platform.system() == "Linux":
info_object["docker"] = os.path.isfile("/.dockerenv")
# Determine installation type on current data
if info_object["docker"]:
info_object["installation_type"] = "Home Assistant Core on Docker"
elif is_virtual_env():
info_object[
"installation_type"
] = "Home Assistant Core in a Python Virtual Environment"
# Enrich with Supervisor information
if hass.components.hassio.is_hassio():
info = hass.components.hassio.get_info()
host = hass.components.hassio.get_host_info()
info_object["supervisor"] = info.get("supervisor")
info_object["host_os"] = host.get("operating_system")
info_object["chassis"] = host.get("chassis")
if info.get("hassos") is not None:
info_object["installation_type"] = "Home Assistant"
else:
info_object["installation_type"] = "Home Assistant Supervised"
return info_object

View File

@ -19,7 +19,7 @@ def hassio_env():
"homeassistant.components.hassio.HassIO.is_connected",
return_value={"result": "ok", "data": {}},
), patch.dict(os.environ, {"HASSIO_TOKEN": "123456"}), patch(
"homeassistant.components.hassio.HassIO.get_homeassistant_info",
"homeassistant.components.hassio.HassIO.get_info",
Mock(side_effect=HassioAPIError()),
):
yield
@ -35,8 +35,7 @@ def hassio_stubs(hassio_env, hass, hass_client, aioclient_mock):
"homeassistant.components.hassio.HassIO.update_hass_timezone",
return_value={"result": "ok"},
), patch(
"homeassistant.components.hassio.HassIO.get_homeassistant_info",
side_effect=HassioAPIError(),
"homeassistant.components.hassio.HassIO.get_info", side_effect=HassioAPIError(),
):
hass.state = CoreState.starting
hass.loop.run_until_complete(async_setup_component(hass, "hassio", {}))

View File

@ -91,7 +91,7 @@ async def test_hassio_discovery_startup_done(hass, aioclient_mock, hassio_client
"homeassistant.components.hassio.HassIO.update_hass_api",
return_value={"result": "ok"},
), patch(
"homeassistant.components.hassio.HassIO.get_homeassistant_info",
"homeassistant.components.hassio.HassIO.get_info",
Mock(side_effect=HassioAPIError()),
), patch(
"homeassistant.components.mqtt.config_flow.FlowHandler.async_step_hassio",

View File

@ -30,26 +30,64 @@ async def test_api_ping_exeption(hassio_handler, aioclient_mock):
assert aioclient_mock.call_count == 1
async def test_api_homeassistant_info(hassio_handler, aioclient_mock):
"""Test setup with API Home Assistant info."""
async def test_api_info(hassio_handler, aioclient_mock):
"""Test setup with API generic info."""
aioclient_mock.get(
"http://127.0.0.1/homeassistant/info",
json={"result": "ok", "data": {"last_version": "10.0"}},
"http://127.0.0.1/info",
json={
"result": "ok",
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
},
)
data = await hassio_handler.get_homeassistant_info()
data = await hassio_handler.get_info()
assert aioclient_mock.call_count == 1
assert data["last_version"] == "10.0"
assert data["hassos"] is None
assert data["homeassistant"] == "0.110.0"
assert data["supervisor"] == "222"
async def test_api_homeassistant_info_error(hassio_handler, aioclient_mock):
async def test_api_info_error(hassio_handler, aioclient_mock):
"""Test setup with API Home Assistant info error."""
aioclient_mock.get(
"http://127.0.0.1/homeassistant/info", json={"result": "error", "message": None}
"http://127.0.0.1/info", json={"result": "error", "message": None}
)
with pytest.raises(HassioAPIError):
await hassio_handler.get_homeassistant_info()
await hassio_handler.get_info()
assert aioclient_mock.call_count == 1
async def test_api_host_info(hassio_handler, aioclient_mock):
"""Test setup with API Host info."""
aioclient_mock.get(
"http://127.0.0.1/host/info",
json={
"result": "ok",
"data": {
"chassis": "vm",
"operating_system": "Debian GNU/Linux 10 (buster)",
"kernel": "4.19.0-6-amd64",
},
},
)
data = await hassio_handler.get_host_info()
assert aioclient_mock.call_count == 1
assert data["chassis"] == "vm"
assert data["kernel"] == "4.19.0-6-amd64"
assert data["operating_system"] == "Debian GNU/Linux 10 (buster)"
async def test_api_host_info_error(hassio_handler, aioclient_mock):
"""Test setup with API Home Assistant info error."""
aioclient_mock.get(
"http://127.0.0.1/host/info", json={"result": "error", "message": None}
)
with pytest.raises(HassioAPIError):
await hassio_handler.get_host_info()
assert aioclient_mock.call_count == 1

View File

@ -20,8 +20,25 @@ def mock_all(aioclient_mock):
aioclient_mock.get("http://127.0.0.1/supervisor/ping", json={"result": "ok"})
aioclient_mock.post("http://127.0.0.1/supervisor/options", json={"result": "ok"})
aioclient_mock.get(
"http://127.0.0.1/homeassistant/info",
json={"result": "ok", "data": {"last_version": "10.0"}},
"http://127.0.0.1/info",
json={
"result": "ok",
"data": {"supervisor": "222", "homeassistant": "0.110.0", "hassos": None},
},
)
aioclient_mock.get(
"http://127.0.0.1/host/info",
json={
"result": "ok",
"data": {
"result": "ok",
"data": {
"chassis": "vm",
"operating_system": "Debian GNU/Linux 10 (buster)",
"kernel": "4.19.0-6-amd64",
},
},
},
)
aioclient_mock.get(
"http://127.0.0.1/ingress/panels", json={"result": "ok", "data": {"panels": {}}}
@ -34,8 +51,8 @@ async def test_setup_api_ping(hass, aioclient_mock):
result = await async_setup_component(hass, "hassio", {})
assert result
assert aioclient_mock.call_count == 5
assert hass.components.hassio.get_homeassistant_version() == "10.0"
assert aioclient_mock.call_count == 6
assert hass.components.hassio.get_homeassistant_version() == "0.110.0"
assert hass.components.hassio.is_hassio()
@ -73,7 +90,7 @@ async def test_setup_api_push_api_data(hass, aioclient_mock):
)
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
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"]
@ -89,7 +106,7 @@ async def test_setup_api_push_api_data_server_host(hass, aioclient_mock):
)
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
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"]
@ -101,7 +118,7 @@ async def test_setup_api_push_api_data_default(hass, aioclient_mock, hass_storag
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
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"]
@ -148,7 +165,7 @@ async def test_setup_api_existing_hassio_user(hass, aioclient_mock, hass_storage
result = await async_setup_component(hass, "hassio", {"http": {}, "hassio": {}})
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
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
@ -162,7 +179,7 @@ async def test_setup_core_push_timezone(hass, aioclient_mock):
result = await async_setup_component(hass, "hassio", {"hassio": {}})
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
assert aioclient_mock.mock_calls[2][2]["timezone"] == "testzone"
await hass.config.async_update(time_zone="America/New_York")
@ -178,7 +195,7 @@ async def test_setup_hassio_no_additional_data(hass, aioclient_mock):
result = await async_setup_component(hass, "hassio", {"hassio": {}})
assert result
assert aioclient_mock.call_count == 5
assert aioclient_mock.call_count == 6
assert aioclient_mock.mock_calls[-1][3]["X-Hassio-Key"] == "123456"

View File

@ -154,7 +154,12 @@ async def test_new_version_shows_entity_after_hour_hassio(
"""Test if binary sensor gets updated if new version is available / Hass.io."""
mock_get_uuid.return_value = MOCK_HUUID
mock_component(hass, "hassio")
hass.data["hassio_hass_version"] = "999.0"
hass.data["hassio_info"] = {"hassos": None, "homeassistant": "999.0"}
hass.data["hassio_host"] = {
"supervisor": "222",
"chassis": "vm",
"operating_system": "HassOS 4.6",
}
assert await async_setup_component(hass, updater.DOMAIN, {updater.DOMAIN: {}})