The rack's link picker read `/nodes`, so it only ever offered devices
someone had already approved onto a logical canvas — two rows on a homelab
holding 74 inventory entries. A device on no canvas is still the record of
a real box, and is exactly what a rack is built out of.
`DevicePickerModal` replaces `NodePickerModal` and lists the Device
Inventory itself. Picking an entry calls the new `relinkDevice`, which
repoints the mount's `deviceId`, adopts that entry's node, status and —
unless the user renamed the plate — its label. One entry, one mount: a row
another plate stands for is not offered, and the store refuses it anyway.
The placeholder a rack-created plate left behind is dropped through the new
`DELETE /api/v1/scan/pending/{id}`, which refuses a device a rack still
mounts (409): foreign keys are off at runtime, so the mount would be left
naming a row that no longer exists.
`LinkedDevicePanel` becomes "Linked device" and now prints what discovery
found even when nothing on a canvas answers for the device; only the
canvas-side rows go missing, under a "Not on a logical canvas." note.
Also renames `pending_devices` to `device_inventory` (and
`pending_device_links` to `device_inventory_links`), with the Python and
TypeScript names that followed it. "Pending devices" was the scanner's word
for a queue of finds awaiting approval; the rows outlive approval, are
edited by hand and are what a rack mounts. Routes, payload keys and MCP
tool names are a published contract and are unchanged — `/scan/pending/*`
and the `pending_devices` key in `/stats` stay as they are.
The rename migration runs before `create_all`, or an empty new table would
be created beside the populated old one and every scanned device would read
as gone; it repairs that state too, for anyone whose app already started
mid-upgrade. Foreign keys are switched on for the rename so SQLite rewrites
the `REFERENCES` clause in `rack_devices`.
ha-relevant: maybe
11 KiB
Rack Canvas
A rack canvas is the physical counterpart to the network diagram: real racks, the gear mounted in them, and the patch cables between their ports. It is a canvas kind of its own — you create it like any other canvas, and Homelable swaps the renderer when you switch to it.
Where the diagram answers what talks to what, the rack answers what is where: which U a machine sits in, what plate it wears, which switch port its uplink lands on.
Works with and without the backend. In the no-backend standalone/demo build a rack canvas persists to your browser's local storage; the Device Inventory picker and the live status check are backend-only (marked 🔒 below).
Feature Overview
- Racks — any U height, 19" or 10" wide, bottom-up or top-down numbering, per-rack frame / rail / interior colours, open or enclosed.
- Mounted gear — a device occupies a U range and part of a 12-column width grid, so half- and third-width machines share a U.
- Faceplates — a visual catalog of plates (servers, switches, routers, patch panels, UPS, PDUs, desktop NAS towers, shelves, blanks, cable managers) drawn as vector artwork that scales with the rack.
- Ports & patching — RJ45 and SFP ports per device, cabled port-to-port by dragging from one to the other, across racks if needed.
- Device Inventory 🔒 — a mount points at a real inventory entry, so a rack shows the same devices your scans found, and gear you rack by hand joins that inventory.
- Live status 🔒 — a mount can follow the status check already configured on the matching diagram node, and light its plate LED accordingly.
- Import links 🔒 — derive patches from the physical links already drawn on your diagrams, as often as you like.
Create a rack canvas
- Open the canvas switcher at the top of the left sidebar.
- Click New Canvas.
- Under Kind, pick Rack (the other kind, Diagram, is the usual node/link canvas).
- Name it, pick an icon, and create.
A canvas cannot change kind afterwards — a diagram and a rack store different things. Deleting a rack canvas deletes its racks, mounts and cables with it; duplicating a canvas duplicates them too.
Add a rack
Add Rack in the header drops a new rack on the canvas. Drag it anywhere; a canvas can hold as many as you like, and cables can run between them.
Double-click the rack chrome (the frame, not a device) to open its settings:
| Setting | What it does |
|---|---|
| Name / Location | Free text — "Baie salon", "Garage", … |
| U height | How many mountable U the rack has (42 by default). |
| Width | 19" or 10" — drives the drawn inner width. |
| Numbering | bottom-up or top-down. Labels only — gear never moves. |
| Show U numbers | Print the U scale on the rails. |
| Enclosed | Draw side panels / a closed chassis. |
| Colours | Frame, rails and interior. Defaults come from your app theme. |
| Delete | Removes the rack and everything mounted in it. |
Mount a device
Click + Device in the left sidebar, or drag an accessory from the sidebar tray straight onto a rack. The device modal offers three sources:
- Device Inventory entry 🔒 — pick something already discovered. The field opens the real Device Inventory, with its search, source and type filters, and it opens pre-filtered to rackable hardware (no light bulbs, no sockets). A device already mounted on this canvas is refused.
- New device — for hardware no scan can find (a patch panel, a PDU, an unmanaged switch). It is created as a normal Device Inventory entry tagged Rack devices, so you can search, filter, hide and delete it like any other.
- Accessory — rack-only furniture: blanking plate, shelf, cable manager. These are not devices and never appear in the inventory.
Then set:
| Field | Notes |
|---|---|
| Label | Shown on the plate. |
| Faceplate | Opens the visual catalog — see below. |
| U position / height | U is counted from the bottom rail, whatever the numbering setting prints. |
| Column / width | Full, half, third, sixth or quarter of the rack width. |
| Status | A fixed colour, or Check device 🔒 — see below. |
| Colour | Overrides the plate's default tint. |
| Ports | The list of RJ45 / SFP ports, seeded by the faceplate and editable afterwards. |
Double-click a plate to reopen this modal on an existing mount; a single click only selects it. Unmount takes the device out of the rack — it stays in the Device Inventory.
Linked device 🔒
Under the port list, a mount that stands for a real device prints what is known about that box: name, type, hostname, IP, MAC, OS, the status check it runs, the canvas it is drawn on, when it was last seen, and the services discovery fingerprinted on it.
It is read-only — edit those facts in the Device Inventory or on the logical canvas, not in the rack — and an accessory shows nothing at all. A device that is on no diagram still prints everything discovery found about it; only the canvas-side lines go missing, and the panel says Not on a logical canvas.
Link to another device… points the plate at a different Device Inventory entry — the whole inventory, not just the devices you approved onto a diagram. Use it when you created the gear from the rack (the entry starts empty, with just a name) or when the plate ended up on the wrong twin of two look-alike hosts. The plate takes the entry's IP, MAC, services, status and — unless you renamed it — its name, Check device becomes available if that device is on a diagram, and the link is saved with the rest of the canvas. A device already mounted elsewhere in the design is not offered: one entry, one plate. The empty placeholder the rack created for the plate is removed from the inventory once nothing uses it.
Placement rules
- A drop snaps to the nearest free slot; a placement that cannot work previews in red.
- Drag a mounted device inside its rack to move it — same snapping.
- Growing a device, by hand or by picking a taller plate, relocates it to the nearest slot that takes the new size. Only a rack with no such slot refuses the edit, and it tells you so.
Faceplates
The Faceplate field opens a catalog, not a dropdown of names: every plate is drawn with the real renderer, at its real relative width and U height, grouped by family and searchable.
| Family | Examples |
|---|---|
| Servers | 1U, 1U with drive bays, 2U with bays, 4U storage, half-width SFF, third-width mini PC |
| Network | 8 / 24 / 48-port switches, 1U router |
| Patch | 24-port copper panel, 12-port fibre panel |
| Storage | 2U NAS, desktop NAS towers in 2, 4 and 5 bays |
| Power | 2U UPS, 1U PDU |
| Accessories | Blanking plate, shelf, cable manager |
Picking a plate reseeds the ports it comes with; your own port edits are kept until you change plate again. Plates are drawn as vector artwork in relative coordinates, so they stay correct at any rack width and U height, and their colours follow the active app theme.
Ports and patching
Ports are RJ45 or SFP/SFP+, drawn as real jack artwork at a fixed size so plates of different heights line up. Power outlets are artwork only — they are never a cable endpoint.
Patch-facing gear (switches, patch panels) shows its ports permanently; everything else reveals them on hover, on selection, or when cables are shown.
To cable:
- Click Patch in the header.
- Drag from one port to another — a dashed rubber band follows the pointer. Clicking the two ports in turn works just as well. Escape drops a half-drawn patch.
- Repeat. One cable per port; copper or fibre follows the port you start from.
- Click Exit patching when done — the canvas returns to the cable visibility it had before.
To unplug: click the cable (it gets an accent halo), then press Delete/Backspace or click Unplug in the header. A stray click never destroys a patch.
A header select controls what you see: cables on hover, always, or hidden. Cables pan and zoom with the canvas and may run from one rack to another. A cable you have selected stays drawn whatever that select says.
Documenting a cable
Click a cable — patching or not — and a panel opens on the right:
| Field | What it does |
|---|---|
| Endpoints | The two devices and ports the run connects. Read-only: move a patch by unplugging it and drawing it again. |
| Type | Ethernet or fibre. A cable still wearing its type's default colour is recoloured to match; a colour you picked yourself is kept. |
| Colour | The sheath colours you actually have on the shelf, plus a free hex field for anything else. |
| Label | A name for the run — "Uplink to core", a patch-panel reference. Show on canvas prints it next to the cable. |
| Properties | Anything else worth recording: length, VLAN, speed, category, patch reference. Same editor as a node's properties on a diagram — a label, a value, an optional icon, and an eye that decides whether it shows on the canvas. |
| Unplug cable | Removes the patch. The devices and their ports stay. |
What you tick as visible is drawn on a small plate at the middle of the run, so a rack photo exports with its cable lengths and VLANs on it. Everything else stays in the panel, one click away.
Import links 🔒
Import links derives patches from the physical links (ethernet, fibre, vlan, cluster) already drawn on your diagrams, matching both ends to mounts that point at those nodes. Run it as often as you like: a pair of devices already cabled is left alone, so a second run after racking more gear only adds what is missing.
Status 🔒
A mount's Status is either pinned by hand (online / offline / unknown) or set to Check device: the plate then follows the status check already configured on the matching diagram node (ping, HTTP, SSH, …) and its LED lights accordingly.
The rack runs no checker of its own — it reads the result of the one your diagram already performs. So:
- Check device is only offered when the mount resolves to a diagram node.
- Losing that link drops the mount back to
unknown, rather than leaving it on a status nothing answers for. - The refresh polls every 60 s, and only while at least one mount is on Check device.
Saving
Like the diagram canvas, a rack canvas is saved explicitly — Save Rack in the left sidebar, or the header's save button. Nothing is written behind your back unless you turn on Autosave in Settings.
The sidebar footer counts racks, mounts, cables and free U instead of the diagram's online/offline tally. PNG export works here too.
Known limits
- Front view only — no rear view, no half-depth pairing.
- No 0U side-mounted PDU.
- No power draw or outlet budgeting.
- No undo/redo on a rack canvas (the diagram canvas keeps its own).
- Rack canvases are not shown by the read-only Live View.
- The MCP server exposes diagram nodes and links only, not racks.
See also
- FEATURES.md — every feature, one page.
- Device Inventory — where racked devices live.
frontend/src/rack/README.md— the developer reference for this canvas.