Skip to content

Commit

Permalink
Add site tags and a ton of refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
WillNilges committed Dec 17, 2023
1 parent 9b31fdb commit 3cfaf01
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 79 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
venv/
venv/*
.env
.env*
__pycache__/
__pycache__/*
*.log
97 changes: 97 additions & 0 deletions datalink.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from dataclasses import dataclass
import dataclasses
from typing import Protocol

from zabbix_client import NUMERIC_FLOAT, TEXT, TemplateItem


class HostProto(Protocol):
name: str
tags: dict
prefix: str

# Parsing stats
def stats(self) -> dict:
...

# For creating a template automatically in Zabbix
# TODO: Figure out better way to define templates
@staticmethod
def build_template():
...


@dataclass
class DataLinkStatistics:
rxRate: int
txRate: int
downlinkCapacity: int
uplinkCapacity: int
downlinkUtilization: float
uplinkUtilization: float
signalLocal: int
signalRemote: int
signalChain0: int
signalChain1: int
signalRemoteChain0: int
signalRemoteChain1: int
linkScore: float
score: int
scoreMax: int
airTimeScore: int
linkScoreHint: str
theoreticalDownlinkCapacity: int
theoreticalUplinkCapacity: int


class DataLink(HostProto):
name: str
tags: dict
from_stats: DataLinkStatistics
to_stats: DataLinkStatistics
prefix = "uisp2zabbix.p2p"

def __init__(self, name, from_site, to_site, from_stats, to_stats):
self.name = name
self.tags = {"from": from_site, "to": to_site}
self.from_stats = from_stats
self.to_stats = to_stats

def stats(self):
stats = {}

for k, v in self.from_stats.__dict__.items():
stats[f"from_{k}"] = v

for k, v in self.to_stats.__dict__.items():
stats[f"to_{k}"] = v

return stats

@staticmethod
def build_template():
# Set up the items in the new template
items = []
for field in dataclasses.fields(DataLinkStatistics):
if field.type == float or field.type == int:
t = NUMERIC_FLOAT
if "signal" in field.name:
u = "dB"
elif "Rate" in field.name or "Capacity" in field.name:
u = "bps" # TODO: Is this bps or Kbps?
else:
u = ""
else:
t = TEXT
u = ""

for direction in ["from", "to"]:
items.append(
TemplateItem(
f"{direction}_{field.name}",
f"{DataLink.prefix}.{direction}_{field.name}",
t,
u,
)
)
return items
26 changes: 21 additions & 5 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import time
import json
from dotenv import load_dotenv
from point_to_point import DataLinkStatistics, DataLink, build_datalink_template
from datalink import DataLinkStatistics, DataLink
from uisp_client import UISPClient
from zabbix_client import NUMERIC_FLOAT, NUMERIC_UNSIGNED, TEXT, ZabbixClient
from zabbix_client import ZabbixClient
from zappix.sender import Sender
from zappix.protocol import SenderData

Expand Down Expand Up @@ -35,6 +35,12 @@ def main():
help="Force updating the items within a template",
)

parser.add_argument(
"--update-hosts",
action="store_true",
help="Force updating hosts",
)

args = parser.parse_args()

load_dotenv()
Expand All @@ -51,7 +57,15 @@ def main():
# Set up template for DataLinks (if needed)
datalink_template_id, created = zapi.get_or_create_template(DataLink)
if created or args.update_template:
build_datalink_template(zapi, datalink_template_id)
for item in DataLink.build_template():
zapi.get_or_create_template_item(
datalink_template_id,
item.name,
item.key,
item.value_type,
item.unit,
update=True,
)

# For pushing data to Zabbix (doing the actual broker-ing)
z_endpoint = os.getenv("ZABBIX_ENDPOINT")
Expand All @@ -66,15 +80,17 @@ def main():
try:
p2p = DataLink(
l["ssid"].strip(),
l["from"]["site"]["identification"]["name"],
l["to"]["site"]["identification"]["name"],
DataLinkStatistics(**l["from"]["interface"]["statistics"]),
DataLinkStatistics(**l["to"]["interface"]["statistics"]),
)

# Create the host if it doesn't already exist
zapi.get_or_create_host(p2p.ssid, datalink_template_id)
zapi.get_or_create_host(p2p, datalink_template_id, update=args.update_hosts)

for k, v in p2p.stats().items():
z_payload.append(SenderData(p2p.ssid, f"{DataLink.prefix}.{k}", v))
z_payload.append(SenderData(p2p.name, f"{DataLink.prefix}.{k}", v))
except Exception as e:
log.exception(f"Got exception processing UISP payload: {e}")

Expand Down
72 changes: 0 additions & 72 deletions point_to_point.py

This file was deleted.

31 changes: 29 additions & 2 deletions zabbix_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from enum import Enum

from pyzabbix.api import ZabbixAPIException
from zappix.protocol import dataclass

SNMP_AGENT = 20
TRAPPER = 2
Expand All @@ -29,6 +30,14 @@
log = logging.getLogger("UISP2Zabbix")


@dataclass
class TemplateItem:
name: str
key: str
value_type: int
unit: str


class ZabbixClient:
def __init__(self):
zabbix_url = os.getenv("ZABBIX_URL")
Expand Down Expand Up @@ -202,12 +211,17 @@ def get_or_create_template_item(
log.exception(f"Error: {e}")
return None

def get_or_create_host(self, host_name, template_id, host_group_id=None):
def get_or_create_host(self, host, template_id, host_group_id=None, update=False):
host_name = host.name
host_tags = []
for k, v in host.tags.items():
host_tags.append({"tag": k, "value": v})

if host_group_id is None:
host_group_id = self.default_host_group_id

# Check our cache for the host
if host_name in self.host_cache.keys():
if not update and host_name in self.host_cache.keys():
host_id = self.host_cache[host_name]
log.info(f"Found Host '{host_name}' with ID {host_id} in cache")
return host_id
Expand All @@ -219,13 +233,26 @@ def get_or_create_host(self, host_name, template_id, host_group_id=None):
# Host already exists, return its ID
host_id = existing_host[0]["hostid"]
log.info(f"Host '{host_name}' already exists with ID {host_id}")
if update:
host_update_params = {
"hostid": host_id,
"name": host_name,
"groups": [{"groupid": host_group_id}],
"templates": [{"templateid": template_id}],
"tags": host_tags,
}

host_info = self.zapi.host.update(host_update_params)
host_id = host_info["hostids"][0]
log.info(f"Host '{host_name}' updated with ID {host_id}")
else:
# Host doesn't exist, create it
host_create_params = {
"host": host_name,
"name": host_name,
"groups": [{"groupid": host_group_id}],
"templates": [{"templateid": template_id}],
"tags": [host_tags],
}

host_info = self.zapi.host.create(host_create_params)
Expand Down

0 comments on commit 3cfaf01

Please sign in to comment.