hass-core/homeassistant/components/proxmoxve/__init__.py
John Hollowell c3cef7227c Add proxmoxve SSLError check and remove log spam (#30818)
* Add SSLError check and remove log spam

* Update homeassistant/components/proxmoxve/manifest.json

remove unnecessary requirement

* Remove log level change

Moved to proxmoxer library

* Update homeassistant/components/proxmoxve/__init__.py

* Update manifest.json

Update to new version of dependency which fixes log issue

* Run formatter and requires updates

* oops, tabs

* Fix quote marks

When you can't get black running, just fix whatever CI says is wrong!
2020-01-28 22:52:59 +01:00

161 lines
4.7 KiB
Python

"""Support for Proxmox VE."""
from enum import Enum
import logging
import time
from proxmoxer import ProxmoxAPI
from proxmoxer.backends.https import AuthenticationError
from requests.exceptions import SSLError
import voluptuous as vol
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_PORT,
CONF_USERNAME,
CONF_VERIFY_SSL,
)
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
DOMAIN = "proxmoxve"
PROXMOX_CLIENTS = "proxmox_clients"
CONF_REALM = "realm"
CONF_NODE = "node"
CONF_NODES = "nodes"
CONF_VMS = "vms"
CONF_CONTAINERS = "containers"
DEFAULT_PORT = 8006
DEFAULT_REALM = "pam"
DEFAULT_VERIFY_SSL = True
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,
)
def setup(hass, config):
"""Set up the component."""
# Create API Clients for later use
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]
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"'
)
continue
hass.data[PROXMOX_CLIENTS][f"{host}:{port}"] = proxmox_client
if hass.data[PROXMOX_CLIENTS]:
hass.helpers.discovery.load_platform(
"binary_sensor", DOMAIN, {"entries": config[DOMAIN]}, config
)
return True
return False
class ProxmoxItemType(Enum):
"""Represents the different types of machines in Proxmox."""
qemu = 0
lxc = 1
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."""
self._proxmox = ProxmoxAPI(
self._host,
port=self._port,
user=f"{self._user}@{self._realm}",
password=self._password,
verify_ssl=self._verify_ssl,
)
self._connection_start_time = time.time()
def get_api_client(self):
"""Return the ProxmoxAPI client and rebuild it if necessary."""
connection_age = time.time() - self._connection_start_time
# Workaround for the Proxmoxer bug where the connection stops working after some time
if connection_age > 30 * 60:
self.build_client()
return self._proxmox