mirror of
https://github.com/home-assistant/core.git
synced 2026-05-08 17:49:37 +01:00
256 lines
8.5 KiB
Python
256 lines
8.5 KiB
Python
"""Binary sensor to read Proxmox VE data."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
from homeassistant.components.binary_sensor import (
|
|
BinarySensorDeviceClass,
|
|
BinarySensorEntity,
|
|
BinarySensorEntityDescription,
|
|
)
|
|
from homeassistant.const import EntityCategory
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
|
|
from .const import (
|
|
NODE_ONLINE,
|
|
STATUS_OK,
|
|
STORAGE_ACTIVE,
|
|
STORAGE_ENABLED,
|
|
STORAGE_SHARED,
|
|
VM_CONTAINER_RUNNING,
|
|
)
|
|
from .coordinator import ProxmoxConfigEntry, ProxmoxNodeData
|
|
from .entity import (
|
|
ProxmoxContainerEntity,
|
|
ProxmoxNodeEntity,
|
|
ProxmoxStorageEntity,
|
|
ProxmoxVMEntity,
|
|
)
|
|
|
|
PARALLEL_UPDATES = 0
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class ProxmoxContainerBinarySensorEntityDescription(BinarySensorEntityDescription):
|
|
"""Class to hold Proxmox container binary sensor description."""
|
|
|
|
state_fn: Callable[[dict[str, Any]], bool | None]
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class ProxmoxVMBinarySensorEntityDescription(BinarySensorEntityDescription):
|
|
"""Class to hold Proxmox endpoint binary sensor description."""
|
|
|
|
state_fn: Callable[[dict[str, Any]], bool | None]
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class ProxmoxNodeBinarySensorEntityDescription(BinarySensorEntityDescription):
|
|
"""Class to hold Proxmox node binary sensor description."""
|
|
|
|
state_fn: Callable[[ProxmoxNodeData], bool | None]
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class ProxmoxStorageBinarySensorEntityDescription(BinarySensorEntityDescription):
|
|
"""Class to hold Proxmox storage binary sensor description."""
|
|
|
|
state_fn: Callable[[dict[str, Any]], bool | None]
|
|
|
|
|
|
NODE_SENSORS: tuple[ProxmoxNodeBinarySensorEntityDescription, ...] = (
|
|
ProxmoxNodeBinarySensorEntityDescription(
|
|
key="status",
|
|
translation_key="status",
|
|
state_fn=lambda data: data.node["status"] == NODE_ONLINE,
|
|
device_class=BinarySensorDeviceClass.RUNNING,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
ProxmoxNodeBinarySensorEntityDescription(
|
|
key="node_backup_status",
|
|
translation_key="node_backup_status",
|
|
state_fn=lambda data: bool(
|
|
data.backups and data.backups[0]["status"] != STATUS_OK
|
|
),
|
|
device_class=BinarySensorDeviceClass.PROBLEM,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
)
|
|
|
|
CONTAINER_SENSORS: tuple[ProxmoxContainerBinarySensorEntityDescription, ...] = (
|
|
ProxmoxContainerBinarySensorEntityDescription(
|
|
key="status",
|
|
translation_key="status",
|
|
state_fn=lambda data: data["status"] == VM_CONTAINER_RUNNING,
|
|
device_class=BinarySensorDeviceClass.RUNNING,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
)
|
|
|
|
VM_SENSORS: tuple[ProxmoxVMBinarySensorEntityDescription, ...] = (
|
|
ProxmoxVMBinarySensorEntityDescription(
|
|
key="status",
|
|
translation_key="status",
|
|
state_fn=lambda data: data["status"] == VM_CONTAINER_RUNNING,
|
|
device_class=BinarySensorDeviceClass.RUNNING,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
)
|
|
|
|
STORAGE_SENSORS: tuple[ProxmoxStorageBinarySensorEntityDescription, ...] = (
|
|
ProxmoxStorageBinarySensorEntityDescription(
|
|
key="storage_active",
|
|
translation_key="storage_active",
|
|
state_fn=lambda data: data["active"] == STORAGE_ACTIVE,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
ProxmoxStorageBinarySensorEntityDescription(
|
|
key="storage_enabled",
|
|
translation_key="storage_enabled",
|
|
state_fn=lambda data: data["enabled"] == STORAGE_ENABLED,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
ProxmoxStorageBinarySensorEntityDescription(
|
|
key="storage_shared",
|
|
translation_key="storage_shared",
|
|
state_fn=lambda data: data["shared"] == STORAGE_SHARED,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
),
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: ProxmoxConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Set up Proxmox VE binary sensors."""
|
|
coordinator = entry.runtime_data
|
|
|
|
def _async_add_new_nodes(nodes: list[ProxmoxNodeData]) -> None:
|
|
"""Add new node binary sensors."""
|
|
async_add_entities(
|
|
ProxmoxNodeBinarySensor(coordinator, entity_description, node)
|
|
for node in nodes
|
|
for entity_description in NODE_SENSORS
|
|
)
|
|
|
|
def _async_add_new_vms(
|
|
vms: list[tuple[ProxmoxNodeData, dict[str, Any]]],
|
|
) -> None:
|
|
"""Add new VM binary sensors."""
|
|
async_add_entities(
|
|
ProxmoxVMBinarySensor(coordinator, entity_description, vm, node_data)
|
|
for (node_data, vm) in vms
|
|
for entity_description in VM_SENSORS
|
|
)
|
|
|
|
def _async_add_new_containers(
|
|
containers: list[tuple[ProxmoxNodeData, dict[str, Any]]],
|
|
) -> None:
|
|
"""Add new container binary sensors."""
|
|
async_add_entities(
|
|
ProxmoxContainerBinarySensor(
|
|
coordinator, entity_description, container, node_data
|
|
)
|
|
for (node_data, container) in containers
|
|
for entity_description in CONTAINER_SENSORS
|
|
)
|
|
|
|
def _async_add_new_storages(
|
|
storages: list[tuple[ProxmoxNodeData, dict[str, Any]]],
|
|
) -> None:
|
|
"""Add new storage binary sensors."""
|
|
async_add_entities(
|
|
ProxmoxStorageBinarySensor(
|
|
coordinator, entity_description, storage, node_data
|
|
)
|
|
for (node_data, storage) in storages
|
|
for entity_description in STORAGE_SENSORS
|
|
)
|
|
|
|
coordinator.new_nodes_callbacks.append(_async_add_new_nodes)
|
|
coordinator.new_vms_callbacks.append(_async_add_new_vms)
|
|
coordinator.new_containers_callbacks.append(_async_add_new_containers)
|
|
coordinator.new_storages_callbacks.append(_async_add_new_storages)
|
|
|
|
_async_add_new_nodes(
|
|
[
|
|
node_data
|
|
for node_data in coordinator.data.values()
|
|
if node_data.node["node"] in coordinator.known_nodes
|
|
]
|
|
)
|
|
_async_add_new_vms(
|
|
[
|
|
(node_data, vm_data)
|
|
for node_data in coordinator.data.values()
|
|
for vmid, vm_data in node_data.vms.items()
|
|
if (node_data.node["node"], vmid) in coordinator.known_vms
|
|
]
|
|
)
|
|
_async_add_new_containers(
|
|
[
|
|
(node_data, container_data)
|
|
for node_data in coordinator.data.values()
|
|
for vmid, container_data in node_data.containers.items()
|
|
if (node_data.node["node"], vmid) in coordinator.known_containers
|
|
]
|
|
)
|
|
_async_add_new_storages(
|
|
[
|
|
(node_data, storage_data)
|
|
for node_data in coordinator.data.values()
|
|
for storage_id, storage_data in node_data.storages.items()
|
|
if (node_data.node["node"], storage_id) in coordinator.known_storages
|
|
]
|
|
)
|
|
|
|
|
|
class ProxmoxNodeBinarySensor(ProxmoxNodeEntity, BinarySensorEntity):
|
|
"""A binary sensor for reading Proxmox VE node data."""
|
|
|
|
entity_description: ProxmoxNodeBinarySensorEntityDescription
|
|
|
|
@property
|
|
def is_on(self) -> bool | None:
|
|
"""Return true if the binary sensor is on."""
|
|
return self.entity_description.state_fn(self.coordinator.data[self.device_name])
|
|
|
|
|
|
class ProxmoxVMBinarySensor(ProxmoxVMEntity, BinarySensorEntity):
|
|
"""Representation of a Proxmox VM binary sensor."""
|
|
|
|
entity_description: ProxmoxVMBinarySensorEntityDescription
|
|
|
|
@property
|
|
def is_on(self) -> bool | None:
|
|
"""Return true if the binary sensor is on."""
|
|
return self.entity_description.state_fn(self.vm_data)
|
|
|
|
|
|
class ProxmoxContainerBinarySensor(ProxmoxContainerEntity, BinarySensorEntity):
|
|
"""Representation of a Proxmox Container binary sensor."""
|
|
|
|
entity_description: ProxmoxContainerBinarySensorEntityDescription
|
|
|
|
@property
|
|
def is_on(self) -> bool | None:
|
|
"""Return true if the binary sensor is on."""
|
|
return self.entity_description.state_fn(self.container_data)
|
|
|
|
|
|
class ProxmoxStorageBinarySensor(ProxmoxStorageEntity, BinarySensorEntity):
|
|
"""Representation of a Proxmox Storage binary sensor."""
|
|
|
|
entity_description: ProxmoxStorageBinarySensorEntityDescription
|
|
|
|
@property
|
|
def is_on(self) -> bool | None:
|
|
"""Return true if the binary sensor is on."""
|
|
return self.entity_description.state_fn(self.storage_data)
|