From 528efd0ff8ade3b64d6b4e92b94a12d6c2ba2c02 Mon Sep 17 00:00:00 2001 From: TheNetworkGuy Date: Wed, 27 Dec 2023 15:33:45 +0100 Subject: [PATCH] Added #39. Updated code, documentation and config example --- README.md | 5 +++ config.py.example | 3 ++ netbox_zabbix_sync.py | 80 +++++++++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 4c405ea..3637f07 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,11 @@ After that make sure that for each host there is at least one template defined i } ``` +You can also opt for the default device type custom field behaviour but with the added benefit of overwriting the template should a device in Netbox have a device specific context defined. In this case the device specific context template(s) will take priority over the device type custom field template. +``` +templates_config_context_overrule = True +``` + ## Permissions ### Netbox diff --git a/config.py.example b/config.py.example index ba03c31..ccf8a3a 100644 --- a/config.py.example +++ b/config.py.example @@ -2,6 +2,9 @@ # Set to true to enable the template source information # coming from config context instead of a custom field. templates_config_context = False +# Set to true to give config context templates a +# higher priority then custom field templates +templates_config_context_overrule = False # Set template and device Netbox "custom field" names # Template_cf is not used when templates_config_context is enabled diff --git a/netbox_zabbix_sync.py b/netbox_zabbix_sync.py index d6b2c69..0a06c4d 100755 --- a/netbox_zabbix_sync.py +++ b/netbox_zabbix_sync.py @@ -84,7 +84,7 @@ def main(arguments): device = NetworkDevice(nb_device, zabbix, netbox_journals, arguments.journal) device.set_hostgroup(arguments.layout) - device.set_template(templates_config_context) + device.set_template(templates_config_context, templates_config_context_overrule) # Checks if device is part of cluster. # Requires the cluster argument. if(device.isCluster() and arguments.cluster): @@ -170,6 +170,8 @@ class ProxyConfigError(SyncError): class HostgroupError(SyncError): pass +class TemplateError(SyncError): + pass class NetworkDevice(): @@ -256,34 +258,55 @@ class NetworkDevice(): logger.error(e) raise SyncInventoryError(e) - def set_template(self, templates_config_context): - if templates_config_context: - # Template lookup using config context - if("zabbix" not in self.config_context): - e = ("Key 'zabbix' not found in config " - f"context for template host {self.name}") + def set_template(self, prefer_config_context, overrule_custom): + self.zbx_template_names = None + # Gather templates ONLY from the device specific context + if prefer_config_context: + try: + self.zbx_template_names = self.get_templates_context() + except TemplateError as e: logger.warning(e) - raise SyncInventoryError(e) - if("templates" not in self.config_context["zabbix"]): - e = ("Key 'zabbix' not found in config " - f"context for template host {self.name}") - logger.warning(e) - raise SyncInventoryError(e) - self.zbx_template_names = self.config_context["zabbix"]["templates"] + return True + # Gather templates from the custom field but overrule + # them should there be any device specific templates + if overrule_custom: + try: + self.zbx_template_names = self.get_templates_context() + except TemplateError: + pass + if not self.zbx_template_names: + self.zbx_template_names = self.get_templates_cf() + return True + # Gather templates ONLY from the custom field + self.zbx_template_names = self.get_templates_cf() + return True + + def get_templates_cf(self): + # Get Zabbix templates from the device type + device_type_cfs = self.nb.device_type.custom_fields + # Check if the ZBX Template CF is present + if(template_cf in device_type_cfs): + # Set value to template + return [device_type_cfs[template_cf]] else: - # Get device type custom fields - device_type_cfs = self.nb.device_type.custom_fields - # Check if the ZBX Template CF is present - if(template_cf in device_type_cfs): - # Set value to template - self.zbx_template_names = [device_type_cfs[template_cf]] - else: - # Custom field not found, return error - e = (f"Custom field {template_cf} not " - f"found for {self.nb.device_type.manufacturer.name}" - f" - {self.nb.device_type.display}.") - logger.warning(e) - raise SyncInventoryError(e) + # Custom field not found, return error + e = (f"Custom field {template_cf} not " + f"found for {self.nb.device_type.manufacturer.name}" + f" - {self.nb.device_type.display}.") + + raise TemplateError(e) + + def get_templates_context(self): + # Get Zabbix templates from the device context + if("zabbix" not in self.config_context): + e = ("Key 'zabbix' not found in config " + f"context for template host {self.name}") + raise TemplateError(e) + if("templates" not in self.config_context["zabbix"]): + e = ("Key 'zabbix' not found in config " + f"context for template host {self.name}") + raise TemplateError(e) + return self.config_context["zabbix"]["templates"] def isCluster(self): """ @@ -337,8 +360,7 @@ class NetworkDevice(): """ # Check if there are templates defined if(not self.zbx_template_names): - e = (f"Device template '{self.nb.device_type.display}' " - "has no Zabbix templates defined.") + e = (f"No templates found for device {self.name}") logger.info(e) raise SyncInventoryError() # Set variable to empty list