Summary
glpiinventory collects hardware module data from network switches via SNMP
and stores it in network_components (XML: <COMPONENT> elements). However,
this data is currently not used to create inventory assets — it is discarded
after the parent switch is inventoried.
Data available
For a Cisco C9300 stack, glpiinventory already collects the following
component structure via SNMP:
<!-- Stack root -->
<COMPONENT>
<INDEX>1</INDEX>
<TYPE>stack</TYPE>
<CONTAINEDININDEX>0</CONTAINEDININDEX>
<MODEL>C9300-48P</MODEL>
<SERIAL>SN_STACK</SERIAL>
</COMPONENT>
<!-- Stack member (chassis) -->
<COMPONENT>
<INDEX>1000</INDEX>
<TYPE>chassis</TYPE>
<CONTAINEDININDEX>1</CONTAINEDININDEX>
<MODEL>C9300-48P</MODEL>
<SERIAL>SN_CHASSIS_1</SERIAL>
<NAME>Switch 1</NAME>
</COMPONENT>
<!-- FRU expansion module inside Switch 1 -->
<COMPONENT>
<INDEX>1110</INDEX>
<TYPE>module</TYPE>
<CONTAINEDININDEX>1061</CONTAINEDININDEX>
<FRU>1</FRU>
<MODEL>C9300-NM-8X</MODEL>
<SERIAL>SN_MODULE_1</SERIAL>
<DESCRIPTION>8x10G Uplink Module</DESCRIPTION>
<REVISION>V03</REVISION>
</COMPONENT>
<!-- Same module in Switch 2 of the same stack -->
<COMPONENT>
<INDEX>2110</INDEX>
<TYPE>module</TYPE>
<CONTAINEDININDEX>2061</CONTAINEDININDEX>
<FRU>1</FRU>
<MODEL>C9300-NM-8X</MODEL>
<SERIAL>SN_MODULE_2</SERIAL>
<DESCRIPTION>8x10G Uplink Module</DESCRIPTION>
<REVISION>V03</REVISION>
</COMPONENT>
Fields available per module:
TYPE — component type (module, chassis, stack, container, other)
FRU — 1 = Field Replaceable Unit (real hardware asset), 2 = non-replaceable
MODEL — hardware model (e.g. C9300-NM-8X, C3850-NM-4-10G)
SERIAL — unique serial number
REVISION — hardware revision
CONTAINEDININDEX — index of the parent component (allows building the hierarchy)
Stack support
A stacked switch is represented as a single NetworkEquipment in GLPI but
physically consists of multiple chassis, each with their own expansion modules.
The CONTAINEDININDEX tree allows resolving which module belongs to which
stack member:
stack (INDEX=1)
└── chassis Switch 1 (INDEX=1000, CONTAINEDININDEX=1, SERIAL=SN_CHASSIS_1)
└── module container (INDEX=1061, CONTAINEDININDEX=1000)
└── C9300-NM-8X (INDEX=1110, CONTAINEDININDEX=1061, SERIAL=SN_MODULE_1) ← FRU
└── chassis Switch 2 (INDEX=2000, CONTAINEDININDEX=1, SERIAL=SN_CHASSIS_2)
└── module container (INDEX=2061, CONTAINEDININDEX=2000)
└── C9300-NM-8X (INDEX=2110, CONTAINEDININDEX=2061, SERIAL=SN_MODULE_2) ← FRU
Each module must be linked to the correct stack member (matched via chassis
SERIAL against the NetworkEquipment already in GLPI), not just to the
top-level stack device.
Proposed behavior
For each COMPONENT where FRU=1 AND MODEL is set AND SERIAL is set,
create or update a NetworkEquipment asset in GLPI linked to its parent switch
or stack member. Modules without MODEL or SERIAL (fixed backplane modules,
containers) should be ignored.
Proof of concept
The following logic (currently implemented as a third-party plugin using the
proposed glpiinventory_post_network_inventory hook, see PR #XXX) works
correctly in production on GLPI 11.0.6:
// Build parent index map for hierarchy traversal
$parent_map = [];
foreach ($components as $component) {
if (property_exists($component, 'index')) {
$parent_map[$component->index] = $component->contained_index ?? 0;
}
}
// Walk up the tree to find the chassis index for a given component
$get_chassis_index = function (int $index) use (&$get_chassis_index, $parent_map): int {
$parent = $parent_map[$index] ?? 0;
if ($parent === 0 || $parent === 1) {
return $index;
}
return $get_chassis_index($parent);
};
// Collect FRU modules, grouped by chassis
$modules_per_chassis = [];
foreach ($components as $component) {
if (
($component->type ?? '') === 'module' &&
($component->fru ?? 0) == 1 &&
!empty($component->serial) &&
!empty($component->model)
) {
$chassis_index = $get_chassis_index($component->index);
$modules_per_chassis[$chassis_index][] = $component;
}
}
// Match chassis to the correct NetworkEquipment via serial (stack-aware)
foreach ($stack_members as $member_ne) {
$chassis_index = /* find chassis index whose SERIAL matches $member_ne->fields['serial'] */;
foreach ($modules_per_chassis[$chassis_index] ?? [] as $mod) {
// create or update NetworkEquipment for $mod, link to $member_ne
}
}
Tested on
glpiinventory 1.6.7 / GLPI 11.0.6 / Cisco Catalyst C9300-48P stack (2 members)
Summary
glpiinventory collects hardware module data from network switches via SNMP
and stores it in
network_components(XML:<COMPONENT>elements). However,this data is currently not used to create inventory assets — it is discarded
after the parent switch is inventoried.
Data available
For a Cisco C9300 stack, glpiinventory already collects the following
component structure via SNMP:
Fields available per module:
TYPE— component type (module,chassis,stack,container,other)FRU—1= Field Replaceable Unit (real hardware asset),2= non-replaceableMODEL— hardware model (e.g.C9300-NM-8X,C3850-NM-4-10G)SERIAL— unique serial numberREVISION— hardware revisionCONTAINEDININDEX— index of the parent component (allows building the hierarchy)Stack support
A stacked switch is represented as a single
NetworkEquipmentin GLPI butphysically consists of multiple chassis, each with their own expansion modules.
The
CONTAINEDININDEXtree allows resolving which module belongs to whichstack member:
Each module must be linked to the correct stack member (matched via chassis
SERIAL against the NetworkEquipment already in GLPI), not just to the
top-level stack device.
Proposed behavior
For each
COMPONENTwhereFRU=1ANDMODELis set ANDSERIALis set,create or update a
NetworkEquipmentasset in GLPI linked to its parent switchor stack member. Modules without MODEL or SERIAL (fixed backplane modules,
containers) should be ignored.
Proof of concept
The following logic (currently implemented as a third-party plugin using the
proposed
glpiinventory_post_network_inventoryhook, see PR #XXX) workscorrectly in production on GLPI 11.0.6:
Tested on
glpiinventory 1.6.7 / GLPI 11.0.6 / Cisco Catalyst C9300-48P stack (2 members)