This commit is contained in:
TheNetworkGuy 2024-07-24 13:14:12 +02:00
parent c0c52f973e
commit d1ec1114ac
3 changed files with 39 additions and 26 deletions

View File

@ -172,8 +172,9 @@ You can modify this behaviour by changing the following list variables in the sc
### Zabbix Inventory ### Zabbix Inventory
This script allows you to enable the inventory on managed Zabbix hosts and sync NetBox device properties to the specified inventory fields. This script allows you to enable the inventory on managed Zabbix hosts and sync NetBox device properties to the specified inventory fields.
To enable, set `inventory_sync` to `True`. To map Netbox information to Netbox inventory fields, set `inventory_sync` to `True`.
Set `inventory_automatic` to `False` to use manual inventory, or `True` for automatic.
You can set the inventory mode to "disabled", "manual" or "automatic" with the inventory_mode variable.
See [Zabbix Manual](https://www.zabbix.com/documentation/current/en/manual/config/hosts/inventory#building-inventory) for more information about the modes. See [Zabbix Manual](https://www.zabbix.com/documentation/current/en/manual/config/hosts/inventory#building-inventory) for more information about the modes.
Use the `inventory_map` variable to map which NetBox properties are used in which Zabbix Inventory fields. Use the `inventory_map` variable to map which NetBox properties are used in which Zabbix Inventory fields.

View File

@ -58,13 +58,14 @@ traverse_site_groups = False
nb_device_filter = {"name__n": "null"} nb_device_filter = {"name__n": "null"}
## Inventory ## Inventory
# See https://www.zabbix.com/documentation/current/en/manual/config/hosts/inventory#building-inventory
# Choice between disabled, manual or automatic.
# Make sure to select at least manual or automatic in use with the inventory_sync function.
inventory_mode = "disabled"
# To allow syncing of NetBox device properties, set inventory_sync to True # To allow syncing of NetBox device properties, set inventory_sync to True
inventory_sync = False inventory_sync = False
# Set inventory_automatic to False to use manual inventory, True for automatic
# See https://www.zabbix.com/documentation/current/en/manual/config/hosts/inventory#building-inventory
inventory_automatic = True
# inventory_map is used to map NetBox properties to Zabbix Inventory fields. # inventory_map is used to map NetBox properties to Zabbix Inventory fields.
# 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:

View File

@ -16,7 +16,7 @@ try:
traverse_site_groups, traverse_site_groups,
traverse_regions, traverse_regions,
inventory_sync, inventory_sync,
inventory_automatic, inventory_mode,
inventory_map inventory_map
) )
except ModuleNotFoundError: except ModuleNotFoundError:
@ -196,12 +196,23 @@ class NetworkDevice():
def set_inventory(self, nbdevice): def set_inventory(self, nbdevice):
""" Set host inventory """ """ Set host inventory """
self.inventory_mode = -1 # Set inventory mode. Default is disabled (see class init function).
self.inventory = {} if inventory_mode == "disabled":
if inventory_sync: if inventory_sync:
# Set inventory mode to automatic or manual self.logger.error(f"Device {self.name}: Unable to map Netbox inventory to Zabbix. "
self.inventory_mode = 1 if inventory_automatic else 0 "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"Device {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"Device {self.name}: Starting inventory mapper")
# Let's build an inventory dict for each property in the inventory_map # Let's build an inventory dict for each property in the inventory_map
for nb_inv_field, zbx_inv_field in inventory_map.items(): for nb_inv_field, zbx_inv_field in inventory_map.items():
field_list = nb_inv_field.split("/") # convert str to list based on delimiter field_list = nb_inv_field.split("/") # convert str to list based on delimiter
@ -218,13 +229,15 @@ class NetworkDevice():
self.inventory[zbx_inv_field] = str(value) self.inventory[zbx_inv_field] = str(value)
elif not value: elif not value:
# empty value should just be an empty string for API compatibility # empty value should just be an empty string for API compatibility
self.logger.debug(f"Inventory lookup for '{nb_inv_field}'" self.logger.debug(f"Device {self.name}: Netbox inventory lookup for "
" returned an empty value") f"'{nb_inv_field}' returned an empty value")
self.inventory[zbx_inv_field] = "" self.inventory[zbx_inv_field] = ""
else: else:
# Value is not a string or numeral, probably not what the user expected. # Value is not a string or numeral, probably not what the user expected.
self.logger.error(f"Inventory lookup for '{nb_inv_field}' returned" self.logger.error(f"Device {self.name}: Inventory lookup for '{nb_inv_field}'"
" an unexpected type: it will be skipped.") " returned an unexpected type: it will be skipped.")
self.logger.debug(f"Device {self.name}: Inventory mapping complete. "
f"Mapped {len(list(filter(None, self.inventory.values())))} field(s)")
return True return True
def isCluster(self): def isCluster(self):
@ -617,16 +630,14 @@ class NetworkDevice():
"changes have been made.") "changes have been made.")
if not proxy_set: if not proxy_set:
self.logger.debug(f"Device {self.name}: proxy in-sync.") self.logger.debug(f"Device {self.name}: proxy in-sync.")
# Check host inventory # Check host inventory mode
if inventory_sync:
# check inventory mode first, as we need it set to parse
# actual inventory values
if str(host['inventory_mode']) == str(self.inventory_mode): if str(host['inventory_mode']) == str(self.inventory_mode):
self.logger.debug(f"Device {self.name}: inventory_mode in-sync.") self.logger.debug(f"Device {self.name}: inventory_mode in-sync.")
else: else:
self.logger.warning(f"Device {self.name}: inventory_mode OUT of sync.") self.logger.warning(f"Device {self.name}: inventory_mode OUT of sync.")
self.updateZabbixHost(inventory_mode=str(self.inventory_mode)) self.updateZabbixHost(inventory_mode=str(self.inventory_mode))
# Now we can check if inventory is in-sync. if inventory_sync and self.inventory_mode in [0,1]:
# Check host inventory mapping
if host['inventory'] == self.inventory: if host['inventory'] == self.inventory:
self.logger.debug(f"Device {self.name}: inventory in-sync.") self.logger.debug(f"Device {self.name}: inventory in-sync.")
else: else: