Initial commit: SNMP scanner and Zabbix template generator
Tools for printer discovery and monitoring: - snmp_scanner.py: SNMP-based printer discovery - generate_printer_templates.py: Generate Zabbix templates - analyze_supplies.py: Analyze printer supply levels - extract_summary.py: Extract printer data summaries Includes Zabbix templates for: - HP Color/Mono printers - HP DesignJet T1700 - Xerox Color/Mono/Enterprise printers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
683
generate_zabbix_config.py
Normal file
683
generate_zabbix_config.py
Normal file
@@ -0,0 +1,683 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate Zabbix SNMP Item Configuration
|
||||
Creates Zabbix item definitions for printer monitoring
|
||||
Includes: Toner, Maintenance Kit, Fuser, Drums, Waste
|
||||
"""
|
||||
|
||||
import json
|
||||
import uuid
|
||||
import yaml
|
||||
|
||||
# Zabbix SNMP items configuration for HP & Xerox printers
|
||||
ZABBIX_ITEMS = {
|
||||
"printer_info": [
|
||||
{
|
||||
"name": "Printer Model",
|
||||
"key": "printer.model",
|
||||
"oid": "1.3.6.1.2.1.25.3.2.1.3.1",
|
||||
"type": "text",
|
||||
"description": "Device model information"
|
||||
},
|
||||
{
|
||||
"name": "Printer Hostname",
|
||||
"key": "printer.hostname",
|
||||
"oid": "1.3.6.1.2.1.1.5.0",
|
||||
"type": "text",
|
||||
"description": "System hostname"
|
||||
},
|
||||
{
|
||||
"name": "Printer Serial Number",
|
||||
"key": "printer.serial",
|
||||
"oid": "1.3.6.1.2.1.43.5.1.1.17.1",
|
||||
"type": "text",
|
||||
"description": "Printer serial number"
|
||||
},
|
||||
{
|
||||
"name": "System Location",
|
||||
"key": "printer.location",
|
||||
"oid": "1.3.6.1.2.1.1.6.0",
|
||||
"type": "text",
|
||||
"description": "Physical location"
|
||||
},
|
||||
{
|
||||
"name": "MAC Address",
|
||||
"key": "printer.macaddress",
|
||||
"oid": "1.3.6.1.2.1.2.2.1.6.2",
|
||||
"type": "text",
|
||||
"description": "Primary network interface MAC address"
|
||||
}
|
||||
],
|
||||
"toner_levels": [
|
||||
{
|
||||
"name": "Black Toner Current",
|
||||
"key": "printer.toner.black.current",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.1",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Black toner current level (raw value)"
|
||||
},
|
||||
{
|
||||
"name": "Black Toner Max",
|
||||
"key": "printer.toner.black.max",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.8.1.1",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Black toner maximum capacity"
|
||||
},
|
||||
{
|
||||
"name": "Black Toner Level",
|
||||
"key": "printer.toner.black",
|
||||
"type": "calculated",
|
||||
"formula": "round((last(//printer.toner.black.current)/last(//printer.toner.black.max))*100,0)",
|
||||
"units": "%",
|
||||
"description": "Black toner percentage",
|
||||
"color": "black",
|
||||
"is_percentage": True,
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Cyan Toner Current",
|
||||
"key": "printer.toner.cyan.current",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.2",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Cyan toner current level (raw value)"
|
||||
},
|
||||
{
|
||||
"name": "Cyan Toner Max",
|
||||
"key": "printer.toner.cyan.max",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.8.1.2",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Cyan toner maximum capacity"
|
||||
},
|
||||
{
|
||||
"name": "Cyan Toner Level",
|
||||
"key": "printer.toner.cyan",
|
||||
"type": "calculated",
|
||||
"formula": "round((last(//printer.toner.cyan.current)/last(//printer.toner.cyan.max))*100,0)",
|
||||
"units": "%",
|
||||
"description": "Cyan toner percentage",
|
||||
"color": "cyan",
|
||||
"is_percentage": True,
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Magenta Toner Current",
|
||||
"key": "printer.toner.magenta.current",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.3",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Magenta toner current level (raw value)"
|
||||
},
|
||||
{
|
||||
"name": "Magenta Toner Max",
|
||||
"key": "printer.toner.magenta.max",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.8.1.3",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Magenta toner maximum capacity"
|
||||
},
|
||||
{
|
||||
"name": "Magenta Toner Level",
|
||||
"key": "printer.toner.magenta",
|
||||
"type": "calculated",
|
||||
"formula": "round((last(//printer.toner.magenta.current)/last(//printer.toner.magenta.max))*100,0)",
|
||||
"units": "%",
|
||||
"description": "Magenta toner percentage",
|
||||
"color": "magenta",
|
||||
"is_percentage": True,
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Yellow Toner Current",
|
||||
"key": "printer.toner.yellow.current",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.4",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Yellow toner current level (raw value)"
|
||||
},
|
||||
{
|
||||
"name": "Yellow Toner Max",
|
||||
"key": "printer.toner.yellow.max",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.8.1.4",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "",
|
||||
"description": "Yellow toner maximum capacity"
|
||||
},
|
||||
{
|
||||
"name": "Yellow Toner Level",
|
||||
"key": "printer.toner.yellow",
|
||||
"type": "calculated",
|
||||
"formula": "round((last(//printer.toner.yellow.current)/last(//printer.toner.yellow.max))*100,0)",
|
||||
"units": "%",
|
||||
"description": "Yellow toner percentage",
|
||||
"color": "yellow",
|
||||
"is_percentage": True,
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"cartridge_info": [
|
||||
{
|
||||
"name": "Black Cartridge Part Number",
|
||||
"key": "printer.cartridge.black",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.1",
|
||||
"type": "text",
|
||||
"description": "Black toner cartridge model/part number"
|
||||
},
|
||||
{
|
||||
"name": "Cyan Cartridge Part Number",
|
||||
"key": "printer.cartridge.cyan",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.2",
|
||||
"type": "text",
|
||||
"description": "Cyan toner cartridge model/part number"
|
||||
},
|
||||
{
|
||||
"name": "Magenta Cartridge Part Number",
|
||||
"key": "printer.cartridge.magenta",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.3",
|
||||
"type": "text",
|
||||
"description": "Magenta toner cartridge model/part number"
|
||||
},
|
||||
{
|
||||
"name": "Yellow Cartridge Part Number",
|
||||
"key": "printer.cartridge.yellow",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.4",
|
||||
"type": "text",
|
||||
"description": "Yellow toner cartridge model/part number"
|
||||
}
|
||||
],
|
||||
"other_supplies": [
|
||||
# Drum Cartridge R1
|
||||
{
|
||||
"name": "Drum Cartridge R1 Part Number",
|
||||
"key": "printer.drum.r1",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.5",
|
||||
"type": "text",
|
||||
"description": "Drum cartridge R1 part number"
|
||||
},
|
||||
{
|
||||
"name": "Drum Cartridge R1 Level",
|
||||
"key": "printer.drum.r1.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.5",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Drum cartridge R1 remaining life percentage",
|
||||
"part_number_item": "printer.drum.r1",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
# Drum Cartridge R2
|
||||
{
|
||||
"name": "Drum Cartridge R2 Part Number",
|
||||
"key": "printer.drum.r2",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.6",
|
||||
"type": "text",
|
||||
"description": "Drum cartridge R2 part number"
|
||||
},
|
||||
{
|
||||
"name": "Drum Cartridge R2 Level",
|
||||
"key": "printer.drum.r2.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.6",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Drum cartridge R2 remaining life percentage",
|
||||
"part_number_item": "printer.drum.r2",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
# Drum Cartridge R3
|
||||
{
|
||||
"name": "Drum Cartridge R3 Part Number",
|
||||
"key": "printer.drum.r3",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.7",
|
||||
"type": "text",
|
||||
"description": "Drum cartridge R3 part number"
|
||||
},
|
||||
{
|
||||
"name": "Drum Cartridge R3 Level",
|
||||
"key": "printer.drum.r3.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.7",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Drum cartridge R3 remaining life percentage",
|
||||
"part_number_item": "printer.drum.r3",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
# Drum Cartridge R4
|
||||
{
|
||||
"name": "Drum Cartridge R4 Part Number",
|
||||
"key": "printer.drum.r4",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.8",
|
||||
"type": "text",
|
||||
"description": "Drum cartridge R4 part number"
|
||||
},
|
||||
{
|
||||
"name": "Drum Cartridge R4 Level",
|
||||
"key": "printer.drum.r4.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.8",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Drum cartridge R4 remaining life percentage",
|
||||
"part_number_item": "printer.drum.r4",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
# Waste Toner Container
|
||||
{
|
||||
"name": "Waste Toner Container Part Number",
|
||||
"key": "printer.waste.partnumber",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.9",
|
||||
"type": "text",
|
||||
"description": "Waste toner container part number"
|
||||
},
|
||||
{
|
||||
"name": "Waste Toner Container Level",
|
||||
"key": "printer.waste.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.9",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Waste toner container fill level (higher is more full)",
|
||||
"part_number_item": "printer.waste.partnumber",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 80, "expression": ">"},
|
||||
{"severity": "high", "threshold": 90, "expression": ">"}
|
||||
]
|
||||
},
|
||||
# Transfer Belt Cleaner
|
||||
{
|
||||
"name": "Transfer Belt Cleaner Part Number",
|
||||
"key": "printer.transfer.belt",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.10",
|
||||
"type": "text",
|
||||
"description": "Transfer belt cleaner part number"
|
||||
},
|
||||
{
|
||||
"name": "Transfer Belt Cleaner Level",
|
||||
"key": "printer.transfer.belt.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.10",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Transfer belt cleaner remaining life percentage",
|
||||
"part_number_item": "printer.transfer.belt",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
},
|
||||
# Second Bias Transfer Roll
|
||||
{
|
||||
"name": "Second Bias Transfer Roll Part Number",
|
||||
"key": "printer.transfer.roller",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.6.1.11",
|
||||
"type": "text",
|
||||
"description": "Second bias transfer roll part number"
|
||||
},
|
||||
{
|
||||
"name": "Second Bias Transfer Roll Level",
|
||||
"key": "printer.transfer.roller.level",
|
||||
"oid": "1.3.6.1.2.1.43.11.1.1.9.1.11",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "%",
|
||||
"description": "Second bias transfer roll remaining life percentage",
|
||||
"part_number_item": "printer.transfer.roller",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 20, "expression": "<"},
|
||||
{"severity": "high", "threshold": 10, "expression": "<"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"maintenance_kit_hp": [
|
||||
{
|
||||
"name": "Maintenance Kit Model (HP)",
|
||||
"key": "printer.maintenance.model",
|
||||
"oid": "1.3.6.1.4.1.11.2.3.9.4.2.1.1.3.3.0",
|
||||
"type": "text",
|
||||
"description": "HP maintenance kit model/serial number"
|
||||
},
|
||||
{
|
||||
"name": "Maintenance Kit Remaining (HP)",
|
||||
"key": "printer.maintenance.remaining",
|
||||
"oid": "1.3.6.1.4.1.11.2.3.9.4.2.1.4.1.2.0",
|
||||
"type": "numeric_unsigned",
|
||||
"units": "pages",
|
||||
"description": "HP maintenance kit remaining pages",
|
||||
"part_number_item": "printer.maintenance.model",
|
||||
"triggers": [
|
||||
{"severity": "warning", "threshold": 10000, "expression": "<"},
|
||||
{"severity": "high", "threshold": 5000, "expression": "<"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Printer Model (HP MIB)",
|
||||
"key": "printer.maintenance.printer_model",
|
||||
"oid": "1.3.6.1.4.1.11.2.3.9.4.2.1.1.3.2.0",
|
||||
"type": "text",
|
||||
"description": "Printer model from HP maintenance MIB"
|
||||
}
|
||||
],
|
||||
"supply_capacity": [
|
||||
{
|
||||
"name": "Supply 1 Max Capacity",
|
||||
"key": "printer.supply.1.max",
|
||||
"oid": "1.3.6.1.2.1.43.10.2.1.4.1.1",
|
||||
"type": "numeric_unsigned",
|
||||
"description": "Maximum capacity for supply index 1 (usually black)"
|
||||
},
|
||||
{
|
||||
"name": "Supply 1 Current Level",
|
||||
"key": "printer.supply.1.current",
|
||||
"oid": "1.3.6.1.2.1.43.10.2.1.9.1.1",
|
||||
"type": "numeric_unsigned",
|
||||
"description": "Current level for supply index 1 (usually black)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def generate_zabbix_cli_commands():
|
||||
"""
|
||||
Generate Zabbix CLI commands for adding SNMP items
|
||||
"""
|
||||
print("=" * 80)
|
||||
print("ZABBIX SNMP ITEM CONFIGURATION")
|
||||
print("=" * 80)
|
||||
print("\nThese commands can be used in Zabbix CLI or adapted for the web interface.\n")
|
||||
|
||||
for category, items in ZABBIX_ITEMS.items():
|
||||
print(f"\n## {category.replace('_', ' ').title()}")
|
||||
print("-" * 80)
|
||||
|
||||
for item in items:
|
||||
print(f"\n### {item['name']}")
|
||||
if 'oid' in item:
|
||||
print(f"OID: {item['oid']}")
|
||||
if 'formula' in item:
|
||||
print(f"Formula: {item['formula']}")
|
||||
print(f"Key: {item['key']}")
|
||||
print(f"Type: {item['type']}")
|
||||
if 'units' in item:
|
||||
print(f"Units: {item['units']}")
|
||||
print(f"Description: {item['description']}")
|
||||
|
||||
if 'triggers' in item:
|
||||
print(f"\nRecommended Triggers:")
|
||||
for trigger in item['triggers']:
|
||||
print(f" - {trigger['severity'].upper()}: "
|
||||
f"{item['name']} {trigger['expression']} {trigger['threshold']}{item.get('units', '')}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def generate_zabbix_import_json():
|
||||
"""
|
||||
Generate a Zabbix 7.4 importable JSON template
|
||||
Note: Zabbix requires UUIDs to be 32 characters without hyphens
|
||||
"""
|
||||
template = {
|
||||
"zabbix_export": {
|
||||
"version": "7.4",
|
||||
"template_groups": [
|
||||
{
|
||||
"uuid": "3cd4e8d0b828464e8f4b3becf13a9dbd",
|
||||
"name": "Printers"
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"uuid": uuid.uuid4().hex,
|
||||
"template": "Printer SNMP Monitor",
|
||||
"name": "Printer SNMP Monitor",
|
||||
"groups": [
|
||||
{
|
||||
"name": "Printers"
|
||||
}
|
||||
],
|
||||
"items": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# Build items list with Zabbix 7.4 format
|
||||
for category, items in ZABBIX_ITEMS.items():
|
||||
for item in items:
|
||||
# Handle calculated items differently
|
||||
if item['type'] == 'calculated':
|
||||
# Only add component:toner and color tags if this is a percentage item
|
||||
is_percentage = item.get('is_percentage', False)
|
||||
|
||||
zabbix_item = {
|
||||
"uuid": uuid.uuid4().hex,
|
||||
"name": item['name'],
|
||||
"type": "CALCULATED",
|
||||
"key": item['key'],
|
||||
"delay": "1h",
|
||||
"history": "90d",
|
||||
"trends": "365d",
|
||||
"value_type": "FLOAT",
|
||||
"params": item['formula'],
|
||||
"description": item['description'],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "component",
|
||||
"value": "toner" if is_percentage else "printer"
|
||||
},
|
||||
{
|
||||
"tag": "category",
|
||||
"value": category
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Add color tag only for toner percentage items
|
||||
if is_percentage and 'color' in item:
|
||||
zabbix_item['tags'].append({
|
||||
"tag": "color",
|
||||
"value": item['color']
|
||||
})
|
||||
else:
|
||||
# Use get[OID] for better performance in Zabbix 7.4
|
||||
snmp_oid = f"get[{item['oid']}]"
|
||||
|
||||
zabbix_item = {
|
||||
"uuid": uuid.uuid4().hex,
|
||||
"name": item['name'],
|
||||
"type": "SNMP_AGENT",
|
||||
"snmp_oid": snmp_oid,
|
||||
"key": item['key'],
|
||||
"delay": "1h",
|
||||
"history": "90d",
|
||||
"trends": "365d" if item['type'] != 'text' else "0d",
|
||||
"value_type": "TEXT" if item['type'] == 'text' else "FLOAT",
|
||||
"description": item['description'],
|
||||
"tags": [
|
||||
{
|
||||
"tag": "component",
|
||||
"value": "printer"
|
||||
},
|
||||
{
|
||||
"tag": "category",
|
||||
"value": category
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Add inventory mapping for specific items
|
||||
if item['key'] == 'printer.model':
|
||||
zabbix_item['inventory_link'] = 'MODEL'
|
||||
elif item['key'] == 'printer.serial':
|
||||
zabbix_item['inventory_link'] = 'SERIALNO_A'
|
||||
elif item['key'] == 'printer.hostname':
|
||||
zabbix_item['inventory_link'] = 'NAME'
|
||||
elif item['key'] == 'printer.macaddress':
|
||||
zabbix_item['inventory_link'] = 'MACADDRESS_A'
|
||||
|
||||
# Add preprocessing for text items to handle hex-encoded strings
|
||||
# Some SNMP values come as hex strings like "FD E8 48 50 20 4C 61..."
|
||||
# or as binary with control chars like "ýèHP LaserJet"
|
||||
if item['type'] == 'text':
|
||||
zabbix_item['preprocessing'] = [
|
||||
{
|
||||
"type": "JAVASCRIPT",
|
||||
"parameters": [
|
||||
"// Handle hex-encoded SNMP strings\n// Try multiple approaches to convert hex to ASCII\n\n// First, check if it looks like hex (with spaces, newlines, or other separators)\nvar hexPattern = /^[0-9A-Fa-f\\s]+$/;\nif (hexPattern.test(value) && value.length > 4) {\n // Extract all hex pairs (2 characters)\n var hexBytes = value.match(/[0-9A-Fa-f]{2}/g);\n if (hexBytes && hexBytes.length > 0) {\n var result = '';\n for (var i = 0; i < hexBytes.length; i++) {\n var code = parseInt(hexBytes[i], 16);\n // Only keep printable ASCII (0x20-0x7E)\n if (code >= 32 && code <= 126) {\n result += String.fromCharCode(code);\n }\n }\n if (result.length > 0) {\n return result;\n }\n }\n}\n\n// Fallback: Remove non-printable characters\nreturn value.replace(/[^\\x20-\\x7E]/g, '');"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
if 'units' in item:
|
||||
zabbix_item['units'] = item['units']
|
||||
|
||||
# Add triggers if defined - nested inside the item
|
||||
if 'triggers' in item:
|
||||
zabbix_item['triggers'] = []
|
||||
for trigger_def in item['triggers']:
|
||||
severity_map = {
|
||||
"warning": "WARNING",
|
||||
"high": "HIGH",
|
||||
"average": "AVERAGE"
|
||||
}
|
||||
|
||||
template_name = template['zabbix_export']['templates'][0]['template']
|
||||
|
||||
# Build description and expression with part number reference
|
||||
description = f"{item['name']} has dropped below {trigger_def['threshold']}{item.get('units', '')}"
|
||||
|
||||
# Build base expression
|
||||
expression = f"last(/{template_name}/{item['key']}){trigger_def['expression']}{trigger_def['threshold']}"
|
||||
|
||||
# Add replacement part reference for toner items
|
||||
# We need to add the part number item to the expression so we can reference it with {ITEM.LASTVALUE2}
|
||||
if 'color' in item and category == "toner_levels":
|
||||
color = item['color'].lower()
|
||||
part_key = f"printer.cartridge.{color}"
|
||||
# Add the part number item to the expression using "and" so it's evaluated but doesn't affect trigger logic
|
||||
expression = f"last(/{template_name}/{item['key']}){trigger_def['expression']}{trigger_def['threshold']} and length(last(/{template_name}/{part_key}))>0"
|
||||
description += ". Replacement part: {ITEM.LASTVALUE2}"
|
||||
# Add replacement part reference for other items with part_number_item
|
||||
elif 'part_number_item' in item:
|
||||
part_key = item['part_number_item']
|
||||
# Add the part number item to the expression using "and" so it's evaluated but doesn't affect trigger logic
|
||||
expression = f"last(/{template_name}/{item['key']}){trigger_def['expression']}{trigger_def['threshold']} and length(last(/{template_name}/{part_key}))>0"
|
||||
description += ". Replacement part: {ITEM.LASTVALUE2}"
|
||||
|
||||
trigger = {
|
||||
"uuid": uuid.uuid4().hex,
|
||||
"expression": expression,
|
||||
"name": f"{item['name']} is low on {{{{HOST.NAME}}}}",
|
||||
"priority": severity_map.get(trigger_def['severity'], "WARNING"),
|
||||
"description": description,
|
||||
"tags": [
|
||||
{
|
||||
"tag": "scope",
|
||||
"value": "availability"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
zabbix_item['triggers'].append(trigger)
|
||||
|
||||
template["zabbix_export"]["templates"][0]["items"].append(zabbix_item)
|
||||
|
||||
return template
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function
|
||||
"""
|
||||
print("\n" + "=" * 80)
|
||||
print("ZABBIX CONFIGURATION GENERATOR FOR PRINTER SNMP MONITORING")
|
||||
print("Includes: Toner, Maintenance Kit, Fuser, Drums, Waste, Transfer components")
|
||||
print("=" * 80)
|
||||
|
||||
# Generate CLI-friendly output
|
||||
generate_zabbix_cli_commands()
|
||||
|
||||
# Generate importable template
|
||||
print("\n" + "=" * 80)
|
||||
print("ZABBIX IMPORT TEMPLATE")
|
||||
print("=" * 80)
|
||||
print("\nSave this template to a file and import it into Zabbix:")
|
||||
print("Configuration -> Templates -> Import\n")
|
||||
|
||||
template_data = generate_zabbix_import_json()
|
||||
|
||||
# Save as YAML (like the working example)
|
||||
# Use default_flow_style=None to let PyYAML choose when to quote
|
||||
yaml_output = yaml.dump(template_data, default_flow_style=False, sort_keys=False, allow_unicode=True, width=1000)
|
||||
print(yaml_output)
|
||||
|
||||
with open('zabbix_printer_template.yaml', 'w') as f:
|
||||
f.write(yaml_output)
|
||||
|
||||
# Also save JSON version
|
||||
json_output = json.dumps(template_data, indent=2)
|
||||
with open('zabbix_printer_template.json', 'w') as f:
|
||||
f.write(json_output)
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print(f"✓ Zabbix template saved to: zabbix_printer_template.yaml (YAML)")
|
||||
print(f"✓ Zabbix template saved to: zabbix_printer_template.json (JSON)")
|
||||
print("=" * 80)
|
||||
|
||||
print("\n## Quick Setup Instructions:")
|
||||
print("1. Import zabbix_printer_template.json into Zabbix")
|
||||
print("2. Create/Edit a host for each printer")
|
||||
print("3. Set the SNMP interface with:")
|
||||
print(" - IP address: [printer IP]")
|
||||
print(" - Port: 161")
|
||||
print(f" - SNMP community: WestJeff2025")
|
||||
print(" - SNMP version: SNMPv2")
|
||||
print("4. Link the 'SNMP Printer Template (HP & Xerox) - Complete' to each host")
|
||||
print("5. Wait 1 hour for data collection to begin (or trigger manual check)")
|
||||
|
||||
print("\n## What Gets Monitored:")
|
||||
print("✓ Toner levels (Black, Cyan, Magenta, Yellow)")
|
||||
print("✓ Cartridge part numbers for ordering")
|
||||
print("✓ Maintenance kit status (HP printers)")
|
||||
print("✓ Fuser assembly part number")
|
||||
print("✓ Drum cartridge part numbers (all colors)")
|
||||
print("✓ Waste cartridge part number")
|
||||
print("✓ Transfer belt/roller part numbers")
|
||||
print("✓ Supply capacity data for percentage calculations")
|
||||
|
||||
print("\n## Triggers Configured:")
|
||||
print("- Warning: Toner < 20%")
|
||||
print("- Critical: Toner < 10%")
|
||||
print("- Warning: Maintenance kit < 10,000 pages")
|
||||
print("- Critical: Maintenance kit < 5,000 pages")
|
||||
|
||||
print("\n## Notes:")
|
||||
print("- Not all OIDs exist on all printers (e.g., drums on HP, maintenance on Xerox)")
|
||||
print("- Color toner OIDs only exist on color printers")
|
||||
print("- HP-specific MIB items only work on HP printers")
|
||||
print("- Check interval is 1 hour (supplies don't change rapidly)")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user