Inventory Format Overview
The inventory is a versioned datastore that holds every piece of hardware cani knows about. Each hardware category is stored as a separate map keyed by UUID.
Top-Level Structure
In Go the inventory is the Inventory struct:
type Inventory struct {
SchemaVersion string
Provider string
Locations map[uuid.UUID]*CaniLocationType
Racks map[uuid.UUID]*CaniRackType
Devices map[uuid.UUID]*CaniDeviceType
Modules map[uuid.UUID]*CaniModuleType
Cables map[uuid.UUID]*CaniCableType
Frus map[uuid.UUID]*CaniFruType
Interfaces map[uuid.UUID]*CaniInterface
Prefixes map[uuid.UUID]*CaniPrefix
IPAddresses map[uuid.UUID]*CaniIPAddress
VLANs map[uuid.UUID]*CaniVLAN
VRFs map[uuid.UUID]*CaniVRF
Metadata *InventoryMetadata // catalog of roles, statuses, tags
}
The current schema generation is v1alpha9. It records the owning module of a
module interface (moduleId) and admits spare modules, which are stored at a
location with no parent device. v1alpha8 added optional device parent-bay
placement and unresolved module-interface name/label templates. Older
inventories are migrated through each generation on load, with the original
file backed up to .canisave. The v1alpha7 to v1alpha8 and v1alpha8 to
v1alpha9 steps only advance the version: they preserve existing values without
inferring bay assignments or missing templates, and module ownership is rebuilt
from the module specs on every load. Earlier cani releases refuse a v1alpha9
inventory rather than load and rewrite one that may contain spares.
Placement validation on load
From v1alpha9 on, every load validates module and device-bay placement. A
module bay the parent device does not declare (on a parent that declares bays),
two authored claims on one bay, or a spare stored at a location that does not
exist is an error; a module with no bay and no name, a spare that still names
a bay, or an installed module whose authored location differs from its
parent's is a warning. Earlier releases accepted any bay name, so a v1alpha8
inventory can carry an error the new rules refuse. Such an inventory still
loads, but the upgrade is deferred: the file stays at v1alpha8, the errors
are reported, and every save is refused until they are repaired. Repair an
undeclared bay with update module --bay <declared bay>, or re-import from the
source system, whose declared bays are recorded on the device so a bay the
library spells differently becomes declared. The upgrade is written on the
first load after the repair.
Hardware Types
| Type | Go Type | Description |
|---|---|---|
| Location | CaniLocationType |
Physical site, building, floor, or room |
| Rack | CaniRackType |
Equipment rack with U-slot tracking |
| Device | CaniDeviceType |
Server, switch, PDU, chassis, or blade |
| Module | CaniModuleType |
Component installed in a device (GPU, NIC, PSU) |
| Cable | CaniCableType |
Physical cable between two endpoints |
| FRU | CaniFruType |
Field-replaceable unit (spare or replacement part) |
| Interface | CaniInterface |
Network or console port on a device or module |
| VRF | CaniVRF |
Virtual routing and forwarding instance used by IPAM objects |
Relationships
Items reference each other by UUID:
- A Location has
Children(child locations) andRacks. - A Rack has a
LocationFK and aDeviceslist. - A Device has
Parent,Children,Rack,Location, andFrusreferences. - A Module has a
ParentDeviceFK, or, as a spare, aLocationFK and no parent device. - A Cable has
TerminationAandTerminationBendpoint UUIDs. - A FRU has a
DeviceorParentFK.
Cable Endpoint Integrity
Each side of an inventory cable is either absent or complete. An absent side has an empty device/module UUID, port name, and interface UUID. A populated side must contain all three fields:
terminationADeviceorterminationBDeviceidentifies a device or module.terminationAPortorterminationBPortnames an interface on that object.terminationAorterminationBis the UUID of that exact interface.
Relationship rebuilding fills a missing interface UUID when the referenced device or module contains the named port. Validation fails if the port cannot be resolved, if fields are only partially populated, or if an explicit interface UUID belongs to another endpoint. Module-owned interfaces may be referenced through the module UUID or found through their parent device.
All command saves validate relationships before writing. Import fails the whole operation before its Load phase when transformed inventory is invalid, and export performs the same preflight before invoking a provider. Existing files remain loadable so operators can inspect and repair invalid data, but migration does not automatically rewrite a file while relationship errors remain.
Example: Device
{
"f7448392-1e1c-45d0-9c59-be7dfc44c15c": {
"id": "f7448392-1e1c-45d0-9c59-be7dfc44c15c",
"name": "nid000001",
"type": "Device",
"manufacturer": "HPE",
"model": "EX420 Compute Blade",
"status": "active",
"role": "Compute",
"parent": "7e3de0fa-e3d6-421b-9d25-c0192d2a5966",
"rack": "a1b2c3d4-0000-0000-0000-000000000001",
"rackPosition": 3,
"children": [
"00050177-a309-4fde-bf85-70452b228e24",
"004ecb7f-50bb-4975-9973-b6c617d6cc82"
],
"providerMetadata": {
"csm": {
"xname": "x3000c0s3b0n0",
"class": "Mountain",
"role": "Compute",
"nid": 1
}
},
"externalIDs": {
"nautobot": "9a8b7c6d-5e4f-3a2b-1c0d-000000000001"
}
}
}
Example: Rack
{
"a1b2c3d4-0000-0000-0000-000000000001": {
"id": "a1b2c3d4-0000-0000-0000-000000000001",
"name": "x3000",
"uHeight": 42,
"location": "b2c3d4e5-0000-0000-0000-000000000001",
"status": "active",
"devices": [
"f7448392-1e1c-45d0-9c59-be7dfc44c15c"
]
}
}
Common Fields
All types embed ObjectMeta, providing a uniform set of metadata fields:
id— unique UUID identifiername— human-readable namestatus— lifecycle state (staged,active,planned, etc.)role— functional role (e.g.Compute,Spine Switch)tags— arbitrary string labelstenant— tenant or ownership groupcustomFields— free-form key/value mapexternalIDs— maps a provider name to that provider's remote UUIDproviderMetadata— provider-specific data (see Metadata)