Skip to main content
Use this as a checklist when adding new devices, sites, or cabling in NetBox.

How the Sync Works

The Matrix connector is event-driven: NetBox changes reach Fleet Manager’s inventory projections and flow to the connector as NATS events, with a polling backstop sweeping every scoped site every 150 seconds so nothing is ever missed. Ethernet devices and InfiniBand inventory are read from NetBox directly on a 120-second delta loop with a 6-hour keep-alive re-stamp. Devices are filtered by role and status (active only), transformed into Matrix table schemas, and ingested to Azure Kusto staging tables. Deletions differ by table: projection-fed tables (Servers, NVSwitches) receive an IsDeleted tombstone within the SLA, while NetBox-direct tables (EthDevices, IbInventory) prune on the next successful full refresh and the stale rows age out under the 7-day staging retention. A NetBox change is typically queryable in Kusto within seconds, well inside the 5-minute SLA. See Matrix Connector Operations for the operational runbook.
The transforms and naming rules on this page previously ran in the retired netbox_matrix agent and are unchanged in the connector — “the agent” in the sections below refers to the sync’s transform behaviour, which is identical.
Only devices in sites listed in CONNECTOR_SITE_FILTER are synced to Matrix. That filter scopes the Matrix connector alone. Fleet Manager’s own NetBox sync agent selects its devices through NETBOX_AGENT_DEVICE_FILTERS instead, so a site the sync agent covers has its RDMA GUID labels (section 6) read whether or not it appears in CONNECTOR_SITE_FILTER.

Device and Asset Naming Conventions

The agent uses the asset_tag field as the primary display name in Matrix (falling back to name if unset). For Ethernet devices, the asset_tag is also the source for asset type extraction — a critical Matrix field. Names must follow specific conventions per device type.

General Rules

  • asset_tag is the preferred identifier sent to Matrix. Set it on every device.
  • name is the NetBox hostname. It acts as a fallback when asset_tag is empty.
  • The agent checks asset_tag first, then name, when resolving display names and extracting asset types.

Ethernet Device Naming (Switches, Firewalls, Routers)

Ethernet device asset_tag values must follow this pattern for asset type extraction to work:
The agent applies the regex -(\d+)([a-z]+\d*)$ (case-insensitive) to extract the type suffix from the end of the name. The <number> is a sequence number and the <type> is a short code identifying the device’s function. Pattern breakdown: Known asset type suffixes: Examples with full extraction:
Role-based fallbacks (when the regex doesn’t match). These apply to the asset type extraction function used by the EthDevices and EthInterfaceLinks transforms: If neither the regex nor a role fallback applies, the asset_type field in Matrix will be empty — this indicates a naming issue that should be fixed.
gpu-node and compute-tray devices sync via the Servers table (section 4a), not EthDevices. If they do appear in EthDevices context (e.g., as cable endpoints in EthInterfaceLinks), the function returns GPUNode as a fallback.

InfiniBand Switch Naming

IB switches have a hard requirement: the device name must contain -ifs-. Without it, the device is filtered out entirely even if it has the correct role. name pattern: <site>-<pod>-ifs-<switch_type><number> asset_tag convention: The asset_tag is used as the display name in Matrix (device_name) when present, and follows a different convention based on the switch’s position in the IB fabric topology. This applies to both NDR and XDR clusters:
The asset_tag may carry a site prefix (e.g. sys1-wdc1.L3.1.1), because NetBox requires asset tags to be globally unique and the same fabric designation is reused across sites. The agent strips the prefix on transform, so Matrix always receives the bare designation (L3.1.1).
Core switches — CX.Y: Example: C1.2 = core group 1, switch 2 Spine switches — SX.Y.Z: Example: S1.3.2 = switch 1, super pod 3, rail 2 Leaf switches — LX.Y.Z: Example: L2.1.4 = switch 2, super pod 1, rail 4

GPU Compute Server Naming

GPU servers don’t have a strict naming regex, but common patterns include: The asset_tag (or name as fallback) becomes the node_name in the Servers table. NVLink switches use asset_tag as the display name. Their asset_type is normalized to nvs when the tag ends in either supported site convention: Any other NVLink asset_tag suffix produces an empty asset_type; correct the tag rather than relying on the device name as a fallback.

UFM Server Naming

UFM servers sync to the IbSwitches table. No -ifs- naming requirement — role match alone is sufficient. The asset_tag (or name) becomes the display name.

NetBox name vs asset_tag Summary

Recommendation: Always set both fields. Use name for the internal infrastructure hostname (e.g., sin1-p-swi-feb1) and asset_tag for the Matrix-facing name that follows the naming convention (e.g., sie50-dh5-dc-01fbs).

TenantId (from the name cluster prefix)

The TenantId column on Servers, NVSwitches, EthDevices, EthInterfaceLinks, IbInventory and IbSwitchLinks is the Nscale cluster number N from the leading sys<N>- prefix of the NetBox name — never from asset_tag, which carries no cluster prefix. The customer calls this number TenantId; it is zero-padded to two digits: A link takes the TenantId of its start device (for IbSwitchLinks, the IB switch end). IB switches share fabric designations across clusters — both sys1-wdc1.L3.1.1 and sys2-wdc1.L3.1.1 publish as L3.1.1 — so on the IB tables TenantId is what tells them apart. A device whose name lacks the sys<N>- prefix publishes an empty TenantId rather than a guessed one, so a misnamed device shows up as a blank, not as the wrong tenant. Every one of these tables also carries a TenantID column (capital D) with the same value. Microsoft’s validator (MTX-2261) reads TenantID and Kusto column names are case-sensitive, so both spellings are published until Microsoft confirms which one to keep; the other is then dropped.

1. Site Setup

NetBox model: dcim/sites Every site that should sync to Matrix must be configured with: Critical: The description field becomes the dc_region value in every Matrix table. If it is missing, region fields will be empty across Servers, IbSwitches, NVSwitches, and EthDevices.

Site Prefixes (for Ethernet devices only)

NetBox model: ipam/prefixes Each site needs an RFC1918 supernet prefix to derive the site_id used in EthDevices and link tables: The second octet of the prefix becomes the site_id (e.g., 10.40.0.0/16 → site_id 40). This value drives:
  • SiteId in EthDevices and EthInterfaceLinks
  • SyslogServerIp → 192.168.<site_id>.97
  • SNMPServerIp → 192.168.<site_id>.135

2. Location Hierarchy

NetBox model: dcim/locations Locations are used to resolve the DataHall for servers and switches. The agent walks the location tree:
  • If a location has no parent → it IS the datahall
  • If the location’s parent has no parent → the parent is site-level, and the current location is the datahall
  • Otherwise → the parent is the datahall
Example hierarchy:
A device assigned to Row 5 will resolve datahall = dh110.

3. Device Types

NetBox model: dcim/device-types Device types must be fully populated since they provide hardware metadata: Fleet Manager writes custom_fields.platform_class on the device (not the device type) during enrolment, once the site’s platform_class_activity_ready gate is on: <GPUTYPE>_<DEVICETYPE>_<FABRICTYPE>_<NN>, e.g. GB300_LENOVOHG635NV2_IB_01. resource_class is deliberately separate: it is operator-set in config_context.ironic_settings, shared by a device type, and customer-facing through Ironic, Nova/Placement, and SLURM. platform_class is the Fleet Manager-owned per-device variant key for hardware-descriptor lookups: burn-in derives GPU-count and GPU-name test parameters that a test’s params leave unset from it, and a test that needs such a value on a device without one fails. Threshold and topology selection still use resource_class. Fleet Manager writes the key only when the NetBox field is empty and never overwrites a populated value. Correct a key by clearing custom_fields.platform_class in NetBox and running fleetctl netbox backfill-platform-class for that device. See enrollment phase 0b for the full derivation and write policy.

4. Devices by Role

4a. GPU Compute Servers (→ Servers table)

Roles: gpu-node, compute-tray Interfaces required: If no interfaces exist for a device, the device is skipped entirely. The location field is built as: <dc_region>-<datahall>-<rack_id> (all lowercase, hyphen-joined). Back-end fabric (config_context.ztp) — Fleet Manager enrolment only. Fleet Manager derives the FABRICTYPE component of platform_class from the device’s rendered config_context.ztp block, and only for GPU compute devices: CPU baremetal and hypervisor devices (no gpu_type) are always NORDMA and their ztp block is never read.

4b. InfiniBand Switches and UFM Servers (→ IbSwitches table)

IB Switch roles: be-core-switch, be-leaf-switch, be-spine-switch Additional filter: Device name must contain -ifs- (e.g., sin1-p-ifs-bes115). Devices with the right role but without -ifs- in the name are excluded. UFM Server role: ufm-server UFM servers sync to the same IbSwitches table using the same transform. No -ifs- naming convention required — role match alone is sufficient. Both IB switches and UFM servers use the same field requirements: Location validation is strict — if all of location, rack, and position are missing, the device fails validation and is skipped. The device_location field is built by joining location_name, rack_name, and position with /. Note that rack_name in NetBox can itself contain / separators (e.g., Row 2 / 11), so the output may have more than 3 visual segments:
  • ("DH110", "Row 2 / 11", 42) → DH110 / Row 2 / 11 / 42
  • ("DH110", "Rack-05", 10) → DH110 / Rack-05 / 10

Role: nvlink-switch Interfaces required: The device_location is: <dc_region>-<datahall>-<rack_id> (all lowercase, hyphen-joined).

4d. Ethernet Devices (→ EthDevices table)

Roles: See full list below. Devices with tenant.slug = "nscale" are excluded. Asset type extraction: The agent extracts asset_type from the device name or asset_tag using the regex pattern -<digits><type>$:
  • sie50-dh5-dc-01fbs → fbs
  • sie50-dh5-dc-01oobfbs → oobfbs
  • pdx51-m34-p1-01t1 → t1
  • pdx51-m34-dc-01cab → cab
If the regex doesn’t match, a role-based fallback applies:
  • console-server / console-manager → console-server
  • nvlink-switch → nvs for the documented NVLink asset-tag suffixes; otherwise empty
Static and TBD fields: The following Matrix fields are set automatically and do not require NetBox data:
  • cloud_type → always "public"
  • asn → from device custom field switch_asn
  • dhcp_gateway → list from device custom fields dhcp_primary and dhcp_secondary
  • vlan_id, mac_address, cluster_id → always empty (TBD / not sourced from NetBox)
For fe-leaf-switch devices only: Two interfaces feed the compute SVI fields, and vlan101-104 takes precedence when both exist. A switch moves from the single aggregate to the per-VLAN values as soon as vlan101-104 is created, so migration is per-device with no coordinated cutover.
  • vlan101-104 — the per-VLAN tenant SVIs. Assign the switch’s own address for each VLAN: one IPv4 (e.g. a /27) and one IPv6 (e.g. a /64) per VLAN. Populates all four of compute_ipv4, compute_subnet, compute_ipv6 and compute_ipv6_subnet as comma-separated lists, ordered by address.
  • vlan100-116 — the legacy single aggregate. Used only when vlan101-104 is absent, and then exactly as before: the lowest non-anycast IPv4 and its subnet, with compute_ipv6 / compute_ipv6_subnet left empty.
Mark VRR gateway addresses with IP role anycast on either interface — they are skipped, as they are not the switch’s own address. If you create vlan101-104 but assign only IPv4, the IPv6 fields stay empty; the IPv4 fields still switch to the per-VLAN list. Example for a switch with four tenant VLANs on vlan101-104:
For all Ethernet devices:
  • Create an interface named lo with an IPv4 address assigned → populates loopback_ipv4

NetBox model: dcim/cables Both termination interfaces must have:
  • name set
  • Belong to devices with name set
  • Belong to devices in the same site
The speed on the A-side interface is converted to bandwidth_in_gbps (kbps ÷ 1,000,000). Only device-to-device cables are synced. Cables to patch panels, power outlets, or console ports are ignored. Same cable requirements as Ethernet links, plus: Connection types:
  • IB_IB: Both endpoints are IB switches
  • IB_SERVER: One endpoint is an IB switch, the other is any non-IB-switch device (typically a gpu-node or compute-tray, but the agent does not enforce a specific role on the non-switch end)
For IB_SERVER links, the output is normalized so the IB switch is always on the start side. Both endpoint devices need location, rack, and position set — the device_location field (built by joining these with /) is required and the transform fails without at least one of these. The speed on the interface is formatted as <N>G (e.g., 400000000 kbps → 400G). For IB_SERVER links, the server’s serial number (or name as fallback) becomes the hostname field.

6. InfiniBand Port GUIDs on RDMA Interfaces

This is the one requirement on this page the Matrix connector does not read. It is consumed by Fleet Manager’s NetBox sync agent, which mirrors NetBox devices into Fleet Manager’s own inventory and fills interfaces[].ib_device_guid from it.
The interface name selects; the interface label carries the value. The sync agent looks at every interface whose name matches ^RDMA[0-9]+$ (case-insensitive — RDMA0, rdma7, and Rdma11 all match) and reads the InfiniBand port GUID out of that interface’s NetBox label. No custom field is involved: it is the built-in label field on the interface. That split between the selecting field and the carrying field is the surprising part of this contract, and it is easy to satisfy one half of it and not the other. A host RDMA port named anything else is silently ignored. Host-side port naming varies by server and NIC vendor, and a switch-style name such as swp1s0 can never match RDMA<N>. A non-matching name yields no GUID, no warning, and no failure, so a whole site can sit at zero GUID coverage with nothing to indicate a problem. Where the names do not match, the interfaces have to be renamed to RDMA<N> — there is no alternative source for this value.

Accepted Label Formats

Both forms normalize to bare lowercase 16 hex digits, which is the only form Fleet Manager stores. Anything else — the wrong digit count, neither a 0x prefix nor colons, a GUID with surrounding commentary — is rejected; the two rows above are the complete list of what the sync agent parses. Bare lowercase hex is Fleet Manager’s canonical form for a GUID: every accepted spelling collapses to one string, so GUIDs compare and de-duplicate as plain text, and it is the representation the NVIDIA UFM pkey GUIDs REST API uses in its own examples, so a stored value can be passed to the fabric manager as-is.
A port GUID is not a system GUID. custom_fields.system_guid (section 4b) is a per-device value on IB switches and UFM servers that syncs to the Matrix guid column. The RDMA interface label is a per-port value on a compute host — one per HCA port, so eight on a typical GPU node. They are different values with different purposes. Copying a device’s system GUID into its interface labels produces eight wrong entries per node that still look populated.

What Happens When the Label is Missing or Malformed

Nothing fails. Enrolment is unaffected, the interface still syncs, and the device stays usable — it simply carries no GUID: Search the sync agent’s logs by structured field, not by message text — the wording of a warning is not a contract and changes between releases; the fields are. Every GUID-gap warning carries: Filter the agent’s stream on ib_guid_gap being present and group by site_slug and ib_guid_gap: that gives coverage gaps per site, by cause, without reading a single message. In Grafana Explore against product-loki (add your hub cluster’s cluster label to the selector):
This gap is silent by default. No job fails, no device condition is raised, and no alert fires. The two warnings above are the only log output there is, and they exist only for interfaces already named RDMA<N> — a port named anything else produces no log line at all. A site whose host ports are all named outside the pattern therefore generates nothing: searching the sync agent’s logs finds no warning, and that absence does not mean there is no gap. Coverage has to be verified deliberately; a healthy-looking sync says nothing about it.
Verify coverage before a fabric partition change, not after. InfiniBand partition (pkey) membership is keyed on port GUIDs. When a node’s GUIDs are missing or only partly populated, some of its HCA ports can be left out of a partition — and on a fabric whose default partition is limited-membership, a port left out is isolated, not merely unconfigured. That presents as a customer-visible fabric outage which looks like a cabling or firmware fault, and it has happened. Confirm full coverage across every host in scope first.

Populating Labels in Bulk

fleetctl netbox populate-ib-guids writes the labels from a per-hostname GPU-to-GUID export. It reads the same NetBox configuration as the sync agent (NETBOX_URL plus a token, or the 1Password credential lookup). The input JSON maps hostname → RDMA<N> → that port’s guid and os_name:
Each hostname must match exactly one NetBox device name. Interfaces are matched on the integer N in RDMA<N> rather than on the exact string, so an export key of rdma01 still resolves to NetBox’s RDMA1. Any additional key inside a port entry is ignored.
Each interface in the plan gets one of three outcomes: The refusal to overwrite is what makes the command safe to re-run: it can never quietly replace a GUID somebody else put there. A conflict can surface at two points, and they behave differently:
  • Preflight (dry-run and --apply alike) — the plan is built from a first read of every interface. A conflict found here — along with an unknown hostname, a hostname matching more than one NetBox device, a missing RDMA<N> interface, a port key that is not RDMA<N>, an unparseable GUID, the same GUID on two entries, a duplicated JSON key, two input keys colliding on one RDMA index, or NetBox itself holding two interface names that resolve to one index (RDMA1 alongside rdma01) — aborts the whole run before a single label is written. Fix the input and run it again.
  • Apply time (--apply only) — NetBox has no compare-and-set, so each label is re-read immediately before it is written. If a different value landed there (or the interface disappeared) between preflight and the write, that one interface is skipped with a warning and the command carries on with the rest; the summary line reports how many were conflicting since preflight and the command exits non-zero. Labels written before the conflict stay written. A non-zero exit from --apply therefore means a partial backfill, not an untouched NetBox — read the summary, resolve the conflict, and re-run; everything already set is a skip on the next pass. If the re-read finds the identical GUID already in place, that counts as already set, not as a conflict.

Verifying Coverage

Labels reach Fleet Manager on the sync agent’s next reconcile. Read a device back from the API and list every interface with its name and GUID:
Every RDMA<N> entry should carry 16 hex digits; null means the label is absent or was rejected. To list only the interfaces with no GUID:
Every name that command prints is an interface with no GUID. Ethernet and BMC interfaces appear in that list as a matter of course; what must not appear is any RDMA<N> name — and a host port that shows up under a non-matching name (swp4s1, say) is the misnamed-port case from the top of this section, visible here precisely because the command does not filter on the pattern. List all interfaces deliberately rather than filtering on the name pattern: a filter on RDMA<N> inherits the contract’s own blind spot, because a physical port that is absent from NetBox or named outside the pattern (swp4s1, say) never appears in the filtered output, and seven valid GUIDs read as a complete node when the hardware has eight ports.
A passing check does not prove coverage. Fleet Manager reads no expected HCA port count for a device — the sync agent does not consult NetBox device-type interface templates, and no Fleet Manager field records how many ports a node should have — so the output above can only be judged against a count you bring yourself. Compare the number of RDMA<N> interfaces carrying a GUID against the node’s physical HCA port count: the GPU-to-GUID export for that hardware (one entry per port the node itself reported), or the node directly (ibstat, or the entries under /sys/class/infiniband/). A shortfall means a port is missing from NetBox or is named outside the pattern; both are fixed in NetBox, not in Fleet Manager.
In NetBox itself, the equivalent check is that each host has as many RDMA<N> interfaces as it has HCA ports and the Label column is populated on every one of them.
Documenting this contract does not populate anyone’s NetBox. Backfilling a site still needs a GPU-to-GUID export for that hardware to exist in the first place, collected from the nodes themselves.

7. RoCE Back-end Ports for the VRF Flip

Like section 6, the Matrix connector does not read this. It is the contract for Fleet Manager’s back-end VRF flip, which is being built (spec 0064): which leaf sub-ports will move between the customer and maintenance VRFs when a host is isolated for repair. Today fleetctl netbox be-port-plan checks a host against it.
A host’s back-end ports are selected by name, never by MAC address or interface type. Each site sets its naming rules in TEMPORAL_WORKER_BACKEND_PORT_SHAPE (the satellite chart’s temporalWorker.backendPortShape); Fleet Manager ships no default, and a site that sets none is refused before NetBox is read. The example below is GSO1’s (XE9712 GB300 trays on SN5610 back-end leaves); the back-end VRF runbook has its JSON. Each PF’s leaf comes from the netbox_datacenter plugin’s fibre graph. A PF reaches its leaf through passive shuffle cassettes, which NetBox’s own cable trace cannot cross, so GSO1 records no native cable for a back-end PF. Fleet Manager reads the plugin’s fiber_graph interface peer mapping instead, one request per host, and needs view on netbox_datacenter.inventoryinfointerfacepeermapping to do so. Each PF must have exactly one mapped row naming the leaf’s interface. A native cable on a PF is not required; if one exists and ends directly on an interface, it must be the mapped one. The plugin recomputes the mapping on its own schedule, and Fleet Manager does not check how old it is. The be-meta and be-nscale VRFs are created on every leaf by network engineering. Fleet Manager never creates or deletes a VRF.

Checking a host

fleetctl netbox be-port-plan reads NetBox only and touches no switch. Run it with the site’s worker settings, including its port shape:
On a correctly modelled host it prints 16 rows (PF, rail, plane, leaf, leaf port, management address) and the SU, and exits 0. Otherwise it exits 1 and lists every defect at once, one line per PF, so an import can be fixed in one pass. A refusal is fixed in NetBox, not in Fleet Manager.

8. Quick Reference Checklist

Use this when adding a new device to NetBox:

Before adding any device:

  • Site exists and has description set (e.g., SIE50)
  • Site is in CONNECTOR_SITE_FILTER
  • Location hierarchy exists (datahall → row) with correct parent relationships
  • Device type exists with model populated (manufacturer too, for Servers/NVSwitches/EthDevices — not required for IB switches/UFM servers)

For every device:

  • name is set
  • asset_tag is set (preferred display name in Matrix)
  • status = active
  • role is one of the supported roles (see sections 4a-4d)
  • site is assigned
  • location is assigned (for datahall resolution)
  • rack is assigned
  • position (rack unit) is set
  • serial number is set

For GPU compute servers (gpu-node, compute-tray):

  • oob_ip is set
  • The device type’s custom_fields.gpu_type is set (e.g. GB300) — enrolment fails without it
  • config_context.ztp is either absent or carries an infiniband section — any other shape fails enrolment
  • description starts with hardware SKU (e.g., GB300 NVL72)
  • At least one interface exists with a MAC address
  • BMC interface exists (named bmc, ipmi, xcc, mgmt, ilo, idrac, or management)
  • Primary network interface exists (named eth0, eth1, ib0, or ib1) with MAC
  • Every RDMA port is named RDMA<N> and its interface label holds that port’s IB GUID (section 6)
  • (optional) custom_fields.backend_id is set — publishes "01" when left empty

For IB switches (be-core-switch, be-leaf-switch, be-spine-switch):

  • Device name contains -ifs-
  • primary_ip or oob_ip is set
  • device_type.part_number is set (SKU)
  • device_type.u_height is set on the device type
  • custom_fields.software_version is set (firmware)
  • custom_fields.os_version is set
  • custom_fields.system_guid is set (InfiniBand GUID)
  • (optional) custom_fields.backend_id is set — publishes "01" when left empty

For UFM servers (ufm-server):

  • Same as IB switches, but no -ifs- naming requirement
  • oob_ip is set (BMC IP)
  • primary_ip is set (OOB management IP)
  • Interfaces created: bmc/ipmi, oob/mgmt, serial/console with MACs
  • (optional) custom_fields.backend_id is set — publishes "01" when left empty

For Ethernet devices:

  • Device is NOT tenanted to nscale
  • Site has an RFC1918 supernet prefix (e.g., 10.40.0.0/16) with tenant.slug = "matrix"
  • asset_tag or name follows naming convention <site>-<rack>-<loc>-<num><type> for asset type extraction
  • custom_fields.os_version is set (firmware version)
  • (fe-leaf-switch only) Interface vlan101-104 exists with the per-VLAN IPv4 and IPv6 SVI addresses — takes precedence over vlan100-116
  • (fe-leaf-switch only) …or, if not yet migrated, interface vlan100-116 exists with IPv4 addresses (legacy single-value output, no IPv6)
  • (fe-leaf-switch only) VRR gateway addresses carry IP role anycast so they are excluded
  • Interface lo exists with IPv4 address (for loopback)

For cables:

  • Both ends terminated on dcim.interface (not patch panels/power/console)
  • Both endpoint interfaces have name set
  • Both endpoint devices have name set
  • Both endpoint devices are in the same site
  • Cable type is set (required — untyped cables are not synced. E.g., cat6a, mmf, smf, dac-passive)
  • Interface speed is set on at least the A-side (for bandwidth calculation)
  • (IB links only) At least one endpoint is an IB switch with -ifs- in the name
  • (IB links only) Both endpoints have location, rack, and position set

9. What Happens When Data is Missing


10. Connector Configuration

The connector is configured through the Fleet Manager hub chart (matrixConnector values), which renders these environment variables: