first commit
Some checks failed
ci / deploy (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled

This commit is contained in:
Vlastislav Svatek
2026-06-05 10:39:05 +02:00
commit 673e67106e
217 changed files with 76612 additions and 0 deletions

259
docs/README.md Normal file
View File

@@ -0,0 +1,259 @@
# NetBox LibreNMS Plugin
### Intro
The NetBox LibreNMS Plugin enables integration between NetBox and LibreNMS, allowing you to leverage data from both systems. NetBox remains the Source of Truth (SoT) for you network, but this plugin allows you to easily onboard device objects from existing data in LibreNMS. The plugin does not automatically create objects in NetBox to ensure only verified data is used to populate NetBox.
## Features
The plugin offers the following key features:
### Device Import
Search and import devices from LibreNMS into NetBox with comprehensive validation and control:
* Filter devices by location, type, OS, hostname, system name, or hardware model
* Validate import prerequisites (Site, Device Type, Device Role)
* Smart matching for Sites, Device Types, and Platforms
* Import as physical Devices or Virtual Machines
* Bulk import multiple devices
* Automatic Virtual Chassis creation for stackable switches
* Background job processing for large device sets
See the [Device Import Guide](librenms_import/overview.md) for detailed usage instructions.
### Device Field Sync
Synchronize device information from LibreNMS to NetBox. The following device fields can be synchronized:
* Device Name (with naming preference support)
* Serial Number (including virtual chassis members)
* Device Type
* Platform
### Interface Sync
Pull interface data from Devices and Virtual Machines from LibreNMS into NetBox. The following interface attributes are synchronized:
* Name
* Description
* Status (Enabled/Disabled)
* Type (with [custom mapping support](usage_tips/interface_mappings.md))
* Speed
* MTU
* MAC Address
* VLAN (Tagged and untagged)
> Set custom mappings for interface types to ensure that the correct interface type is used when syncing from LibreNMS to NetBox.
### Cable Sync
Create cable connection in NetBox from LibreNMS links data.
### IP Address Sync
Create IP address in NetBox from LibreNMS device IP data.
### VLAN Sync
- Create VLAN objects in NetBox from LibreNMS device VLAN data
- Per-VLAN group assignment with scope-aware auto-selection
### Add device to LibreNMS from Netbox
* Add device to LibreNMS from Netbox device page. SNMP v2c and v3 are supported.
### Site & Location Sync
The plugin also supports synchronizing NetBox Sites with LibreNMS locations:
* Compare NetBox sites to LibreNMS location data
* Create LibreNMS locations to match NetBox sites
* Update existing LibreNMS locations latitude and longitude values based on NetBox data ⚠️ *(currently not working due to LibreNMS API issue)*
* Sync device site to LibreNMS location
### Screenshots/GIFs
> Screenshots from older plugin version
#### Site & Location Sync
![Site Location Sync](img/Netbox-librenms-plugin-Sites.gif)
#### Sync devices and Interfaces
![Add device and interfaces](img/Netbox-librenms-plugin-interfaceadd.gif)
#### Virtual Chassis Member Select
![Virtual Chassis Member Selection](img/Netbox-librenms-plugin-virtualchassis.gif)
#### Interface Type Mappings
![Interfaces Type Mappings](img/Netbox-librenms-plugin-mappings.png)
## Contributing
There's more to do! Coding is not my day job so bugs will exist and improvements will be needed. Contributions are very welcome! I've got more ideas for new features and improvements but please [contribute](contributing.md) if you can!
Or just share your ideas for the plugin over in [discussions](https://github.com/bonzo81/netbox-librenms-plugin/discussions).
## Compatibility
| NetBox Version | Plugin Version |
| -------------- | -------------- |
| 4.1 | 0.2.x - 0.3.5 |
| 4.2 - 4.5 | 0.3.6+ |
## Installing
### Standard Installation
Activate your virtual environment and install the plugin:
```bash
source /opt/netbox/venv/bin/activate
```
Install with pip:
```bash
(venv) $ pip install netbox-librenms-plugin
```
Add to your `local_requirements.txt` to ensure it is automatically reinstalled during future upgrades.
```bash
echo "netbox-librenms-plugin" >> /opt/netbox/local_requirements.txt #Check your NetBox install location
```
### Docker
For adding to a NetBox Docker setup see how to create a custom Docker image. [the general instructions for using netbox-docker with plugins](https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins).
Add the plugin to `plugin_requirements.txt` (netbox-docker):
```bash
# plugin_requirements.txt
netbox-librenms-plugin
```
## Configuration
### 1. Enable the Plugin
Enable the plugin in `/opt/netbox/netbox/netbox/configuration.py`, or if you use netbox-docker, your `/configuration/plugins.py` file :
```python
PLUGINS = [
'netbox_librenms_plugin'
]
```
### 2. Apply the plugin configuration
Multi server example:
```python
PLUGINS_CONFIG = {
'netbox_librenms_plugin': {
'servers': {
'production': {
'display_name': 'Production LibreNMS',
'librenms_url': 'https://librenms-prod.example.com',
'api_token': 'your_production_token',
'cache_timeout': 300,
'verify_ssl': True,
'interface_name_field': 'ifDescr'
},
'testing': {
'display_name': 'Test LibreNMS',
'librenms_url': 'https://librenms-test.example.com',
'api_token': 'your_test_token',
'cache_timeout': 300,
'verify_ssl': False,
'interface_name_field': 'ifName'
},
'development': {
'display_name': 'Dev LibreNMS',
'librenms_url': 'https://librenms-dev.example.com',
'api_token': 'your_dev_token',
'cache_timeout': 180,
'verify_ssl': False,
'interface_name_field': 'ifDescr'
}
}
}
}
```
Or use the original single server confiig example:
```python
PLUGINS_CONFIG = {
'netbox_librenms_plugin': {
'librenms_url': 'https://your-librenms-instance.com',
'api_token': 'your_librenms_api_token',
'cache_timeout': 300,
'verify_ssl': True, # Optional: Change to False if needed,
'interface_name_field': 'ifDescr', # Optional: LibreNMS field used for interface name. ifName used as default
}
}
```
### 3. Apply Database Migrations
Apply database migrations with Netbox `manage.py`:
```
(venv) $ python manage.py migrate
```
### 4. Collect Static Files
The plugin includes static files that need to be collected by NetBox. Run the following command to collect static files:
```
(venv) $ python manage.py collectstatic --no-input
```
### 5. Restart Netbox
Restart the Netbox service to apply changes:
```
sudo systemctl restart netbox
```
### 6. Custom Field
As of version 0.4.4, the plugin **automatically creates** the `librenms_id` custom field (JSON type) when migrations are run. No manual setup is required.
The field is created for Device, Virtual Machine, Interface, and VM Interface objects and stores a per-server mapping (e.g., `{"production": 42}`).
For more info check out [custom field docs](usage_tips/custom_field.md)
## Update
```
source /opt/netbox/venv/bin/activate
pip install -U netbox-librenms-plugin
python manage.py migrate
python manage.py collectstatic --no-input
systemctl restart netbox
```
## Uninstall
See [the instructions for uninstalling plugins](https://netboxlabs.com/docs/netbox/en/stable/plugins/removal/).
## Credits
Based on the NetBox plugin tutorial and docs:
* [demo repository](https://github.com/netbox-community/netbox-plugin-demo)
* [tutorial](https://github.com/netbox-community/netbox-plugin-tutorial)
* [docs](https://netboxlabs.com/docs/netbox/en/stable/plugins/development/)
This package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter). Thanks to the [`netbox-community/cookiecutter-netbox-plugin`](https://github.com/netbox-community/cookiecutter-netbox-plugin) for the project template.

28
docs/SUMMARY.md Normal file
View File

@@ -0,0 +1,28 @@
# Table of contents
* [NetBox LibreNMS Plugin](README.md)
* [Getting Started](usage_tips/README.md)
* [Feature Overview](feature_list.md)
* [Initial Setup](usage_tips/README.md)
* [Custom Field Setup](usage_tips/custom_field.md)
* [Multi-Server Setup](usage_tips/multi_server_configuration.md)
* [Permissions & Access](usage_tips/permissions.md)
* [Suggested Workflow](usage_tips/suggested_workflow.md)
* [Import Devices](librenms_import/overview.md)
* [Overview](librenms_import/overview.md)
* [Searching for Devices](librenms_import/search.md)
* [Validation & Configuration](librenms_import/validation.md)
* [Import Settings](librenms_import/import_settings.md)
* [Background Jobs & Caching](librenms_import/background_jobs.md)
* [Sync & Configuration](usage_tips/virtual_chassis.md)
* [Virtual Chassis](usage_tips/virtual_chassis.md)
* [Interface Mappings](usage_tips/interface_mappings.md)
* [Development](development/README.md)
* [Overview](development/README.md)
* [Project Structure](development/structure.md)
* [Views & Inheritance](development/views.md)
* [Mixins](development/mixins.md)
* [Templates](development/templates.md)
* [Testing](development/testing.md)
* [Changelog](changelog.md)
* [Contributing](contributing.md)

428
docs/changelog.md Normal file
View File

@@ -0,0 +1,428 @@
# Changelog
## 0.4.6 (2026-04-20)
### Fixes
* Fix VC master device showing 0 module bays after import by preventing stale counter overwrites during virtual chassis creation (#275)
* Defer VC master assignment until after all members are attached
* Add `_sync_module_bay_counter()` safety net to reconcile counter after master assignment
## 0.4.5 (2026-04-16)
### Fixes
* Fix VLAN group modal not closing on dismiss button, cancel button, save button, or backdrop click on the interface sync page
* Align `showModal()`/`hideModal()` with `ModalManager` pattern — try Bootstrap 5 native first, fall back to manual DOM manipulation
* Prevent stacking backdrop click handlers on repeated `showModal()` calls
## 0.4.4 (2026-04-15)
### New Features
* **Multi-Server Support**: JSON-based `librenms_id` custom field with per-server device tracking, server management, and migration from legacy integer format
* **Auto-Create Custom Field**: Automatically create the `librenms_id` custom field via `post_migrate` signal
* **Sync Page Naming Preferences**: Apply `use_sysname` and `strip_domain` naming preferences to device name matching on sync pages
* **VC Import Enhancements**: Show virtual chassis members in import confirm modal, enforce stack VC permissions before import, and fix VC flag propagation across the import flow
### Improvements
* Refactor `import_utils.py` into a package with aligned module boundaries
* Security hardening — URL-encode `server_key` in redirects, reject `librenms_id` <= 0, CSRF safety, XSS label escaping in cable verify
* JS hardening — extract `showModal`/`hideModal` helpers, harden `getDeviceIdFromUrl`, guard `interfaceNameField`, remove dead code
* Server-key propagation, UI polish, and view hardening across multi-server import pipeline
* Cable sync matching by `local_port_id` instead of display name; strip stale fields on cable verify POST
* Simplify migration — always revert to integer, handle non-integer custom field types gracefully
* Skip `device_type` check for VMs; add `sync_platform` to VM supported actions
* Update supported NetBox versions in README
### Fixes
* Fix VC master detection, 0-based position correction, and import propagation
* Fix VC verify view crash by using `get_librenms_sync_device()` in verify views
* Fix cables view caching, `interface_name_field` per-request, and `LibreNMSAPIMixin`
* Fix operator precedence in message fallback expressions
* Fix import validation, template bugs, and pagination
* Correct `vc_detection_enabled` default in `validate_device_for_import` call
* Fix stale docstrings, test names, and duplicate functions
* Guard `dt_match` None on ambiguous hardware match in `validate_device_for_import`
* Write enriched links data back to cache on non-fresh path
* Restore multi-key naming preferences and early-exit on missing name
### Development
* Expanded test coverage with new test files and reorganized existing tests
* Smoke tests, integration tests, and mock LibreNMS server
* Add `pytest-cov` coverage report (no gating)
* Updated pre-commit hooks, ruff config, and uv Dependabot
* Bump GitHub Actions dependencies (upload-artifact, download-artifact, pypi-publish)
* Update pull request template for contributions
### Documentation
* Update documentation for 0.4.4 release
* Testing docs updates with new test files and philosophy
## 0.4.3 (2026-03-03)
### New Features
* **VLAN Sync**: Full VLAN synchronization with per-row verification, per-VLAN group selection, color-coded summary UI, edit modal, and form spinners
* **Two-Tier Permission System**: Plugin-level and object-level access control with `LibreNMSPermissionMixin` and `NetBoxObjectPermissionMixin`
* **Serial Number Matching & Conflict Resolution**: Import detects serial number matches and guides users through device conflicts
* **Per-User Preferences**: Persistent user preferences for import toggles and interface name field
* **Device Identity Mismatch Modal**: Informational mismatch display on sync pages when device name differs between NetBox and LibreNMS
* **Empty State Cards**: Friendly empty state cards on sync tabs when no data is available
* **Naming Preferences in Validation**: Honour `use_sysname` and `strip_domain` settings in the import validation path with badge indicators
* **SNMPv1 Support**: Add SNMPv1 option to the LibreNMS add device form
### Improvements
* Security hardening — XSS escaping, input validation, open-redirect prevention, and VC member validation
* Block import when validation issues are present; fix modal titles and hostname conflict display
* Code deduplication and minor bug fixes across views and utilities
* Add docstrings to models, tables, views, forms, and API modules
* Pin all GitHub Actions to commit SHAs and add Dependabot configuration
* Add pull request template for contributions
### Fixes
* Fix KeyError for missing non-default server keys in `LibreNMSAPI`
* Fix device redirect URL and inaccurate docstrings
* Correct device role refresh to preserve schema keys
* Fix validation readiness, VM form guards, and sync_info accuracy
* Use flash message + redirect for import permission denied
* Add virtual chassis permission check and validate `object_type`
### Development
* Comprehensive test suite with CI workflow (GitHub Actions, pytest, ruff lint/format)
* Pre-commit hooks and updated format/lint dependencies
* DevContainer refactor with script consolidation, proxy/MITM support, and diagnostic tooling
* Modular copilot instructions split into per-concern `.instructions.md` files
### Documentation
* VLAN sync feature and view architecture documentation
* Permission system documentation
* Improved README, workflow guides, and troubleshooting notes
## 0.4.2 (2026-01-16)
### Fixes
* Fix device sync not working after update (Issue #199)
* Fix API endpoints for hostname lookup and port retrieval that were incorrectly changed
* Fix NameError in get_device_id_by_ip method - correct undefined 'mac_address' variable error (Issue #197)
## 0.4.1 (2026-01-12)
### Fixes
* Fix librenms_id custom field to use integer values in import process
## 0.4.0 (2026-01-09)
## Major Features
- **LibreNMS Bulk Device Import**: Complete workflow for importing devices from LibreNMS with HTMX-based UI, validation, and background job processing
- **Background Job Support**: Asynchronous processing for large device imports with real-time status tracking and cancellation
- **Enhanced Caching**: Improved caching system with expiration countdown, metadata storage, and multi-server isolation
- **Virtual Chassis Detection**: Automatic detection and handling of virtual chassis during import
- Add hardware and exclude-existing filters to device import
- Client-side table sorting for import page
- Active LibreNMS server display on import page
- Improved logging patterns and documentation
- Cache management with discard controls
- Refactored settings page with HTMX (removed fetch-based JavaScript)
- Enhanced virtual chassis sync device detection logic
- Better error handling and connection exhaustion prevention
## Development
- Improved dev container with RQ worker management
- Comprehensive test coverage for background jobs
- Enhanced copilot instructions for AI-assisted development
- Better process management and reload scripts
## Documentation
- Extensive import documentation (overview, process, settings, validation, search)
- Background job architecture documentation
- Improved README and workflow guides
- Virtual chassis usage documentation
## 0.3.18 (2025-11-21)
### Improvements
* Add all LibreNMS SNMP fields to add device form
## 0.3.17 (2025-10-24)
### Improvements
* Improve device type matching with prioritized matching strategy
* Centralize device type matching logic in utils.py (DRY principle)
* Add word boundary detection for more precise substring matches
## 0.3.16 (2025-10-24)
### New Features
* Add device field synchronization (serial number, device type, platform)
* Add virtual chassis inventory support with serial assignment to individual members
* Add VM information display in LibreNMS status card
* Add bulk interface mapping import functionality
### Improvements
* Improve virtual chassis device matching with LibreNMS for devices with VC member suffixes
* Enhance virtual chassis logic and member selection
### Development
* Add GitHub DevContainer setup for easier development environment
### Fixes
* Fix FieldError for librenms_status on device/VM status pages
### Documentation
* Update README with device field sync details
* Improve virtual chassis documentation
* Added example Interface Mapping YAML for bulk import
## 0.3.15 (2025-07-12)
### Improvements
* Improve multi-server configuration handling and add connection testing
## 0.3.14 (2025-07-08)
### Fixes
* Filter out invalid IP entries in BaseIPAddressTableView
### New Features
* View/Delete NetBox-only (unmatched) interfaces
* Add multi LibreNMS server configuration support for LibreNMS plugin
### Documentation
* Add page for multi server configuration instructions and example
## 0.3.13 (2025-06=27)
### New Feature
* Add support for IPv6 handling in IP address synchronization
### Documentation
* Add basic development documentation
## 0.3.12 (2025-04-11)
### Improvements
* Add VRF selection support to IP address table and sync
* Implement single IP address verification and VRF assignment
* Extend single IP verification to support Virtual Machines
### Under the hood
* Refactor cable and IP address synchronization methods for improved transaction handling
* Refactor IP address enrichment for improved performance
## 0.3.11 (2025-03-31)
### Improvements
* Enhance remote port enrichment for virtual chassis devices
## 0.3.10 (2025-03-17)
### Fixes
* Fix URL error when no interfaces are selected during sync
* Add hidden SNMP version field to forms and update sync logic
## 0.3.9 (2025-03-14)
### Fixes
* Fix missing add_device_modal.html template and form handling
* Fix missing interfacetypemapping template
## 0.3.8 (2025-03-06)
### Fixes
* Fix cable table error when more than one remote device returned
* Fix cable table checkboxes controls for virtual chassis devices
### Improvements
* Add slug check to Site and Location Sync
## 0.3.7 (2025-01-22)
### Fixes
* Fix issue with empty queryset to stop fielderror
### Improvements
* Enhance filtering options for devices and virtual machines
### Under the hood
* Review and refactor docstrings across all files
## 0.3.6 (2025-01-21)
### NOTE
***Netbox v4.2+ required for this release***
### New Feature
* New dedicated plugin menu item
* Add device and VM status pages
### Fixes
* Add description to interface mapping page
### Under the hood
* Update to use new Mac Address object for Netbox v4.2
## 0.3.5 (2025-01-13)
### Fixes
* Fix IP Address table not displaying for Virutal Machines
## 0.3.4 (2025-01-08)
### Fixes
* Fix VM Interface table not dispalying
## 0.3.3 (2025-01-03)
### New Feature
* Add IP address synchronization
### Fixes
* Refactor librenms_id handling in SyncInterfacesView
### Under the hood
* Refactor table.py into separate modules for better maintainability
* Enhance interface data retrieval efficiency
## 0.3.2 (2024-12-16)
### Fixes
* Refactor tab handling for interface and cable views
* Fix Duplicate ID in SNMP forms
* Refactor cable link processing and fix CSRF token error.
* Generate unique base ID for TomSelect components in VCInterfaceTable
* Add countdown interval variable to initializeCountdown function
## 0.3.1 (2024-12-13)
### Fixes
* Fix issue with tab selection not working after sync task
* Updated interface name field tooltip
## 0.3.0 (2024-12-13)
### New Setting
* Add `interface_name_feild` optional setting to allow choice of interface name field used when syncing interface data.
* Add `interface_name_field` override in GUI for per device control and flexibility.
### Improvements
* Add `librenms_id` to interface sync table and data sync
* Use of `librenms_id` custom field on interface lookup for improved matching in the cables table.
* Add Pagination support to the cables table.
### Fixes
* Fix issue with case sensitive hostname matching
### Under the hood
* Refactor views into seperate modules for better maintainability
## 0.2.9 (2024-11-30)
## Fix pypi release
Add static include in MANIFEST.in for pypi release
## 0.2.8 (2024-11-29)
### Use of Custom Field
This release introduces the option of using a custom field `librenms_id` (integer) to device and virtual machine objects in NetBox. The plugin will work without it but it is recommended for LibreNMS API lookups especially if no primary IP or FQDN available.
**Note: New static javascript file requires running collectstatic after update**
```
(venv) $ python manage.py collectstatic --no-input
```
### New Features
* Add device to LibreNMS using SNMPv3
* Create cable connection from LIbreNMS links data31
* Plugin can now use primary IP, hostname or Primary IP DNS Name to identify device in LibreNMS
* Exclude specific columns when syncing data
* Filter interface and cable tables
* Bulk edit Virtual Chassis members
### Improvements
* Add pagination to SiteLocationSyncTable
* Add site location filtering functionality and update template for search
* Refactor LibreNMSAPI to enhance device ID retrieval logic and include DNS name handling
* Enhance cable sync with device ID handling and user guidance modal
* Add device mismatch check and user feedback
* Add check for empty MAC address in format_mac_address function
* Increase API request timeout to 20 seconds
* Fix dropdown menu size issue on click
### Under the hood
* Refactor interface enabled status logic
* Fix handling of data-enabled attribute in interface table
* Improve interface mapping logic for speed matchingpull/24
* Refactor cable context handling and improve data rendering in cable tables
* Refactor Javascript into single file. Add cable sync filters and countdown timer
* Refactor device addition and enhance SNMP v3 support
## 0.2.7 (2024-11-11)
### What's Changed
* Add new interface table logic to handle virtual chassis member selection
* Update LibreNMS plugin configuration to allow disabling of SSL verification
### Interface name change
*The LibreNMS Sync interface names now use the ifDescr from Librenms. This displays the full interface name to better align with the device type library convention. e.g GigabitEthernet1/0/1 instead of Gig1/0/1.*
## 0.2.6 (2024-10-25)
### New Feature
* Sync Virtual Machine interfaces
### Bug fix
* Pagination bug where page contents would duplicate now fixed.
### Under the hood
* Refactoring of views into separate files for better maintainability.
* Code formatting improvements
* Remove unused elements
## 0.2.5 (2024-10-21)
Bug fix release:
* Missing commas in LibreNMS api module
## 0.2.4 (2024-10-21)
### Enhancements
* Add mac_address, MTU to interface sync
* Enable select all and shift click on interface sync page rows, and other improvements
* Interface mapping now accounts for speed of interface
> Update to Interface mapping modal may require recreation of existing mapping.
* Updated LibreNMS Sync page layout to prepare for new features
### Under the hood
* Refactor all views to be class-based
* Big refactor of device LibreNMS sync views to make way for new features
## 0.2.3 (2024-09-30)
* Fix bug where wrong template is used when editing interface mappings
* Remove unused templates from view
## 0.2.2 (2024-09-27)
* Fix too many arguments to add_device error
## 0.2.1 (2024-09-27)
* Fix LibreNMS hardware variable not found
* Add update_device_field to LibreNMS API
* Add device location Sync button to device plugin tab
* Change SNMP community from 'text' to 'password' for privacy
## 0.2.0 (2024-09-25)
* Update to v0.2.0 of the plugin
## 0.1.1 (2024-09-24)
* First release on PyPI.

112
docs/contributing.md Normal file
View File

@@ -0,0 +1,112 @@
# Contributing
Contributions are welcome, and they are greatly appreciated! Every little bit
helps, and credit will always be given.
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
## Types of Contributions
### Report Bugs
Report bugs at https://github.com/bonzo81/netbox-librenms-plugin/issues.
If you are reporting a bug, please include:
* Any details about your local environment that might be helpful in troubleshooting.
* Detailed steps to reproduce the bug.
### Fix Bugs
Look through the GitHub issues for bugs. Anything tagged with "bug" and "help
wanted" is open to whoever wants to implement it.
### Implement Features
Look through the GitHub issues for features. Anything tagged with "enhancement"
and "help wanted" is open to whoever wants to implement it.
### Write Documentation
NetBox LibreNMS Plugin could always use more documentation, whether as part of the
official NetBox LibreNMS Plugin docs, in docstrings, or even on the web in blog posts,
articles, and such.
### Submit Feedback
The best way to send feedback is to file an issue at https://github.com/bonzo81/netbox-librenms-plugin/issues.
If you are proposing a feature:
* Explain in detail how it would work.
* Keep the scope as narrow as possible, to make it easier to implement.
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
## Get Started!
Ready to contribute? Here's how to set up `netbox-librenms-plugin` for local development.
1. Fork the `netbox-librenms-plugin` repo on GitHub.
2. Clone your fork locally
```
$ git clone git@github.com:<username>/netbox-librenms-plugin.git
```
3. Activate the NetBox virtual environment (see the NetBox documentation under [Setting up a Development Environment](https://docs.netbox.dev/en/stable/development/getting-started/)):
```
$ source /opt/netbox/venv/bin/activate
```
4. Add the plugin to NetBox virtual environment in Develop mode (see [Plugins Development](https://docs.netbox.dev/en/stable/plugins/development/)):
To ease development, it is recommended to go ahead and install the plugin at this point using setuptools' `develop` mode. This will create symbolic links within your Python environment to the plugin development directory. Call `pip` from the plugin's root directory with the `-e` flag:
```
$ pip install -e .
```
5. Create a branch for local development:
```
$ git checkout -b name-of-your-bugfix-or-feature
```
Now you can make your changes locally.
6. Commit your changes and push your branch to GitHub:
```
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
```
7. Submit a pull request through the GitHub website.
## Pull Request Guidelines
Before you submit a pull request, check that it meets these guidelines:
1. The pull request should include tests.
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.md.
3. The pull request should work for Python 3.10+. Check
https://github.com/bonzo81/netbox-librenms-plugin/actions
and make sure that the tests pass for all supported Python versions.
## Deploying
A reminder for the maintainers on how to deploy.
Make sure all your changes are committed (including an entry in CHANGELOG.md) and that all tests pass.
Then in the github project go to `Releases` and create a new release with a new tag. This will automatically upload the release to pypi:

View File

@@ -0,0 +1,10 @@
# Development Guide: Navigating the Codebase
This guide is intended for developers and contributors working on the NetBox LibreNMS Plugin. It provides a broad overview of the codebase structure and key elements. For detailed NetBox plugin development documentation, see the [official NetBox documentation](https://docs.netbox.dev/en/stable/plugins/development/).
## Contents
- [Project Structure](./structure.md): Overview of the main folders and files in the plugin.
- [Views & Inheritance](./views.md): How views are organized, inheritance patterns, and extension tips.
- [Mixins](./mixins.md): Reusable logic for views, including API access and caching.
- [Templates](./templates.md): Template structure, conventions, and customization tips.

View File

@@ -0,0 +1,44 @@
# Mixins
Mixins in `views/mixins.py` provide reusable logic to keep views clean and DRY (Don't Repeat Yourself). They are designed to be combined with Django or NetBox views to add specific behaviors or shared functionality. When adding new views, consider using or extending these mixins to maintain consistency and reduce code duplication.
### Key Mixins
**LibreNMSAPIMixin**
- Provides a `librenms_api` property for accessing the LibreNMS API from any view.
- Ensures a single instance of the API client is reused per view instance.
- Example usage: Add to views that need to fetch or sync data with LibreNMS.
**CacheMixin**
- Supplies helper methods for generating cache keys related to objects and data types (e.g., ports, links, vlans).
- Useful for views that cache data fetched from LibreNMS to improve performance.
- Methods:
- `get_cache_key(obj, data_type="ports")`: Returns a unique cache key for the object and data type.
- `get_last_fetched_key(obj, data_type="ports")`: Returns a cache key for tracking when data was last fetched.
- `get_vlan_overrides_key(obj)`: Returns a cache key for storing user VLAN group override selections.
**VlanAssignmentMixin**
- Provides VLAN group resolution and assignment logic used by both the Interfaces tab (per-interface VLAN assignments) and the VLANs tab (VLAN object sync).
- Resolves which VLAN groups are relevant to a device based on a scope hierarchy: Rack → Location → Site → SiteGroup → Region → Global.
- Methods:
- `get_vlan_groups_for_device(device)`: Returns all VLAN groups relevant to the device based on scope hierarchy.
- `_build_vlan_lookup_maps(vlan_groups)`: Builds lookup dictionaries mapping VIDs to groups, VLANs, and names.
- `_select_most_specific_group(groups, device)`: Resolves ambiguity when a VID exists in multiple groups by selecting the most specific scope.
- `_find_vlan_in_group(vid, vlan_group_id, lookup_maps)`: Finds a VLAN by VID, preferring the specified group.
- `_update_interface_vlan_assignment(interface, vlan_data, vlan_group_map, lookup_maps)`: Updates interface mode, untagged VLAN, and tagged VLANs in NetBox.
### How to Use Mixins
To use a mixin, simply add it to the inheritance list of your view class. For example:
```python
from .mixins import LibreNMSAPIMixin, CacheMixin
class MyCustomView(LibreNMSAPIMixin, CacheMixin, SomeBaseView):
# ... your view logic ...
```
Mixins can be combined as needed. Place mixins before the main base view to ensure their methods and properties are available.

View File

@@ -0,0 +1,35 @@
# Project Structure
This document provides an overview of the NetBox LibreNMS Plugin's codebase organization.
## Main Directories
- `netbox_librenms_plugin/` — Main plugin code
- `views/` — Custom views for devices, mappings, VMs, etc.
- `base/` — Abstract base views for shared logic (interfaces, cables, IP addresses, VLANs)
- `object_sync/` — Per-model sync views registered as tabs on Device/VM detail pages
- `sync/` — POST-only views that apply sync changes (interfaces, cables, IP addresses, VLANs, devices)
- `models.py` — Database models
- `forms.py` — Custom forms
- `tables/` — Table definitions for UI
- `templates/` — Custom templates
- `netbox_librenms_plugin/` — Main template directory
- `inc/` — Shared template fragments (e.g., paginator)
- `api/` — API serializers, views, and URLs
- `import_utils/` — Import pipeline logic, split into focused modules
- `device_operations.py` — Device validation, single-device import, filtered fetch
- `vm_operations.py` — VM creation and import logic
- `bulk_import.py` — Multi-device / bulk import orchestration
- `filters.py` — LibreNMS device filtering and retrieval
- `permissions.py` — User permission checking helpers
- `cache.py` — Cache key generation
- `virtual_chassis.py` — Virtual chassis data helpers
- `import_validation_helpers.py` — Validation state mutation during import (role/cluster/rack assignment, issue removal, status recalculation)
- `migrations/` — Django migrations
- `utils.py` — Utility functions
- `navigation.py` — Menu/navigation integration
- `static/` — Static assets (JS, CSS)
- `netbox_librenms_plugin/` — Plugin-specific static files
- `js/` — JavaScript files
- `tests/` — Test suite
- `docs/` — Documentation

View File

@@ -0,0 +1,28 @@
# Templates
Templates are located in `templates/netbox_librenms_plugin/` and follow NetBox's conventions, using Django's template language. The plugin uses a combination of base templates, partials, and includes to keep the UI modular and maintainable.
### Structure and Conventions
- **Base templates** (e.g., `librenms_sync_base.html`, `interfacetypemapping.html`) typically extend NetBox's generic templates (like `generic/object.html` or `generic/object_list.html`).
- **Partials and includes** (e.g., `_interface_sync.html`, `_interface_sync_content.html`, `_cable_sync.html`) are used for reusable UI components and AJAX/HTMX content updates.
- **The `inc/` directory** contains shared fragments, such as pagination controls (`paginator.html`).
### Customization and Inheritance
- Use the Django template tag `extends` to build on top of NetBox or plugin base templates, and the `block` tag to override or inject content.
- Use the Django template tag `include` for reusable sections (e.g., tables, forms, or modal dialogs).
- Static assets (JS/CSS) are loaded with the Django template tag `load static` and referenced using the `static` tag.
- Context variables and template tags (e.g., `helpers`, `plugins`, `render_table`) are used to render dynamic content and integrate with NetBox features.
### Examples
**Sync Views:**
- `librenms_sync_base.html` provides the main layout for device/VM sync pages, extending NetBox's object template and including custom blocks for status, actions, and content.
- `_interface_sync.html` and `_interface_sync_content.html` are used for the interface sync tab, supporting dynamic updates and user actions (like syncing selected interfaces).
- `_vlan_sync.html` and `_vlan_sync_content.html` provide the VLAN sync tab (Devices only), with per-VLAN group selection dropdowns, color-coded status indicators (green/yellow/red), and a cache countdown timer. The VLANs tab is conditionally rendered only for devices in `librenms_sync_base.html`.
**Mapping Views:**
- `interfacetypemapping.html` and `interfacetypemapping_list.html` display and manage interface type mappings, using table layouts and info alerts.
For more on NetBox's template system, see the [NetBox documentation](https://netbox.readthedocs.io/en/stable/plugins/development/#templates).

247
docs/development/testing.md Normal file
View File

@@ -0,0 +1,247 @@
# Testing Guide
This guide explains how to run the test suite, write new tests, and debug failures.
## Quick Start
Run all tests with a single command:
```bash
make unittest
```
Or run pytest directly:
```bash
pytest netbox_librenms_plugin/tests/ -v
```
## Test Structure
The test suite covers all major plugin functionality. Tests are organized by the module they verify:
| Test File | What It Tests |
|-----------|---------------|
| [test_librenms_api.py](../../netbox_librenms_plugin/tests/test_librenms_api.py) | LibreNMS API client—connections, device operations, locations, ports, and error handling |
| [test_import_utils.py](../../netbox_librenms_plugin/tests/test_import_utils.py) | Device import logic—filtering, validation, and data transformation |
| [test_import_validation_helpers.py](../../netbox_librenms_plugin/tests/test_import_validation_helpers.py) | Field validation for sites, roles, platforms, and device types |
| [test_utils.py](../../netbox_librenms_plugin/tests/test_utils.py) | General utilities—name matching, speed conversion, and data formatting |
| [test_background_jobs.py](../../netbox_librenms_plugin/tests/test_background_jobs.py) | Background job execution and view decision logic |
| [test_vlan_sync.py](../../netbox_librenms_plugin/tests/test_vlan_sync.py) | VLAN sync—API fetching, comparison logic, CSS class utilities, and sync actions |
| [test_interface_vlan_sync.py](../../netbox_librenms_plugin/tests/test_interface_vlan_sync.py) | Interface VLAN assignments—group resolution, mode detection, and per-interface VLAN assignment |
| [test_librenms_id.py](../../netbox_librenms_plugin/tests/test_librenms_id.py) | Multi-server librenms_id helpers—get/set/find/migrate and boolean rejection |
| [test_mixins.py](../../netbox_librenms_plugin/tests/test_mixins.py) | View mixins—CacheMixin key generation, LibreNMSAPIMixin lazy init |
| [test_sync_devices.py](../../netbox_librenms_plugin/tests/test_sync_devices.py) | Device sync views—field updates, platform creation |
| [test_sync_interfaces.py](../../netbox_librenms_plugin/tests/test_sync_interfaces.py) | Interface sync—port matching, attribute updates, MAC handling, librenms_id assignment |
| [test_virtual_chassis.py](../../netbox_librenms_plugin/tests/test_virtual_chassis.py) | Virtual chassis detection—VC member naming patterns and name generation |
| [test_sync_view_mismatch.py](../../netbox_librenms_plugin/tests/test_sync_view_mismatch.py) | Sync page context—device type mismatch detection and badge rendering |
| [test_coverage_device_fields.py](../../netbox_librenms_plugin/tests/test_coverage_device_fields.py) | Device field sync view—field update logic and device field mapping |
| [test_coverage_list.py](../../netbox_librenms_plugin/tests/test_coverage_list.py) | Import list view—background job decision, job result loading, and GET handler |
| [test_coverage_api.py](../../netbox_librenms_plugin/tests/test_coverage_api.py) | LibreNMS API client—malformed payload guards, error paths, and edge cases |
| [test_coverage_api2.py](../../netbox_librenms_plugin/tests/test_coverage_api2.py) | API views—device status, background job management, VM status endpoints |
| [test_coverage_base_views.py](../../netbox_librenms_plugin/tests/test_coverage_base_views.py) | Base view coverage tests—sync table views, context data, and data pipeline |
| [test_coverage_base_views2.py](../../netbox_librenms_plugin/tests/test_coverage_base_views2.py) | Additional base view coverage—IP address sync, cable matching, edge cases |
| [test_coverage_cache.py](../../netbox_librenms_plugin/tests/test_coverage_cache.py) | Import cache helpers—cache key generation, active search tracking, metadata |
| [test_coverage_device_operations.py](../../netbox_librenms_plugin/tests/test_coverage_device_operations.py) | Device validation—type matching, serial handling, VC detection, role lookup |
| [test_coverage_forms.py](../../netbox_librenms_plugin/tests/test_coverage_forms.py) | Import forms—filter form choices, background-job option guards, field validation |
| [test_coverage_mixins.py](../../netbox_librenms_plugin/tests/test_coverage_mixins.py) | View mixins—VLAN group scope resolution, VlanAssignmentMixin, scope priority |
| [test_coverage_sync_interfaces.py](../../netbox_librenms_plugin/tests/test_coverage_sync_interfaces.py) | Interface sync view—port caching, attribute updates, MAC handling, VC member routing |
| [test_coverage_sync_view.py](../../netbox_librenms_plugin/tests/test_coverage_sync_view.py) | Sync view base class—context preparation and tab rendering |
| [test_coverage_sync_views.py](../../netbox_librenms_plugin/tests/test_coverage_sync_views.py) | Sync action views—cables, IP addresses, VLAN sync action handlers |
| [test_coverage_sync_views2.py](../../netbox_librenms_plugin/tests/test_coverage_sync_views2.py) | Additional sync action view coverage—device fields, device name/type sync |
| [test_coverage_sync_views3.py](../../netbox_librenms_plugin/tests/test_coverage_sync_views3.py) | Further sync action view coverage—location sync, VLAN assignment edge cases |
| [test_coverage_actions.py](../../netbox_librenms_plugin/tests/test_coverage_actions.py) | Import action views—bulk import, device role/cluster/rack update, validation details |
| [test_coverage_filters.py](../../netbox_librenms_plugin/tests/test_coverage_filters.py) | Import filter logic—filter form processing and device count helpers |
| [test_init.py](../../netbox_librenms_plugin/tests/test_init.py) | Plugin startup—`_ensure_librenms_id_custom_field` creation, type migration, and multi-DB alias handling |
| [test_coverage_tables.py](../../netbox_librenms_plugin/tests/test_coverage_tables.py) | Sync tables—column rendering, row data, interface and cable table helpers |
| [test_coverage_utils.py](../../netbox_librenms_plugin/tests/test_coverage_utils.py) | Utility function coverage—name matching, speed conversion, site/platform lookup |
| [test_coverage_virtual_chassis.py](../../netbox_librenms_plugin/tests/test_coverage_virtual_chassis.py) | Virtual chassis coverage—VC creation, position conflict handling, member naming |
| [test_coverage_vlans_table.py](../../netbox_librenms_plugin/tests/test_coverage_vlans_table.py) | VLAN sync table—column rendering, group assignment, VLAN comparison rows |
| [test_sync_modules.py](../../netbox_librenms_plugin/tests/test_sync_modules.py) | Module sync—inventory matching, module type resolution, and normalization rules |
| [test_modules_view.py](../../netbox_librenms_plugin/tests/test_modules_view.py) | Module sync view—context preparation, table rendering, and module bay mapping |
| [test_tables_modules.py](../../netbox_librenms_plugin/tests/test_tables_modules.py) | Module tables—column rendering, row formatting, and action buttons |
| [test_permissions.py](../../netbox_librenms_plugin/tests/test_permissions.py) | Permission enforcement—mixin contracts, object-level permissions, and write guards |
| [test_vm_operations.py](../../netbox_librenms_plugin/tests/test_vm_operations.py) | VM operations—virtual machine sync, interface handling, and VM-specific views |
| [test_integration_sync.py](../../netbox_librenms_plugin/tests/test_integration_sync.py) | Integration tests—API client against local mock HTTP server |
| [test_integration_virtual_chassis.py](../../netbox_librenms_plugin/tests/test_integration_virtual_chassis.py) | Integration tests—VC detection, negative cache, multi-server cache isolation |
| [test_view_wiring.py](../../netbox_librenms_plugin/tests/test_view_wiring.py) | Smoke tests—view class MRO, mixin wiring, permission contracts, and template syntax |
Supporting files:
| File | Purpose |
|------|---------|
| [conftest.py](../../netbox_librenms_plugin/tests/conftest.py) | Shared pytest fixtures |
| [test_librenms_api_helpers.py](../../netbox_librenms_plugin/tests/test_librenms_api_helpers.py) | Auto-use fixture for API configuration mocking |
| [mock_librenms_server.py](../../netbox_librenms_plugin/tests/mock_librenms_server.py) | Minimal HTTP mock server for integration tests |
## Running Tests
### Running Specific Tests
```bash
# Run a specific test file
pytest netbox_librenms_plugin/tests/test_librenms_api.py -v
# Run a specific test class
pytest netbox_librenms_plugin/tests/test_librenms_api.py::TestLibreNMSAPIConnection -v
# Run a specific test method
pytest netbox_librenms_plugin/tests/test_librenms_api.py::TestLibreNMSAPIConnection::test_connection_success -v
```
### Running Tests by Area
```bash
# API client tests
pytest netbox_librenms_plugin/tests/test_librenms_api.py netbox_librenms_plugin/tests/test_coverage_api.py netbox_librenms_plugin/tests/test_coverage_api2.py -v
# Import and validation tests
pytest netbox_librenms_plugin/tests/test_import_utils.py netbox_librenms_plugin/tests/test_import_validation_helpers.py netbox_librenms_plugin/tests/test_utils.py -v
# Background job tests
pytest netbox_librenms_plugin/tests/test_background_jobs.py -v
# Multi-server librenms_id tests
pytest netbox_librenms_plugin/tests/test_librenms_id.py -v
# Sync view tests (devices, interfaces, modules)
pytest netbox_librenms_plugin/tests/test_sync_devices.py netbox_librenms_plugin/tests/test_sync_interfaces.py netbox_librenms_plugin/tests/test_sync_modules.py -v
# Integration tests (API client against mock HTTP server)
pytest netbox_librenms_plugin/tests/test_integration_*.py -v
# Sync view mismatch detection and permission enforcement
pytest netbox_librenms_plugin/tests/test_sync_view_mismatch.py netbox_librenms_plugin/tests/test_permissions.py -v
# View wiring and template syntax smoke tests
pytest netbox_librenms_plugin/tests/test_view_wiring.py -v
```
### Debugging Failed Tests
```bash
# Show full traceback
pytest netbox_librenms_plugin/tests/ -v --tb=long
# Show print statements during tests
pytest netbox_librenms_plugin/tests/ -v -s
# Stop on first failure
pytest netbox_librenms_plugin/tests/ -v -x
# Re-run only failed tests from last run
pytest netbox_librenms_plugin/tests/ -v --lf
```
## Testing Philosophy
The test suite prioritizes speed and isolation so you can run tests frequently during development:
- **Mock-based**: Unit tests use `MagicMock` instead of real database objects. No Django database setup required.
- **Fast execution**: The full suite runs in approximately 15-20 seconds (varies by environment).
- **Isolated**: Each test is independent with no shared state between tests.
- **No external network access**: Tests never call external services. Integration tests use a local loopback HTTP server (`mock_librenms_server.py`) to exercise the real API client against realistic HTTP responses without requiring a running LibreNMS instance.
- **Coverage exclusions**: Test files themselves are excluded from coverage reports (see `[tool.coverage.run]` omit list in `pyproject.toml`).
This approach means tests work identically in your local development environment, in the devcontainer, and in CI pipelines.
## Writing New Tests
### Basic Test Template
New tests should follow this structure:
```python
from unittest.mock import MagicMock, patch
class TestFeatureName:
"""Tests for [feature description]."""
pytest_plugins = ["tests.test_librenms_api_helpers"]
@patch("netbox_librenms_plugin.module_name.external_dependency")
def test_specific_behavior(self, mock_dependency, mock_librenms_config):
"""Describe what this test verifies."""
# Arrange - set up test data and mocks
mock_dependency.return_value = {"expected": "response"}
# Act - call the code being tested
from netbox_librenms_plugin.module_name import function_to_test
result = function_to_test(input_data)
# Assert - verify the results
assert result == expected_value
mock_dependency.assert_called_once_with(expected_args)
```
### Key Testing Conventions
**Use inline imports** inside test methods to avoid Django initialization at module load time:
```python
def test_something(self):
from netbox_librenms_plugin.librenms_api import LibreNMSAPI
api = LibreNMSAPI(server_key="default")
```
**Mock NetBox models** with `MagicMock()` instead of creating real database objects:
```python
device = MagicMock()
device.name = "test-device"
device.primary_ip.address.ip = "192.168.1.1"
```
**Patch at the source module**, not where the function is imported:
```python
# Correct - patch where the function is defined
@patch("netbox_librenms_plugin.import_utils.process_device_filters")
# Incorrect - patching the import location
@patch("netbox_librenms_plugin.views.imports.list.process_device_filters")
```
### Available Fixtures
These fixtures are defined in [conftest.py](../../netbox_librenms_plugin/tests/conftest.py):
- `mock_librenms_config` — Automatically mocks plugin configuration for all tests
- `mock_response_factory` — Factory for creating mock HTTP responses
- `mock_netbox_device` — Pre-configured mock NetBox Device object
- `mock_netbox_vm` — Pre-configured mock NetBox VM object
### Common Assertion Patterns
```python
# Methods returning (success, data) tuples
success, data = api.get_device_info(123)
assert success is True
assert data["hostname"] == "expected-hostname"
# Methods returning dicts with error flags
result = api.test_connection()
assert "error" not in result
# Verifying exceptions are raised
with pytest.raises(ValueError, match="Invalid configuration"):
api.method_that_should_fail()
# Verifying mock calls
mock_get.assert_called_once()
mock_post.assert_called_with(expected_url, headers=expected_headers, json=expected_data)
mock_delete.assert_not_called()
```
## CI/CD Compatibility
The tests run in any environment without external dependencies:
- No database connection required
- No external network access needed (integration tests use local loopback only)
- Fast execution suitable for pre-commit hooks
- Clear failure messages for debugging
- Works in containerized environments
This makes the test suite suitable for GitHub Actions, pre-commit hooks, or any CI pipeline you choose to implement.

74
docs/development/views.md Normal file
View File

@@ -0,0 +1,74 @@
# Views & Inheritance
Views are organized by resource type (e.g., devices, mappings, VMs) in the `views/` directory. The codebase uses a layered approach to views, leveraging inheritance and mixins to maximize code reuse and maintainability.
### View Organization
**Resource-specific views:**
- Device and VM sync tabs live under `object_sync/` (see `object_sync/devices.py` and `object_sync/vms.py`), while mappings/settings/status views remain as individual modules alongside the package.
- The LibreNMS import workflow is grouped under `views/imports/`: `list.py` renders the main table view and `actions.py` contains the HTMX endpoints (preview, validation, bulk execute). All legacy handlers formerly in `librenms_import_views.py` and `device_import_views.py` were folded into this package.
**Base views:**
- The `base/` subdirectory contains abstract base views (e.g., `BaseLibreNMSSyncView`, `BaseInterfaceTableView`, `BaseCableTableView`, `BaseIPAddressTableView`, `BaseVLANTableView`) that encapsulate shared logic for related resources.
**Mixins:**
- Shared behaviors (e.g., API access, caching) are factored into mixins in `mixins.py` and combined with base or resource-specific views as needed.
### Inheritance Patterns
- Most resource-specific views inherit from a base view in `base/` and one or more mixins.
- Base views themselves often inherit from NetBox or Django generic views (e.g., `generic.ObjectListView`, `django.views.View`).
- This allows resource-specific views to override or extend only the methods they need, while inheriting default behaviors from base classes and mixins.
#### Example: Device Sync View
```python
from .base.librenms_sync_view import BaseLibreNMSSyncView
from .mixins import LibreNMSAPIMixin
class DeviceLibreNMSSyncView(BaseLibreNMSSyncView):
# Inherits API access and sync logic from base/mixins
# Only device-specific logic needs to be implemented here
...
```
#### Example: Interface Table View
```python
from .base.interfaces_view import BaseInterfaceTableView
from .mixins import CacheMixin, LibreNMSAPIMixin
class DeviceInterfaceTableView(BaseInterfaceTableView):
model = Device
# Implements get_interfaces and get_redirect_url for devices
...
```
#### Example: VLAN Table View
```python
from .base.vlan_table_view import BaseVLANTableView
class DeviceVLANTableView(BaseVLANTableView):
model = Device
# Inherits VLAN comparison, group resolution, and caching from base view
# Only the model attribute needs to be set
...
```
`BaseVLANTableView` additionally inherits `VlanAssignmentMixin` for VLAN group scope resolution. It fetches device VLANs from LibreNMS, compares them against NetBox VLAN objects across relevant VLAN groups, and renders a color-coded table with per-VLAN group dropdowns.
### Customizing or Adding Views
- To add a new view for a resource, inherit from the relevant base view and mixins, then override or extend methods as needed.
- Use the base views as templates for structure and required methods.
- Register new views in `urls.py` and add templates if needed.
### Tips
- Check the `base/` directory for reusable logic before writing new view code.
- Use mixins for cross-cutting concerns (API, caching, permissions).
- Keep resource-specific views focused on their unique logic; delegate shared logic to base classes and mixins.

72
docs/feature_list.md Normal file
View File

@@ -0,0 +1,72 @@
### [Device Import](librenms_import/overview.md)
* Search and discover devices from LibreNMS using flexible filters
* Validate device prerequisites before import (Site, Device Type, Device Role)
* Import devices as physical Devices or Virtual Machines
* Smart matching for Sites, Device Types, and Platforms
* Bulk import support
* Automatic Virtual Chassis creation for stackable devices
* Background job processing for large device sets
* Duplicate detection to prevent re-importing existing devices
### Plugin Settings
* Multi-server LibreNMS configuration support
* Configurable device naming defaults (sysName vs hostname)
* Domain stripping options during import for cleaner device names
* Virtual Chassis member naming pattern customization during import
### Device
* LibreNMS device identification via:
* [Custom field `librenms_id`](usage_tips/custom_field.md) _(recommended)_
* Primary IP address
* Primary IP DNS name
* Hostname
* Add device to LibreNMS from netbox via SNMP v2c or v3
### [Virtual Chassis Support](usage_tips/virtual_chassis.md)
* Automatic VC member selection for each interface
* Member-specific interface synchronization
* Bulk member editing capabilities
### Interface Sync {#interface-sync}
* Create or Update interface in NetBox from LibreNMS interface data
* Name
* Description
* Status (Enabled/Disabled)
* Type (with custom mapping support)
* Speed
* MAC Address
* MTU
* VLAN assignments
* Sync all or specific fields
### Cable Sync {#cable-sync}
* Create Cable connection in NetBox from LibreNMS links data
* Best results when the [custom field](usage_tips/custom_field.md) `librenms_id` is populated on interfaces
### IP Address Sync {#ip-address-sync}
* Create IP address objects in Netbox from LibreNMS device IP data
* Best results when the [custom field](usage_tips/custom_field.md) `librenms_id` is populated on interfaces
### VLAN Sync {#vlan-sync}
* Create VLAN objects in NetBox from LibreNMS device VLAN data
* Per-VLAN group assignment with scope-aware auto-selection
### Location
* NetBox Site to LibreNMS location synchronization
* Sync location latitude and longitude values from NetBox to LibreNMS
### [Interface Mapping](usage_tips/interface_mappings.md)
* Customizable LibreNMS to NetBox interface type mappings
* Interface Speed-based mapping rules
* Bulk import support

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,76 @@
# Background Jobs & Caching
The Device Import feature uses background job processing and intelligent caching for both searching and importing devices. Background jobs are enabled by default for both operations to handle large device sets efficiently.
## Background Jobs
Background jobs run asynchronously in NetBox's job system for both device searches and import operations.
### Background Job Processing
Both device searches and import operations can run as background jobs (default) or synchronously. Background jobs are recommended for:
- Large device sets (especially searches with more than 50 devices)
- Operations with Virtual Chassis detection enabled
- Import operations of any size
**Benefits of background jobs:**
- Avoid browser timeouts on long-running operations
- Cancel operations in progress if needed
- Continue using NetBox while the job runs
- Review detailed logs and results after completion
### Viewing Job Status
All background jobs appear in NetBox's **Jobs** interface, where you can view status, start time, duration, and results.
## Caching
The import table caches data for 5 minutes to reduce load times and minimize API calls to LibreNMS. Cache keys are unique per filter combination.
### What Gets Cached
The cache includes both LibreNMS device data AND NetBox reference data used in the import table:
**From LibreNMS:**
- Device lists matching your search filters
- Device details (hostname, sysName, location, hardware, etc.)
- Virtual chassis detection results
**From NetBox:**
- Available device roles (for the role dropdown in each row)
- Available VM clusters (for VM imports)
- Available racks for each site (filtered by the device's matched site)
This means if you add a new role, create a new rack, or add a new cluster in NetBox, those changes won't appear in the import table dropdowns until you clear the cache or wait for it to expire (5 minutes).
### Controlling Cache
The search form includes a "Clear cache before search" checkbox:
| Setting | Behavior |
|---------|----------|
| Unchecked (default) | Uses cached data if available. Fastest results. |
| Checked | Forces fresh data retrieval from both LibreNMS and NetBox. |
**When to clear cache:**
- After adding or updating devices in LibreNMS
- After adding new roles, racks, or clusters in NetBox that should appear in import dropdowns
- When troubleshooting import issues
- When you need to verify current state
**When to keep cache enabled:**
- Normal operations and when refining search filters
- When repeatedly working with the same set of devices
- When NetBox reference data hasn't changed
### Active Cached Searches
The import page displays all your recent searches at the top, showing which filter combinations, that are still found in the cache. Each cached search shows the filters used, device count, and time remaining before expiration.
Click any cached search to instantly reload those results without re-running filters or Virtual Chassis detection. This is particularly useful when switching between different filter combinations.
Cached searches expire after 5 minutes of inactivity (or what you set as the cache timeout). The countdown timer shows how long each search remains available.
The "Clear cache before search" option only clears the cache for the specific filter combination you're searching—other cached searches remain available.

View File

@@ -0,0 +1,71 @@
# Import Settings
Configure how devices are named and what data is imported from LibreNMS to NetBox.
## Setting Defaults
To configure global defaults for all imports:
1. Navigate to **Plugins → LibreNMS Plugin → Settings**
2. Click **Plugin Settings**
3. Configure Use sysName and Strip Domain to your preferred defaults
4. Save changes
These defaults apply to all future imports unless overridden during the import process.
## User Preferences and Defaults
The plugin uses a two-tier preference system for the **Use sysName** and **Strip Domain** toggles:
1. **Plugin defaults** (set by admins on the Settings page) apply to all users who have not yet changed their own toggle settings.
2. **Per-user preferences** are saved automatically when a user changes a toggle on the import page. Once saved, the user's preference takes priority over the plugin default.
**Important notes:**
- Changing the plugin defaults does **not** override existing user preferences. Users who have previously changed a toggle keep their personal setting.
- When an admin saves import settings, only the admin's own preferences are updated to match the new defaults. Other users are unaffected.
- There is no "reset to defaults" for individual users. To revert to the plugin default, a user simply needs to toggle the setting to match.
## Device Naming Options
The plugin provides two settings that control how device names are created in NetBox. Both are configured in Plugin Settings under **Plugins → LibreNMS Plugin → Settings → Plugin Settings** and can be overridden on the LibreNMS import page.
### Use sysName
Controls which field from LibreNMS becomes the device name in NetBox.
- **Enabled** (default): Uses the SNMP sysName, falling back to LibreNMS hostname if sysName is not available
- **Disabled**: Uses the LibreNMS hostname field
### Strip Domain
Removes domain suffixes from device names to create shorter, cleaner names.
- **Enabled**: Removes domain suffixes (e.g., "router.example.com" becomes "router"). IP addresses are preserved without modification
- **Disabled**: Keeps the full name as-is
### Naming Examples
```
LibreNMS sysName: router-core-01.example.com
LibreNMS hostname: 10.0.0.1
Use sysName + Strip domain → "router-core-01"
Use sysName + Keep domain → "router-core-01.example.com"
Use hostname + Strip domain → "10.0.0.1" (IP preserved)
Use hostname + Keep domain → "10.0.0.1"
```
If neither sysName nor hostname exists, the plugin generates a name as `device-{librenms_id}`.
## Per-Import Overrides
On the import page, the **Use sysName** and **Strip Domain** toggles are pre-populated from your saved preference (or the plugin default if you haven't set one). Changing a toggle immediately saves your preference for next time and applies to the current import.
This allows you to:
- Import some devices with sysName and others with hostname
- Apply domain stripping selectively based on device type or location
- Test different naming conventions — your last choice is remembered automatically

View File

@@ -0,0 +1,71 @@
# Device Import Overview
The Device Import feature allows you to discover and import devices from LibreNMS into NetBox. This streamlines the process of populating NetBox with devices that are already monitored in LibreNMS, while giving you full control over how devices are imported.
The import page should be clear and intuitive to use, but this overview provides additional context and details.
## How It Works
The import workflow consists of three main steps:
1. **[Search & Filter](search.md)** - Find devices in LibreNMS using flexible filter criteria
2. **[Review & Validate](validation.md)** - Validate import readiness and configure missing NetBox objects
3. **[Import](import_settings.md)** - Configure import settings and create devices in NetBox
The plugin validates all required NetBox objects (Site, Device Type, Device Role) before allowing import.
## Key Features
**Flexible Filtering**
: Search by location, type, operating system, hostname, system name, or hardware model. Combine filters for precise device selection.
**Smart Validation**
: Automatic matching for Sites, Device Types, and Platforms based on LibreNMS data. Clear indicators for what's missing.
**Device or VM**
: Import as physical Devices (requires Site, Device Type, Role) or Virtual Machines (requires Cluster).
**Virtual Chassis Support**
: Automatic detection and creation of Virtual Chassis objects for stackable switches.
**Background Processing**
: Large device sets can be processed using NetBox background jobs with progress tracking and cancellation.
## Accessing the Feature
Navigate to the import interface through the NetBox menu:
**Plugins → LibreNMS Plugin → Import → LibreNMS Import**
This opens the device import page where you can search for and import devices from your LibreNMS instance.
## What Gets Created
When a device is imported, the plugin creates:
**Device or VirtualMachine Object**
: With all validated attributes (name, site, device type, role, platform, serial, rack, etc.). Note that rack assignment places the device in the rack without setting a specific rack unit (U) position—devices appear in the "Non racked" section and require manual U assignment.
**LibreNMS ID Custom Field**
: Automatically set to link the NetBox object to the LibreNMS device. This enables all other plugin features (interface sync, cable sync, etc.)
**Virtual Chassis** (if detected)
: For stackable devices, creates the Virtual Chassis object and assigns member positions based on detected inventory data.
After import, devices appear in NetBox with a comment indicating they were imported by the plugin, including the import timestamp.
## Multi-Server Support
If your NetBox installation is configured with multiple LibreNMS servers, the import feature automatically uses the currently selected server from Plugin Settings.
All imported devices are linked to the server used during import, allowing you to maintain devices from multiple LibreNMS instances in a single NetBox installation.
## Next Steps
Explore each step of the import workflow:
- [Search for Devices](search.md) - Learn about filters, matching rules, and search options
- [Validation & Configuration](validation.md) - Understand validation status and resolve issues
- [Import Settings](import_settings.md) - Configure device naming and import options
- [Background Jobs & Caching](background_jobs.md) - Job processing and performance optimization

View File

@@ -0,0 +1,98 @@
The import feature requires at least one filter to search for devices. This prevents accidentally loading thousands of devices and helps you work with focused device sets.
## Available Filters
LibreNMS Location
: Exact match by LibreNMS location ID. The dropdown shows all locations from your LibreNMS instance with their names and IDs.
LibreNMS Type
: Exact match by device type (network, server, storage, wireless, firewall, power, appliance, printer, loadbalancer, other).
Operating System
: Partial match by OS name. For example, "ios" matches "cisco-ios", "ios-xe", "cisco-ios-xr".
LibreNMS Hostname
: Partial match by the hostname or IP address used to add the device to LibreNMS.
LibreNMS System Name
: When used alone, performs an exact match on the SNMP sysName. When combined with other filters, performs a partial match.
Hardware
: Partial match by LibreNMS hardware model. For example, "C9300" matches devices with hardware like "Cisco C9300-48P".
## Additional Search Options
Include Disabled Devices
: When checked, includes devices marked as disabled in LibreNMS. By default, only active devices are shown.
Include Virtual Chassis Detection
: When checked, analyzes device inventory to detect stackable switches and chassis. This adds processing time but provides helpful information about multi-member devices. See [Virtual Chassis](../usage_tips/virtual_chassis.md) for details.
Clear cache before search
: Forces the plugin to fetch fresh data from LibreNMS instead of using cached results. LibreNMS data is normally cached for 5 minutes to improve performance.
Exclude Existing Devices
: When checked, hides devices that already exist in NetBox. By default, all devices are shown including those already imported.
## Filter Matching Rules
Understanding how filters work helps you get the right results:
Exact Match Filters
: Location, Type, and OS (when used alone) must match exactly as shown in LibreNMS.
Partial Match Filters
: Hostname, OS (with other filters), and System Name (with other filters) find devices containing your search text.
Multiple Filters
: All filters must match for a device to appear in results. Start with Location or Type to narrow results, then refine with additional filters.
### Filter Examples
**Find all network devices in New York**
```
Location: New York
Type: network
```
**Find Cisco devices**
```
Type: network
OS: ios
```
**Find specific hardware model at New York**
```
Location: New York
Hardware: C9300
Type: network
```
**Find a specific device by name**
```
System Name: router-core-01.example.com
```
**Find devices with "F" in hostname at New York with device type firewall**
```
Hostname: F
Location: New York
Type: firewall
```
## Search Options
Run as background job
: Enabled by default. Runs searches asynchronously, allowing you to track progress and cancel operations. Recommended for most use cases, especially with Virtual Chassis detection or large device sets. See [Background Jobs & Caching](background_jobs.md) for details.
Clear cache before search
: Forces fresh data from LibreNMS instead of using cached results. LibreNMS data is normally cached for 5 minutes to improve performance. See [Background Jobs & Caching](background_jobs.md) for caching details.
## Saved Cached Searches
The import page displays all your recent searches at the top, showing which filter combinations, that are still found in the cache. Each cached search shows the filters used, device count, and time remaining before expiration. Click any cached search to instantly reload those results without re-running filters. This is particularly useful when switching between different filter combinations.
## Next Steps
After searching, proceed to:
- [Validation & Configuration](validation.md) - Review and configure devices for import
- [Background Jobs & Caching](background_jobs.md) - Understand job processing and performance optimization

View File

@@ -0,0 +1,51 @@
# Validation & Configuration
After searching, the import table displays devices with action buttons that reflect their validation status.
## Validation States
Import Button (Green)
: Device is ready to import. All required fields are matched or configured.
Disabled Import Button + Details Button (Gray/Red)
: Device has missing required fields. Click Details to configure.
Link to Existing Device
: Device already exists in NetBox. Link navigates to the existing device.
## Required Fields
NetBox requires three fields before importing a device: **Site**, **Device Type**, and **Device Role**. The plugin attempts to match Site and Device Type automatically by comparing LibreNMS data to existing NetBox objects. Device Role must always be selected manually.
Click the validation details button to review what's missing and select values from the dropdowns. The validation status updates immediately.
### Import as Device
- **Site** (required) - Auto-matched from LibreNMS location
- **Device Type** (required) - Auto-matched from LibreNMS hardware string
- **Device Role** (required) - Must be selected manually
- **Platform** (optional) - Auto-matched from LibreNMS OS
- **Rack** (optional) - Available if Site has racks
### Import as Virtual Machine
- **Cluster** (required) - Must be selected manually
- **Platform** (optional) - Auto-matched from LibreNMS OS
## Virtual Chassis Detection
When Virtual Chassis Detection is enabled during search, the validation details show detected stack members with their positions, serials, and suggested names. The plugin automatically creates the Virtual Chassis object during import. See [Virtual Chassis](../usage_tips/virtual_chassis.md) for details.
## Duplicate Detection
The plugin checks for existing devices using:
1. **LibreNMS ID custom field** (most reliable) - If set, device is marked "Already Exists"
2. **Hostname match** - Exact name match against Devices and VMs
3. **Primary IP address** (weak match) - If IP is already assigned to a device
If both a VM and Device with the same hostname exist, the plugin cannot determine which to match and allows import. Set the `librenms_id` custom field on the correct existing object to clarify the match.
## Next Steps
- [Import Settings](import_settings.md) - Configure device naming and import options

94
docs/usage_tips/README.md Normal file
View File

@@ -0,0 +1,94 @@
# Usage Tips
## Initial Setup
1. [Configure Custom Field](custom_field.md)
- Set up the `librenms_id` custom field for optimal device matching
- This ensures reliable device identification between NetBox and LibreNMS
2. [Configure Interface Mappings](interface_mappings.md)
- Review and set up interface type mappings before synchronization
- Create specific mappings for your network equipment types
- Pay attention to speed-based mappings for accurate interface types
3. [Multi Server Configuration](multi_server_configuration.md)
- Configure multiple LibreNMS instances in your NetBox configuration
- Switch between different LibreNMS servers through the web interface
- Maintain backward compatibility with single-server configurations
## Device Import
[Device Import Guide](../librenms_import/overview.md) - Import devices from LibreNMS into NetBox
1. Search for devices using flexible filters (location, type, OS, hostname, sysname)
2. Validate import prerequisites (Site, Device Type, Device Role)
3. Configure missing mappings or select from suggestions
4. Import devices individually or in bulk
5. Automatic Virtual Chassis creation for stackable switches
The Device Import feature automatically sets the `librenms_id` custom field, enabling all other plugin features.
> **Rack Position Assignment:** Imported devices can be assigned to racks without specific rack unit (U) positions. After import, assign U positions through the "Non racked" section of each rack. The [NetBox Reorder Rack plugin](https://github.com/minitriga/netbox-reorder-rack) simplifies this workflow.
## Device Synchronization
### Devices
> **Note:** If you imported devices using the [Device Import feature](../librenms_import/overview.md), the `librenms_id` is already set and will be used automatically. The steps below apply to devices added to NetBox manually.
1. Ensure devices have either:
- Primary IP configured
- Valid DNS name (set on the Primary IP)
- hostname (that matches LibreNMS hostname)
2. The plugin will populate the `librenms_id` custom field if the device is found in LibreNMS
### Virtual Chassis
LibreNMS treats a Virtual Chassis as one logical device. The plugin selects a single "sync device" from your chassis to communicate with LibreNMS using this priority:
1. **Member with `librenms_id` set** (if already configured)
2. **Master device with primary IP** (most common)
3. **Any member with primary IP** (fallback)
4. **Member with lowest position number** (last resort)
Only the selected sync device should have the `librenms_id` custom field populated—leave it empty on all other members.
For best results, align chassis member positions with interface naming patterns. For example, if switch 1 has interfaces like `eth1/0/1` and switch 2 has `eth2/0/1`, the plugin can auto-detect the correct member for each interface. Always verify the member selection before running bulk synchronization.
## Interface Management
1. Verify Before Sync
- Review interface mappings indicated by the icons (🔗 shows a mapping is configured)
- Check speed and type matches
- Confirm member assignments for virtual chassis
2. Exclude columns to exclude from interface sync
- Sync only the values you want to sync
3. Sync VLANs first to ensure that VLANs are created in NetBox before syncing interfaces, allowing for proper VLAN assignments. Use the VLAN tab on the device sync page to create VLANs from LibreNMS data.
## Cable Management
1. Preparation
- Ensure devices are properly identified in both systems
- Open LibreNMS Sync on all devices to populate librenms_id custom field
- Remote Device and Remote interface need to be found in NetBox for cable creation to work
- Check Device and Interface naming
## VLAN Management
1. Preparation
- Configure VLAN Groups in NetBox if you want scoped VLAN assignment (e.g., per-site or per-rack groups)
- The plugin resolves VLAN groups using a scope hierarchy: Rack → Location → Site → SiteGroup → Region → Global
2. Review the VLANs tab on the device sync page
- Select the appropriate VLAN Group for each VLAN, or let the plugin auto-select based on scope
- A warning icon appears when a VID does not exist in the selected VLAN group.
3. Sync selected VLANs to create or update them in NetBox
## Best Practices
1. Regular Maintenance
- Periodically review and update interface mappings
- Keep custom fields current
## Optimization
- DNS lookup time can slow response of the API call to LibreNMS

View File

@@ -0,0 +1,97 @@
# Using the `librenms_id` Custom Field
## Overview
To enhance device identification and synchronization between NetBox and LibreNMS, this plugin supports using a custom field `librenms_id` on Device, Virtual Machine and Interface objects. While the plugin works without it, using this custom field is recommended for LibreNMS API lookups, and to assist with matching the remote device and remote interfaces for cable creation in Netbox. It can also be entered manually if no primary IP or FQDN is available.
!!! info "Automatic Creation"
As of version 0.4.4, the plugin **automatically creates** the `librenms_id` custom field when migrations are run. You no longer need to create it manually. The field is created for Device, Virtual Machine, Interface, and VM Interface objects with JSON type for per-server device tracking.
For the Device and Virtual Machine objects the plugin will automatically populate the LibreNMS ID custom field when opening the LibreNMS Sync page if the device has been found in LibreNMS.
For the Interface object, the plugin will automatically populate the LibreNMS ID custom field when the interface data is synced from LibreNMS.
## Benefits of Using `librenms_id`
- **Improved Device Matching:** Ensures accurate matching between NetBox and LibreNMS devices.
- **Fallback Identification:** Useful when devices lack a primary IP or FQDN.
- **Efficient Synchronization:** Enhances the reliability of API lookups.
- **Cable creation:** Allows better device identification for the creation of cables between NetBox devices.
## Manual Custom Field Setup
!!! note
On 0.4.4+, rerun migrations first (`manage.py migrate`). If you need to recreate the field manually on current releases, use the JSON schema below. Pre-0.4.2 releases used an Integer field — do not use Integer for new entries.
Follow these steps to create the `librenms_id` custom field in NetBox:
1. **Navigate to Custom Fields:**
- Go to **Customization** in the NetBox sidebar.
- Click on **Custom Fields**.
2. **Add a New Custom Field:**
- Click the **Add a custom field** button.
3. **Configure the Custom Field:**
- **Object Types:**
- Check **dcim > device**
- Check **virtualization > virtual machine**
- Check **dcim > interface**
- Check **virtualization > interfaces (optional)**
- **Name:** `librenms_id`
- **Label:** `LibreNMS ID`
- **Description:** (Optional) Add a description like "LibreNMS Device ID for synchronization".
- **Type:** JSON (object) — stores a per-server mapping.
- Multi-server example:
```json
{"production": 42, "staging": 17}
```
- Legacy single-server example (integer) — read-only/deprecated; do not use for new entries:
```
42
```
> Note: to create new entries manually use the JSON format shown above.
- **Required:** Leave unchecked (optional).
- **Default Value:** Leave blank.
4. **Save the Custom Field:**
- Click **Create** to save the custom field.
### Manually assign a value to `librenms_id`
You can manually assign a value to the `librenms_id` custom field for a device using the following steps:
1. **Edit the Device:**
- Navigate to the device in NetBox.
- Click the **Edit** button.
2. **Set the LibreNMS ID:**
- Scroll to the **Custom Fields** section.
- Enter the `librenms_id` value as a JSON object with your server key(s):
```json
{"production": 42}
```
For multiple servers: `{"production": 42, "staging": 17}`
3. **Save Changes:**
- Click **Update** to save the device.
## Notes
- If `librenms_id` is set, the plugin will prioritize it over other identification methods.
- Ensure the `librenms_id` corresponds to the correct device ID in LibreNMS to prevent mismatches.
- The custom field is optional but recommended for optimal plugin performance.
- Using the custom field on interfaces will greatly improve the interface matching required for cable synchronization.

View File

@@ -0,0 +1,137 @@
# interface\_mappings
### Quick Intro
Interface type mappings control how LibreNMS interface types are translated to NetBox interface types during synchronization.
The mappings can be customized in the plugin settings menu.
A mapping of LibreNMS Type an LibreNMS Speed combine to make a unique group that map to a Netbox interface type. This means multiple mapping for the same LibreNMS Type can be created.
> Note: The LibreNMS Speed is entered as Kbps
Example:
```
* ethernetCsmacd + 10000000 = 10GBASE-T (10GE)
* ethernetCsmacd + 1000000 = 1000BASE-T (1GE)
* ethernetCsmacd + 100000 = 100BASE-TX (10/100ME)
```
### How to Use Interface Mappings
#### Accessing the Page:
![Interface Mappings Page](../img/interface_mappings/interfacemappings_menu.png){ width="250" }
* From the main menu, navigate to the Plugins section
* Under Netbox Librenms Plugin, Select "Interface Mappings"
#### Creating a New Mapping:
![](../img/interface_mappings/addmapping.png){ width="50" }
* Click the green `+` or `Add` button either from the menu or on the Interface Mappings page
* Enter LibreNMS interface type. _You can copy this from plugin's device interface sync page_
* Enter Librenms interface speed as Kbps
* Select the Netbox interface type from the dropdown
* Click `Create` to save the mapping
#### Bulk Importing Mappings:
The plugin supports NetBox's standard bulk import feature for interface mappings. Click the **Import** button on the Interface Mappings page to access the import interface.
**YAML Example:**
```yaml
---
- librenms_type: ethernetCsmacd
librenms_speed: 1000000
netbox_type: 1000base-t
description: "Standard Gigabit Ethernet ports"
- librenms_type: propVirtual
librenms_speed: 1000000
netbox_type: virtual
description: "Virtual interfaces with 1G speed"
- librenms_type: softwareLoopback
librenms_speed: 8000000
netbox_type: virtual
description: "Loopback interfaces"
- librenms_type: ethernetCsmacd
librenms_speed: 10000000
netbox_type: 10gbase-t
description: "10 Gigabit Ethernet copper connections"
- librenms_type: ethernetCsmacd
librenms_speed: 100000
netbox_type: 100base-tx
description: "Fast Ethernet 100Mbps ports"
- librenms_type: ethernetCsmacd
librenms_speed: null
netbox_type: 1000base-t
description: "Default mapping for Ethernet without speed detection"
- librenms_type: ethernetCsmacd
librenms_speed: 40000000
netbox_type: 40gbase-x-qsfpp
description: "40 Gigabit QSFP+ interfaces"
- librenms_type: ethernetCsmacd
librenms_speed: 25000000
netbox_type: 25gbase-x-sfp28
description: "25 Gigabit SFP28 interfaces"
- librenms_type: propVirtual
librenms_speed: null
netbox_type: virtual
description: "Generic virtual interfaces"
- librenms_type: ieee8023adLag
librenms_speed: null
netbox_type: lag
description: "Link aggregation groups (port channels)"
- librenms_type: softwareLoopback
librenms_speed: null
netbox_type: virtual
description: "Software loopback interfaces"
```
**Notes:**
* `librenms_speed` is optional - use `null` or omit for type-only mappings
* `description` is optional - provides context for each mapping
* The combination of `librenms_type` and `librenms_speed` must be unique
* Supports CSV, JSON, and YAML formats
#### Editing Existing Mappings:
![](../img/interface_mappings/editmapping.png){ width="50" }
* On the Mappings page, Locate the desired mapping in the list
* Click the `edit` (pencil icon) button
* Modify the field mappings as needed
* Save the changes
#### Deleting Mappings:
![](../img/interface_mappings/deletemapping.png){ width="150" }
* Find the mapping you wish to remove
* Select the `Delete` button from the drop down
* Confirm the deletion when prompted
#### Applying Mappings:
* Mappings are automatically applied when interface data is synced between LibreNMS and Netbox
* If a mapping exist for an interface, it will show on the interface sync page with the icon :material-link-variant:
* If a mapping does not exist, it will show the icon :material-link-variant-off:
### Best Practices
* Check mappings are correct before performing a sync to avoid data errors
* Regularly review and update your mappings to ensure they remain accurate

View File

@@ -0,0 +1,92 @@
# Multi-Server LibreNMS Configuration
## Overview
The NetBox LibreNMS plugin now supports multiple LibreNMS servers. This allows you to:
- Configure multiple LibreNMS instances in your NetBox configuration
- Switch between different LibreNMS servers through the web interface
- Maintain backward compatibility with single-server configurations
## Configuration
### Multi-Server Configuration
Update your NetBox `configuration.py` file:
```python
PLUGINS_CONFIG = {
'netbox_librenms_plugin': {
'servers': {
'production': {
'display_name': 'Production LibreNMS',
'librenms_url': 'https://librenms-prod.example.com',
'api_token': 'your_production_token',
'cache_timeout': 300,
'verify_ssl': True,
'interface_name_field': 'ifDescr'
},
'testing': {
'display_name': 'Test LibreNMS',
'librenms_url': 'https://librenms-test.example.com',
'api_token': 'your_test_token',
'cache_timeout': 300,
'verify_ssl': False,
'interface_name_field': 'ifName'
},
'development': {
'display_name': 'Dev LibreNMS',
'librenms_url': 'https://librenms-dev.example.com',
'api_token': 'your_dev_token',
'cache_timeout': 180,
'verify_ssl': False,
'interface_name_field': 'ifDescr'
}
}
}
}
```
### Legacy Single-Server Configuration (Backward Compatible)
The original configuration format is still supported:
```python
PLUGINS_CONFIG = {
'netbox_librenms_plugin': {
'librenms_url': 'https://your-librenms-instance.com',
'api_token': 'your_librenms_api_token',
'cache_timeout': 300,
'verify_ssl': True,
'interface_name_field': 'ifDescr'
}
}
```
## Usage
1. Navigate to **LibreNMS Plugin** > **Settings** > **Server Settings**
2. Select your desired LibreNMS server from the dropdown
3. Click **Save Settings**
All subsequent LibreNMS operations will use the selected server.
## Configuration Options
Each server configuration supports the following options:
- `display_name`: Human-readable name for the server (optional)
- `librenms_url`: URL of the LibreNMS instance (required)
- `api_token`: API token for authentication (required)
- `cache_timeout`: Cache timeout in seconds (optional, default: 300)
- `verify_ssl`: Whether to verify SSL certificates (optional, default: True)
- `interface_name_field`: LibreNMS field for interface names (optional, default: 'ifDescr')
## Migration from Single to Multi-Server
1. Add the `servers` configuration block to your `configuration.py`
2. Move your existing single-server configuration into a server block (e.g., 'default' or 'production')
3. Restart NetBox
4. Select your server in the plugin settings
The plugin will automatically detect and use the new configuration format.

View File

@@ -0,0 +1,153 @@
# Permissions & Access Control
## Overview
The plugin uses a two-tier permission system that works with NetBox's built-in permissions. Both tiers must be satisfied for users to perform actions:
1. **Plugin permissions** control access to plugin pages and features
2. **NetBox object permissions** control what objects users can create or modify
This design ensures the plugin respects your existing NetBox permission structure. A user might have full plugin access but still be restricted to creating certain objects based on their NetBox permissions.
> Superusers have full access to all plugin features and NetBox objects by default. So the following applies only to regular users who can be granted specific permissions as needed.
## Two-Tier Permission Model
### How Do the Tiers Work Together?
A user needs both tiers of permissions to complete an action. For example, to view the Librenms Import page AND import a device:
1. **Tier 1: Plugin permission**: User needs View AND Change permission on **LibreNMS Settings**
- View: allows access to the plugin pages and pulling data from LibreNMS.
- Change: allows performing actions that modify Netbox or Librenms data
The Plugin also enforces Netbox object permissions so the following permission would also be required:
2. **Tier 2: Object permission**: User needs `dcim.add_device` (to create the device in NetBox)
If either permission is missing, the operation fails with an appropriate error message.
## Creating Permissions
All permissions are created using Netbox's standard Object permissions UI.
For details on how NetBox permissions work, see the [NetBox Permissions documentation](https://netboxlabs.com/docs/netbox/administration/permissions/).
### Plugin Permissions
To grant a user or group access to the plugin:
1. Go to **Admin → Permissions**
2. Click **Add**
3. For **Object types**, select "NetBox Librenms Plugin | LibreNMS Settings"
4. Under **Actions**, check the permissions to grant:
-**Can view** — for read-only access
-**Can change** — for write access (requires View as well)
5. Assign to specific **Users** or **Groups**
6. Click **Save**
### NetBox Object Permissions
NetBox object permissions are created similarly but for different object types (DCIM, IPAM, VIRTUALIZATION, etc.).
### Interface Type Mapping Permissions
The Interface Type Mapping feature uses its own object permissions in addition to the plugin permissions. To manage interface mappings, users need:
- **Plugin permission**: View permission on LibreNMS Settings (to access the page)
- **Object permissions**: `netbox_librenms_plugin.add_interfacetypemapping`, `netbox_librenms_plugin.change_interfacetypemapping`, or `netbox_librenms_plugin.delete_interfacetypemapping` as needed
These permissions are enforced automatically by NetBox's generic views.
## Example Scenarios
### Read-Only Access
- **Plugin permissions**: Librenms Setting View only (Can view LibreNMS Plugin pages)
- **NetBox permissions**: View permissions for devices, interfaces, etc.
Users can access all plugin pages, refresh data from LibreNMS, and review comparison tables, but cannot import devices or sync data.
### Full Plugin Access
- **Plugin permissions**: View + Change (Can view LibreNMS Plugin Pages and Import and sync devices data)
- **NetBox permissions**: Add/change permissions for devices, interfaces, cables, IP addresses, VLANs
Users have full access to all plugin features and can import devices, sync interfaces, and create cables.
## Further Details
### Tier 1: Plugin Permissions
Plugins permissions use the **LibreNMS Settings** model permissions:
| Permission | NetBox UI Selection | Grants |
|------------|---------------------|--------|
| `view_librenmssettings` | LibreNMS Settings → ☑ Can view | Access all plugin pages, view LibreNMS data |
| `change_librenmssettings` | LibreNMS Settings → ☑ Can change | Import devices, sync data, save settings |
Users without View permission won't see the LibreNMS menu or the LibreNMS Sync tab. Users with **View** but not **Change** can browse all plugin pages but cannot perform import or sync actions that modify Netbox data and Librenms data like Locations and Adding devices.
### Tier 2: NetBox Object Permissions
When the plugin creates or modifies NetBox objects (devices, interfaces, cables, IP addresses, VLANs), NetBox enforces its standard object permissions. The plugin checks these permissions and will block operations if the user lacks the required access.
| Plugin Action | Required Object Permissions |
|---------------|----------------------------|
| Import device | `dcim.add_device`, `dcim.add_interface` |
| Import device with VC | Above + `dcim.add_virtualchassis` |
| Import VM | `virtualization.add_virtualmachine` |
| Sync interfaces | `dcim.add_interface`, `dcim.change_interface` |
| Delete interfaces | `dcim.delete_interface` |
| Sync VM interfaces | `virtualization.add_vminterface`, `virtualization.change_vminterface` |
| Delete VM interfaces | `virtualization.delete_vminterface` |
| Sync cables | `dcim.add_cable`, `dcim.change_cable` |
| Sync IP addresses | `ipam.add_ipaddress`, `ipam.change_ipaddress` |
| Sync VLANs | `ipam.add_vlan`, `ipam.change_vlan` |
| Sync device fields | `dcim.change_device` |
| Create platform | `dcim.add_platform` |
### Why LibreNMS Settings Permissions?
NetBox's permission system is object-based—permissions are tied to specific models like Device, Interface, or Cable. However, the plugin's Import and Sync pages are feature pages that don't have their own dedicated models. They work with LibreNMS data and create or modify existing NetBox objects.
To control access to these pages, the plugin uses the **LibreNMS Settings** model permissions as a gate for all plugin features:
- **No dedicated models for pages** — The Import and Sync pages aren't objects, so we need an existing model to attach permissions to
- **No custom migrations required** — Uses Django's built-in model permissions that NetBox already understands
- **Standard NetBox workflow** — Administrators assign permissions the same way they do for any other NetBox object
- **Single permission per access level** — One "View" permission for read access, one "Change" permission for write access
While using a settings model for access control may seem unconventional, it provides a simple and maintainable way to gate plugin access without introducing custom permission infrastructure.
## Special note: Background Jobs and Superuser Access
The device import page can use background jobs to help support large device sets, and virtual chassis detection. However, NetBox restricts access to background job status APIs to superusers. There is no permission in NetBox for this. This is a core design decision, not a plugin limitation.
| User Type | Background Jobs |
|-----------|-----------------|
| Superuser | Full access to background jobs with real-time status updates |
| Non-superuser | Automatic fallback to synchronous processing |
The plugin automatically detects whether the current user is a superuser and adjusts behavior accordingly. Non-superuser users don't need to change any settings—the plugin simply processes requests synchronously instead of as background jobs. All import and filter operations work correctly regardless of superuser status.
## Troubleshooting
**User can't see the LibreNMS menu**
: The user doesn't have View permission for the plugin. Add an Object Permission for "LibreNMS Settings" with "Can view" checked.
**User sees pages but can't import or sync**
: The user has View permission but not Change permission. Edit their Object Permission to also include "Can change".
**User gets "permission denied" when importing devices**
: The user has plugin permissions but may be missing NetBox object permissions. Check that they have `dcim.add_device` and related permissions.
**Background jobs show 403 errors in console**
: In normal usage, the UI only enables background jobs for users allowed to use them and falls back to synchronous processing otherwise, so 403s from background job APIs should not appear. If you see these errors, it usually means a direct API call or custom integration is hitting background-task endpoints without superuser access; update that integration to use synchronous flows or run it with appropriate permissions.

View File

@@ -0,0 +1,88 @@
# Suggested Workflow
This guide provides a recommended workflow for using the plugin after installation. Following this order helps ensure smooth operation and avoids common issues.
## 1. Configure Plugin Settings
Navigate to **Plugins → LibreNMS Plugin → Settings** and configure:
- **LibreNMS Server**: Select which server to use (if multi-server setup)
- **Device Naming**: Set your preferred defaults for "Use sysName" and "Strip Domain" - see [Import Settings](../librenms_import/import_settings.md)
- **Virtual Chassis Naming**: Configure the member naming pattern if you plan to import stackable devices
**Why first**: These defaults apply to all imports and save time by reducing per-import configuration.
## 2. Verify Custom Field
As of version 0.4.4, the plugin **automatically creates** the `librenms_id` custom field when migrations are run. No manual setup is required. See the [Custom Field Setup](custom_field.md) guide for details on how the field works and optional manual configuration.
**Why early**: This field enables the most reliable device matching and is required for interface, cable, and IP address synchronization features. It is created automatically during `manage.py migrate`, so just verify it exists before importing.
## 3. Prepare NetBox Data
Ensure NetBox has the basic objects needed for device imports:
- **Sites**: Create Sites that match your LibreNMS locations (exact name matching works best)
- **Device Types**: Add Device Types for your common hardware models
- **Device Roles**: Create appropriate roles (Switch, Router, Firewall, etc.)
- **Platforms**: Add Platforms matching your LibreNMS OS names (optional but helpful)
**Why before importing**: The plugin auto-matches these objects during import. Pre-creating them reduces manual configuration during the import process.
## 4. Configure Interface Mappings
If you have specific interface type mapping requirements, configure them via **Plugins → LibreNMS Plugin → Interface Type Mappings** - see [Interface Mappings](interface_mappings.md).
**Why**: Ensure specific NetBox interface types are used for your LibreNMS interface data.
## 5. Import Devices
Use the [Device Import](../librenms_import/overview.md) feature to bring devices into NetBox:
1. Navigate to **Plugins → LibreNMS Plugin → Import → LibreNMS Import**
2. Apply filters to find devices (start with Location or Type)
3. Review validation status and configure missing fields
4. Import devices individually or in bulk
**Tips**:
- Start with a small set (single location or device type) to verify your setup
- Enable Virtual Chassis detection only when importing stackable switches
## 6. Sync VLAN
- Create VLAN objects in NetBox from LibreNMS device VLAN data
- Per-VLAN group assignment with scope-aware auto-selection
## 7. Sync Interfaces
After devices are imported, sync their interfaces:
1. Navigate to a device in NetBox
2. Use the LibreNMS sync button to pull interface data
3. Review and adjust [Interface Mappings](interface_mappings.md) if needed
**Why after import**: Interfaces require the device to exist in NetBox first. The `librenms_id` field set during import enables accurate synchronization.
## 8. Sync Cables and IP Addresses
Complete your device data by syncing:
- **Cables**: Pull link data from LibreNMS to create cable connections
- **IP Addresses**: Import IP assignments to populate NetBox's IPAM
**Why last**: Both features require that interfaces already exist in NetBox and ideally with the `librenms_id` field set. The `librenms_id` field on interfaces ensures accurate matching.
## 9. Sync Locations (Optional)
If you want to synchronize location latitude/longitude data between NetBox Sites and LibreNMS locations, use the location sync feature.
**Why optional**: Only needed if you maintain geographic coordinates and want bidirectional sync.
## Next Steps
After completing the initial workflow:
- Regular imports: Use the same import process for new devices as they're added to LibreNMS
- Interface updates: Re-sync interfaces periodically to capture configuration changes
- Virtual Chassis: See [Virtual Chassis](virtual_chassis.md) for managing multi-member devices
- Background Jobs: Understand [Background Jobs & Caching](../librenms_import/background_jobs.md) for performance optimization

View File

@@ -0,0 +1,31 @@
# Virtual Chassis Support
## Overview
The plugin automatically detects Virtual Chassis configurations and displays all VC interfaces on the LibreNMS Sync page of the designated sync device.
**LibreNMS Sync Device Selection Priority:**
1. Member with `librenms_id` custom field (highest priority)
2. Master device with primary IP
3. Any member with primary IP
4. Member with lowest VC position
> **Note:** LibreNMS treats a Virtual Chassis as a single logical device. Only one member (the sync device) should have the `librenms_id` custom field set.
## How It Works
### Member Selection
When viewing a device that is part of a virtual chassis, the plugin will:
1. Detects if the device is part of a virtual chassis and displays 'Virtual Chassis Member' column.
2. Automatically select the VC member by matching the device VC position to the first number in the interface name.
3. Allows selection of specific members if the auto select is not correct.
> Selecting a new member will trigger a new interface details comparison against the newly selected NetBox VC member.
Interfaces data is then synced to the selected VC member in Netbox.
#### Virtual Chassis Member Select
![Virtual Chassis Member Selection](../img/Netbox-librenms-plugin-virtualchassis.gif)