Cluster and Node Tracking¶
Proxbox tracks Proxmox cluster and node information, linking them to NetBox's native virtualization.Cluster and dcim.Device objects for full infrastructure visibility.
Overview¶
When a Proxmox environment runs in cluster mode, multiple hypervisor nodes form a single logical unit managed by Corosync/Proxmox VE cluster services. Proxbox reflects this topology inside NetBox by:
- Creating a
ProxmoxClusterrecord that mirrors the Proxmox cluster and optionally links to a NetBoxvirtualization.Cluster. - Creating a
ProxmoxNoderecord per hypervisor node, each optionally linked to a NetBoxdcim.Device. - Updating the
ProxmoxEndpoint.modefield toclusterorstandaloneautomatically after each sync.
Features¶
| Feature | Description |
|---|---|
| Cluster discovery | Detects cluster name, quorum status, and node count from Proxmox |
| Node monitoring | Tracks online/offline state, CPU usage, memory (used/total), and uptime per node |
| NetBox Cluster link | Optional FK to virtualization.Cluster for unified cluster inventory |
| NetBox Device link | Optional FK to dcim.Device for unified device/server inventory |
| Mode auto-detection | Sets standalone or cluster on the endpoint during sync |
| REST API | Full CRUD and filtering for clusters and nodes via the plugin API |
Viewing Cluster and Node Data¶
Navigate to the endpoint detail page:
Plugins → ProxBox → Endpoints → Proxmox → [Endpoint name] → Cluster & Nodes tab
The tab shows:
- Cluster summary card — name, mode badge, quorum badge, version, and total node count.
- Node table — one row per node with columns for status, IP address, CPU %, memory (used GB / total GB), and uptime.
Mode Badges¶
The Mode field on the endpoint detail page uses colour-coded badges:
| Badge | Meaning |
|---|---|
| Green — Cluster | Multi-node Proxmox cluster |
| Blue — Standalone | Single-node installation |
| Gray — Undefined | Sync has not run yet |
Syncing Cluster Data¶
NetBox Device names¶
Each node's NetBox Device name is rendered from the effective node Device name
template. The endpoint override wins when non-empty, otherwise the global
plugin value applies; the default is {node}. Available placeholders are
{node}, {cluster}, {cluster_slug}, and {endpoint}. For clusters that
reuse short node names, use a value such as
{node}.{cluster}.example.com.
Proxmox requests continue to use the original short node name. Typed sync state also stores the short node and cluster names, so VM and interface attachment is stable across template changes. Managed legacy names are renamed in place; operator-assigned Device names are not overwritten.
Programmatic Sync¶
Call sync_cluster_and_nodes() from anywhere in the NetBox Django environment:
from netbox_proxbox.services.sync_cluster import sync_cluster_and_nodes
result = sync_cluster_and_nodes(endpoint_id=1)
# result = {
# "mode": "cluster",
# "clusters": {"created": 1, "updated": 0},
# "nodes": {"created": 3, "updated": 0, "deleted": 0},
# }
print(result)
The function:
- Calls
proxbox-api /proxmox/cluster/statusto get cluster and node topology. - Calls
proxbox-api /proxmox/nodes/to get per-node resource metrics. - Creates or updates
ProxmoxClusterandProxmoxNoderecords in a single DB transaction. - Deletes
ProxmoxNoderows that no longer exist in Proxmox. - Sets
ProxmoxEndpoint.modetoclusterorstandalone.
Automatic Sync¶
The cluster sync is designed to be called inside the existing Proxbox background sync job. Add a call to sync_cluster_and_nodes() at the end of your custom sync flow, or wait for it to be wired into the full-update job in a future release.
REST API¶
All cluster and node objects are accessible through the plugin REST API.
Cluster Endpoints¶
GET /api/plugins/proxbox/clusters/
GET /api/plugins/proxbox/clusters/{id}/
POST /api/plugins/proxbox/clusters/
PUT /api/plugins/proxbox/clusters/{id}/
PATCH /api/plugins/proxbox/clusters/{id}/
DELETE /api/plugins/proxbox/clusters/{id}/
Example — list clusters:
curl -H "Authorization: Token <token>" \
http://netbox.example.com/api/plugins/proxbox/clusters/
Filterable fields: id, endpoint, netbox_cluster, name, mode, quorate
Searchable fields: name, cluster_id
Node Endpoints¶
GET /api/plugins/proxbox/nodes/
GET /api/plugins/proxbox/nodes/{id}/
POST /api/plugins/proxbox/nodes/
PUT /api/plugins/proxbox/nodes/{id}/
PATCH /api/plugins/proxbox/nodes/{id}/
DELETE /api/plugins/proxbox/nodes/{id}/
Example — list online nodes for a specific endpoint:
curl -H "Authorization: Token <token>" \
"http://netbox.example.com/api/plugins/proxbox/nodes/?endpoint_id=1&online=true"
Filterable fields: id, endpoint, proxmox_cluster, netbox_device, name, ip_address, online, local
Searchable fields: name, ip_address, ssl_fingerprint
Sample Cluster Response¶
{
"id": 1,
"url": "/api/plugins/proxbox/clusters/1/",
"endpoint": {"id": 1, "name": "prod-proxmox"},
"netbox_cluster": {"id": 5, "name": "prod-cluster"},
"name": "pve-cluster",
"cluster_id": "abc123",
"mode": {"value": "cluster", "label": "Cluster"},
"nodes_count": 3,
"node_count": 3,
"quorate": true,
"version": 7,
"tags": [],
"custom_fields": {},
"created": "2026-04-01T00:00:00Z",
"last_updated": "2026-04-01T00:00:00Z"
}
Sample Node Response¶
{
"id": 1,
"url": "/api/plugins/proxbox/nodes/1/",
"endpoint": {"id": 1, "name": "prod-proxmox"},
"proxmox_cluster": {"id": 1, "name": "pve-cluster"},
"netbox_device": {"id": 42, "name": "pve-node-01"},
"name": "pve-node-01",
"node_id": 1,
"ip_address": "10.0.0.10",
"online": true,
"local": false,
"cpu_usage": 12.5,
"cpu_usage_percent": 12.5,
"max_cpu": 32,
"memory_usage": 17179869184,
"memory_usage_percent": 25.0,
"max_memory": 68719476736,
"ssl_fingerprint": "AB:CD:EF:...",
"support_level": "",
"tags": [],
"custom_fields": {},
"created": "2026-04-01T00:00:00Z",
"last_updated": "2026-04-01T00:00:00Z"
}
Linking to NetBox Objects¶
Link ProxmoxCluster to a NetBox Cluster¶
After creating both objects, assign the FK through the API or in Python:
from netbox_proxbox.models import ProxmoxCluster
from virtualization.models import Cluster
proxmox_cluster = ProxmoxCluster.objects.get(name="pve-cluster")
netbox_cluster = Cluster.objects.get(name="prod-cluster")
proxmox_cluster.netbox_cluster = netbox_cluster
proxmox_cluster.save()
Or via REST PATCH:
curl -X PATCH \
-H "Authorization: Token <token>" \
-H "Content-Type: application/json" \
-d '{"netbox_cluster": 5}' \
http://netbox.example.com/api/plugins/proxbox/clusters/1/
Link ProxmoxNode to a NetBox Device¶
from netbox_proxbox.models import ProxmoxNode
from dcim.models import Device
proxmox_node = ProxmoxNode.objects.get(name="pve-node-01")
netbox_device = Device.objects.get(name="pve-node-01")
proxmox_node.netbox_device = netbox_device
proxmox_node.save()
Both FKs are nullable (SET_NULL on delete). Deleting a NetBox Cluster or Device clears the pointer on the Proxbox object without deleting the Proxbox record.
Data Model¶
ProxmoxCluster¶
| Field | Type | Description |
|---|---|---|
endpoint |
FK → ProxmoxEndpoint | Parent Proxmox endpoint |
netbox_cluster |
FK → virtualization.Cluster (nullable) | Linked NetBox cluster |
name |
CharField | Cluster name from Proxmox |
cluster_id |
CharField | Proxmox internal cluster identifier |
mode |
CharField | undefined, standalone, or cluster |
nodes_count |
IntegerField | Number of member nodes |
quorate |
BooleanField | Corosync quorum status |
version |
IntegerField (nullable) | Corosync configuration version |
ProxmoxNode¶
| Field | Type | Description |
|---|---|---|
endpoint |
FK → ProxmoxEndpoint | Parent Proxmox endpoint |
proxmox_cluster |
FK → ProxmoxCluster (nullable) | Owning cluster (null for standalone) |
netbox_device |
FK → dcim.Device (nullable) | Linked NetBox device |
name |
CharField | Node name |
node_id |
IntegerField | Proxmox-assigned numeric node ID |
ip_address |
GenericIPAddressField | Node management IP address |
online |
BooleanField | Whether node is online |
local |
BooleanField | Whether this is the local node on the endpoint |
cpu_usage |
FloatField | Raw CPU usage value from Proxmox |
cpu_usage_percent |
FloatField (computed) | CPU usage as a percentage (0–100) |
max_cpu |
IntegerField | Total CPU thread count |
memory_usage |
BigIntegerField | Used memory in bytes |
memory_usage_percent |
FloatField (computed) | Memory usage as a percentage (0–100) |
max_memory |
BigIntegerField | Total memory in bytes |
ssl_fingerprint |
CharField | TLS certificate fingerprint |
support_level |
CharField | Proxmox support subscription level |
Troubleshooting¶
- Mode shows "Undefined"
- The endpoint sync has not run yet. Call
sync_cluster_and_nodes(endpoint_id=<id>)or trigger a Proxbox sync job. - "Cluster & Nodes" tab is empty
- Verify that
proxbox-apiis reachable from NetBox and that endpoint credentials are correct. Check the proxbox-api logs for errors on/proxmox/cluster/status. - Nodes not updating after a topology change
- Stale nodes are deleted automatically during sync. If they persist, check that
proxbox-apiis returning the updated node list for that endpoint. - Node table shows 0 % CPU or 0 GB memory
- The
/proxmox/nodes/endpoint may have returned missing metric fields. This is non-fatal; values default to zero and will update on the next successful sync.