From 6f044cb22861ede44fbb421b67fe81658ba79287 Mon Sep 17 00:00:00 2001 From: TheNetworkGuy Date: Tue, 11 Jun 2024 16:13:45 +0200 Subject: [PATCH] Added logic for proxy groups. Only thing left is consistency check --- modules/device.py | 108 ++++++++++++++++++++++++++---------------- modules/tools.py | 20 ++++++++ netbox_zabbix_sync.py | 13 +++-- 3 files changed, 95 insertions(+), 46 deletions(-) diff --git a/modules/device.py b/modules/device.py index e48d98d..fb50913 100644 --- a/modules/device.py +++ b/modules/device.py @@ -3,7 +3,6 @@ """ Device specific handeling for Netbox to Zabbix """ - from os import sys from logging import getLogger from pyzabbix import ZabbixAPIException @@ -48,7 +47,7 @@ class NetworkDevice(): self.hostgroup = None self.tenant = nb.tenant self.config_context = nb.config_context - self.zbxproxy = "0" + self.zbxproxy = None self.zabbix_state = 0 self.journal = journal self.nb_journals = nb_journal_class @@ -372,23 +371,50 @@ class NetworkDevice(): self.logger.warning(e) raise SyncInventoryError(e) from e - def setProxy(self, proxy_list): - """ check if Zabbix Proxy has been defined in config context """ - if "zabbix" in self.nb.config_context: - if "proxy" in self.nb.config_context["zabbix"]: - proxy = self.nb.config_context["zabbix"]["proxy"] - # Try matching proxy - for px in proxy_list: - if px["name"] == proxy: - self.zbxproxy = px["proxyid"] - self.logger.debug(f"Found proxy {proxy}" - f" for {self.name}.") - return True - e = f"{self.name}: Defined proxy {proxy} not found." - self.logger.warning(e) - return False + # def setProxy(self, proxy_list): + # """ check if Zabbix Proxy has been defined in config context """ + # if "zabbix" in self.nb.config_context: + # if "proxy" in self.nb.config_context["zabbix"]: + # proxy = self.nb.config_context["zabbix"]["proxy"] + # # Try matching proxy + # for px in proxy_list: + # if px["name"] == proxy: + # self.zbxproxy = px["proxyid"] + # self.logger.debug(f"Found proxy {proxy}" + # f" for {self.name}.") + # return True + # e = f"{self.name}: Defined proxy {proxy} not found." + # self.logger.warning(e) + # return False return True + def setProxy(self, proxy_list): + """ + Sets proxy or proxy group if this + value has been defined in config context + + input: List of all proxies and proxy gorups in standardized format + """ + # check if the key Zabbix is defined in the config context + if not "zabbix" in self.nb.config_context: + return False + # Proxy group takes priority over a proxy due + # to it being HA and therefore being more reliable + for proxy_type in ('proxy_group', 'proxy'): + # Check if the key exists in Netbox CC + if proxy_type in self.nb.config_context["zabbix"]: + proxy_name = self.nb.config_context["zabbix"][proxy_type] + # go through all proxies + for proxy in proxy_list: + # If the proxy does not match the type, ignore and continue + if not proxy["type"] == proxy_type: + continue + # If the proxy name matches + if proxy["name"] == proxy_name: + self.zbxproxy = proxy + return True + return False + def createInZabbix(self, groups, templates, proxies, description="Host added by Netbox sync script."): """ @@ -408,30 +434,30 @@ class NetworkDevice(): groups = [{"groupid": self.group_id}] # Set Zabbix proxy if defined self.setProxy(proxies) + # Set basic data for host creation + create_data = {"host": self.name, + "name": self.visible_name, + "status": self.zabbix_state, + "interfaces": interfaces, + "groups": groups, + "templates": templateids, + "description": description, + "inventory_mode": self.inventory_mode, + "inventory": self.inventory + } + # If a Zabbix proxy or Zabbix Proxy group has been defined + if self.zbxproxy: + # If a lower version than 7 is used, we can assume that + # the proxy is a normal proxy and not a proxy group + if version.parse(self.zabbix.version) < version.parse("7.0.0"): + create_data["proxy_hostid"] = self.zbxproxy["id"] + else: + # Configure either a proxy or proxy group + create_data[self.zbxproxy["idtype"]] = self.zbxproxy["id"] + create_data["monitored_by"] = self.zbxproxy["monitored_by"] # Add host to Zabbix try: - if version.parse(self.zabbix.api_version()) < version.parse("7.0.0"): - host = self.zabbix.host.create(host=self.name, - name=self.visible_name, - status=self.zabbix_state, - interfaces=interfaces, - groups=groups, - templates=templateids, - proxy_hostid=self.zbxproxy, - description=description, - inventory_mode=self.inventory_mode, - inventory=self.inventory) - else: - host = self.zabbix.host.create(host=self.name, - name=self.visible_name, - status=self.zabbix_state, - interfaces=interfaces, - groups=groups, - templates=templateids, - proxyid=self.zbxproxy, - description=description, - inventory_mode=self.inventory_mode, - inventory=self.inventory) + host = self.zabbix.host.create(**create_data) self.zabbix_id = host["hostids"][0] except ZabbixAPIException as e: e = f"Couldn't add {self.name}, Zabbix returned {str(e)}." @@ -540,9 +566,9 @@ class NetworkDevice(): else: self.logger.warning(f"Device {self.name}: status OUT of sync.") self.updateZabbixHost(status=str(self.zabbix_state)) - + ### CHANGE THIS # Check if a proxy has been defined - if self.zbxproxy != "0": + if self.zbxproxy: # Check if expected proxyID matches with configured proxy if (("proxy_hostid" in host and host["proxy_hostid"] == self.zbxproxy) or ("proxyid" in host and host["proxyid"] == self.zbxproxy)): diff --git a/modules/tools.py b/modules/tools.py index 1260dd9..f722524 100644 --- a/modules/tools.py +++ b/modules/tools.py @@ -22,3 +22,23 @@ def build_path(endpoint, list_of_dicts): item_path.append(item['name']) item_path.reverse() return item_path + +def proxy_prepper(proxy_list, proxy_group_list): + """ + Function that takes 2 lists and converts them using a + standardized format for further processing. + """ + output = [] + for proxy in proxy_list: + proxy["type"] = "proxy" + proxy["id"] = proxy["proxyid"] + proxy["idtype"] = "proxyid" + proxy["monitored_by"] = 1 + output.append(proxy) + for group in proxy_group_list: + group["type"] = "proxy_group" + group["id"] = group["proxy_groupid"] + group["idtype"] = "proxy_groupid" + group["monitored_by"] = 2 + output.append(group) + return output diff --git a/netbox_zabbix_sync.py b/netbox_zabbix_sync.py index 2cf1d4a..a6c28b3 100755 --- a/netbox_zabbix_sync.py +++ b/netbox_zabbix_sync.py @@ -10,7 +10,7 @@ from pynetbox import api #from pyzabbix import ZabbixAPI, ZabbixAPIException from zabbix_utils import ZabbixAPI, APIRequestError, ProcessingError from modules.device import NetworkDevice -from modules.tools import convert_recordset +from modules.tools import convert_recordset, proxy_prepper from modules.exceptions import EnvironmentVarError, HostgroupError, SyncError try: from config import ( @@ -117,12 +117,15 @@ def main(arguments): zabbix_templates = zabbix.template.get(output=['templateid', 'name']) zabbix_proxies = zabbix.proxy.get(output=['proxyid', proxy_name]) zabbix_proxygroups = zabbix.proxygroup.get(output=["proxy_groupid", "name"]) - # Get Netbox API version - nb_version = netbox.version # Sanitize proxy data if proxy_name == "host": for proxy in zabbix_proxies: proxy['name'] = proxy.pop('host') + # Prepare list of all proxy and proxy_groups + zabbix_proxy_list = proxy_prepper(zabbix_proxies, zabbix_proxygroups) + + # Get Netbox API version + nb_version = netbox.version # Go through all Netbox devices for nb_device in netbox_devices: @@ -167,7 +170,7 @@ def main(arguments): # Check if device is already in Zabbix if device.zabbix_id: device.ConsistencyCheck(zabbix_groups, zabbix_templates, - zabbix_proxies, full_proxy_sync) + zabbix_proxy_list, full_proxy_sync) continue # Add hostgroup is config is set # and Hostgroup is not present in Zabbix @@ -182,7 +185,7 @@ def main(arguments): zabbix_groups.append(hostgroup) # Add device to Zabbix device.createInZabbix(zabbix_groups, zabbix_templates, - zabbix_proxies) + zabbix_proxy_list) except SyncError: pass