Add fallback for webmin systems without MAC address (#113261)

This commit is contained in:
Sid 2024-07-19 10:01:46 +02:00 committed by GitHub
parent 53870617e8
commit c8a6c6a5c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 149 additions and 18 deletions

View File

@ -53,9 +53,10 @@ async def validate_user_input(
except Exception as err:
raise SchemaFlowError("unknown") from err
await cast(SchemaConfigFlowHandler, handler.parent_handler).async_set_unique_id(
get_sorted_mac_addresses(data)[0]
)
if len(mac_addresses := get_sorted_mac_addresses(data)) > 0:
await cast(SchemaConfigFlowHandler, handler.parent_handler).async_set_unique_id(
mac_addresses[0]
)
return user_input

View File

@ -23,6 +23,7 @@ class WebminUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
"""The Webmin data update coordinator."""
mac_address: str
unique_id: str
def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
"""Initialize the Webmin data update coordinator."""
@ -41,14 +42,19 @@ class WebminUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
async def async_setup(self) -> None:
"""Provide needed data to the device info."""
mac_addresses = get_sorted_mac_addresses(self.data)
self.mac_address = mac_addresses[0]
self.device_info[ATTR_CONNECTIONS] = {
(CONNECTION_NETWORK_MAC, format_mac(mac_address))
for mac_address in mac_addresses
}
self.device_info[ATTR_IDENTIFIERS] = {
(DOMAIN, format_mac(mac_address)) for mac_address in mac_addresses
}
if len(mac_addresses) > 0:
self.mac_address = mac_addresses[0]
self.unique_id = self.mac_address
self.device_info[ATTR_CONNECTIONS] = {
(CONNECTION_NETWORK_MAC, format_mac(mac_address))
for mac_address in mac_addresses
}
self.device_info[ATTR_IDENTIFIERS] = {
(DOMAIN, format_mac(mac_address)) for mac_address in mac_addresses
}
else:
assert self.config_entry
self.unique_id = self.config_entry.entry_id
async def _async_update_data(self) -> dict[str, Any]:
data = await self.instance.update()

View File

@ -235,7 +235,7 @@ class WebminSensor(CoordinatorEntity[WebminUpdateCoordinator], SensorEntity):
super().__init__(coordinator)
self.entity_description = description
self._attr_device_info = coordinator.device_info
self._attr_unique_id = f"{coordinator.mac_address}_{description.key}"
self._attr_unique_id = f"{coordinator.unique_id}_{description.key}"
@property
def native_value(self) -> int | float:

View File

@ -37,14 +37,21 @@ def mock_setup_entry() -> Generator[AsyncMock]:
yield mock_setup
async def async_init_integration(hass: HomeAssistant) -> MockConfigEntry:
async def async_init_integration(
hass: HomeAssistant, with_mac_address: bool = True
) -> MockConfigEntry:
"""Set up the Webmin integration in Home Assistant."""
entry = MockConfigEntry(domain=DOMAIN, options=TEST_USER_INPUT, title="name")
entry.add_to_hass(hass)
with patch(
"homeassistant.components.webmin.helpers.WebminInstance.update",
return_value=load_json_object_fixture("webmin_update.json", DOMAIN),
return_value=load_json_object_fixture(
"webmin_update.json"
if with_mac_address
else "webmin_update_without_mac.json",
DOMAIN,
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

View File

@ -0,0 +1,108 @@
{
"disk_total": 18104905818112,
"io": [0, 4],
"load": [
1.29,
1.36,
1.37,
3589,
"Intel(R) Core(TM) i7-5820K CPU @ 3.30GHz",
"GenuineIntel",
15728640,
12
],
"disk_free": 7749321486336,
"kernel": { "os": "Linux", "arch": "x86_64", "version": "6.6.18-1-lts" },
"disk_fs": [
{
"device": "UUID=00000000-80b6-0000-8a06-000000000000",
"dir": "/",
"ifree": 14927206,
"total": 248431161344,
"used_percent": 80,
"type": "ext4",
"itotal": 15482880,
"iused": 555674,
"free": 49060442112,
"used": 186676502528,
"iused_percent": 4
},
{
"total": 11903838912512,
"used_percent": 38,
"iused": 3542318,
"type": "ext4",
"itotal": 366198784,
"device": "/dev/md127",
"ifree": 362656466,
"dir": "/media/disk2",
"iused_percent": 1,
"free": 7028764823552,
"used": 4275077644288
},
{
"dir": "/media/disk1",
"ifree": 183130757,
"device": "UUID=00000000-2bb2-0000-896c-000000000000",
"type": "ext4",
"itotal": 183140352,
"iused": 9595,
"used_percent": 89,
"total": 5952635744256,
"used": 4981066997760,
"free": 671496220672,
"iused_percent": 1
}
],
"drivetemps": [
{ "temp": 49, "device": "/dev/sda", "failed": "", "errors": "" },
{ "failed": "", "errors": "", "device": "/dev/sdb", "temp": 49 },
{ "device": "/dev/sdc", "temp": 51, "failed": "", "errors": "" },
{ "failed": "", "errors": "", "device": "/dev/sdd", "temp": 51 },
{ "errors": "", "failed": "", "temp": 43, "device": "/dev/sde" },
{ "device": "/dev/sdf", "temp": 40, "errors": "", "failed": "" }
],
"mem": [32766344, 28530480, 1953088, 1944384, 27845756, ""],
"disk_used": 9442821144576,
"cputemps": [
{ "temp": 51, "core": 0 },
{ "temp": 49, "core": 1 },
{ "core": 2, "temp": 59 },
{ "temp": 51, "core": 3 },
{ "temp": 50, "core": 4 },
{ "temp": 49, "core": 5 }
],
"procs": 310,
"cpu": [0, 8, 92, 0, 0],
"cpufans": [
{ "rpm": 0, "fan": 1 },
{ "fan": 2, "rpm": 1371 },
{ "rpm": 0, "fan": 3 },
{ "rpm": 927, "fan": 4 },
{ "rpm": 801, "fan": 5 }
],
"load_1m": 1.29,
"load_5m": 1.36,
"load_15m": 1.37,
"mem_total": 32766344,
"mem_free": 28530480,
"swap_total": 1953088,
"swap_free": 1944384,
"uptime": { "days": 11, "minutes": 1, "seconds": 28 },
"active_interfaces": [
{
"scope6": ["host"],
"address": "127.0.0.1",
"address6": ["::1"],
"name": "lo",
"broadcast": 0,
"up": 1,
"index": 0,
"fullname": "lo",
"netmask6": [128],
"netmask": "255.0.0.0",
"mtu": 65536,
"edit": 1
}
]
}

View File

@ -33,15 +33,16 @@ async def user_flow(hass: HomeAssistant) -> str:
return result["flow_id"]
@pytest.mark.parametrize(
"fixture", ["webmin_update_without_mac.json", "webmin_update.json"]
)
async def test_form_user(
hass: HomeAssistant,
user_flow: str,
mock_setup_entry: AsyncMock,
hass: HomeAssistant, user_flow: str, mock_setup_entry: AsyncMock, fixture: str
) -> None:
"""Test a successful user initiated flow."""
with patch(
"homeassistant.components.webmin.helpers.WebminInstance.update",
return_value=load_json_object_fixture("webmin_update.json", DOMAIN),
return_value=load_json_object_fixture(fixture, DOMAIN),
):
result = await hass.config_entries.flow.async_configure(
user_flow, TEST_USER_INPUT

View File

@ -19,3 +19,11 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
assert entry.state is ConfigEntryState.NOT_LOADED
assert not hass.data.get(DOMAIN)
async def test_entry_without_mac_address(hass: HomeAssistant) -> None:
"""Test an entry without MAC address."""
entry = await async_init_integration(hass, False)
assert entry.runtime_data.unique_id == entry.entry_id