442 lines
18 KiB
Markdown
442 lines
18 KiB
Markdown
# NetBox Utilities
|
||
|
||
A collection of quality-of-life improvements for NetBox: personalised navigation,
|
||
a global tenant filter, mandatory tenancy, partial-width rack devices, bulk
|
||
uploads and more.
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Plugin name** | `netbox_utilities` |
|
||
| **Package** | `netbox-utilities` |
|
||
| **NetBox** | `4.6.5` – `4.7.x` |
|
||
| **Python** | `>=3.12` |
|
||
| **Repository** | <https://git.mrblake.cc/MrBlake/Netbox-Utilities> |
|
||
|
||
## Features
|
||
|
||
- Every user can reorder or hide the menus of the left navigation.
|
||
- A header dropdown sets a session-wide filter for a tenant or tenant group.
|
||
- Optional mandatory tenant assignment for all tenant-aware objects.
|
||
- Automatic pre-fill of tenant and tenant group from the object or filter context.
|
||
- Automatic 1:1 mapping of front and rear ports on devices with the role `Patchpanel`.
|
||
- Devices with an optional partial width can share the same rack unit.
|
||
- The rack view of the optional [MrBlake NetBox Topology Views](https://git.mrblake.cc/MrBlake/mrb-netbox-topology-views) plugin renders partial-width devices correctly.
|
||
- Upload multiple images at once in an object's **Images** tab.
|
||
- Install multiple modules of the same type into free module bays in one step.
|
||
- Optional bulk save for devices moved in NetBox Reorder Rack.
|
||
- Rack widths are preserved by the optional [NetBox-Export](https://git.mrblake.cc/MrBlake/NetBox-Export) export/import.
|
||
- Cables and wireless links can be assigned to one or more VLANs.
|
||
- The B-side device selection of a cable can be pre-filtered by tenant group, tenant and site.
|
||
- A **Prefix** column (first word of the site name) for device and rack lists, including sorting and filtering.
|
||
|
||
Navigation settings are stored per user. The active tenant or tenant-group
|
||
selection is stored in the browser session.
|
||
|
||
## Compatibility
|
||
|
||
- NetBox `4.6.5` – `4.7.x`
|
||
- Python `>=3.12`
|
||
- Optional: NetBox Reorder Rack `1.1.4`
|
||
- Optional: NetBox-Export `0.3.11` or newer
|
||
- Optional: MrBlake NetBox Topology Views with rack view
|
||
|
||
Other NetBox versions are rejected on purpose, because the navigation
|
||
customisation depends on the HTML structure of the NetBox core menu.
|
||
|
||
## Installation
|
||
|
||
All paths assume a standard installation under `/opt/netbox`.
|
||
|
||
### 1. Install the package
|
||
|
||
```bash
|
||
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
|
||
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@main"
|
||
```
|
||
|
||
For reproducible production installs, replace `main` with a release tag or a
|
||
full commit ID.
|
||
|
||
### 2. Add the plugin to `local_requirements.txt`
|
||
|
||
This makes `upgrade.sh` reinstall the plugin automatically on every NetBox upgrade:
|
||
|
||
```bash
|
||
grep -qxF "git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@main" /opt/netbox/local_requirements.txt \
|
||
|| echo "git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@main" | sudo tee -a /opt/netbox/local_requirements.txt
|
||
```
|
||
|
||
If the repository is private, the NetBox server needs a read-only deploy token
|
||
or an SSH key. Do not store credentials in `local_requirements.txt`. With SSH the
|
||
entry looks like this:
|
||
|
||
```text
|
||
git+ssh://git@git.mrblake.cc/MrBlake/Netbox-Utilities.git@main
|
||
```
|
||
|
||
### 3. Enable the plugin
|
||
|
||
In `/opt/netbox/netbox/netbox/configuration.py`:
|
||
|
||
```python
|
||
PLUGINS = [
|
||
"netbox_utilities",
|
||
]
|
||
|
||
PLUGINS_CONFIG = {
|
||
"netbox_utilities": {
|
||
"navigation_customization_enabled": True,
|
||
"connection_vlans_enabled": True,
|
||
"connection_tenant_filter_enabled": True,
|
||
"reorder_rack_bulk_save_enabled": True,
|
||
"topology_views_rack_width_enabled": True,
|
||
"tenant_filter_enabled": True,
|
||
"tenant_required": True,
|
||
"site_prefix_column_enabled": True,
|
||
},
|
||
}
|
||
```
|
||
|
||
If other plugins are already configured, add `netbox_utilities` to the existing
|
||
list and dictionary instead of replacing them.
|
||
|
||
### 4. Apply migrations, collect static files, restart
|
||
|
||
```bash
|
||
cd /opt/netbox/netbox
|
||
/opt/netbox/venv/bin/python manage.py migrate netbox_utilities
|
||
/opt/netbox/venv/bin/python manage.py collectstatic --no-input
|
||
sudo systemctl restart netbox netbox-rq
|
||
```
|
||
|
||
After changes to JavaScript or CSS a hard reload in the browser (`Ctrl+F5`) may
|
||
be necessary.
|
||
|
||
### Verify the installation
|
||
|
||
```bash
|
||
/opt/netbox/venv/bin/python -c \
|
||
"import netbox_utilities; print(netbox_utilities.__version__, netbox_utilities.__file__)"
|
||
|
||
test -f /opt/netbox/netbox/static/netbox_utilities/reorder-rack-width.js
|
||
test -f /opt/netbox/netbox/static/netbox_utilities/topology-rack-width.js
|
||
|
||
cd /opt/netbox/netbox
|
||
/opt/netbox/venv/bin/python manage.py shell -c \
|
||
"from django.urls import reverse; print(reverse('dcim:rack_reorder', kwargs={'pk': 1})); print(reverse('plugins:netbox_topology_views:rack_elevation'))"
|
||
```
|
||
|
||
The last two routes only resolve when Reorder Rack and Topology Views are installed.
|
||
|
||
## Update
|
||
|
||
```bash
|
||
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
|
||
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@main"
|
||
|
||
cd /opt/netbox/netbox
|
||
/opt/netbox/venv/bin/python manage.py migrate netbox_utilities
|
||
/opt/netbox/venv/bin/python manage.py collectstatic --no-input
|
||
sudo systemctl restart netbox netbox-rq
|
||
```
|
||
|
||
`--force-reinstall` makes pip pick up branch changes even if the package
|
||
version has not been bumped.
|
||
|
||
When NetBox itself is upgraded, `upgrade.sh` reinstalls the plugin from
|
||
`local_requirements.txt` and runs migrations and `collectstatic`:
|
||
|
||
```bash
|
||
sudo /opt/netbox/upgrade.sh
|
||
sudo systemctl restart netbox netbox-rq
|
||
```
|
||
|
||
If you pinned a release tag in `local_requirements.txt`, change the tag there
|
||
before running the upgrade. Test updates in a staging instance and back up the
|
||
NetBox database first.
|
||
|
||
### Migrating from NetBox Site Prefix
|
||
|
||
The Prefix column is now part of NetBox Utilities. Remove the separate
|
||
`netbox_site_prefix` plugin, otherwise the column is registered twice:
|
||
|
||
1. Remove `"netbox_site_prefix"` from `PLUGINS` in `configuration.py`.
|
||
2. Remove `git+https://git.mrblake.cc/MrBlake/Netbox-Prefixes.git` from
|
||
`/opt/netbox/local_requirements.txt`.
|
||
3. Run `/opt/netbox/venv/bin/pip uninstall netbox-site-prefix` and restart NetBox.
|
||
|
||
The column name `site_prefix` is unchanged, so saved user table configurations keep working.
|
||
|
||
## Uninstall
|
||
|
||
1. Resolve all shared rack units first (see [Multiple devices in one rack unit](#multiple-devices-in-one-rack-unit)).
|
||
2. Remove `"netbox_utilities"` from `PLUGINS` and `PLUGINS_CONFIG`.
|
||
3. Remove the line from `/opt/netbox/local_requirements.txt`.
|
||
4. Uninstall the package and restart NetBox:
|
||
|
||
```bash
|
||
/opt/netbox/venv/bin/pip uninstall netbox-utilities
|
||
sudo systemctl restart netbox netbox-rq
|
||
```
|
||
|
||
## Configuration
|
||
|
||
| Key | Default | Description |
|
||
|---|---|---|
|
||
| `navigation_customization_enabled` | `True` | Per-user navigation ordering, hiding, resizing and icon mode |
|
||
| `connection_vlans_enabled` | `True` | VLAN assignment on cables and wireless links |
|
||
| `connection_tenant_filter_enabled` | `True` | Tenant group / tenant / site pre-filter on the cable B-side |
|
||
| `reorder_rack_bulk_save_enabled` | `True` | Bulk save integration for NetBox Reorder Rack `1.1.4` |
|
||
| `topology_views_rack_width_enabled` | `True` | Partial-width rendering in Topology Views' rack view |
|
||
| `tenant_filter_enabled` | `True` | Global tenant / tenant-group filter (overrides the UI setting) |
|
||
| `tenant_required` | `True` | Mandatory tenant assignment (overrides the UI setting) |
|
||
| `site_prefix_column_enabled` | `True` | Prefix column in device and rack lists |
|
||
|
||
## Usage
|
||
|
||
### Prefix column in device and rack lists
|
||
|
||
Device and rack lists get a **Prefix** column as the first data column. The
|
||
value is the first word of the site name, e.g. `Berlin` for `Berlin Campus West`
|
||
or `DC01` for `DC01 Frankfurt`. Without a site the cell stays empty.
|
||
|
||
Clicking the column header sorts ascending/descending by site name. If a user
|
||
has saved a custom column selection, add **Prefix** under **Configure Table**
|
||
or reset the table configuration.
|
||
|
||
Both lists offer a **Prefix** filter in the **Site** section. The comparison is
|
||
case-insensitive and only matches the first word: `DC01` matches
|
||
`DC01 Frankfurt` but not `DC011 Hamburg`. Separate multiple prefixes with commas
|
||
(`Berlin, DC01`). The filter also works via URL and REST API, e.g.
|
||
`/dcim/devices/?site_prefix=DC01` or
|
||
`/api/dcim/racks/?site_prefix=Berlin&site_prefix=DC01`.
|
||
|
||
### Pre-filter for the B-side of a cable
|
||
|
||
When creating or editing a cable, the **B-side** section shows optional
|
||
**Tenant group**, **Tenant** and **Site** fields above the device selection.
|
||
They filter the B-side dropdowns live (devices, power panels — site only — and
|
||
circuits).
|
||
|
||
The fields are pre-filled with the tenant and site of the selected A-side if
|
||
they are unambiguous, otherwise with the tenant or tenant group of the global
|
||
header filter.
|
||
|
||
This is only a **pre-filter**: the values are not stored on the cable. To cable
|
||
across tenants or sites, simply clear the field. The tenant filter uses the
|
||
device's own `tenant` field; devices whose tenant is only implied by their site
|
||
do not appear — use the site filter in that case.
|
||
|
||
### VLANs on connections
|
||
|
||
The create/edit form of cables and wireless links has an optional
|
||
**Connection VLANs** field. One or more existing VLANs can be selected; the
|
||
assignment is also shown on the connection's detail page.
|
||
|
||
It documents which VLANs are carried over the connection. It intentionally does
|
||
**not** change the **Untagged VLAN** / **Tagged VLANs** of the connected
|
||
interfaces, since both ends can use different interface modes.
|
||
|
||
- Applies to physical cables (including paths through patch panels) and `WirelessLink`s.
|
||
- In the cable form the field sits in the **B-side** section, below the B-side termination.
|
||
- An optional **VLAN group** field acts as a dynamic filter for the VLAN selection; it is not stored.
|
||
- Empty selections create no record; deleting a connection removes its VLAN assignment.
|
||
- With NetBox-Export installed, the assignments are exported and imported together with connections and VLANs.
|
||
|
||
### Multiple devices in one rack unit
|
||
|
||
The regular device create/edit form gets two optional fields right after **Position**:
|
||
|
||
- **Rack width**: full, half, third or quarter width;
|
||
- **Width position**: position 1 to 4, counted from the left.
|
||
|
||
Example: for a router and a second device in the same U, choose **1/2 rack width**
|
||
for both, give the router **Position 1 (left)** and the other device
|
||
**Position 2**. Rack, U and face may then be identical. Collision checks take
|
||
height and width into account; multi-U devices are supported. The width
|
||
position updates immediately when the rack width changes.
|
||
|
||
Without a width, a device occupies the full rack width as before. If two to
|
||
four devices already share a U and face without plugin placements, the display
|
||
splits the space evenly between them. This does not change database values.
|
||
|
||
NetBox enforces a unique constraint on rack, U and face. Plugin migration
|
||
`0007` removes only this core constraint so that multiple devices can share a U;
|
||
the plugin performs the width-aware check on save instead. **Before removing the
|
||
plugin, shared rack units must be resolved** — the constraint is not restored
|
||
automatically on uninstall.
|
||
|
||
The extra fields are maintained in the web form. REST or standard CSV
|
||
operations without these fields treat new devices as full width; the portable
|
||
ZIP export of NetBox-Export does transfer them.
|
||
|
||
### Rack widths in NetBox-Export
|
||
|
||
With [NetBox-Export](https://git.mrblake.cc/MrBlake/NetBox-Export) installed,
|
||
NetBox Utilities extends its ZIP export and import automatically. Rack width and
|
||
width position are stored for every device. The import conflict check considers
|
||
both height and horizontal rack space, so two half-width devices can be imported
|
||
into the same U. Full width is stored explicitly, so a device reset to full
|
||
width in a newer export loses its stale partial-width placement. Older archives
|
||
without these metadata remain importable.
|
||
|
||
### Partial widths in MrBlake NetBox Topology Views
|
||
|
||
If [MrBlake NetBox Topology Views](https://git.mrblake.cc/MrBlake/mrb-netbox-topology-views)
|
||
with its **rack view** is installed, NetBox Utilities detects it automatically.
|
||
Partial-width devices are rendered side by side, including the **SVG**, **PNG**
|
||
and **draw.io** exports. The cable topology is unchanged.
|
||
|
||
Both plugins must be enabled (order does not matter):
|
||
|
||
```python
|
||
PLUGINS = [
|
||
"netbox_topology_views",
|
||
"netbox_utilities",
|
||
]
|
||
```
|
||
|
||
The integration does not modify Topology Views' files and creates no database
|
||
records. Disable it with `topology_views_rack_width_enabled = False`.
|
||
|
||
### Automatic front/rear port mapping for patch panels
|
||
|
||
Devices whose role is named `Patchpanel` (case-insensitive) are treated as patch
|
||
panels. The plugin maps ports with the same number on port position 1:
|
||
`Front 1` ↔ `Rear 1`, `Front 2` ↔ `Rear 2`, and so on. Short forms such as
|
||
`F01` and `R1` and additional labels such as `LC` are recognised. If the
|
||
counterpart is missing, the port stays unmapped; following numbers do not shift.
|
||
|
||
The mapping is only created when a patch panel is first created, a new module
|
||
is installed, or a new front or rear port is created. Editing existing objects
|
||
does not trigger it, and there is no automatic run over existing data on
|
||
install or update.
|
||
|
||
### Moving multiple devices with NetBox Reorder Rack
|
||
|
||
With `netbox-reorder-rack` `1.1.4` installed and enabled, NetBox Utilities
|
||
extends its save action: several devices can be moved or swapped in the
|
||
drag-and-drop view and saved together via **Save**. Partial-width devices are
|
||
shown side by side on a 12-column grid and snap to valid positions; height,
|
||
face and width position are saved in one transaction.
|
||
|
||
```bash
|
||
/opt/netbox/venv/bin/pip install "netbox-reorder-rack==1.1.4"
|
||
echo "netbox-reorder-rack==1.1.4" | sudo tee -a /opt/netbox/local_requirements.txt
|
||
```
|
||
|
||
```python
|
||
PLUGINS = [
|
||
"netbox_reorder_rack",
|
||
"netbox_utilities",
|
||
]
|
||
```
|
||
|
||
Reorder Rack's files are not modified; its UI and API are extended at startup.
|
||
On save, all affected devices and the rack are locked and validated with the
|
||
normal NetBox model validation. If any placement, validation or permission
|
||
error occurs, the whole rack stays unchanged. Every moved device still gets a
|
||
normal changelog entry. Versions other than `1.1.4` are left untouched and only
|
||
produce a log message.
|
||
|
||
### Uploading multiple images
|
||
|
||
In the **Images** tab of supported objects, the single upload is replaced by
|
||
**Upload multiple images**. Up to 50 images can be selected at once, with
|
||
previews before saving. Each file is validated by NetBox; if one is invalid,
|
||
none are saved. An optional shared description can be applied; the original
|
||
file name is kept as the display name. Requires permission to add image
|
||
attachments and to view the target object.
|
||
|
||
### Installing multiple modules
|
||
|
||
Under **Plugins > NetBox Utilities > Install multiple modules** (or via the
|
||
button on device pages with free module bays), choose a device, a module type
|
||
and several free module bays — or enter a **Quantity (1–x)** to use the first
|
||
free bays in natural order. All modules get the same type, status and
|
||
description; component replication from the module type templates is optional.
|
||
The operation is atomic: if a bay is taken meanwhile or a naming conflict
|
||
occurs, nothing is saved. Requires the permission to add modules; object
|
||
permissions still apply.
|
||
|
||
<<<<<<< HEAD
|
||
NetBox begrenzt Pillow global auf 25 Megapixel und lehnt Bilder ab 50
|
||
Megapixeln ab. Damit aktuelle 50-MP-Smartphone-Fotos (z. B. Google Pixel,
|
||
8160×6144) hochgeladen werden können, hebt der Mehrfach-Upload dieses Limit
|
||
während der Verarbeitung auf 100 Megapixel an. Wird ein Bild abgelehnt, zeigt
|
||
das Formular zusätzlich die genaue Fehlermeldung von Pillow an.
|
||
|
||
### Module mehrfach einbauen
|
||
=======
|
||
### Personalised navigation
|
||
>>>>>>> a85e4d6375a673a333d601fa8867e00a96423fec
|
||
|
||
Under **Plugins > NetBox Utilities > Customize navigation** users see every menu
|
||
they have access to. Arrow buttons change the order; a toggle hides a menu.
|
||
|
||
The desktop sidebar can be resized between 216 and 408 px by dragging its right
|
||
edge. A small handle collapses it into an **icon mode** where menus open as a
|
||
flyout (closed on selection, outside click or Escape). **Reset** restores order,
|
||
visibility and the default width of 288 px.
|
||
|
||
### Global tenant and tenant-group filter
|
||
|
||
The building icon in the header opens the selection of tenants and tenant
|
||
groups the user may see. A tenant group includes tenants of its child groups.
|
||
**All tenants** removes the filter.
|
||
|
||
The filter:
|
||
|
||
- enforces `tenant_id` or `tenant_group_id` in supported NetBox lists;
|
||
- restricts the tenant list itself;
|
||
- restricts NetBox global search results;
|
||
- applies to HTMX table updates and exports from filtered lists;
|
||
- does **not** change REST or GraphQL requests.
|
||
|
||
Superusers can disable it at runtime under **Plugins > NetBox Utilities > Settings**;
|
||
`tenant_filter_enabled = False` disables it permanently and takes precedence.
|
||
|
||
### Mandatory tenant assignment
|
||
|
||
Enabled by default under **Plugins > NetBox Utilities > Settings**. For all
|
||
object types with a `tenant` field, the field becomes required — in forms, CSV
|
||
imports, the REST API and `Model.save()` calls from scripts. Existing objects
|
||
without a tenant remain until they are next saved. Global reference models
|
||
without a `tenant` field are not affected.
|
||
|
||
When a form opens, missing values are pre-filled carefully: first from a
|
||
recognisable parent object (rack, site, device, cluster, …), otherwise from the
|
||
global tenant filter. Existing values are never overwritten. For cables, both
|
||
cable ends are evaluated; the tenant is only set if it is unambiguous. If an
|
||
automatically set tenant is saved unchanged, the browser asks for an explicit
|
||
confirmation.
|
||
|
||
`tenant_required = False` disables the feature permanently and takes precedence
|
||
over the UI setting.
|
||
|
||
## Important semantics
|
||
|
||
The tenant filter is a **view filter, not access control**. Direct object URLs
|
||
are not blocked; NetBox object permissions remain the security boundary. The
|
||
mandatory tenant assignment, however, is server-side data validation.
|
||
|
||
Only models with a tenant relation are filtered. Global reference data such as
|
||
manufacturers, roles or platforms stays visible.
|
||
|
||
The sidebar personalisation uses NetBox's official global
|
||
`PluginTemplateExtension` and reorders the already rendered core menus in the
|
||
browser. It changes neither core templates nor NetBox files.
|
||
|
||
## Development and tests
|
||
|
||
In a NetBox development environment:
|
||
|
||
```bash
|
||
pip install -e /path/to/Netbox-Utilities
|
||
python netbox/manage.py test netbox_utilities
|
||
```
|
||
|
||
## License
|
||
|
||
See [LICENSE](LICENSE).
|