Files
2026-09-30 13:36:35 +02:00

284 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NetBox Rack Concept
Rack blueprints for NetBox. A "rack concept" is a fully planned rack including
its equipment — but **not** a real rack and **no** real devices. Concepts
therefore appear neither in the rack list nor in the device list, do not skew
utilisation reports and do not consume serial numbers or IP addresses.
Once the plan is final, a concept is turned into real NetBox objects with one
click — once or twenty times.
| | |
|---|---|
| **Plugin name** | `netbox_rack_concept` |
| **Package** | `netbox-rack-concept` |
| **NetBox** | `4.6.0` – `4.7.x` |
| **Python** | `>=3.12` |
| **Repository** | <https://git.mrblake.cc/MrBlake/NetBox-Concept> |
## Features
| Workflow | Where |
|---|---|
| Real rack → concept | **Copy to concept** button on the rack detail page. Width, height and starting unit of the concept rack are freely selectable; devices that no longer fit are skipped and reported as warnings |
| Concept → concept (variant) | **Clone concept** button on the concept detail page |
| 2 concepts → 1 larger concept | **Merge** in the menu or **Merge with another** on the concept detail page — e.g. stacks two half-height racks into a full one; the top concept is shifted up by the height of the bottom one, both sources stay unchanged |
| 2 real racks → 1 new concept | **Merge into concept** above the real rack list. Select two racks via checkbox and click the button — you land on the same merge form, pre-filled with the two real racks as sources |
| Concept → real racks (n times) | **Deploy to NetBox** button, with naming scheme `DC1-R{n:02d}` |
| Create a concept manually | Menu **Rack Concepts → Rack Concepts → +** |
In addition:
- **Drag & drop elevation** – move devices with the mouse, including from the front to the rear view (and vice versa). Everything is validated server-side; an invalid move is rejected and changes nothing.
- **Devices with image and label** – device type front/rear images are shown in the elevation with the device name as white, black-outlined text. On the rear, a **full-depth** device only shows its own rear image; a **non-full-depth** device without a rear image (e.g. a power strip) shows its front image. A dropdown switches between "Images and labels", "Images only" and "Labels only" — just like real racks in NetBox, remembered in the browser.
- **Partial widths** (1/1, 1/2, 1/3, 1/4 plus horizontal slot position), matching the partial-width feature of `netbox_utilities`.
- **Tenant and tenant group** on the concept and on every planned device.
- **Placeholders without device type** – reserved space with only a height.
- **Click on an empty U** opens "Add planned device", pre-filled with position and face — just like a real rack elevation.
- **Cabling of concept devices, 1:1 like real devices** – the device detail page has the same tabs as a real `dcim.Device` (interfaces, front/rear ports, console ports, console server ports, power ports, power outlets; tabs only shown when populated). **Sync components** copies them 1:1 from the device type's component templates, including front ↔ rear mapping of patch panels. **Connect** on every uncabled component creates a concept cable. An **Add Components** dropdown creates new components per type — needed for placeholders without a device type.
- **Export** – **Export** button above the elevation: front or rear as standalone **SVG**, as **PNG** (single or both sides), and the whole concept as a **draw.io** diagram (`.drawio`). PNG is drawn directly on a `<canvas>` in the browser; device type images are fetched individually, so a failing image only affects that one image. No server-side image library is needed.
- Full REST API, filters, CSV import/export, bulk edit, changelog, journal, tags, custom fields and global search — like any core object.
## Compatibility
- NetBox `4.6.0` – `4.7.x`
- Python `>=3.12`
- Optional: [Netbox-Utilities](https://git.mrblake.cc/MrBlake/Netbox-Utilities) for partial widths
- Optional: `netbox-reorder-rack` — **v1.1.5 requires NetBox 4.7**; on NetBox 4.6 pin `netbox-reorder-rack<1.1.5`
## 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-Concept.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-Concept.git@main" /opt/netbox/local_requirements.txt \
|| echo "git+https://git.mrblake.cc/MrBlake/NetBox-Concept.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`.
### 3. Enable the plugin
In `/opt/netbox/netbox/netbox/configuration.py`:
```python
PLUGINS = [
"netbox_rack_concept",
# optional, in any order:
"netbox_utilities",
"netbox_reorder_rack",
]
```
If other plugins are already configured, add `netbox_rack_concept` to the
existing list instead of replacing it. See [Configuration](#configuration) for
optional settings.
### 4. Apply migrations, collect static files, restart
```bash
cd /opt/netbox/netbox
/opt/netbox/venv/bin/python manage.py migrate netbox_rack_concept
/opt/netbox/venv/bin/python manage.py collectstatic --no-input
sudo systemctl restart netbox netbox-rq
```
> If `migrate` cannot apply the bundled migration because base fields differ in
> your NetBox installation: delete `netbox_rack_concept/migrations/0001_initial.py`
> and run `manage.py makemigrations netbox_rack_concept`. The migration was
> written by hand against NetBox 4.6.8.
## Update
```bash
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall --no-deps \
"git+https://git.mrblake.cc/MrBlake/NetBox-Concept.git@main"
cd /opt/netbox/netbox
/opt/netbox/venv/bin/python manage.py migrate netbox_rack_concept
/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
```
## Uninstall
1. Remove `"netbox_rack_concept"` from `PLUGINS` and `PLUGINS_CONFIG`.
2. Remove the line from `/opt/netbox/local_requirements.txt`.
3. Uninstall the package and restart NetBox:
```bash
/opt/netbox/venv/bin/pip uninstall netbox-rack-concept
sudo systemctl restart netbox netbox-rq
```
## Configuration
All values are optional; the defaults are shown.
```python
PLUGINS_CONFIG = {
"netbox_rack_concept": {
# Defaults when creating a new concept
"default_u_height": 42,
"default_width": 19,
# Show the "Copy to concept" button on the rack page
"enable_rack_tab": True,
# Status of objects created on deployment
"deployed_rack_status": "planned",
"deployed_device_status": "planned",
# Link to the partial widths of netbox_utilities.
# Leave "model" empty if netbox_utilities stores the fields on dcim.Device directly.
"partial_width": {
"enabled": True,
"model": "netbox_utilities.RackDevicePosition",
"device_field": "device",
"fraction_field": "width_fraction",
"position_field": "horizontal_position",
},
},
}
```
## Usage
### Cabling
Concept devices can be cabled, but **not** via NetBox's real `dcim.Cable`,
which can only connect real `dcim` components. Instead the plugin ships its own
lightweight model pair:
- **ConceptComponent** — an interface, front/rear port, power port/outlet or
console port on a planned device. **Sync components** creates them 1:1 from
the device type's component templates (name, label, type, positions) —
repeatable, without duplicates or data loss on already cabled components.
Placeholders without a device type get components via **Add component**.
- **ConceptCable** — connects two `ConceptComponent`s. Both ends must belong to
devices in the same rack concept; a component can only be in one cable at a time.
**Patch panels work exactly like real devices**, because the plugin reads the
same front ↔ rear mapping NetBox maintains on the device type
(`PortTemplateMapping`). It does not depend on the role name "Patchpanel" but on
whether the device type defines front/rear ports with a mapping.
**When copying a real rack into a concept** (and when merging two real racks),
components of all copied devices are synced automatically, and every real cable
whose **both** ends lie within the copied rack(s) is recreated as a
`ConceptCable` — including status, type, colour and label. Cables leaving the
rack and multi-trunk cables (e.g. MPO) cannot be taken over and are reported as
warnings with a count. Cloning or merging concepts leaves cabling unchanged.
### Interaction with other plugins
**netbox-reorder-rack** works on `dcim.Device` querysets. A concept has none by
definition, so this plugin ships its own drag & drop elevation
(`static/netbox_rack_concept/elevation.js`). Once deployed, the result is a
normal rack and reorder-rack applies as usual.
**netbox_utilities** provides partial widths for real devices. On deployment,
this plugin writes `width_fraction` and `horizontal_position` there; when
copying a real rack it reads them. The field mapping is configurable in
`PLUGINS_CONFIG`. If `netbox_utilities` is not installed or the mapping does not
match, partial widths are simply not written and a warning is logged.
### What is not deployed
A concept describes space, not operational data. Intentionally **not** created:
cables, interfaces beyond the device type templates, IP addresses, serial
numbers, asset tags. Planned devices without a role, device type or position are
skipped — the confirmation page lists them before deployment.
### REST API
Base path: `/api/plugins/rack-concepts/`
| Method | Endpoint | Purpose |
|---|---|---|
| `GET/POST` | `concepts/` | List and create concepts |
| `GET/PATCH/DELETE` | `concepts/{id}/` | Single concept |
| `POST` | `concepts/copy-from-rack/` | Copy a real rack into a concept (with `override_width`/`override_u_height`/`override_starting_unit`) |
| `POST` | `concepts/{id}/clone/` | Duplicate a concept |
| `POST` | `concepts/merge/` | Stack two concepts into a larger one (`concept_bottom`, `concept_top`) |
| `POST` | `concepts/{id}/deploy/` | Deploy a concept (`dry_run` supported) |
| `GET` | `concepts/{id}/elevation/` | Computed elevation as JSON |
| `GET/POST` | `devices/` | Planned devices |
| `GET/POST` | `components/` | Components of planned devices |
| `GET/POST` | `cables/` | Concept cables |
Example — ten racks from one concept, as a dry run first:
```bash
curl -s -X POST https://netbox.example/api/plugins/rack-concepts/concepts/3/deploy/ \
-H "Authorization: Token $NETBOX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name_pattern": "DC1-R{n:02d}",
"count": 10,
"start_index": 1,
"site": 4,
"location": 12,
"create_devices": true,
"device_name_pattern": "{rack}-{name}",
"dry_run": true
}'
```
Response:
```json
{
"dry_run": true,
"racks": ["DC1-R01", "…", "DC1-R10"],
"devices_per_rack": 7,
"total_devices": 70,
"warnings": ["Blanking panel 3 has no role. NetBox requires one, so it will not be created."]
}
```
Set `dry_run` to `false` to actually create the objects. Deployment runs in
**one** transaction: if a rack or device fails, nothing is created.
### Permissions
Standard NetBox object permissions apply:
`netbox_rack_concept.view_rackconcept`, `add_`, `change_`, `delete_` — and
analogously for `conceptdevice`. Deployment additionally checks `dcim.add_rack`.
### Language
The plugin is available in English (source) and German. Switch the display
language as usual in the user profile (**Preferences → Language**). Translations
live in `netbox_rack_concept/locale/de/LC_MESSAGES/`.
## License
MIT