text: """Support for Proxmox VE."""
  from datetime import timedelta
  import logging
  
  from proxmoxer import ProxmoxAPI
  from proxmoxer.backends.https import AuthenticationError
  from proxmoxer.core import ResourceException
  import requests.exceptions
  from requests.exceptions import ConnectTimeout, SSLError
  import voluptuous as vol
  
  from homeassistant.const import (
      CONF_HOST,
      CONF_PASSWORD,
      CONF_PORT,
      CONF_USERNAME,
      CONF_VERIFY_SSL,
  )
  from homeassistant.core import HomeAssistant
  import homeassistant.helpers.config_validation as cv
  from homeassistant.helpers.update_coordinator import (
      CoordinatorEntity,
      DataUpdateCoordinator,
  )
  
  PLATFORMS = ["binary_sensor"]
  DOMAIN = "proxmoxve"
  PROXMOX_CLIENTS = "proxmox_clients"
  CONF_REALM = "realm"
  CONF_NODE = "node"
  CONF_NODES = "nodes"
  CONF_VMS = "vms"
  CONF_CONTAINERS = "containers"
  
  COORDINATORS = "coordinators"
  API_DATA = "api_data"
  
  DEFAULT_PORT = 8006
  DEFAULT_REALM = "pam"
  DEFAULT_VERIFY_SSL = True
  TYPE_VM = 0
  TYPE_CONTAINER = 1
  UPDATE_INTERVAL = 60
  
  _LOGGER = logging.getLogger(__name__)
  
  CONFIG_SCHEMA = vol.Schema(
      {
          DOMAIN: vol.All(
              cv.ensure_list,
              [
                  vol.Schema(
                      {
                          vol.Required(CONF_HOST): cv.string,
                          vol.Required(CONF_USERNAME): cv.string,
                          vol.Required(CONF_PASSWORD): cv.string,
                          vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
                          vol.Optional(CONF_REALM, default=DEFAULT_REALM): cv.string,
                          vol.Optional(
                              CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL
                          ): cv.boolean,
                          vol.Required(CONF_NODES): vol.All(
                              cv.ensure_list,
                              [
                                  vol.Schema(
                                      {
                                          vol.Required(CONF_NODE): cv.string,
                                          vol.Optional(CONF_VMS, default=[]): [
                                              cv.positive_int
                                          ],
                                          vol.Optional(CONF_CONTAINERS, default=[]): [
                                              cv.positive_int
                                          ],
                                      }
                                  )
                              ],
                          ),
                      }
                  )
              ],
          )
      },
      extra=vol.ALLOW_EXTRA,
  )
  
  
  async def async_setup(hass: HomeAssistant, config: dict):
      """Set up the platform."""
      hass.data.setdefault(DOMAIN, {})
  
      def build_client() -> ProxmoxAPI:
          """Build the Proxmox client connection."""
          hass.data[PROXMOX_CLIENTS] = {}
  
          for entry in config[DOMAIN]:
              host = entry[CONF_HOST]
              port = entry[CONF_PORT]
              user = entry[CONF_USERNAME]
              realm = entry[CONF_REALM]
              password = entry[CONF_PASSWORD]
              verify_ssl = entry[CONF_VERIFY_SSL]
  
              hass.data[PROXMOX_CLIENTS][host] = None
  
              try:
                  # Construct an API client with the given data for the given host
                  proxmox_client = ProxmoxClient(
                      host, port, user, realm, password, verify_ssl
                  )
                  proxmox_client.build_client()
              except AuthenticationError:
                  _LOGGER.warning(
                      "Invalid credentials for proxmox instance %s:%d", host, port
                  )
                  continue
              except SSLError:
                  _LOGGER.error(
                      "Unable to verify proxmox server SSL. "
                      'Try using "verify_ssl: false" for proxmox instance %s:%d',
                      host,
                      port,
                  )
                  continue
              except ConnectTimeout:
                  _LOGGER.warning("Connection to host %s timed out during setup", host)
                  continue
  
              hass.data[PROXMOX_CLIENTS][host] = proxmox_client
  
      await hass.async_add_executor_job(build_client)
  
      coordinators = hass.data[DOMAIN][COORDINATORS] = {}
  
      # Create a coordinator for each vm/container
      for host_config in config[DOMAIN]:
          host_name = host_config["host"]
          coordinators[host_name] = {}
  
          proxmox_client = hass.data[PROXMOX_CLIENTS][host_name]
  
          # Skip invalid hosts
          if proxmox_client is None:
              continue
  
          proxmox = proxmox_client.get_api_client()
  
          for node_config in host_config["nodes"]:
              node_name = node_config["node"]
              node_coordinators = coordinators[host_name][node_name] = {}
  
              for vm_id in node_config["vms"]:
                  coordinator = create_coordinator_container_vm(
                      hass, proxmox, host_name, node_name, vm_id, TYPE_VM
                  )
  
                  # Fetch initial data
                  await coordinator.async_refresh()
  
                  node_coordinators[vm_id] = coordinator
  
              for container_id in node_config["containers"]:
                  coordinator = create_coordinator_container_vm(
                      hass, proxmox, host_name, node_name, container_id, TYPE_CONTAINER
                  )
  
                  # Fetch initial data
                  await coordinator.async_refresh()
  
                  node_coordinators[container_id] = coordinator
  
      for component in PLATFORMS:
          await hass.async_create_task(
              hass.helpers.discovery.async_load_platform(
                  component, DOMAIN, {"config": config}, config
              )
          )
  
      return True
  
  
  def create_coordinator_container_vm(
      hass, proxmox, host_name, node_name, vm_id, vm_type
  ):
      """Create and return a DataUpdateCoordinator for a vm/container."""
  
      async def async_update_data():
          """Call the api and handle the response."""
  
          def poll_api():
              """Call the api."""
              vm_status = call_api_container_vm(proxmox, node_name, vm_id, vm_type)
              return vm_status
  
          vm_status = await hass.async_add_executor_job(poll_api)
  
          if vm_status is None:
              _LOGGER.warning(
                  "Vm/Container %s unable to be found in node %s", vm_id, node_name
              )
              return None
  
          return parse_api_container_vm(vm_status)
  
      return DataUpdateCoordinator(
          hass,
          _LOGGER,
          name=f"proxmox_coordinator_{host_name}_{node_name}_{vm_id}",
          update_method=async_update_data,
          update_interval=timedelta(seconds=UPDATE_INTERVAL),
      )
  
  
  def parse_api_container_vm(status):
      """Get the container or vm api data and return it formatted in a dictionary.
  
      It is implemented in this way to allow for more data to be added for sensors
      in the future.
      """
  
      return {"status": status["status"], "name": status["name"]}
  
  
  def call_api_container_vm(proxmox, node_name, vm_id, machine_type):
      """Make proper api calls."""
      status = None
  
      try:
          if machine_type == TYPE_VM:
              status = proxmox.nodes(node_name).qemu(vm_id).status.current.get()
          elif machine_type == TYPE_CONTAINER:
              status = proxmox.nodes(node_name).lxc(vm_id).status.current.get()
      except (ResourceException, requests.exceptions.ConnectionError):
          return None
  
      return status
  
  
  class ProxmoxEntity(CoordinatorEntity):
      """Represents any entity created for the Proxmox VE platform."""
  
      def __init__(
          self,
          coordinator: DataUpdateCoordinator,
          unique_id,
          name,
          icon,
          host_name,
          node_name,
          vm_id=None,
      ):
          """Initialize the Proxmox entity."""
          super().__init__(coordinator)
  
          self.coordinator = coordinator
          self._unique_id = unique_id
          self._name = name
          self._host_name = host_name
          self._icon = icon
          self._available = True
          self._node_name = node_name
          self._vm_id = vm_id
  
          self._state = None
  
      @property
      def unique_id(self) -> str:
          """Return the unique ID for this sensor."""
          return self._unique_id
  
      @property
      def name(self) -> str:
          """Return the name of the entity."""
          return self._name
  
      @property
      def icon(self) -> str:
          """Return the mdi icon of the entity."""
          return self._icon
  
      @property
      def available(self) -> bool:
          """Return True if entity is available."""
          return self.coordinator.last_update_success and self._available
  
  
  class ProxmoxClient:
      """A wrapper for the proxmoxer ProxmoxAPI client."""
  
      def __init__(self, host, port, user, realm, password, verify_ssl):
          """Initialize the ProxmoxClient."""
  
          self._host = host
          self._port = port
          self._user = user
          self._realm = realm
          self._password = password
          self._verify_ssl = verify_ssl
  
          self._proxmox = None
          self._connection_start_time = None
  
      def build_client(self):
          """Construct the ProxmoxAPI client. Allows inserting the realm within the `user` value."""
  
          if "@" in self._user:
              user_id = self._user
          else:
              user_id = f"{self._user}@{self._realm}"
  
          self._proxmox = ProxmoxAPI(
              self._host,
              port=self._port,
              user=user_id,
              password=self._password,
              verify_ssl=self._verify_ssl,
          )
  
      def get_api_client(self):
          """Return the ProxmoxAPI client."""
          return self._proxmox
  