mirror of
https://github.com/thegeeklab/prometheus-pve-sd.git
synced 2024-06-02 07:59:40 +02:00
Add proxmox client wrapper
This commit is contained in:
parent
dfb18c1dd8
commit
8ff74fa420
90
prometheuspvesd/client.py
Normal file
90
prometheuspvesd/client.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
"""Proxmox Client."""
|
||||
import requests
|
||||
from prometheus_client import Counter
|
||||
|
||||
from prometheuspvesd.config import SingleConfig
|
||||
from prometheuspvesd.exception import APIError
|
||||
from prometheuspvesd.logger import SingleLog
|
||||
from prometheuspvesd.model import HostList
|
||||
from prometheuspvesd.utils import to_bool
|
||||
|
||||
try:
|
||||
from proxmoxer import ProxmoxAPI
|
||||
HAS_PROXMOXER = True
|
||||
except ImportError:
|
||||
HAS_PROXMOXER = False
|
||||
|
||||
PVE_REQUEST_COUNT_TOTAL = Counter("pve_sd_requests_total", "Total count of requests to PVE API")
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL = Counter(
|
||||
"pve_sd_requests_error_total", "Total count of failed requests to PVE API"
|
||||
)
|
||||
|
||||
|
||||
class ProxmoxClient:
|
||||
"""Proxmox API Client."""
|
||||
|
||||
def __init__(self):
|
||||
if not HAS_PROXMOXER:
|
||||
self.log.sysexit_with_message(
|
||||
"The Proxmox VE Prometheus SD requires proxmoxer: "
|
||||
"https://pypi.org/project/proxmoxer/"
|
||||
)
|
||||
|
||||
self.config = SingleConfig()
|
||||
self.log = SingleLog()
|
||||
self.logger = SingleLog().logger
|
||||
self.client = self._auth()
|
||||
self.logger.debug("Successfully authenticated")
|
||||
self.host_list = HostList()
|
||||
|
||||
def _auth(self):
|
||||
try:
|
||||
self.logger.debug(
|
||||
"Trying to authenticate against {} as user {}".format(
|
||||
self.config.config["pve"]["server"], self.config.config["pve"]["user"]
|
||||
)
|
||||
)
|
||||
return ProxmoxAPI(
|
||||
self.config.config["pve"]["server"],
|
||||
user=self.config.config["pve"]["user"],
|
||||
password=self.config.config["pve"]["password"],
|
||||
verify_ssl=to_bool(self.config.config["pve"]["verify_ssl"]),
|
||||
timeout=self.config.config["pve"]["auth_timeout"]
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL.inc()
|
||||
raise APIError(str(e))
|
||||
|
||||
def _do_request(self, *args):
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
try:
|
||||
# create a new tuple containing nodes and unpack it again for client.get
|
||||
return self.client.get(*("nodes", *args))
|
||||
except requests.RequestException as e:
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL.inc()
|
||||
raise APIError(str(e))
|
||||
|
||||
def get_nodes(self):
|
||||
self.logger.debug("fetching all nodes")
|
||||
return self._do_request()
|
||||
|
||||
def get_all_vms(self, pve_node):
|
||||
self.logger.debug("fetching all vms on node {}".format(pve_node))
|
||||
return self._do_request(pve_node, "qemu")
|
||||
|
||||
def get_all_containers(self, pve_node):
|
||||
self.logger.debug("fetching all containers on node {}".format(pve_node))
|
||||
return self._do_request(pve_node, "lxc")
|
||||
|
||||
def get_instance_config(self, pve_node, pve_type, vmid):
|
||||
self.logger.debug("fetching instance config for {} on {}".format(vmid, pve_node))
|
||||
return self._do_request(pve_node, pve_type, vmid, "config")
|
||||
|
||||
def get_agent_info(self, pve_node, pve_type, vmid):
|
||||
self.logger.debug("fetching agent info for {} on {}".format(vmid, pve_node))
|
||||
return self._do_request(pve_node, pve_type, vmid, "agent", "info")["result"]
|
||||
|
||||
def get_network_interfaces(self, pve_node, vmid):
|
||||
self.logger.debug("fetching network interfaces for {} on {}".format(vmid, pve_node))
|
||||
return self._do_request(pve_node, "qemu", vmid, "agent",
|
||||
"network-get-interfaces")["result"]
|
|
@ -6,63 +6,32 @@ import json
|
|||
import re
|
||||
from collections import defaultdict
|
||||
|
||||
import requests
|
||||
from prometheus_client import Counter
|
||||
from prometheus_client import Gauge
|
||||
from prometheus_client import Summary
|
||||
|
||||
from prometheuspvesd.client import ProxmoxClient
|
||||
from prometheuspvesd.config import SingleConfig
|
||||
from prometheuspvesd.exception import APIError
|
||||
from prometheuspvesd.logger import SingleLog
|
||||
from prometheuspvesd.model import Host
|
||||
from prometheuspvesd.model import HostList
|
||||
from prometheuspvesd.utils import to_bool
|
||||
|
||||
try:
|
||||
from proxmoxer import ProxmoxAPI
|
||||
HAS_PROXMOXER = True
|
||||
except ImportError:
|
||||
HAS_PROXMOXER = False
|
||||
|
||||
PROPAGATION_TIME = Summary(
|
||||
"pve_sd_propagate_seconds", "Time spent propagating the inventory from PVE"
|
||||
)
|
||||
HOST_GAUGE = Gauge("pve_sd_hosts", "Number of hosts discovered by PVE SD")
|
||||
PVE_REQUEST_COUNT_TOTAL = Counter("pve_sd_requests_total", "Total count of requests to PVE API")
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL = Counter(
|
||||
"pve_sd_requests_error_total", "Total count of failed requests to PVE API"
|
||||
)
|
||||
|
||||
|
||||
class Discovery():
|
||||
"""Prometheus PVE Service Discovery."""
|
||||
|
||||
def __init__(self):
|
||||
if not HAS_PROXMOXER:
|
||||
self.log.sysexit_with_message(
|
||||
"The Proxmox VE Prometheus SD requires proxmoxer: "
|
||||
"https://pypi.org/project/proxmoxer/"
|
||||
)
|
||||
|
||||
self.config = SingleConfig()
|
||||
self.log = SingleLog()
|
||||
self.logger = SingleLog().logger
|
||||
self.client = self._auth()
|
||||
self.client = ProxmoxClient()
|
||||
self.host_list = HostList()
|
||||
|
||||
def _auth(self):
|
||||
try:
|
||||
return ProxmoxAPI(
|
||||
self.config.config["pve"]["server"],
|
||||
user=self.config.config["pve"]["user"],
|
||||
password=self.config.config["pve"]["password"],
|
||||
verify_ssl=to_bool(self.config.config["pve"]["verify_ssl"]),
|
||||
timeout=self.config.config["pve"]["auth_timeout"]
|
||||
)
|
||||
except requests.RequestException as e:
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL.inc()
|
||||
raise APIError(str(e))
|
||||
|
||||
def _get_names(self, pve_list, pve_type):
|
||||
names = []
|
||||
|
||||
|
@ -92,11 +61,8 @@ class Discovery():
|
|||
if pve_type == "qemu":
|
||||
# If qemu agent is enabled, try to gather the IP address
|
||||
try:
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
if self.client.get("nodes", pve_node, pve_type, vmid, "agent", "info") is not None:
|
||||
networks = self.client.get(
|
||||
"nodes", pve_node, "qemu", vmid, "agent", "network-get-interfaces"
|
||||
)["result"]
|
||||
if self.client.get_agent_info(pve_node, pve_type, vmid) is not None:
|
||||
networks = self.client.get_network_interfaces(pve_node, vmid)
|
||||
except Exception: # noqa # nosec
|
||||
pass
|
||||
|
||||
|
@ -108,10 +74,9 @@ class Discovery():
|
|||
elif ip_address["ip-address-type"] == "ipv6" and not ipv6_address:
|
||||
ipv6_address = self._validate_ip(ip_address["ip-address"])
|
||||
|
||||
if not ipv4_address:
|
||||
config = self.client.get_instance_config(pve_node, pve_type, vmid)
|
||||
if config and not ipv4_address:
|
||||
try:
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
config = self.client.get("nodes", pve_node, pve_type, vmid, "config")
|
||||
if "ipconfig0" in config.keys():
|
||||
sources = [config["net0"], config["ipconfig0"]]
|
||||
else:
|
||||
|
@ -125,10 +90,8 @@ class Discovery():
|
|||
except Exception: # noqa # nosec
|
||||
pass
|
||||
|
||||
if not ipv6_address:
|
||||
if config and not ipv6_address:
|
||||
try:
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
config = self.client.get("nodes", pve_node, pve_type, vmid, "config")
|
||||
if "ipconfig0" in config.keys():
|
||||
sources = [config["net0"], config["ipconfig0"]]
|
||||
else:
|
||||
|
@ -194,15 +157,11 @@ class Discovery():
|
|||
def propagate(self):
|
||||
self.host_list.clear()
|
||||
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
for node in self._get_names(self.client.get("nodes"), "node"):
|
||||
for node in self._get_names(self.client.get_nodes(), "node"):
|
||||
try:
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
qemu_list = self._filter(self.client.get("nodes", node, "qemu"))
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
container_list = self._filter(self.client.get("nodes", node, "lxc"))
|
||||
qemu_list = self._filter(self.client.get_all_vms(node))
|
||||
container_list = self._filter(self.client.get_all_containers(node))
|
||||
except Exception as e: # noqa
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL.inc()
|
||||
raise APIError(str(e))
|
||||
|
||||
# Merge QEMU and Containers lists from this node
|
||||
|
@ -220,15 +179,13 @@ class Discovery():
|
|||
except KeyError:
|
||||
pve_type = "qemu"
|
||||
|
||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||
config = self.client.get("nodes", node, pve_type, vmid, "config")
|
||||
config = self.client.get_instance_config(node, pve_type, vmid)
|
||||
|
||||
try:
|
||||
description = (config["description"])
|
||||
except KeyError:
|
||||
description = None
|
||||
except Exception as e: # noqa
|
||||
PVE_REQUEST_COUNT_ERROR_TOTAL.inc()
|
||||
raise APIError(str(e))
|
||||
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue
Block a user