Rework Proxmoxve to use a DataUpdateCoordinator (#45068)
Co-authored-by: Paulus Schoutsen <paulus@home-assistant.io>
This commit is contained in:
parent
4efe6762c4
commit
4bca9596ee
2 changed files with 264 additions and 130 deletions
|
@ -1,112 +1,95 @@
|
|||
"""Binary sensor to read Proxmox VE data."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.const import ATTR_ATTRIBUTION, CONF_HOST, CONF_PORT
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import CONF_CONTAINERS, CONF_NODES, CONF_VMS, PROXMOX_CLIENTS, ProxmoxItemType
|
||||
from . import COORDINATOR, DOMAIN, ProxmoxEntity
|
||||
|
||||
ATTRIBUTION = "Data provided by Proxmox VE"
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up the sensor platform."""
|
||||
async def async_setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up binary sensors."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
coordinator = hass.data[DOMAIN][COORDINATOR]
|
||||
|
||||
sensors = []
|
||||
|
||||
for entry in discovery_info["entries"]:
|
||||
port = entry[CONF_PORT]
|
||||
for host_config in discovery_info["config"][DOMAIN]:
|
||||
host_name = host_config["host"]
|
||||
|
||||
for node in entry[CONF_NODES]:
|
||||
for virtual_machine in node[CONF_VMS]:
|
||||
sensors.append(
|
||||
ProxmoxBinarySensor(
|
||||
hass.data[PROXMOX_CLIENTS][f"{entry[CONF_HOST]}:{port}"],
|
||||
node["node"],
|
||||
ProxmoxItemType.qemu,
|
||||
virtual_machine,
|
||||
)
|
||||
for node_config in host_config["nodes"]:
|
||||
node_name = node_config["node"]
|
||||
|
||||
for vm_id in node_config["vms"]:
|
||||
coordinator_data = coordinator.data[host_name][node_name][vm_id]
|
||||
|
||||
# unfound vm case
|
||||
if coordinator_data is None:
|
||||
continue
|
||||
|
||||
vm_name = coordinator_data["name"]
|
||||
vm_status = create_binary_sensor(
|
||||
coordinator, host_name, node_name, vm_id, vm_name
|
||||
)
|
||||
sensors.append(vm_status)
|
||||
|
||||
for container in node[CONF_CONTAINERS]:
|
||||
sensors.append(
|
||||
ProxmoxBinarySensor(
|
||||
hass.data[PROXMOX_CLIENTS][f"{entry[CONF_HOST]}:{port}"],
|
||||
node["node"],
|
||||
ProxmoxItemType.lxc,
|
||||
container,
|
||||
)
|
||||
for container_id in node_config["containers"]:
|
||||
coordinator_data = coordinator.data[host_name][node_name][container_id]
|
||||
|
||||
# unfound container case
|
||||
if coordinator_data is None:
|
||||
continue
|
||||
|
||||
container_name = coordinator_data["name"]
|
||||
container_status = create_binary_sensor(
|
||||
coordinator, host_name, node_name, container_id, container_name
|
||||
)
|
||||
sensors.append(container_status)
|
||||
|
||||
add_entities(sensors, True)
|
||||
add_entities(sensors)
|
||||
|
||||
|
||||
class ProxmoxBinarySensor(BinarySensorEntity):
|
||||
def create_binary_sensor(coordinator, host_name, node_name, vm_id, name):
|
||||
"""Create a binary sensor based on the given data."""
|
||||
return ProxmoxBinarySensor(
|
||||
coordinator=coordinator,
|
||||
unique_id=f"proxmox_{node_name}_{vm_id}_running",
|
||||
name=f"{node_name}_{name}_running",
|
||||
icon="",
|
||||
host_name=host_name,
|
||||
node_name=node_name,
|
||||
vm_id=vm_id,
|
||||
)
|
||||
|
||||
|
||||
class ProxmoxBinarySensor(ProxmoxEntity):
|
||||
"""A binary sensor for reading Proxmox VE data."""
|
||||
|
||||
def __init__(self, proxmox_client, item_node, item_type, item_id):
|
||||
"""Initialize the binary sensor."""
|
||||
self._proxmox_client = proxmox_client
|
||||
self._item_node = item_node
|
||||
self._item_type = item_type
|
||||
self._item_id = item_id
|
||||
|
||||
self._vmname = None
|
||||
self._name = None
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator,
|
||||
unique_id,
|
||||
name,
|
||||
icon,
|
||||
host_name,
|
||||
node_name,
|
||||
vm_id,
|
||||
):
|
||||
"""Create the binary sensor for vms or containers."""
|
||||
super().__init__(
|
||||
coordinator, unique_id, name, icon, host_name, node_name, vm_id
|
||||
)
|
||||
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if VM/container is running."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return device attributes of the entity."""
|
||||
return {
|
||||
"node": self._item_node,
|
||||
"vmid": self._item_id,
|
||||
"vmname": self._vmname,
|
||||
"type": self._item_type.name,
|
||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||
}
|
||||
|
||||
def update(self):
|
||||
"""Check if the VM/Container is running."""
|
||||
item = self.poll_item()
|
||||
|
||||
if item is None:
|
||||
_LOGGER.warning("Failed to poll VM/container %s", self._item_id)
|
||||
return
|
||||
|
||||
self._state = item["status"] == "running"
|
||||
|
||||
def poll_item(self):
|
||||
"""Find the VM/Container with the set item_id."""
|
||||
items = (
|
||||
self._proxmox_client.get_api_client()
|
||||
.nodes(self._item_node)
|
||||
.get(self._item_type.name)
|
||||
)
|
||||
item = next(
|
||||
(item for item in items if item["vmid"] == str(self._item_id)), None
|
||||
)
|
||||
|
||||
if item is None:
|
||||
_LOGGER.warning("Couldn't find VM/Container with the ID %s", self._item_id)
|
||||
return None
|
||||
|
||||
if self._vmname is None:
|
||||
self._vmname = item["name"]
|
||||
|
||||
if self._name is None:
|
||||
self._name = f"{self._item_node} {self._vmname} running"
|
||||
|
||||
return item
|
||||
def state(self):
|
||||
"""Return the state of the binary sensor."""
|
||||
data = self.coordinator.data[self._host_name][self._node_name][self._vm_id]
|
||||
if data["status"] == "running":
|
||||
return STATE_ON
|
||||
return STATE_OFF
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue