Skip to content

Commit 554bbbf

Browse files
Merge pull request #2752 from alegacy/feature/save-lldp-information
✨ Capture and store LLDP data in HardwareData
2 parents 6d812ed + 9599083 commit 554bbbf

File tree

9 files changed

+295
-57
lines changed

9 files changed

+295
-57
lines changed

apis/metal3.io/v1alpha1/baremetalhost_types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,21 @@ type VLAN struct {
678678
Name string `json:"name,omitempty"`
679679
}
680680

681+
// LLDP represents Link Layer Discovery Protocol data for a network interface.
682+
type LLDP struct {
683+
// The switch chassis ID from LLDP
684+
// +optional
685+
SwitchID string `json:"switchID,omitempty"`
686+
687+
// The switch port ID from LLDP
688+
// +optional
689+
PortID string `json:"portID,omitempty"`
690+
691+
// The switch system name from LLDP
692+
// +optional
693+
SwitchSystemName string `json:"switchSystemName,omitempty"`
694+
}
695+
681696
// NIC describes one network interface on the host.
682697
type NIC struct {
683698
// The name of the network interface, e.g. "en0"
@@ -707,6 +722,10 @@ type NIC struct {
707722

708723
// Whether the NIC is PXE Bootable
709724
PXE bool `json:"pxe,omitempty"`
725+
726+
// LLDP data for this interface
727+
// +optional
728+
LLDP *LLDP `json:"lldp,omitempty"`
710729
}
711730

712731
// Firmware describes the firmware on the host.

apis/metal3.io/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/base/crds/bases/metal3.io_baremetalhosts.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,19 @@ spec:
716716
if one is present. If both IPv4 and IPv6 addresses are present in a
717717
dual-stack environment, two nics will be output, one with each IP.
718718
type: string
719+
lldp:
720+
description: LLDP data for this interface
721+
properties:
722+
portID:
723+
description: The switch port ID from LLDP
724+
type: string
725+
switchID:
726+
description: The switch chassis ID from LLDP
727+
type: string
728+
switchSystemName:
729+
description: The switch system name from LLDP
730+
type: string
731+
type: object
719732
mac:
720733
description: The device MAC address
721734
pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'

config/base/crds/bases/metal3.io_hardwaredata.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ spec:
9797
if one is present. If both IPv4 and IPv6 addresses are present in a
9898
dual-stack environment, two nics will be output, one with each IP.
9999
type: string
100+
lldp:
101+
description: LLDP data for this interface
102+
properties:
103+
portID:
104+
description: The switch port ID from LLDP
105+
type: string
106+
switchID:
107+
description: The switch chassis ID from LLDP
108+
type: string
109+
switchSystemName:
110+
description: The switch system name from LLDP
111+
type: string
112+
type: object
100113
mac:
101114
description: The device MAC address
102115
pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'

config/render/capm3.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,19 @@ spec:
716716
if one is present. If both IPv4 and IPv6 addresses are present in a
717717
dual-stack environment, two nics will be output, one with each IP.
718718
type: string
719+
lldp:
720+
description: LLDP data for this interface
721+
properties:
722+
portID:
723+
description: The switch port ID from LLDP
724+
type: string
725+
switchID:
726+
description: The switch chassis ID from LLDP
727+
type: string
728+
switchSystemName:
729+
description: The switch system name from LLDP
730+
type: string
731+
type: object
719732
mac:
720733
description: The device MAC address
721734
pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'
@@ -1631,6 +1644,19 @@ spec:
16311644
if one is present. If both IPv4 and IPv6 addresses are present in a
16321645
dual-stack environment, two nics will be output, one with each IP.
16331646
type: string
1647+
lldp:
1648+
description: LLDP data for this interface
1649+
properties:
1650+
portID:
1651+
description: The switch port ID from LLDP
1652+
type: string
1653+
switchID:
1654+
description: The switch chassis ID from LLDP
1655+
type: string
1656+
switchSystemName:
1657+
description: The switch system name from LLDP
1658+
type: string
1659+
type: object
16341660
mac:
16351661
description: The device MAC address
16361662
pattern: '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'

internal/controller/metal3.io/baremetalhost_controller_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,42 @@ func TestInspectEnabled(t *testing.T) {
579579
assert.NotNil(t, host.Status.HardwareDetails)
580580
}
581581

582+
// TestInspectLLDPData ensures that LLDP data is removed from BareMetalHost status
583+
// but retained in HardwareData resource.
584+
func TestInspectLLDPData(t *testing.T) {
585+
host := newDefaultHost(t)
586+
r := newTestReconciler(t, host)
587+
588+
// Wait for inspection to complete
589+
waitForProvisioningState(t, r, host, metal3api.StatePreparing)
590+
591+
// Verify that the BMH status has hardware details
592+
assert.NotNil(t, host.Status.HardwareDetails, "Hardware details should not be nil")
593+
assert.Len(t, host.Status.HardwareDetails.NIC, 2, "Should have 2 NICs")
594+
595+
// Verify that HardwareData resource was created with LLDP data intact
596+
hardwareData := &metal3api.HardwareData{}
597+
hardwareDataKey := client.ObjectKey{
598+
Name: host.Name,
599+
Namespace: host.Namespace,
600+
}
601+
err := r.Client.Get(t.Context(), hardwareDataKey, hardwareData)
602+
require.NoError(t, err, "HardwareData should be created")
603+
assert.NotNil(t, hardwareData.Spec.HardwareDetails, "HardwareData should have hardware details")
604+
assert.Len(t, hardwareData.Spec.HardwareDetails.NIC, 2, "HardwareData should have 2 NICs")
605+
606+
// Verify LLDP data is present in HardwareData
607+
assert.NotNil(t, hardwareData.Spec.HardwareDetails.NIC[0].LLDP, "LLDP data should be present in HardwareData for NIC 0")
608+
assert.Equal(t, "aa:bb:cc:dd:ee:ff", hardwareData.Spec.HardwareDetails.NIC[0].LLDP.SwitchID)
609+
assert.Equal(t, "Ethernet1/1", hardwareData.Spec.HardwareDetails.NIC[0].LLDP.PortID)
610+
assert.Equal(t, "switch01.example.com", hardwareData.Spec.HardwareDetails.NIC[0].LLDP.SwitchSystemName)
611+
612+
assert.NotNil(t, hardwareData.Spec.HardwareDetails.NIC[1].LLDP, "LLDP data should be present in HardwareData for NIC 1")
613+
assert.Equal(t, "ff:ee:dd:cc:bb:aa", hardwareData.Spec.HardwareDetails.NIC[1].LLDP.SwitchID)
614+
assert.Equal(t, "Ethernet1/2", hardwareData.Spec.HardwareDetails.NIC[1].LLDP.PortID)
615+
assert.Equal(t, "switch02.example.com", hardwareData.Spec.HardwareDetails.NIC[1].LLDP.SwitchSystemName)
616+
}
617+
582618
// TestAddFinalizers ensures that the finalizers for the host are
583619
// updated as part of reconciling it.
584620
func TestAddFinalizers(t *testing.T) {

pkg/provisioner/fixture/fixture.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@ func (p *fixtureProvisioner) InspectHardware(_ provisioner.InspectData, _, _, _
171171
IP: "192.168.100.1",
172172
SpeedGbps: 1,
173173
PXE: true,
174+
LLDP: &metal3api.LLDP{
175+
SwitchID: "aa:bb:cc:dd:ee:ff",
176+
PortID: "Ethernet1/1",
177+
SwitchSystemName: "switch01.example.com",
178+
},
174179
},
175180
{
176181
Name: "nic-2",
@@ -179,6 +184,11 @@ func (p *fixtureProvisioner) InspectHardware(_ provisioner.InspectData, _, _, _
179184
IP: "192.168.100.2",
180185
SpeedGbps: 1,
181186
PXE: false,
187+
LLDP: &metal3api.LLDP{
188+
SwitchID: "ff:ee:dd:cc:bb:aa",
189+
PortID: "Ethernet1/2",
190+
SwitchSystemName: "switch02.example.com",
191+
},
182192
},
183193
},
184194
Storage: []metal3api.Storage{

pkg/provisioner/ironic/hardwaredetails/hardwaredetails.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,42 @@ func getVLANs(lldp map[string]interface{}) (vlans []metal3api.VLAN, vlanid metal
5353
return
5454
}
5555

56+
func getLLDPData(lldp map[string]interface{}) *metal3api.LLDP {
57+
if lldp == nil {
58+
return nil
59+
}
60+
61+
lldpData := &metal3api.LLDP{}
62+
hasData := false
63+
64+
if val, ok := lldp["switch_chassis_id"].(string); ok && val != "" {
65+
lldpData.SwitchID = val
66+
hasData = true
67+
}
68+
if val, ok := lldp["switch_port_id"].(string); ok && val != "" {
69+
lldpData.PortID = val
70+
hasData = true
71+
}
72+
if val, ok := lldp["switch_system_name"].(string); ok && val != "" {
73+
lldpData.SwitchSystemName = val
74+
hasData = true
75+
}
76+
77+
if !hasData {
78+
return nil
79+
}
80+
81+
return lldpData
82+
}
83+
5684
func getNICDetails(ifdata []inventory.InterfaceType, ironicData inventory.StandardPluginData) []metal3api.NIC {
5785
var nics []metal3api.NIC
5886
for _, intf := range ifdata {
5987
pxeEnabled := ironicData.AllInterfaces[intf.Name].PXEEnabled
6088
lldp := ironicData.ParsedLLDP[intf.Name]
6189

6290
vlans, vlanid := getVLANs(lldp)
91+
lldpData := getLLDPData(lldp)
6392
// We still store one nic even if both ips are unset
6493
// if both are set, we store two nics with each ip
6594
if intf.IPV4Address != "" || intf.IPV6Address == "" {
@@ -73,6 +102,7 @@ func getNICDetails(ifdata []inventory.InterfaceType, ironicData inventory.Standa
73102
VLANID: vlanid,
74103
SpeedGbps: intf.SpeedMbps / 1000, //nolint:mnd
75104
PXE: pxeEnabled,
105+
LLDP: lldpData,
76106
})
77107
}
78108
if intf.IPV6Address != "" {
@@ -86,6 +116,7 @@ func getNICDetails(ifdata []inventory.InterfaceType, ironicData inventory.Standa
86116
VLANID: vlanid,
87117
SpeedGbps: intf.SpeedMbps / 1000, //nolint:mnd
88118
PXE: pxeEnabled,
119+
LLDP: lldpData,
89120
})
90121
}
91122
}

0 commit comments

Comments
 (0)