🚨 Linted and formatted file

This commit is contained in:
Wouter de Bruijn 2025-02-26 10:07:51 +01:00
parent 1e269780ce
commit 525904cf43
No known key found for this signature in database
GPG Key ID: AC71F96733B92BFA

View File

@ -2,46 +2,55 @@
# pylint: disable=invalid-name, logging-not-lazy, too-many-locals, logging-fstring-interpolation # pylint: disable=invalid-name, logging-not-lazy, too-many-locals, logging-fstring-interpolation
"""NetBox to Zabbix sync script.""" """NetBox to Zabbix sync script."""
import logging
import argparse import argparse
import logging
import ssl import ssl
from os import environ, path, sys from os import environ, path, sys
from pynetbox import api from pynetbox import api
from pynetbox.core.query import RequestError as NBRequestError from pynetbox.core.query import RequestError as NBRequestError
from requests.exceptions import ConnectionError as RequestsConnectionError from requests.exceptions import ConnectionError as RequestsConnectionError
from zabbix_utils import ZabbixAPI, APIRequestError, ProcessingError from zabbix_utils import APIRequestError, ProcessingError, ZabbixAPI
from modules.device import PhysicalDevice from modules.device import PhysicalDevice
from modules.virtual_machine import VirtualMachine
from modules.tools import convert_recordset, proxy_prepper
from modules.exceptions import EnvironmentVarError, HostgroupError, SyncError from modules.exceptions import EnvironmentVarError, HostgroupError, SyncError
from modules.tools import convert_recordset, proxy_prepper
from modules.virtual_machine import VirtualMachine
try: try:
from config import ( from config import (
clustering,
create_hostgroups,
create_journal,
full_proxy_sync,
hostgroup_format,
nb_device_filter,
nb_vm_filter,
sync_vms,
templates_config_context, templates_config_context,
templates_config_context_overrule, templates_config_context_overrule,
clustering, create_hostgroups,
create_journal, full_proxy_sync,
zabbix_device_removal,
zabbix_device_disable,
hostgroup_format,
vm_hostgroup_format, vm_hostgroup_format,
nb_device_filter, zabbix_device_disable,
sync_vms, zabbix_device_removal,
nb_vm_filter
) )
except ModuleNotFoundError: except ModuleNotFoundError:
print("Configuration file config.py not found in main directory." print(
"Please create the file or rename the config.py.example file to config.py.") "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(1) sys.exit(1)
# Set logging # Set logging
log_format = logging.Formatter('%(asctime)s - %(name)s - ' log_format = logging.Formatter(
'%(levelname)s - %(message)s') "%(asctime)s - %(name)s - " "%(levelname)s - %(message)s"
)
lgout = logging.StreamHandler() lgout = logging.StreamHandler()
lgout.setFormatter(log_format) lgout.setFormatter(log_format)
lgout.setLevel(logging.DEBUG) lgout.setLevel(logging.DEBUG)
lgfile = logging.FileHandler(path.join(path.dirname( lgfile = logging.FileHandler(
path.realpath(__file__)), "sync.log")) path.join(path.dirname(path.realpath(__file__)), "sync.log")
)
lgfile.setFormatter(log_format) lgfile.setFormatter(log_format)
lgfile.setLevel(logging.DEBUG) lgfile.setLevel(logging.DEBUG)
@ -84,15 +93,26 @@ def main(arguments):
netbox = api(netbox_host, token=netbox_token, threading=True) netbox = api(netbox_host, token=netbox_token, threading=True)
# Check if the provided Hostgroup layout is valid # Check if the provided Hostgroup layout is valid
hg_objects = hostgroup_format.split("/") hg_objects = hostgroup_format.split("/")
allowed_objects = ["location", "role", "manufacturer", "region", allowed_objects = [
"site", "site_group", "tenant", "tenant_group"] "location",
"role",
"manufacturer",
"region",
"site",
"site_group",
"tenant",
"tenant_group",
]
# Create API call to get all custom fields which are on the device objects # Create API call to get all custom fields which are on the device objects
try: try:
device_cfs = list(netbox.extras.custom_fields.filter( device_cfs = list(
type="text", content_type_id=23)) netbox.extras.custom_fields.filter(type="text", content_type_id=23)
)
except RequestsConnectionError: except RequestsConnectionError:
logger.error(f"Unable to connect to NetBox with URL {netbox_host}." logger.error(
" Please check the URL and status of NetBox.") f"Unable to connect to NetBox with URL {netbox_host}."
" Please check the URL and status of NetBox."
)
sys.exit(1) sys.exit(1)
except NBRequestError as e: except NBRequestError as e:
logger.error(f"NetBox error: {e}") logger.error(f"NetBox error: {e}")
@ -101,8 +121,10 @@ def main(arguments):
allowed_objects.append(cf.name) allowed_objects.append(cf.name)
for hg_object in hg_objects: for hg_object in hg_objects:
if hg_object not in allowed_objects: if hg_object not in allowed_objects:
e = (f"Hostgroup item {hg_object} is not valid. Make sure you" e = (
" use valid items and seperate them with '/'.") f"Hostgroup item {hg_object} is not valid. Make sure you"
" use valid items and seperate them with '/'."
)
logger.error(e) logger.error(e)
raise HostgroupError(e) raise HostgroupError(e)
# Set Zabbix API # Set Zabbix API
@ -114,18 +136,18 @@ def main(arguments):
ssl_ctx.load_verify_locations(environ["REQUESTS_CA_BUNDLE"]) ssl_ctx.load_verify_locations(environ["REQUESTS_CA_BUNDLE"])
if not zabbix_token: if not zabbix_token:
zabbix = ZabbixAPI(zabbix_host, user=zabbix_user,
password=zabbix_pass, ssl_context=ssl_ctx)
else:
zabbix = ZabbixAPI( zabbix = ZabbixAPI(
zabbix_host, token=zabbix_token, ssl_context=ssl_ctx) zabbix_host, user=zabbix_user, password=zabbix_pass, ssl_context=ssl_ctx
)
else:
zabbix = ZabbixAPI(zabbix_host, token=zabbix_token, ssl_context=ssl_ctx)
zabbix.check_auth() zabbix.check_auth()
except (APIRequestError, ProcessingError) as e: except (APIRequestError, ProcessingError) as e:
e = f"Zabbix returned the following error: {str(e)}" e = f"Zabbix returned the following error: {str(e)}"
logger.error(e) logger.error(e)
sys.exit(1) sys.exit(1)
# Set API parameter mapping based on API version # Set API parameter mapping based on API version
if not str(zabbix.version).startswith('7'): if not str(zabbix.version).startswith("7"):
proxy_name = "host" proxy_name = "host"
else: else:
proxy_name = "name" proxy_name = "name"
@ -133,23 +155,21 @@ def main(arguments):
netbox_devices = list(netbox.dcim.devices.filter(**nb_device_filter)) netbox_devices = list(netbox.dcim.devices.filter(**nb_device_filter))
netbox_vms = [] netbox_vms = []
if sync_vms: if sync_vms:
netbox_vms = list( netbox_vms = list(netbox.virtualization.virtual_machines.filter(**nb_vm_filter))
netbox.virtualization.virtual_machines.filter(**nb_vm_filter))
netbox_site_groups = convert_recordset((netbox.dcim.site_groups.all())) netbox_site_groups = convert_recordset((netbox.dcim.site_groups.all()))
netbox_regions = convert_recordset(netbox.dcim.regions.all()) netbox_regions = convert_recordset(netbox.dcim.regions.all())
netbox_journals = netbox.extras.journal_entries netbox_journals = netbox.extras.journal_entries
zabbix_groups = zabbix.hostgroup.get(output=['groupid', 'name']) zabbix_groups = zabbix.hostgroup.get(output=["groupid", "name"])
zabbix_templates = zabbix.template.get(output=['templateid', 'name']) zabbix_templates = zabbix.template.get(output=["templateid", "name"])
zabbix_proxies = zabbix.proxy.get(output=['proxyid', proxy_name]) zabbix_proxies = zabbix.proxy.get(output=["proxyid", proxy_name])
# Set empty list for proxy processing Zabbix <= 6 # Set empty list for proxy processing Zabbix <= 6
zabbix_proxygroups = [] zabbix_proxygroups = []
if str(zabbix.version).startswith('7'): if str(zabbix.version).startswith("7"):
zabbix_proxygroups = zabbix.proxygroup.get( zabbix_proxygroups = zabbix.proxygroup.get(output=["proxy_groupid", "name"])
output=["proxy_groupid", "name"])
# Sanitize proxy data # Sanitize proxy data
if proxy_name == "host": if proxy_name == "host":
for proxy in zabbix_proxies: for proxy in zabbix_proxies:
proxy['name'] = proxy.pop('host') proxy["name"] = proxy.pop("host")
# Prepare list of all proxy and proxy_groups # Prepare list of all proxy and proxy_groups
zabbix_proxy_list = proxy_prepper(zabbix_proxies, zabbix_proxygroups) zabbix_proxy_list = proxy_prepper(zabbix_proxies, zabbix_proxygroups)
@ -159,15 +179,15 @@ def main(arguments):
# Go through all NetBox devices # Go through all NetBox devices
for nb_vm in netbox_vms: for nb_vm in netbox_vms:
try: try:
vm = VirtualMachine(nb_vm, zabbix, netbox_journals, nb_version, vm = VirtualMachine(
create_journal, logger) nb_vm, zabbix, netbox_journals, nb_version, create_journal, logger
)
logger.debug(f"Host {vm.name}: Started operations on VM.") logger.debug(f"Host {vm.name}: Started operations on VM.")
vm.set_vm_template() vm.set_vm_template()
# Check if a valid template has been found for this VM. # Check if a valid template has been found for this VM.
if not vm.zbx_template_names: if not vm.zbx_template_names:
continue continue
vm.set_hostgroup(vm_hostgroup_format, vm.set_hostgroup(vm_hostgroup_format, netbox_site_groups, netbox_regions)
netbox_site_groups, netbox_regions)
# Check if a valid hostgroup has been found for this VM. # Check if a valid hostgroup has been found for this VM.
if not vm.hostgroup: if not vm.hostgroup:
continue continue
@ -184,17 +204,23 @@ def main(arguments):
continue continue
# Device has been added to NetBox # Device has been added to NetBox
# but is not in Activate state # but is not in Activate state
logger.info(f"VM {vm.name}: skipping since this VM is " logger.info(
f"not in the active state.") f"VM {vm.name}: skipping since this VM is "
f"not in the active state."
)
continue continue
# Check if the VM is in the disabled state # Check if the VM is in the disabled state
if vm.status in zabbix_device_disable: if vm.status in zabbix_device_disable:
vm.zabbix_state = 1 vm.zabbix_state = 1
# Check if VM is already in Zabbix # Check if VM is already in Zabbix
if vm.zabbix_id: if vm.zabbix_id:
vm.ConsistencyCheck(zabbix_groups, zabbix_templates, vm.ConsistencyCheck(
zabbix_proxy_list, full_proxy_sync, zabbix_groups,
create_hostgroups) zabbix_templates,
zabbix_proxy_list,
full_proxy_sync,
create_hostgroups,
)
continue continue
# Add hostgroup is config is set # Add hostgroup is config is set
if create_hostgroups: if create_hostgroups:
@ -205,24 +231,24 @@ def main(arguments):
# Add new hostgroups to zabbix group list # Add new hostgroups to zabbix group list
zabbix_groups.append(group) zabbix_groups.append(group)
# Add VM to Zabbix # Add VM to Zabbix
vm.createInZabbix(zabbix_groups, zabbix_templates, vm.createInZabbix(zabbix_groups, zabbix_templates, zabbix_proxy_list)
zabbix_proxy_list)
except SyncError: except SyncError:
pass pass
for nb_device in netbox_devices: for nb_device in netbox_devices:
try: try:
# Set device instance set data such as hostgroup and template information. # Set device instance set data such as hostgroup and template information.
device = PhysicalDevice(nb_device, zabbix, netbox_journals, nb_version, device = PhysicalDevice(
create_journal, logger) nb_device, zabbix, netbox_journals, nb_version, create_journal, logger
)
logger.debug(f"Host {device.name}: started operations on device.") logger.debug(f"Host {device.name}: started operations on device.")
device.set_template(templates_config_context, device.set_template(
templates_config_context_overrule) templates_config_context, templates_config_context_overrule
)
# Check if a valid template has been found for this VM. # Check if a valid template has been found for this VM.
if not device.zbx_template_names: if not device.zbx_template_names:
continue continue
device.set_hostgroup( device.set_hostgroup(hostgroup_format, netbox_site_groups, netbox_regions)
hostgroup_format, netbox_site_groups, netbox_regions)
# Check if a valid hostgroup has been found for this VM. # Check if a valid hostgroup has been found for this VM.
if not device.hostgroup: if not device.hostgroup:
continue continue
@ -234,14 +260,15 @@ def main(arguments):
if device.isCluster() and clustering: if device.isCluster() and clustering:
# Check if device is primary or secondary # Check if device is primary or secondary
if device.promoteMasterDevice(): if device.promoteMasterDevice():
e = (f"Device {device.name}: is " e = f"Device {device.name}: is " f"part of cluster and primary."
f"part of cluster and primary.")
logger.info(e) logger.info(e)
else: else:
# Device is secondary in cluster. # Device is secondary in cluster.
# Don't continue with this device. # Don't continue with this device.
e = (f"Device {device.name}: is part of cluster " e = (
f"but not primary. Skipping this host...") f"Device {device.name}: is part of cluster "
f"but not primary. Skipping this host..."
)
logger.info(e) logger.info(e)
continue continue
# Checks if device is in cleanup state # Checks if device is in cleanup state
@ -254,17 +281,23 @@ def main(arguments):
continue continue
# Device has been added to NetBox # Device has been added to NetBox
# but is not in Activate state # but is not in Activate state
logger.info(f"Device {device.name}: skipping since this device is " logger.info(
f"not in the active state.") f"Device {device.name}: skipping since this device is "
f"not in the active state."
)
continue continue
# Check if the device is in the disabled state # Check if the device is in the disabled state
if device.status in zabbix_device_disable: if device.status in zabbix_device_disable:
device.zabbix_state = 1 device.zabbix_state = 1
# Check if device is already in Zabbix # Check if device is already in Zabbix
if device.zabbix_id: if device.zabbix_id:
device.ConsistencyCheck(zabbix_groups, zabbix_templates, device.ConsistencyCheck(
zabbix_proxy_list, full_proxy_sync, zabbix_groups,
create_hostgroups) zabbix_templates,
zabbix_proxy_list,
full_proxy_sync,
create_hostgroups,
)
continue continue
# Add hostgroup is config is set # Add hostgroup is config is set
if create_hostgroups: if create_hostgroups:
@ -275,17 +308,17 @@ def main(arguments):
# Add new hostgroups to zabbix group list # Add new hostgroups to zabbix group list
zabbix_groups.append(group) zabbix_groups.append(group)
# Add device to Zabbix # Add device to Zabbix
device.createInZabbix(zabbix_groups, zabbix_templates, device.createInZabbix(zabbix_groups, zabbix_templates, zabbix_proxy_list)
zabbix_proxy_list)
except SyncError: except SyncError:
pass pass
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='A script to sync Zabbix with NetBox device data.' description="A script to sync Zabbix with NetBox device data."
)
parser.add_argument(
"-v", "--verbose", help="Turn on debugging.", action="store_true"
) )
parser.add_argument("-v", "--verbose", help="Turn on debugging.",
action="store_true")
args = parser.parse_args() args = parser.parse_args()
main(args) main(args)