mirror of
https://github.com/TheNetworkGuy/netbox-zabbix-sync.git
synced 2025-07-14 01:41:25 -06:00
Forced integer to Netbox custom field HostID, added support for #8. Added new -p flag to force proxy link removal.
This commit is contained in:
parent
140d7d96e2
commit
135c04af98
@ -68,6 +68,7 @@ def main(arguments):
|
|||||||
netbox_devices = netbox.dcim.devices.all()
|
netbox_devices = netbox.dcim.devices.all()
|
||||||
zabbix_groups = zabbix.hostgroup.get(output=['name'])
|
zabbix_groups = zabbix.hostgroup.get(output=['name'])
|
||||||
zabbix_templates = zabbix.template.get(output=['name'])
|
zabbix_templates = zabbix.template.get(output=['name'])
|
||||||
|
zabbix_proxys = zabbix.proxy.get(output=['host'])
|
||||||
# Go through all Netbox devices
|
# Go through all Netbox devices
|
||||||
for nb_device in netbox_devices:
|
for nb_device in netbox_devices:
|
||||||
try:
|
try:
|
||||||
@ -127,10 +128,11 @@ def main(arguments):
|
|||||||
zabbix_groups.append(hostgroup)
|
zabbix_groups.append(hostgroup)
|
||||||
# Device is already present in Zabbix
|
# Device is already present in Zabbix
|
||||||
if(device.zabbix_id):
|
if(device.zabbix_id):
|
||||||
device.ConsistencyCheck(zabbix_groups, zabbix_templates)
|
device.ConsistencyCheck(zabbix_groups, zabbix_templates,
|
||||||
|
zabbix_proxys, arguments.proxy_power)
|
||||||
# Add device to Zabbix
|
# Add device to Zabbix
|
||||||
else:
|
else:
|
||||||
device.createInZabbix(zabbix_groups, zabbix_templates)
|
device.createInZabbix(zabbix_groups, zabbix_templates, zabbix_proxys)
|
||||||
except SyncError:
|
except SyncError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -159,6 +161,10 @@ class InterfaceConfigError(SyncError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyConfigError(SyncError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NetworkDevice():
|
class NetworkDevice():
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -175,6 +181,7 @@ class NetworkDevice():
|
|||||||
self.tenant = nb.tenant
|
self.tenant = nb.tenant
|
||||||
self.hostgroup = None
|
self.hostgroup = None
|
||||||
self.secrets = None
|
self.secrets = None
|
||||||
|
self.zbxproxy = "0"
|
||||||
self.hg_format = [self.nb.site.name,
|
self.hg_format = [self.nb.site.name,
|
||||||
self.nb.device_type.manufacturer.name,
|
self.nb.device_type.manufacturer.name,
|
||||||
self.nb.device_role.name]
|
self.nb.device_role.name]
|
||||||
@ -351,7 +358,7 @@ class NetworkDevice():
|
|||||||
# If not fall back to old config.
|
# If not fall back to old config.
|
||||||
if(interface.get_context()):
|
if(interface.get_context()):
|
||||||
# If device is SNMP type, add aditional information.
|
# If device is SNMP type, add aditional information.
|
||||||
if(interface.type == 2):
|
if(interface.interface["type"] == 2):
|
||||||
interface.set_snmp()
|
interface.set_snmp()
|
||||||
else:
|
else:
|
||||||
interface.set_default()
|
interface.set_default()
|
||||||
@ -361,7 +368,24 @@ class NetworkDevice():
|
|||||||
logger.warning(e)
|
logger.warning(e)
|
||||||
raise SyncInventoryError(e)
|
raise SyncInventoryError(e)
|
||||||
|
|
||||||
def createInZabbix(self, groups, templates,
|
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["host"] == proxy):
|
||||||
|
self.zbxproxy = px["proxyid"]
|
||||||
|
logger.debug(f"Found proxy {proxy}"
|
||||||
|
f" for {self.name}.")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
e = f"{self.name}: Defined proxy {proxy} not found."
|
||||||
|
logger.warning(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def createInZabbix(self, groups, templates, proxys,
|
||||||
description="Host added by Netbox sync script."):
|
description="Host added by Netbox sync script."):
|
||||||
"""
|
"""
|
||||||
Creates Zabbix host object with parameters from Netbox object.
|
Creates Zabbix host object with parameters from Netbox object.
|
||||||
@ -376,12 +400,15 @@ class NetworkDevice():
|
|||||||
interfaces = self.setInterfaceDetails()
|
interfaces = self.setInterfaceDetails()
|
||||||
groups = [{"groupid": self.group_id}]
|
groups = [{"groupid": self.group_id}]
|
||||||
templates = [{"templateid": self.template_id}]
|
templates = [{"templateid": self.template_id}]
|
||||||
|
# Set Zabbix proxy if defined
|
||||||
|
self.setProxy(proxys)
|
||||||
# Add host to Zabbix
|
# Add host to Zabbix
|
||||||
try:
|
try:
|
||||||
host = self.zabbix.host.create(host=self.name, status=0,
|
host = self.zabbix.host.create(host=self.name, status=0,
|
||||||
interfaces=interfaces,
|
interfaces=interfaces,
|
||||||
groups=groups,
|
groups=groups,
|
||||||
templates=templates,
|
templates=templates,
|
||||||
|
proxy_hostid=self.zbxproxy,
|
||||||
description=description)
|
description=description)
|
||||||
self.zabbix_id = host["hostids"][0]
|
self.zabbix_id = host["hostids"][0]
|
||||||
except ZabbixAPIException as e:
|
except ZabbixAPIException as e:
|
||||||
@ -389,7 +416,7 @@ class NetworkDevice():
|
|||||||
logger.error(e)
|
logger.error(e)
|
||||||
raise SyncExternalError(e)
|
raise SyncExternalError(e)
|
||||||
# Set Netbox custom field to hostID value.
|
# Set Netbox custom field to hostID value.
|
||||||
self.nb.custom_fields[device_cf] = self.zabbix_id
|
self.nb.custom_fields[device_cf] = int(self.zabbix_id)
|
||||||
self.nb.save()
|
self.nb.save()
|
||||||
logger.info(f"Created host {self.name} in Zabbix.")
|
logger.info(f"Created host {self.name} in Zabbix.")
|
||||||
else:
|
else:
|
||||||
@ -424,12 +451,13 @@ class NetworkDevice():
|
|||||||
raise SyncExternalError(e)
|
raise SyncExternalError(e)
|
||||||
logger.info(f"Updated host {self.name} with data {kwargs}.")
|
logger.info(f"Updated host {self.name} with data {kwargs}.")
|
||||||
|
|
||||||
def ConsistencyCheck(self, groups, templates):
|
def ConsistencyCheck(self, groups, templates, proxys, proxy_power):
|
||||||
"""
|
"""
|
||||||
Checks if Zabbix object is still valid with Netbox parameters.
|
Checks if Zabbix object is still valid with Netbox parameters.
|
||||||
"""
|
"""
|
||||||
self.getZabbixGroup(groups)
|
self.getZabbixGroup(groups)
|
||||||
self.getZabbixTemplate(templates)
|
self.getZabbixTemplate(templates)
|
||||||
|
self.setProxy(proxys)
|
||||||
host = self.zabbix.host.get(filter={'hostid': self.zabbix_id},
|
host = self.zabbix.host.get(filter={'hostid': self.zabbix_id},
|
||||||
selectInterfaces=['type', 'ip',
|
selectInterfaces=['type', 'ip',
|
||||||
'port', 'details',
|
'port', 'details',
|
||||||
@ -473,6 +501,29 @@ class NetworkDevice():
|
|||||||
logger.warning(f"Device {self.name}: hostgroup OUT of sync.")
|
logger.warning(f"Device {self.name}: hostgroup OUT of sync.")
|
||||||
self.updateZabbixHost(groups={'groupid': self.group_id})
|
self.updateZabbixHost(groups={'groupid': self.group_id})
|
||||||
|
|
||||||
|
# Check if a proxy has been defined
|
||||||
|
if(self.zbxproxy != "0"):
|
||||||
|
# Check if expected proxyID matches with configured proxy
|
||||||
|
if(host["proxy_hostid"] == self.zbxproxy):
|
||||||
|
logger.debug(f"Device {self.name}: proxy in-sync.")
|
||||||
|
else:
|
||||||
|
# Proxy diff, update value
|
||||||
|
logger.warning(f"Device {self.name}: proxy OUT of sync.")
|
||||||
|
self.updateZabbixHost(proxy_hostid=self.zbxproxy)
|
||||||
|
else:
|
||||||
|
if(not host["proxy_hostid"] == "0"):
|
||||||
|
if(proxy_power):
|
||||||
|
# If the -p flag has been issued,
|
||||||
|
# delete the proxy link in Zabbix
|
||||||
|
self.updateZabbixHost(proxy_hostid=self.zbxproxy)
|
||||||
|
else:
|
||||||
|
# Instead of deleting the proxy config in zabbix and
|
||||||
|
# forcing potential data loss,
|
||||||
|
# an error message is displayed.
|
||||||
|
logger.error(f"Device {self.name} is configured "
|
||||||
|
f"with proxy in Zabbix but not in Netbox. The"
|
||||||
|
" -p flag was ommited: no "
|
||||||
|
"changes have been made.")
|
||||||
# If only 1 interface has been found
|
# If only 1 interface has been found
|
||||||
if(len(host['interfaces']) == 1):
|
if(len(host['interfaces']) == 1):
|
||||||
updates = {}
|
updates = {}
|
||||||
@ -541,7 +592,6 @@ class ZabbixInterface():
|
|||||||
def __init__(self, context, ip, secrets=None):
|
def __init__(self, context, ip, secrets=None):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.secrets = secrets
|
self.secrets = secrets
|
||||||
self.type = None
|
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.skelet = {"main": "1", "useip": "1", "dns": "", "ip": self.ip}
|
self.skelet = {"main": "1", "useip": "1", "dns": "", "ip": self.ip}
|
||||||
self.interface = self.skelet
|
self.interface = self.skelet
|
||||||
@ -549,18 +599,15 @@ class ZabbixInterface():
|
|||||||
def get_context(self):
|
def get_context(self):
|
||||||
# check if Netbox custom context has been defined.
|
# check if Netbox custom context has been defined.
|
||||||
if("zabbix" in self.context):
|
if("zabbix" in self.context):
|
||||||
try:
|
|
||||||
zabbix = self.context["zabbix"]
|
zabbix = self.context["zabbix"]
|
||||||
|
if("interface_type" in zabbix and "interface_port" in zabbix):
|
||||||
self.interface["type"] = zabbix["interface_type"]
|
self.interface["type"] = zabbix["interface_type"]
|
||||||
self.interface["port"] = zabbix["interface_port"]
|
self.interface["port"] = zabbix["interface_port"]
|
||||||
self.type = zabbix["interface_type"]
|
|
||||||
except KeyError:
|
|
||||||
e = ("Interface port or type is not defined under "
|
|
||||||
"config context 'zabbix'.")
|
|
||||||
raise InterfaceConfigError(e)
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def set_snmp(self):
|
def set_snmp(self):
|
||||||
# Check if interface is type SNMP
|
# Check if interface is type SNMP
|
||||||
@ -647,6 +694,11 @@ if(__name__ == "__main__"):
|
|||||||
"hostgroup name scheme."))
|
"hostgroup name scheme."))
|
||||||
parser.add_argument("-s", "--secret", action="store_true",
|
parser.add_argument("-s", "--secret", action="store_true",
|
||||||
help=("Use Netbox secrets for SNMP interfaces."))
|
help=("Use Netbox secrets for SNMP interfaces."))
|
||||||
|
parser.add_argument("-p", "--proxy_power", action="store_true",
|
||||||
|
help=("USE WITH CAUTION. If there is a proxy "
|
||||||
|
"configured in Zabbix but not in Netbox, sync "
|
||||||
|
"the device and remove the host - proxy "
|
||||||
|
"link in Zabbix."))
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
main(args)
|
main(args)
|
||||||
|
Loading…
Reference in New Issue
Block a user