mirror of
https://github.com/TheNetworkGuy/netbox-zabbix-sync.git
synced 2025-07-14 01:41:25 -06:00
reverted module split, switched to class inheretance instead. Updated config example.
This commit is contained in:
parent
ba2f77a640
commit
c7d3dab27c
@ -80,10 +80,10 @@ inventory_sync = False
|
|||||||
# For nested properties, you can use the '/' seperator.
|
# For nested properties, you can use the '/' seperator.
|
||||||
# For example, the following map will assign the custom field 'mycustomfield' to the 'alias' Zabbix inventory field:
|
# For example, the following map will assign the custom field 'mycustomfield' to the 'alias' Zabbix inventory field:
|
||||||
#
|
#
|
||||||
# inventory_map = { "custom_fields/mycustomfield/name": "alias"}
|
# device_inventory_map = { "custom_fields/mycustomfield/name": "alias"}
|
||||||
#
|
#
|
||||||
# The following map should provide some nice defaults:
|
# The following maps should provide some nice defaults:
|
||||||
inventory_map = { "asset_tag": "asset_tag",
|
device_inventory_map = { "asset_tag": "asset_tag",
|
||||||
"virtual_chassis/name": "chassis",
|
"virtual_chassis/name": "chassis",
|
||||||
"status/label": "deployment_status",
|
"status/label": "deployment_status",
|
||||||
"location/name": "location",
|
"location/name": "location",
|
||||||
@ -96,3 +96,12 @@ inventory_map = { "asset_tag": "asset_tag",
|
|||||||
"device_type/model": "type",
|
"device_type/model": "type",
|
||||||
"device_type/manufacturer/name": "vendor",
|
"device_type/manufacturer/name": "vendor",
|
||||||
"oob_ip/address": "oob_ip" }
|
"oob_ip/address": "oob_ip" }
|
||||||
|
|
||||||
|
# We also support inventory mapping on Virtual Machines.
|
||||||
|
vm_inventory_map = { "asset_tag": "asset_tag",
|
||||||
|
"status/label": "deployment_status",
|
||||||
|
"location/name": "location",
|
||||||
|
"latitude": "location_lat",
|
||||||
|
"longitude": "location_lon",
|
||||||
|
"comments": "notes",
|
||||||
|
"name": "name" }
|
||||||
|
@ -11,7 +11,6 @@ from modules.exceptions import (SyncInventoryError, TemplateError, SyncExternalE
|
|||||||
InterfaceConfigError, JournalError)
|
InterfaceConfigError, JournalError)
|
||||||
from modules.interface import ZabbixInterface
|
from modules.interface import ZabbixInterface
|
||||||
from modules.hostgroups import Hostgroup
|
from modules.hostgroups import Hostgroup
|
||||||
from modules.inventory import Inventory
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from config import (
|
from config import (
|
||||||
@ -19,6 +18,7 @@ try:
|
|||||||
traverse_site_groups,
|
traverse_site_groups,
|
||||||
traverse_regions,
|
traverse_regions,
|
||||||
inventory_sync,
|
inventory_sync,
|
||||||
|
inventory_mode,
|
||||||
device_inventory_map
|
device_inventory_map
|
||||||
)
|
)
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
@ -63,6 +63,10 @@ class PhysicalDevice():
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__repr__()
|
return self.__repr__()
|
||||||
|
|
||||||
|
def _inventory_map(self):
|
||||||
|
""" Use device inventory maps """
|
||||||
|
return device_inventory_map
|
||||||
|
|
||||||
def _setBasics(self):
|
def _setBasics(self):
|
||||||
"""
|
"""
|
||||||
Sets basic information like IP address.
|
Sets basic information like IP address.
|
||||||
@ -162,56 +166,56 @@ class PhysicalDevice():
|
|||||||
return [self.config_context["zabbix"]["templates"]]
|
return [self.config_context["zabbix"]["templates"]]
|
||||||
return self.config_context["zabbix"]["templates"]
|
return self.config_context["zabbix"]["templates"]
|
||||||
|
|
||||||
def set_inventory(self, nbdevice):
|
|
||||||
""" Set inventory """
|
|
||||||
Inventory.set_inventory(self, nbdevice)
|
|
||||||
|
|
||||||
# def set_inventory(self, nbdevice):
|
# def set_inventory(self, nbdevice):
|
||||||
# """ Set host inventory """
|
# """ Set inventory """
|
||||||
# # Set inventory mode. Default is disabled (see class init function).
|
# Inventory.set_inventory(self, nbdevice)
|
||||||
# if inventory_mode == "disabled":
|
|
||||||
# if inventory_sync:
|
def set_inventory(self, nbdevice):
|
||||||
# self.logger.error(f"Host {self.name}: Unable to map NetBox inventory to Zabbix. "
|
""" Set host inventory """
|
||||||
# "Inventory sync is enabled in config but inventory mode is disabled.")
|
# Set inventory mode. Default is disabled (see class init function).
|
||||||
# return True
|
if inventory_mode == "disabled":
|
||||||
# if inventory_mode == "manual":
|
if inventory_sync:
|
||||||
# self.inventory_mode = 0
|
self.logger.error(f"Host {self.name}: Unable to map NetBox inventory to Zabbix. "
|
||||||
# elif inventory_mode == "automatic":
|
"Inventory sync is enabled in config but inventory mode is disabled.")
|
||||||
# self.inventory_mode = 1
|
return True
|
||||||
# else:
|
if inventory_mode == "manual":
|
||||||
# self.logger.error(f"Host {self.name}: Specified value for inventory mode in"
|
self.inventory_mode = 0
|
||||||
# f" config is not valid. Got value {inventory_mode}")
|
elif inventory_mode == "automatic":
|
||||||
# return False
|
self.inventory_mode = 1
|
||||||
# self.inventory = {}
|
else:
|
||||||
# if inventory_sync and self.inventory_mode in [0,1]:
|
self.logger.error(f"Host {self.name}: Specified value for inventory mode in"
|
||||||
# self.logger.debug(f"Host {self.name}: Starting inventory mapper")
|
f" config is not valid. Got value {inventory_mode}")
|
||||||
# # Let's build an inventory dict for each property in the inventory_map
|
return False
|
||||||
# for nb_inv_field, zbx_inv_field in inventory_map.items():
|
self.inventory = {}
|
||||||
# field_list = nb_inv_field.split("/") # convert str to list based on delimiter
|
if inventory_sync and self.inventory_mode in [0,1]:
|
||||||
# # start at the base of the dict...
|
self.logger.debug(f"Host {self.name}: Starting inventory mapper")
|
||||||
# value = nbdevice
|
# Let's build an inventory dict for each property in the inventory_map
|
||||||
# # ... and step through the dict till we find the needed value
|
for nb_inv_field, zbx_inv_field in self._inventory_map().items():
|
||||||
# for item in field_list:
|
field_list = nb_inv_field.split("/") # convert str to list based on delimiter
|
||||||
# value = value[item] if value else None
|
# start at the base of the dict...
|
||||||
# # Check if the result is usable and expected
|
value = nbdevice
|
||||||
# # We want to apply any int or float 0 values,
|
# ... and step through the dict till we find the needed value
|
||||||
# # even if python thinks those are empty.
|
for item in field_list:
|
||||||
# if ((value and isinstance(value, int | float | str )) or
|
value = value[item] if value else None
|
||||||
# (isinstance(value, int | float) and int(value) ==0)):
|
# Check if the result is usable and expected
|
||||||
# self.inventory[zbx_inv_field] = str(value)
|
# We want to apply any int or float 0 values,
|
||||||
# elif not value:
|
# even if python thinks those are empty.
|
||||||
# # empty value should just be an empty string for API compatibility
|
if ((value and isinstance(value, int | float | str )) or
|
||||||
# self.logger.debug(f"Host {self.name}: NetBox inventory lookup for "
|
(isinstance(value, int | float) and int(value) ==0)):
|
||||||
# f"'{nb_inv_field}' returned an empty value")
|
self.inventory[zbx_inv_field] = str(value)
|
||||||
# self.inventory[zbx_inv_field] = ""
|
elif not value:
|
||||||
# else:
|
# empty value should just be an empty string for API compatibility
|
||||||
# # Value is not a string or numeral, probably not what the user expected.
|
self.logger.debug(f"Host {self.name}: NetBox inventory lookup for "
|
||||||
# self.logger.error(f"Host {self.name}: Inventory lookup for '{nb_inv_field}'"
|
f"'{nb_inv_field}' returned an empty value")
|
||||||
# " returned an unexpected type: it will be skipped.")
|
self.inventory[zbx_inv_field] = ""
|
||||||
# self.logger.debug(f"Host {self.name}: Inventory mapping complete. "
|
else:
|
||||||
# f"Mapped {len(list(filter(None, self.inventory.values())))} field(s)")
|
# Value is not a string or numeral, probably not what the user expected.
|
||||||
# return True
|
self.logger.error(f"Host {self.name}: Inventory lookup for '{nb_inv_field}'"
|
||||||
#
|
" returned an unexpected type: it will be skipped.")
|
||||||
|
self.logger.debug(f"Host {self.name}: Inventory mapping complete. "
|
||||||
|
f"Mapped {len(list(filter(None, self.inventory.values())))} field(s)")
|
||||||
|
return True
|
||||||
|
|
||||||
def isCluster(self):
|
def isCluster(self):
|
||||||
"""
|
"""
|
||||||
Checks if device is part of cluster.
|
Checks if device is part of cluster.
|
||||||
@ -546,7 +550,7 @@ class PhysicalDevice():
|
|||||||
'interfaceid'],
|
'interfaceid'],
|
||||||
selectGroups=["groupid"],
|
selectGroups=["groupid"],
|
||||||
selectParentTemplates=["templateid"],
|
selectParentTemplates=["templateid"],
|
||||||
selectInventory=list(device_inventory_map.values()))
|
selectInventory=list(self._inventory_map().values()))
|
||||||
if len(host) > 1:
|
if len(host) > 1:
|
||||||
e = (f"Got {len(host)} results for Zabbix hosts "
|
e = (f"Got {len(host)} results for Zabbix hosts "
|
||||||
f"with ID {self.zabbix_id} - hostname {self.name}.")
|
f"with ID {self.zabbix_id} - hostname {self.name}.")
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# pylint: disable=invalid-name, logging-not-lazy, too-many-locals, logging-fstring-interpolation, too-many-lines
|
|
||||||
"""
|
|
||||||
Device specific handeling for NetBox to Zabbix
|
|
||||||
"""
|
|
||||||
from pprint import pprint
|
|
||||||
from logging import getLogger
|
|
||||||
from zabbix_utils import APIRequestError
|
|
||||||
from modules.exceptions import (SyncInventoryError, TemplateError, SyncExternalError,
|
|
||||||
InterfaceConfigError, JournalError)
|
|
||||||
try:
|
|
||||||
from config import (
|
|
||||||
inventory_sync,
|
|
||||||
inventory_mode,
|
|
||||||
device_inventory_map,
|
|
||||||
vm_inventory_map
|
|
||||||
)
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
print("Configuration file config.py not found in main directory."
|
|
||||||
"Please create the file or rename the config.py.example file to config.py.")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
class Inventory():
|
|
||||||
# pylint: disable=too-many-instance-attributes, too-many-arguments, too-many-positional-arguments
|
|
||||||
"""
|
|
||||||
Represents Network device.
|
|
||||||
INPUT: (NetBox device class, ZabbixAPI class, journal flag, NB journal class)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# def __init__(self, nb, logger=None):
|
|
||||||
# self.nb = nb
|
|
||||||
|
|
||||||
def set_inventory(self, nbobject):
|
|
||||||
if hasattr(nbobject, 'device_type'):
|
|
||||||
inventory_map = device_inventory_map
|
|
||||||
else:
|
|
||||||
inventory_map = vm_inventory_map
|
|
||||||
""" Set host inventory """
|
|
||||||
# Set inventory mode. Default is disabled (see class init function).
|
|
||||||
if inventory_mode == "disabled":
|
|
||||||
if inventory_sync:
|
|
||||||
self.logger.error(f"Host {self.name}: Unable to map NetBox inventory to Zabbix. "
|
|
||||||
"Inventory sync is enabled in config but inventory mode is disabled.")
|
|
||||||
return True
|
|
||||||
if inventory_mode == "manual":
|
|
||||||
self.inventory_mode = 0
|
|
||||||
elif inventory_mode == "automatic":
|
|
||||||
self.inventory_mode = 1
|
|
||||||
else:
|
|
||||||
self.logger.error(f"Host {self.name}: Specified value for inventory mode in"
|
|
||||||
f" config is not valid. Got value {inventory_mode}")
|
|
||||||
return False
|
|
||||||
self.inventory = {}
|
|
||||||
if inventory_sync and self.inventory_mode in [0,1]:
|
|
||||||
self.logger.debug(f"Host {self.name}: Starting inventory mapper")
|
|
||||||
# Let's build an inventory dict for each property in the inventory_map
|
|
||||||
for nb_inv_field, zbx_inv_field in inventory_map.items():
|
|
||||||
field_list = nb_inv_field.split("/") # convert str to list based on delimiter
|
|
||||||
# start at the base of the dict...
|
|
||||||
value = nbobject
|
|
||||||
# ... and step through the dict till we find the needed value
|
|
||||||
for item in field_list:
|
|
||||||
value = value[item] if value else None
|
|
||||||
# Check if the result is usable and expected
|
|
||||||
# We want to apply any int or float 0 values,
|
|
||||||
# even if python thinks those are empty.
|
|
||||||
if ((value and isinstance(value, int | float | str )) or
|
|
||||||
(isinstance(value, int | float) and int(value) ==0)):
|
|
||||||
self.inventory[zbx_inv_field] = str(value)
|
|
||||||
elif not value:
|
|
||||||
# empty value should just be an empty string for API compatibility
|
|
||||||
self.logger.debug(f"Host {self.name}: NetBox inventory lookup for "
|
|
||||||
f"'{nb_inv_field}' returned an empty value")
|
|
||||||
self.inventory[zbx_inv_field] = ""
|
|
||||||
else:
|
|
||||||
# Value is not a string or numeral, probably not what the user expected.
|
|
||||||
self.logger.error(f"Host {self.name}: Inventory lookup for '{nb_inv_field}'"
|
|
||||||
" returned an unexpected type: it will be skipped.")
|
|
||||||
self.logger.debug(f"Host {self.name}: Inventory mapping complete. "
|
|
||||||
f"Mapped {len(list(filter(None, self.inventory.values())))} field(s)")
|
|
||||||
# return True
|
|
@ -6,11 +6,11 @@ from os import sys
|
|||||||
from modules.device import PhysicalDevice
|
from modules.device import PhysicalDevice
|
||||||
from modules.hostgroups import Hostgroup
|
from modules.hostgroups import Hostgroup
|
||||||
from modules.interface import ZabbixInterface
|
from modules.interface import ZabbixInterface
|
||||||
from modules.inventory import Inventory
|
|
||||||
from modules.exceptions import TemplateError, InterfaceConfigError, SyncInventoryError
|
from modules.exceptions import TemplateError, InterfaceConfigError, SyncInventoryError
|
||||||
try:
|
try:
|
||||||
from config import (
|
from config import (
|
||||||
inventory_sync,
|
inventory_sync,
|
||||||
|
inventory_mode,
|
||||||
vm_inventory_map,
|
vm_inventory_map,
|
||||||
traverse_site_groups,
|
traverse_site_groups,
|
||||||
traverse_regions
|
traverse_regions
|
||||||
@ -27,6 +27,10 @@ class VirtualMachine(PhysicalDevice):
|
|||||||
self.hostgroup = None
|
self.hostgroup = None
|
||||||
self.zbx_template_names = None
|
self.zbx_template_names = None
|
||||||
|
|
||||||
|
def _inventory_map(self):
|
||||||
|
""" use VM inventory maps """
|
||||||
|
return vm_inventory_map
|
||||||
|
|
||||||
def set_hostgroup(self, hg_format, nb_site_groups, nb_regions):
|
def set_hostgroup(self, hg_format, nb_site_groups, nb_regions):
|
||||||
"""Set the hostgroup for this device"""
|
"""Set the hostgroup for this device"""
|
||||||
# Create new Hostgroup instance
|
# Create new Hostgroup instance
|
||||||
@ -38,9 +42,9 @@ class VirtualMachine(PhysicalDevice):
|
|||||||
# Generate hostgroup based on hostgroup format
|
# Generate hostgroup based on hostgroup format
|
||||||
self.hostgroup = hg.generate(hg_format)
|
self.hostgroup = hg.generate(hg_format)
|
||||||
|
|
||||||
def set_inventory(self, nbvm):
|
# def set_inventory(self, nbvm):
|
||||||
""" Set inventory """
|
# """ Set inventory """
|
||||||
Inventory.set_inventory(self, nbvm)
|
# Inventory.set_inventory(self, nbvm)
|
||||||
|
|
||||||
def set_vm_template(self):
|
def set_vm_template(self):
|
||||||
""" Set Template for VMs. Overwrites default class
|
""" Set Template for VMs. Overwrites default class
|
||||||
|
Loading…
Reference in New Issue
Block a user