mirror of
https://github.com/thegeeklab/prometheus-pve-sd.git
synced 2024-11-28 12:20:35 +00:00
fix: add proper discovery of IPv6 and IPv4 addresses (#155)
BREAKING CHANGE: The label `__meta_pve_ip` was removed in favor of `__meta_pve_ipv4` and `__meta_pve_ipv6`.
This commit is contained in:
parent
4f4e1950ab
commit
d15a01fd6a
@ -25,6 +25,7 @@ loop_delay: 300
|
|||||||
service: true
|
service: true
|
||||||
|
|
||||||
exclude_state: []
|
exclude_state: []
|
||||||
|
# needs to be a list of strings
|
||||||
exclude_vmid: []
|
exclude_vmid: []
|
||||||
|
|
||||||
pve:
|
pve:
|
||||||
|
@ -16,7 +16,9 @@ run prometheus-pve-sd -vv --loop-delay 900 -o /etc/prometheus/pve.json
|
|||||||
|
|
||||||
The following list of meta labels can be used to relabel your scrape results:
|
The following list of meta labels can be used to relabel your scrape results:
|
||||||
|
|
||||||
`__meta_pve_ip`
|
`__meta_pve_ipv4`
|
||||||
|
|
||||||
|
`__meta_pve_ipv6`
|
||||||
|
|
||||||
`__meta_pve_name`
|
`__meta_pve_name`
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Prometheus Discovery."""
|
"""Prometheus Discovery."""
|
||||||
|
|
||||||
|
import ipaddress
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import socket
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@ -85,19 +85,18 @@ class Discovery():
|
|||||||
|
|
||||||
return variables
|
return variables
|
||||||
|
|
||||||
def _get_ip_address(self, pve_type, pve_node, vmid):
|
def _get_ip_addresses(self, pve_type, pve_node, vmid):
|
||||||
|
|
||||||
def validate(address):
|
def validate_ip(address: object) -> object:
|
||||||
try:
|
try:
|
||||||
# IP address validation
|
if not ipaddress.ip_address(address).is_loopback \
|
||||||
if socket.inet_aton(address):
|
and not ipaddress.ip_address(address).is_link_local:
|
||||||
# Ignore localhost
|
return address
|
||||||
if address != "127.0.0.1":
|
except ValueError:
|
||||||
return address
|
|
||||||
except socket.error:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
address = False
|
ipv4_address = False
|
||||||
|
ipv6_address = False
|
||||||
networks = False
|
networks = False
|
||||||
if pve_type == "qemu":
|
if pve_type == "qemu":
|
||||||
# If qemu agent is enabled, try to gather the IP address
|
# If qemu agent is enabled, try to gather the IP address
|
||||||
@ -114,23 +113,46 @@ class Discovery():
|
|||||||
if type(networks) is list:
|
if type(networks) is list:
|
||||||
for network in networks:
|
for network in networks:
|
||||||
for ip_address in network["ip-addresses"]:
|
for ip_address in network["ip-addresses"]:
|
||||||
address = validate(ip_address["ip-address"])
|
if ip_address["ip-address-type"] == "ipv4":
|
||||||
|
ipv4_address = validate_ip(ip_address["ip-address"])
|
||||||
|
elif ip_address["ip-address-type"] == "ipv6":
|
||||||
|
ipv6_address = validate_ip(ip_address["ip-address"])
|
||||||
|
|
||||||
if not address:
|
if not ipv4_address:
|
||||||
try:
|
try:
|
||||||
PVE_REQUEST_COUNT_TOTAL.inc()
|
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||||
config = self.client.nodes(pve_node).get(pve_type, vmid, "config")
|
config = self.client.nodes(pve_node).get(pve_type, vmid, "config")
|
||||||
sources = [config["net0"], config["ipconfig0"]]
|
if "ipconfig0" in config.keys():
|
||||||
|
sources = [config["net0"], config["ipconfig0"]]
|
||||||
|
else:
|
||||||
|
sources = [config["net0"]]
|
||||||
|
|
||||||
for s in sources:
|
for s in sources:
|
||||||
find = re.search(r"ip=(\d*\.\d*\.\d*\.\d*)", str(sources))
|
find = re.search(r"ip=(\d*\.\d*\.\d*\.\d*)", str(s))
|
||||||
if find and find.group(1):
|
if find and find.group(1):
|
||||||
address = find.group(1)
|
ipv4_address = find.group(1)
|
||||||
break
|
break
|
||||||
except Exception: # noqa # nosec
|
except Exception: # noqa # nosec
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return address
|
if not ipv6_address:
|
||||||
|
try:
|
||||||
|
PVE_REQUEST_COUNT_TOTAL.inc()
|
||||||
|
config = self.client.nodes(pve_node).get(pve_type, vmid, "config")
|
||||||
|
if "ipconfig0" in config.keys():
|
||||||
|
sources = [config["net0"], config["ipconfig0"]]
|
||||||
|
else:
|
||||||
|
sources = [config["net0"]]
|
||||||
|
|
||||||
|
for s in sources:
|
||||||
|
find = re.search(r"ip=(\d*:\d*:\d*:\d*:\d*:\d*)", str(s))
|
||||||
|
if find and find.group(1):
|
||||||
|
ipv6_address = find.group(1)
|
||||||
|
break
|
||||||
|
except Exception: # noqa # nosec
|
||||||
|
pass
|
||||||
|
|
||||||
|
return ipv4_address, ipv6_address
|
||||||
|
|
||||||
def _exclude(self, pve_list):
|
def _exclude(self, pve_list):
|
||||||
filtered = []
|
filtered = []
|
||||||
@ -196,9 +218,9 @@ class Discovery():
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
metadata = {"notes": description}
|
metadata = {"notes": description}
|
||||||
|
|
||||||
address = self._get_ip_address(pve_type, node, vmid) or host
|
ipv4_address, ipv6_address = self._get_ip_addresses(pve_type, node, vmid) or host
|
||||||
|
|
||||||
prom_host = Host(vmid, host, address, pve_type)
|
prom_host = Host(vmid, host, ipv4_address, ipv6_address, pve_type)
|
||||||
|
|
||||||
config_flags = [("cpu", "sockets"), ("cores", "cores"), ("memory", "memory")]
|
config_flags = [("cpu", "sockets"), ("cores", "cores"), ("memory", "memory")]
|
||||||
meta_flags = [("status", "proxmox_status")]
|
meta_flags = [("status", "proxmox_status")]
|
||||||
|
@ -5,19 +5,22 @@
|
|||||||
class Host:
|
class Host:
|
||||||
"""Represents a virtual machine or container in PVE."""
|
"""Represents a virtual machine or container in PVE."""
|
||||||
|
|
||||||
def __init__(self, vmid, hostname, ip_address, pve_type):
|
def __init__(self, vmid, hostname, ipv4_address, ipv6_address, pve_type):
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.ip_address = ip_address
|
self.ipv4_address = ipv4_address
|
||||||
|
self.ipv6_address = ipv6_address
|
||||||
self.vmid = vmid
|
self.vmid = vmid
|
||||||
self.pve_type = pve_type
|
self.pve_type = pve_type
|
||||||
self.labels = {}
|
self.labels = {}
|
||||||
self.labels["__meta_pve_ip"] = ip_address
|
self.labels["__meta_pve_ipv4"] = ipv4_address
|
||||||
|
self.labels["__meta_pve_ipv6"] = ipv6_address
|
||||||
self.labels["__meta_pve_name"] = hostname
|
self.labels["__meta_pve_name"] = hostname
|
||||||
self.labels["__meta_pve_type"] = pve_type
|
self.labels["__meta_pve_type"] = pve_type
|
||||||
self.labels["__meta_pve_vmid"] = str(vmid)
|
self.labels["__meta_pve_vmid"] = str(vmid)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.hostname}({self.vmid}): {self.pve_type} {self.ip_address}"
|
return f"{self.hostname}({self.vmid}): {self.pve_type} \
|
||||||
|
{self.ipv4_address} {self.ipv6_address}"
|
||||||
|
|
||||||
def add_label(self, key, value):
|
def add_label(self, key, value):
|
||||||
key = key.replace("-", "_").replace(" ", "_")
|
key = key.replace("-", "_").replace(" ", "_")
|
||||||
|
Loading…
Reference in New Issue
Block a user