1 """Support for Proxmox VE."""
3 from __future__
import annotations
5 from datetime
import timedelta
8 from proxmoxer
import AuthenticationError, ProxmoxAPI
9 from proxmoxer.core
import ResourceException
10 import requests.exceptions
11 from requests.exceptions
import ConnectTimeout, SSLError
12 import voluptuous
as vol
46 PLATFORMS = [Platform.BINARY_SENSOR]
48 CONFIG_SCHEMA = vol.Schema(
55 vol.Required(CONF_HOST): cv.string,
56 vol.Required(CONF_USERNAME): cv.string,
57 vol.Required(CONF_PASSWORD): cv.string,
58 vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
59 vol.Optional(CONF_REALM, default=DEFAULT_REALM): cv.string,
61 CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL
63 vol.Required(CONF_NODES): vol.All(
68 vol.Required(CONF_NODE): cv.string,
69 vol.Optional(CONF_VMS, default=[]): [
72 vol.Optional(CONF_CONTAINERS, default=[]): [
84 extra=vol.ALLOW_EXTRA,
88 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
89 """Set up the platform."""
90 hass.data.setdefault(DOMAIN, {})
92 def build_client() -> ProxmoxAPI:
93 """Build the Proxmox client connection."""
94 hass.data[PROXMOX_CLIENTS] = {}
96 for entry
in config[DOMAIN]:
97 host = entry[CONF_HOST]
98 port = entry[CONF_PORT]
99 user = entry[CONF_USERNAME]
100 realm = entry[CONF_REALM]
101 password = entry[CONF_PASSWORD]
102 verify_ssl = entry[CONF_VERIFY_SSL]
104 hass.data[PROXMOX_CLIENTS][host] =
None
109 host, port, user, realm, password, verify_ssl
111 proxmox_client.build_client()
112 except AuthenticationError:
114 "Invalid credentials for proxmox instance %s:%d", host, port
120 "Unable to verify proxmox server SSL. "
121 'Try using "verify_ssl: false" for proxmox instance %s:%d'
127 except ConnectTimeout:
128 _LOGGER.warning(
"Connection to host %s timed out during setup", host)
130 except requests.exceptions.ConnectionError:
131 _LOGGER.warning(
"Host %s is not reachable", host)
134 hass.data[PROXMOX_CLIENTS][host] = proxmox_client
136 await hass.async_add_executor_job(build_client)
139 str, dict[str, dict[int, DataUpdateCoordinator[dict[str, Any] |
None]]]
141 hass.data[DOMAIN][COORDINATORS] = coordinators
144 for host_config
in config[DOMAIN]:
145 host_name = host_config[
"host"]
146 coordinators[host_name] = {}
148 proxmox_client = hass.data[PROXMOX_CLIENTS][host_name]
151 if proxmox_client
is None:
154 proxmox = proxmox_client.get_api_client()
156 for node_config
in host_config[
"nodes"]:
157 node_name = node_config[
"node"]
158 node_coordinators = coordinators[host_name][node_name] = {}
160 for vm_id
in node_config[
"vms"]:
162 hass, proxmox, host_name, node_name, vm_id, TYPE_VM
166 await coordinator.async_refresh()
168 node_coordinators[vm_id] = coordinator
170 for container_id
in node_config[
"containers"]:
172 hass, proxmox, host_name, node_name, container_id, TYPE_CONTAINER
176 await coordinator.async_refresh()
178 node_coordinators[container_id] = coordinator
180 for component
in PLATFORMS:
181 await hass.async_create_task(
195 ) -> DataUpdateCoordinator[dict[str, Any] |
None]:
196 """Create and return a DataUpdateCoordinator for a vm/container."""
198 async
def async_update_data() -> dict[str, Any] | None:
199 """Call the api and handle the response."""
201 def poll_api() -> dict[str, Any] | None:
205 vm_status = await hass.async_add_executor_job(poll_api)
207 if vm_status
is None:
209 "Vm/Container %s unable to be found in node %s", vm_id, node_name
218 name=f
"proxmox_coordinator_{host_name}_{node_name}_{vm_id}",
219 update_method=async_update_data,
220 update_interval=
timedelta(seconds=UPDATE_INTERVAL),
225 """Get the container or vm api data and return it formatted in a dictionary.
227 It is implemented in this way to allow for more data to be added for sensors
231 return {
"status": status[
"status"],
"name": status[
"name"]}
239 ) -> dict[str, Any] |
None:
240 """Make proper api calls."""
244 if machine_type == TYPE_VM:
245 status = proxmox.nodes(node_name).qemu(vm_id).status.current.get()
246 elif machine_type == TYPE_CONTAINER:
247 status = proxmox.nodes(node_name).lxc(vm_id).status.current.get()
248 except (ResourceException, requests.exceptions.ConnectionError):
255 """A wrapper for the proxmoxer ProxmoxAPI client."""
268 """Initialize the ProxmoxClient."""
278 """Construct the ProxmoxAPI client.
280 Allows inserting the realm within the `user` value.
283 if "@" in self.
_user_user:
284 user_id = self.
_user_user
286 user_id = f
"{self._user}@{self._realm}"
290 port=self.
_port_port,
297 """Return the ProxmoxAPI client."""
None __init__(self, str host, int port, str user, str realm, str password, bool verify_ssl)
ProxmoxAPI get_api_client(self)
bool async_setup(HomeAssistant hass, ConfigType config)
DataUpdateCoordinator[dict[str, Any]|None] create_coordinator_container_vm(HomeAssistant hass, ProxmoxAPI proxmox, str host_name, str node_name, int vm_id, int vm_type)
dict[str, Any]|None call_api_container_vm(ProxmoxAPI proxmox, str node_name, int vm_id, int machine_type)
dict[str, Any] parse_api_container_vm(dict[str, Any] status)
None async_load_platform(core.HomeAssistant hass, Platform|str component, str platform, DiscoveryInfoType|None discovered, ConfigType hass_config)