A comprehensive Python package for gathering network device inventory via SNMP and storing it in NetBox using the inventory-monitor-plugin.
This package performs the following key functions:
- Loads inventory data from network devices via SNMP (v2c and v3 supported)
- Processes and normalizes inventory data from multiple vendor platforms
- Cisco (IOS, IOS-XE, IOS-XR)
- Juniper (JunOS)
- Nokia (SROS)
- Merges inventory items with the same serial numbers based on priority class
- Uploads inventory data to NetBox as Probes via the inventory-monitor-plugin
- Python 3.7+
- NetBox instance with the inventory-monitor-plugin installed
- Network access to your devices via SNMP
- System SNMP libraries (required for easysnmp)
Install the net-snmp development libraries based on your OS:
# macOS (Homebrew)
brew install net-snmp
# Debian/Ubuntu
sudo apt-get install libsnmp-dev
# RHEL/CentOS
sudo yum install net-snmp-develThe easysnmp dependency has known compilation issues on macOS with Apple Silicon processors. This is a limitation of the easysnmp package itself, not this project.
Recommended Workarounds:
-
Use Docker (Recommended for Production)
# Use Linux-based container where easysnmp works reliably docker run -it --rm -v $(pwd):/app python:3.11-slim bash apt-get update && apt-get install -y libsnmp-dev gcc cd /app && pip install -e .
-
Use Linux VM or Server - Deploy on Linux where easysnmp has better support
-
Development on macOS - If you must develop locally on ARM64 Mac:
- Install OpenSSL via Homebrew:
brew install openssl@3 - Try manual installation with build flags:
export CFLAGS="-I/opt/homebrew/opt/openssl@3/include" export LDFLAGS="-L/opt/homebrew/opt/openssl@3/lib" pip install easysnmp
- Note: This may still fail due to upstream bugs in easysnmp
- Install OpenSSL via Homebrew:
For production deployments, we strongly recommend using Linux (Docker, VM, or bare metal) where all dependencies install reliably.
See Troubleshooting section for more details on easysnmp installation issues.
Clone the repository and install:
git clone https://github.com/yourusername/inventory_monitor_scripts.git
cd inventory_monitor_scripts
pip install -e .Verify installation:
python -m inventory_monitor.main --helpCreate a .env file in the repository root with required settings. Copy .env.sample as a starting point:
cp .env.sample .env
# Edit .env with your credentialsYou can maintain separate configuration files for different environments (production, staging, development) and specify which one to use with the --env-file flag:
# Create environment-specific files
cp .env.sample .env.production
cp .env.sample .env.staging
# Use production config
python -m inventory_monitor.main --env-file .env.production
# Use staging config with different device filter
python -m inventory_monitor.main --env-file .env.staging --netbox-tags stagingIf --env-file is not specified, the default .env file is used. This allows you to keep separate SNMP credentials, NetBox instances, and other settings per environment without modifying the default configuration.
Recommended approach:
- ✅ Use environment variables (
.envfile or exported variables) - ✅ Use
--env-filefor different environments (keeps credentials in files, not CLI) - ❌ Avoid CLI arguments for secrets (visible in
ps aux, shell history, logs)
While CLI arguments like --snmp-community and --netbox-api-token are supported for convenience, they expose credentials in process listings. Use them only for testing in secure environments.
# NetBox API Configuration
NETBOX_API_TOKEN="your_netbox_api_token"
NETBOX_INSTANCE_URL="https://your-netbox-instance/"
# SNMP Protocol Version (comma-separated, tried in order)
SNMP_VERSION="3,2" # Try SNMPv3 first, fall back to SNMPv2
# SNMPv2 Configuration
SNMP_COMMUNITY="public" # SNMPv2 community string
# SNMPv3 Configuration (only needed if using SNMPv3)
SNMP_USER="snmp_user"
SNMP_AUTH="auth_password"
SNMP_AUTH_METHOD="SHA" # MD5 or SHA
SNMP_PRIVACY="privacy_password"
SNMP_PRIVACY_METHOD="AES" # DES or AES
SNMP_SECURITY="authPriv" # noAuthNoPriv, authNoPriv, or authPriv# Device Filtering
NETBOX_TAGS="tag1,tag2" # Only process devices with these tags
NETBOX_TAGS__N="tag3,tag4" # Exclude devices with these tags
entPhysicalModelName_excludes="ASR-9900-AC-PEM,ASR-9900-DC-PEM" # Exclude specific models
# Note: the legacy spelling "entPhysicalModelName_exludes" is also accepted
# SNMP Connection Tuning
SNMP_TIMEOUT=1 # SNMP timeout in seconds (default: 1)
SNMP_RETRIES=1 # Number of retries per SNMP version (default: 1)
# NetBox SSL
NETBOX_VERIFY_SSL=true # Set to "false" to skip SSL certificate verification
# Performance Tuning
PARALLEL_JOBS=50 # Number of parallel device processing jobs (default: 50)
# Logging
LOG_LEVEL="INFO" # DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO)Security Note: The .env file contains sensitive credentials and is automatically ignored by git. The application loads config in priority order: .env file → environment variables (CLI and exported vars override .env values).
Run the script to process all active devices with primary IPs in NetBox:
python -m inventory_monitor.mainThe script will:
- Query NetBox for matching devices
- Establish SNMP connections to each device in parallel
- Retrieve inventory data
- Merge inventory items by serial number
- Create or update Probes in NetBox
To process a specific device by name (useful for testing):
python -m inventory_monitor.main --device router-1Single device processing runs sequentially without parallelization.
All SNMP and NetBox parameters can be overridden directly from the command line. CLI values take precedence over .env settings:
# Override SNMPv2 community string
python -m inventory_monitor.main --snmp-version 2 --snmp-community my_community
# Override SNMPv3 credentials
python -m inventory_monitor.main --snmp-user admin --snmp-auth MyPass --snmp-auth-method SHA
# Override SNMPv3 with full privacy
python -m inventory_monitor.main \
--snmp-user admin \
--snmp-auth AuthPass \
--snmp-auth-method SHA \
--snmp-privacy PrivPass \
--snmp-privacy-method AES \
--snmp-security authPriv
# Adjust timeout and retries
python -m inventory_monitor.main --snmp-timeout 30 --snmp-retries 3
# Combine with device selection
python -m inventory_monitor.main --device router-1 --snmp-version 2 --snmp-community secret
# Override NetBox settings
python -m inventory_monitor.main --netbox-url https://netbox.example.com/ --netbox-api-token mytoken
# Filter by tags via CLI
python -m inventory_monitor.main --netbox-tags production,core
# Exclude tags via CLI
python -m inventory_monitor.main --netbox-tags-exclude decommissioned
# Adjust parallel jobs
python -m inventory_monitor.main --parallel-jobs 10Full list of CLI options:
| Option | Description |
|---|---|
--env-file |
Path to environment file (default: .env) |
-d, --device |
Process a specific device by name |
--snmp-version |
Comma-separated SNMP versions to try (e.g. "3,2") |
--snmp-community |
SNMPv2 community string |
--snmp-user |
SNMPv3 username |
--snmp-auth |
SNMPv3 auth password |
--snmp-auth-method |
SNMPv3 auth protocol (MD5 or SHA) |
--snmp-privacy |
SNMPv3 privacy password |
--snmp-privacy-method |
SNMPv3 privacy protocol (DES or AES) |
--snmp-security |
SNMPv3 security level (noAuthNoPriv, authNoPriv, authPriv) |
--snmp-timeout |
SNMP timeout per request (integer) |
--snmp-retries |
Number of retries per SNMP version (integer) |
--netbox-api-token |
NetBox API token |
--netbox-url |
NetBox instance URL |
--netbox-tags |
Comma-separated tags to filter devices |
--netbox-tags-exclude |
Comma-separated tags to exclude devices |
--parallel-jobs |
Number of parallel processing jobs (integer) |
--log-level |
Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
--model-excludes |
Comma-separated model names to exclude from inventory |
--debug-dump |
Dump raw SNMP data to JSON file for debugging |
--env-file with separate environment files instead.
You can also still use environment variable overrides:
# Force SNMPv2 only
SNMP_VERSION='2' python -m inventory_monitor.main
# Process only devices tagged 'production'
NETBOX_TAGS='production' python -m inventory_monitor.main
# Combine multiple overrides
LOG_LEVEL=DEBUG PARALLEL_JOBS=10 python -m inventory_monitor.main --device test-deviceFor large device sets, adjust parallelism:
# Reduce load on SNMP devices (10 parallel jobs)
PARALLEL_JOBS=10 python -m inventory_monitor.main
# Maximize throughput (200 parallel jobs, requires more system resources)
PARALLEL_JOBS=200 python -m inventory_monitor.mainThe application logs which SNMP version successfully connects to each device. Run with LOG_LEVEL=DEBUG (or at default INFO) and look for these log messages:
# Successful SNMPv3:
device-name (10.0.0.1): SNMPv3 connection successful
# SNMPv3 failed, fell back to SNMPv2:
device-name (10.0.0.1): Unable to use SNMPv3 - <reason>
device-name (10.0.0.1): SNMPv2 connection successful
# Both failed:
device-name (10.0.0.1): All SNMP connection attempts failed
The version try order is controlled by SNMP_VERSION (env) or --snmp-version (CLI). With the default "3,2", SNMPv3 is tried first. If it fails, SNMPv2 is tried. To force a specific version:
# Force SNMPv2 only (skip v3 entirely)
python -m inventory_monitor.main --snmp-version 2
# Force SNMPv3 only (no v2 fallback)
python -m inventory_monitor.main --snmp-version 3
# Try v2 first, then v3
python -m inventory_monitor.main --snmp-version "2,3"At DEBUG log level, you will also see retry attempts. The default SNMP_RETRIES=1 means one attempt per version (no retries). With --snmp-retries 3:
device-name (10.0.0.1): SNMPv3 attempt 1/3 failed, retrying
device-name (10.0.0.1): SNMPv3 attempt 2/3 failed, retrying
device-name (10.0.0.1): SNMPv3 authentication failed - check username and password/keys
device-name (10.0.0.1): SNMPv2 connection successful
Logs are created in the logs/ directory with automatic rotation:
logs/all.log- All messages at the configured log level (default: INFO)logs/errors.log- Error and critical messages with detailed traces
Both logs rotate at 10 MB and are retained for 1 week.
Set LOG_LEVEL=DEBUG for detailed troubleshooting:
LOG_LEVEL=DEBUG python -m inventory_monitor.main --device router-1easysnmp on macOS ARM64: The easysnmp dependency has known issues on Apple Silicon Macs. For production use, deploy on Linux (recommended) or use Docker.
"All SNMP connection attempts failed"
- Verify device IP is reachable:
ping <device-ip> - Confirm SNMP is enabled on the device
- Check SNMP credentials in
.env - Try forcing a specific version:
python -m inventory_monitor.main --device <name> --snmp-version 2
"SNMPv3 authentication failed"
- Verify
SNMP_USERmatches device configuration - Check
SNMP_AUTHpassword andSNMP_AUTH_METHOD(SHA vs MD5) - If using privacy, ensure
SNMP_PRIVACYpassword andSNMP_PRIVACY_METHODare correct - Override from CLI to test:
--snmp-user myuser --snmp-auth mypass --snmp-auth-method SHA
"SNMPv2 timeout"
- Device may not support SNMPv2
- Increase timeout:
--snmp-timeout 200 - Increase retries:
--snmp-retries 3 - Try SNMPv3:
--snmp-version 3
- Device may not support Entity MIB (standard OIDs)
- Cisco devices fall back to legacy OIDs automatically
- Check device is actively reporting SNMP inventory
"API token invalid"
- Regenerate token in NetBox under Settings > API Tokens
- Verify token has write permissions to inventory-monitor plugin
"Probe creation failed"
- Ensure inventory-monitor-plugin is installed in NetBox
- Check device exists in NetBox with correct name
- Verify device has primary IPv4 address assigned
"NetBox API error ... 500"
- NetBox server encountered an internal error
- Check NetBox server logs for details
- Retry after the server recovers
"NetBox API error ... 400 ... not one of the available choices"
- A tag specified in
NETBOX_TAGSor--netbox-tagsdoes not exist in NetBox - Verify tag names match exactly (case-sensitive)
- Create missing tags in NetBox under Organization > Tags
Use --debug-dump to save raw SNMP data as a JSON file for inspection:
python -m inventory_monitor.main --device router-1 --debug-dump debug_output.jsonThen inspect it in Python:
import json
with open('debug_output.json') as f:
data = json.load(f)
# Inspect raw SNMP resultsSee CLAUDE.md for detailed architecture and development guidance.
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Commit your changes (
git commit -am 'Add feature') - Push to the branch (
git push origin feature/your-feature) - Create a Pull Request
[Insert your license information here]
Developed by [Your Organization/Team Name]