From 70115c50b035716066f8a8683e6717cef7fe0464 Mon Sep 17 00:00:00 2001 From: fst0 Date: Tue, 23 May 2023 16:15:21 +0200 Subject: [PATCH 01/19] Update anx-ci.yml --- .github/workflows/anx-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/anx-ci.yml b/.github/workflows/anx-ci.yml index a08f3e19..9ce3d46e 100644 --- a/.github/workflows/anx-ci.yml +++ b/.github/workflows/anx-ci.yml @@ -56,15 +56,15 @@ jobs: - uses: actions/setup-python@v4 - - name: publish anx-prod to s3://$S3_BUCKET/junos_images/junos_exporter/$GITHUB_REF_NAME/junos_exporter + - name: publish anx-prod to s3://$S3_BUCKET/public/junos_exporter/$GITHUB_REF_NAME/junos_exporter run: | pip install s4cmd - s4cmd put --endpoint-url https://$S3_URL -f junos_exporter s3://$S3_BUCKET/junos_images/junos_exporter/$GITHUB_REF_NAME/junos_exporter + s4cmd put --endpoint-url https://$S3_URL -f junos_exporter s3://$S3_BUCKET/public/junos_exporter/$GITHUB_REF_NAME/junos_exporter if: github.ref_type == 'tag' || github.ref == 'refs/heads/anx-prod' - - name: "publish feature-branch to s3://$S3_BUCKET/junos_images/junos_exporter/staging/junos_exporter" + - name: "publish feature-branch to s3://$S3_BUCKET/public/junos_exporter/staging/junos_exporter" run: | pip install s4cmd - s4cmd put --endpoint-url https://$S3_URL -f junos_exporter s3://$S3_BUCKET/junos_images/junos_exporter/staging/junos_exporter + s4cmd put --endpoint-url https://$S3_URL -f junos_exporter s3://$S3_BUCKET/public/junos_exporter/staging/junos_exporter # value only there if pull_request or pull_request_target if: github.head_ref From 5cc4b0110184b110651d0d4bb0b51b9fb64060d3 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 7 Jun 2023 18:50:32 +0200 Subject: [PATCH 02/19] implement structs for show chassis hardware xml --- pkg/features/interfacediagnostics/rpc.go | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index ccde663b..eac2c0b1 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -1,5 +1,47 @@ package interfacediagnostics +type chassisHardware struct { + ChassisInventory chassisInventory `xml:"chassis-inventory"` +} + +type chassisInventory struct { + Chassis chassis `xml:"chassis"` +} + +type chassis struct { + Name string `xml:"name"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + ChassisModule []chassisModule `xml:"chassis-module"` +} + +type chassisModule struct { + Name string `xml:"name"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + CleiCode string `xml:"clei-code"` + ModelNumber string `xml:"model-number"` + ChassisSubModule []chassisSubModule `xml:"chassis-sub-module"` +} + +type chassisSubModule struct { + Name string `xml:"name"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + CleiCode string `xml:"clei-code"` + ModelNumber string `xml:"model-number"` + ChassisSubSubModule []chassisSubSubModule `xml:"chassis-sub-sub-module"` +} +type chassisSubSubModule struct { + Name string `xml:"name"` + Version string `xml:"version"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` +} + type result struct { Information struct { Diagnostics []phyDiagInterface `xml:"physical-interface"` From 8ef44f8678bba5922907ad688a615d3abf29daca Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 14 Jun 2023 11:22:51 +0200 Subject: [PATCH 03/19] make new gauge for interface_transceiver (show chassis hardware) --- .../interfacediagnostics/collector.go | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 77053b29..884bdedc 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -62,6 +62,8 @@ type interfaceDiagnosticsCollector struct { rxSignalAvgOpticalPowerDesc *prometheus.Desc rxSignalAvgOpticalPowerDbmDesc *prometheus.Desc + + transceiverDesc *prometheus.Desc } // NewCollector creates a new collector @@ -127,6 +129,9 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold_dbm", "Laser rx power low alarm threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) + + transceiver_labels := []string{"target", "slot", "version", "part_number", "serial_number", "description"} + c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } // Describe describes the metrics @@ -171,6 +176,8 @@ func (c *interfaceDiagnosticsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.rxSignalAvgOpticalPowerDesc ch <- c.rxSignalAvgOpticalPowerDbmDesc + + ch <- c.transceiverDesc } // Collect collects metrics from JunOS @@ -180,6 +187,15 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr return err } + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + for _, t := range transceiverInfo { + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description) + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } + // add satellite details if feature is enabled if client.Satellite { diagnosticsSatellite, err := c.interfaceDiagnosticsSatellite(client) @@ -263,6 +279,42 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) return interfaceDiagnosticsFromRPCResult(x), nil } +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*chassisSubSubModule, error) { + var x = chassisHardware{} + err := client.RunCommandAndParse("show chassis hardware", &x) + if err != nil { + return nil, err + } + + return transceiverInfoFromRPCResult(x), nil +} + +func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { + transceiverList := make([]*chassisSubSubModule, 0) + + var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule + for _, module := range chassisModules { + for _, subModule := range module.ChassisSubModule { + for _, subSubModule := range subModule.ChassisSubSubModule { + i := strings.Split(module.Name, " ")[1] + j := strings.Split(subModule.Name, " ")[1] + k := strings.Split(subSubModule.Name, " ")[1] + + id := i + "/" + j + "/" + k + transceiver := &chassisSubSubModule{ + Name: id, + Version: subSubModule.Version, + PartNumber: subSubModule.PartNumber, + SerialNumber: subSubModule.SerialNumber, + Description: subSubModule.Description, + } + transceiverList = append(transceiverList, transceiver) + } + } + } + return transceiverList +} + func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rpc.Client) ([]*interfaceDiagnostics, error) { var x = result{} From 26314b3ea4221cfdc445f2dbe5a25dd5a0bb0d9a Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 5 Jul 2023 10:17:10 +0200 Subject: [PATCH 04/19] only include transceiver if it is an actual transceiver (didnt check before) --- pkg/features/interfacediagnostics/collector.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 884bdedc..a9c48c79 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -300,6 +300,11 @@ func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSub j := strings.Split(subModule.Name, " ")[1] k := strings.Split(subSubModule.Name, " ")[1] + name := strings.Split(subSubModule.Name, " ")[0] + if name != "Xcvr" { + continue + } + id := i + "/" + j + "/" + k transceiver := &chassisSubSubModule{ Name: id, From 73be159e67889a1e3c722a5affef9e960e246087 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 5 Jul 2023 16:42:09 +0200 Subject: [PATCH 05/19] combined "show chassis hardware" with "interface diagnostics optics" --- .../interfacediagnostics/collector.go | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index a9c48c79..43663d7e 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -130,7 +130,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "slot", "version", "part_number", "serial_number", "description"} + transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -187,15 +187,6 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr return err } - transceiverInfo, err := c.chassisHardwareInfos(client) - if err != nil { - return err - } - for _, t := range transceiverInfo { - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description) - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) - } - // add satellite details if feature is enabled if client.Satellite { diagnosticsSatellite, err := c.interfaceDiagnosticsSatellite(client) @@ -206,7 +197,13 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr diagnostics = append(diagnostics, diagnosticsSatellite...) } + diagnostics_dict := make(map[string]*interfaceDiagnostics) + for _, d := range diagnostics { + + index := strings.Split(d.Name, "-")[1] + diagnostics_dict[index] = d + l := append(labelValues, d.Name) l = append(l, c.labels.ValuesForInterface(client.Device(), d.Name)...) @@ -266,6 +263,24 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr } } + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + + for _, t := range transceiverInfo { + + if diag, hit := diagnostics_dict[t.Name]; hit { + t.Name = diag.Name + continue + } + if t.Description == "SFP-T" { + t.Name = "ge-" + t.Name + continue + } + t.Name = "slot-" + t.Name + } + return nil } From d45951c5e2f91eab9ab88616e549c4d07b1098f5 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Thu, 6 Jul 2023 14:12:39 +0200 Subject: [PATCH 06/19] add show interfaces media info as datatype add port speed from interfaces media to Metric set value of metric to 1 only if both operstatus and adminstatus 1 --- .../interfacediagnostics/collector.go | 76 +++++++++++++++---- .../interfacediagnostics/interface_stats.go | 6 ++ pkg/features/interfacediagnostics/rpc.go | 46 +++++++++++ 3 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 pkg/features/interfacediagnostics/interface_stats.go diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 43663d7e..2514d270 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -130,7 +130,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description"} + transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description", "speed"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -193,7 +193,6 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr if err != nil { return err } - diagnostics = append(diagnostics, diagnosticsSatellite...) } @@ -263,22 +262,44 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr } } + ifMediaDict, err := c.interfaceInformation(client) + if err != nil { + return err + } + transceiverInfo, err := c.chassisHardwareInfos(client) if err != nil { return err } - for _, t := range transceiverInfo { + interfaceDictList := make(map[string]*interfaceStatsAggregate) + for _, t := range transceiverInfo { if diag, hit := diagnostics_dict[t.Name]; hit { t.Name = diag.Name - continue - } - if t.Description == "SFP-T" { + } else if t.Description == "SFP-T" { t.Name = "ge-" + t.Name + } else { + t.Name = "slot-" + t.Name + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, "") + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) continue } - t.Name = "slot-" + t.Name + + s := interfaceStatsAggregate{ + ChassisHardwareInfo: t, + InterfacesMediaInfo: (ifMediaDict[t.Name]), + } + + interfaceDictList[t.Name] = &s + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, s.InterfacesMediaInfo.Speed) + + if s.InterfacesMediaInfo.AdminStatus == "up" && s.InterfacesMediaInfo.OperStatus == "up" { + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } else { + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) + } + } return nil @@ -304,23 +325,46 @@ func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) return transceiverInfoFromRPCResult(x), nil } +func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { + var x = interfacesMediaStruct{} + err := client.RunCommandAndParse("show interfaces media", &x) + if err != nil { + return nil, err + } + + return interfaceMediaInfoFromRPCResult(&x.InterfaceInformation.PhysicalInterface), nil +} + +func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) map[string]*physicalInterface { + + interfaceMediaDict := make(map[string]*physicalInterface) + + for _, i := range *interfaceMediaList { + iface := i + interfaceMediaDict[iface.Name] = &iface + } + + return interfaceMediaDict +} + func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { transceiverList := make([]*chassisSubSubModule, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule for _, module := range chassisModules { + if strings.Split(module.Name, " ")[0] != "FPC" { + continue + } for _, subModule := range module.ChassisSubModule { + if strings.Split(subModule.Name, " ")[0] != "PIC" { + continue + } for _, subSubModule := range subModule.ChassisSubSubModule { - i := strings.Split(module.Name, " ")[1] - j := strings.Split(subModule.Name, " ")[1] - k := strings.Split(subSubModule.Name, " ")[1] - - name := strings.Split(subSubModule.Name, " ")[0] - if name != "Xcvr" { - continue - } + fpc := strings.Split(module.Name, " ")[1] + pic := strings.Split(subModule.Name, " ")[1] + port := strings.Split(subSubModule.Name, " ")[1] - id := i + "/" + j + "/" + k + id := fpc + "/" + pic + "/" + port transceiver := &chassisSubSubModule{ Name: id, Version: subSubModule.Version, diff --git a/pkg/features/interfacediagnostics/interface_stats.go b/pkg/features/interfacediagnostics/interface_stats.go new file mode 100644 index 00000000..7c761ffb --- /dev/null +++ b/pkg/features/interfacediagnostics/interface_stats.go @@ -0,0 +1,6 @@ +package interfacediagnostics + +type interfaceStatsAggregate struct { + ChassisHardwareInfo *chassisSubSubModule + InterfacesMediaInfo *physicalInterface +} diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index eac2c0b1..6412578a 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -1,5 +1,51 @@ package interfacediagnostics +type interfacesMediaStruct struct { + InterfaceInformation struct { + PhysicalInterface []physicalInterface `xml:"physical-interface"` + } `xml:"interface-information"` +} + +type physicalInterface struct { + Name string `xml:"name"` + AdminStatus string `xml:"admin-status"` + OperStatus string `xml:"oper-status"` + LocalIndex string `xml:"local-index"` + SnmpIndex string `xml:"snmp-index"` + IfType string `xml:"if-type"` + LinkLevelType string `xml:"link-level-type"` + Mtu string `xml:"mtu"` + Speed string `xml:"speed"` + LinkType string `xml:"link-type"` + InterfaceFlapped struct { + Seconds uint64 `xml:"seconds,attr"` + Value string `xml:",chardata"` + } `xml:"interface-flapped"` + IfDeviceFlags ifDeviceFlags `xml:"if-device-flags"` + Stats trafficStat `xml:"traffic-statistics"` +} + +type trafficStat struct { + InputBytes uint64 `xml:"input-bytes"` + InputPackets uint64 `xml:"input-packets"` + OutputBytes uint64 `xml:"output-bytes"` + OutputPackets uint64 `xml:"output-packets"` + IPv6Traffic ipv6Stat `xml:"ipv6-transit-statistics"` +} +type ipv6Stat struct { + InputBytes uint64 `xml:"input-bytes"` + InputPackets uint64 `xml:"input-packets"` + OutputBytes uint64 `xml:"output-bytes"` + OutputPackets uint64 `xml:"output-packets"` +} + +type ifDeviceFlags struct { + Present bool `xml:"ifdf-present"` + Running bool `xml:"ifdf-running"` + Loopback bool `xml:"ifdf-loopback"` + Down bool `xml:"ifdf-down"` +} + type chassisHardware struct { ChassisInventory chassisInventory `xml:"chassis-inventory"` } From d5b43f304a028d5b246e9ddf8c091731480ad0b0 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 19 Jul 2023 16:29:25 +0200 Subject: [PATCH 07/19] add show chassis pic port info --- .../interfacediagnostics/collector.go | 125 ++++++++++-------- .../interfacediagnostics/interface_stats.go | 5 +- pkg/features/interfacediagnostics/rpc.go | 32 +++++ 3 files changed, 104 insertions(+), 58 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 2514d270..2064cd9a 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -2,6 +2,7 @@ package interfacediagnostics import ( "encoding/xml" + "fmt" "log" "math" "strconv" @@ -130,7 +131,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description", "speed"} + transceiver_labels := []string{"target", "name", "serial_number", "description", "speed", "fiber_type", "vendor_name", "vendor_part_number", "wavelength"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -262,46 +263,10 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr } } - ifMediaDict, err := c.interfaceInformation(client) - if err != nil { - return err - } - - transceiverInfo, err := c.chassisHardwareInfos(client) + err = createTransceiverMetrics(c, client, diagnostics_dict, ch, labelValues) if err != nil { return err } - - interfaceDictList := make(map[string]*interfaceStatsAggregate) - - for _, t := range transceiverInfo { - if diag, hit := diagnostics_dict[t.Name]; hit { - t.Name = diag.Name - } else if t.Description == "SFP-T" { - t.Name = "ge-" + t.Name - } else { - t.Name = "slot-" + t.Name - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, "") - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) - continue - } - - s := interfaceStatsAggregate{ - ChassisHardwareInfo: t, - InterfacesMediaInfo: (ifMediaDict[t.Name]), - } - - interfaceDictList[t.Name] = &s - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, s.InterfacesMediaInfo.Speed) - - if s.InterfacesMediaInfo.AdminStatus == "up" && s.InterfacesMediaInfo.OperStatus == "up" { - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) - } else { - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) - } - - } - return nil } @@ -315,14 +280,14 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) return interfaceDiagnosticsFromRPCResult(x), nil } -func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*chassisSubSubModule, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { var x = chassisHardware{} err := client.RunCommandAndParse("show chassis hardware", &x) if err != nil { return nil, err } - return transceiverInfoFromRPCResult(x), nil + return transceiverInfoFromRPCResult(client, x) } func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { @@ -347,8 +312,8 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma return interfaceMediaDict } -func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { - transceiverList := make([]*chassisSubSubModule, 0) +func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { + transceiverList := make([]*transceiverInformation, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule for _, module := range chassisModules { @@ -359,24 +324,72 @@ func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSub if strings.Split(subModule.Name, " ")[0] != "PIC" { continue } - for _, subSubModule := range subModule.ChassisSubSubModule { - fpc := strings.Split(module.Name, " ")[1] - pic := strings.Split(subModule.Name, " ")[1] - port := strings.Split(subSubModule.Name, " ")[1] - - id := fpc + "/" + pic + "/" + port - transceiver := &chassisSubSubModule{ - Name: id, - Version: subSubModule.Version, - PartNumber: subSubModule.PartNumber, - SerialNumber: subSubModule.SerialNumber, - Description: subSubModule.Description, + fpc := strings.Split(module.Name, " ")[1] + pic := strings.Split(subModule.Name, " ")[1] + + picPortsInformation, err := getPicPortsFromRPCResult(client, fpc, pic) + if err != nil { + return nil, err + } + + for port, subSubModule := range subModule.ChassisSubSubModule { + port_name := strings.Split(subSubModule.Name, " ")[1] + + id := fpc + "/" + pic + "/" + port_name + transceiver := transceiverInformation{ + Name: id, + ChassisHardwareInfo: &subSubModule, + PicPort: &picPortsInformation[port], } - transceiverList = append(transceiverList, transceiver) + transceiverList = append(transceiverList, &transceiver) } } } - return transceiverList + return transceiverList, nil +} + +func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { + var x = fPCInformationStruct{} + command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) + err := client.RunCommandAndParse(command, &x) + if err != nil { + return nil, err + } + + return x.FPCInformation.FPC.PicDetail.PicPortInfoList, nil +} + +func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { + + ifMediaDict, err := c.interfaceInformation(client) + if err != nil { + return err + } + + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + + for _, t := range transceiverInfo { + chassisInfo := t.ChassisHardwareInfo + port_speed := "0" + + if diag, hit := diagnostics_dict[t.Name]; hit { + t.Name = diag.Name + port_speed = ifMediaDict[t.Name].Speed + } else if t.ChassisHardwareInfo.Description == "SFP-T" { + t.Name = "ge-" + t.Name + port_speed = ifMediaDict[t.Name].Speed + } else { + t.Name = "slot-" + t.Name + } + + transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength) + + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } + return nil } func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rpc.Client) ([]*interfaceDiagnostics, error) { diff --git a/pkg/features/interfacediagnostics/interface_stats.go b/pkg/features/interfacediagnostics/interface_stats.go index 7c761ffb..3cfa8fb4 100644 --- a/pkg/features/interfacediagnostics/interface_stats.go +++ b/pkg/features/interfacediagnostics/interface_stats.go @@ -1,6 +1,7 @@ package interfacediagnostics -type interfaceStatsAggregate struct { +type transceiverInformation struct { + Name string ChassisHardwareInfo *chassisSubSubModule - InterfacesMediaInfo *physicalInterface + PicPort *picPort } diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index 6412578a..abbe6c47 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -1,5 +1,37 @@ package interfacediagnostics +type fPCInformationStruct struct { + FPCInformation fPCInformation `xml:"fpc-information"` +} +type fPCInformation struct { + FPC fPC `xml:"fpc"` +} + +type fPC struct { + PicDetail picDetail `xml:"pic-detail"` +} + +type picDetail struct { + Slot int `xml:"slot"` + PicSlot int `xml:"pic-slot"` + PicType string `xml:"pic-type"` + State string `xml:"state"` + PicVersion string `xml:"pic-version"` + UpTime string `xml:"up-time"` + PicPortInfoList []picPort `xml:"port-information>port"` +} + +type picPort struct { + PortNumber int `xml:"port-number"` + CableType string `xml:"cable-type"` + FiberMode string `xml:"fiber-mode"` + SFPVendorName string `xml:"sfp-vendor-name"` + SFPVendorPno string `xml:"sfp-vendor-pno"` + Wavelength string `xml:"wavelength"` + SFPVendorFwVer string `xml:"sfp-vendor-fw-ver"` + SFPJnprVer string `xml:"sfp-jnpr-ver"` +} + type interfacesMediaStruct struct { InterfaceInformation struct { PhysicalInterface []physicalInterface `xml:"physical-interface"` From 67e336af2ef4f324f677259b0c9ba1b42aa27ab8 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 19 Jul 2023 18:59:46 +0200 Subject: [PATCH 08/19] fix bug, change transceiver metric so that it uses show interface media for naming --- .../interfacediagnostics/collector.go | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 2064cd9a..7215cb06 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -270,27 +270,7 @@ func (c *interfaceDiagnosticsCollector) Collect(client *rpc.Client, ch chan<- pr return nil } -func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) ([]*interfaceDiagnostics, error) { - var x = result{} - err := client.RunCommandAndParse("show interfaces diagnostics optics", &x) - if err != nil { - return nil, err - } - - return interfaceDiagnosticsFromRPCResult(x), nil -} - -func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { - var x = chassisHardware{} - err := client.RunCommandAndParse("show chassis hardware", &x) - if err != nil { - return nil, err - } - - return transceiverInfoFromRPCResult(client, x) -} - -func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { +func (c *interfaceDiagnosticsCollector) interfaceMediaInfo(client *rpc.Client) (map[string]*physicalInterface, error) { var x = interfacesMediaStruct{} err := client.RunCommandAndParse("show interfaces media", &x) if err != nil { @@ -305,14 +285,26 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma interfaceMediaDict := make(map[string]*physicalInterface) for _, i := range *interfaceMediaList { - iface := i - interfaceMediaDict[iface.Name] = &iface + if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") { + iface := i + afterThirdIndex := iface.Name[3:] + interfaceMediaDict[afterThirdIndex] = &iface + } } - return interfaceMediaDict } -func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { + var x = chassisHardware{} + err := client.RunCommandAndParse("show chassis hardware", &x) + if err != nil { + return nil, err + } + + return c.transceiverInfoFromRPCResult(client, x) +} + +func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { transceiverList := make([]*transceiverInformation, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule @@ -327,18 +319,18 @@ func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHar fpc := strings.Split(module.Name, " ")[1] pic := strings.Split(subModule.Name, " ")[1] - picPortsInformation, err := getPicPortsFromRPCResult(client, fpc, pic) + picPortsInformation, err := c.getPicPortsFromRPCResult(client, fpc, pic) if err != nil { return nil, err } for port, subSubModule := range subModule.ChassisSubSubModule { port_name := strings.Split(subSubModule.Name, " ")[1] - + subSubModule_pointer := subSubModule id := fpc + "/" + pic + "/" + port_name transceiver := transceiverInformation{ Name: id, - ChassisHardwareInfo: &subSubModule, + ChassisHardwareInfo: &subSubModule_pointer, PicPort: &picPortsInformation[port], } transceiverList = append(transceiverList, &transceiver) @@ -348,7 +340,7 @@ func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHar return transceiverList, nil } -func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { +func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { var x = fPCInformationStruct{} command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) err := client.RunCommandAndParse(command, &x) @@ -361,7 +353,7 @@ func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]pic func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { - ifMediaDict, err := c.interfaceInformation(client) + ifMediaDict, err := c.interfaceMediaInfo(client) if err != nil { return err } @@ -374,20 +366,21 @@ func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Clie for _, t := range transceiverInfo { chassisInfo := t.ChassisHardwareInfo port_speed := "0" + oper_status := 0.0 - if diag, hit := diagnostics_dict[t.Name]; hit { - t.Name = diag.Name - port_speed = ifMediaDict[t.Name].Speed - } else if t.ChassisHardwareInfo.Description == "SFP-T" { - t.Name = "ge-" + t.Name - port_speed = ifMediaDict[t.Name].Speed + if media, hit := ifMediaDict[t.Name]; hit { + if media.OperStatus == "up" { + oper_status = 1.0 + } + t.Name = media.Name + port_speed = media.Speed } else { t.Name = "slot-" + t.Name } transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength) - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, oper_status, transceiver_labels...) } return nil } @@ -449,6 +442,16 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rp return interfaceDiagnosticsFromRPCResult(x), nil } +func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) ([]*interfaceDiagnostics, error) { + var x = result{} + err := client.RunCommandAndParse("show interfaces diagnostics optics", &x) + if err != nil { + return nil, err + } + + return interfaceDiagnosticsFromRPCResult(x), nil +} + func interfaceDiagnosticsFromRPCResult(res result) []*interfaceDiagnostics { diagnostics := make([]*interfaceDiagnostics, 0) From 30e8b043ee00d81d836c8adf559a69080f249625 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 26 Jul 2023 11:51:24 +0200 Subject: [PATCH 09/19] rename variable to be meaningful --- pkg/features/interfacediagnostics/collector.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 7215cb06..4dc14f64 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -287,8 +287,8 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma for _, i := range *interfaceMediaList { if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") { iface := i - afterThirdIndex := iface.Name[3:] - interfaceMediaDict[afterThirdIndex] = &iface + slotIndex := iface.Name[3:] + interfaceMediaDict[slotIndex] = &iface } } return interfaceMediaDict From 40b58b4959a69c563c2c0479f3824cd824bd3224 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 7 Jun 2023 18:50:32 +0200 Subject: [PATCH 10/19] implement structs for show chassis hardware xml --- pkg/features/interfacediagnostics/rpc.go | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index 78e8746c..0ade1296 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -2,6 +2,48 @@ package interfacediagnostics +type chassisHardware struct { + ChassisInventory chassisInventory `xml:"chassis-inventory"` +} + +type chassisInventory struct { + Chassis chassis `xml:"chassis"` +} + +type chassis struct { + Name string `xml:"name"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + ChassisModule []chassisModule `xml:"chassis-module"` +} + +type chassisModule struct { + Name string `xml:"name"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + CleiCode string `xml:"clei-code"` + ModelNumber string `xml:"model-number"` + ChassisSubModule []chassisSubModule `xml:"chassis-sub-module"` +} + +type chassisSubModule struct { + Name string `xml:"name"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` + CleiCode string `xml:"clei-code"` + ModelNumber string `xml:"model-number"` + ChassisSubSubModule []chassisSubSubModule `xml:"chassis-sub-sub-module"` +} +type chassisSubSubModule struct { + Name string `xml:"name"` + Version string `xml:"version"` + PartNumber string `xml:"part-number"` + SerialNumber string `xml:"serial-number"` + Description string `xml:"description"` +} + type result struct { Information struct { Diagnostics []phyDiagInterface `xml:"physical-interface"` From 5dfe8992d6b0af58a79e18d29fc6ae6d84147781 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 14 Jun 2023 11:22:51 +0200 Subject: [PATCH 11/19] make new gauge for interface_transceiver (show chassis hardware) --- .../interfacediagnostics/collector.go | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index f1fd0991..0eeae51b 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -6,6 +6,7 @@ import ( "encoding/xml" "log" "math" + "net/rpc" "strconv" "strings" @@ -63,6 +64,8 @@ type interfaceDiagnosticsCollector struct { rxSignalAvgOpticalPowerDesc *prometheus.Desc rxSignalAvgOpticalPowerDbmDesc *prometheus.Desc + + transceiverDesc *prometheus.Desc } // NewCollector creates a new collector @@ -128,6 +131,9 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold_dbm", "Laser rx power low alarm threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) + + transceiver_labels := []string{"target", "slot", "version", "part_number", "serial_number", "description"} + c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } // Describe describes the metrics @@ -172,6 +178,8 @@ func (c *interfaceDiagnosticsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.rxSignalAvgOpticalPowerDesc ch <- c.rxSignalAvgOpticalPowerDbmDesc + + ch <- c.transceiverDesc } // Collect collects metrics from JunOS @@ -181,6 +189,15 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan return err } + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + for _, t := range transceiverInfo { + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description) + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } + // add satellite details if feature is enabled if client.IsSatelliteEnabled() { diagnosticsSatellite, err := c.interfaceDiagnosticsSatellite(client) @@ -264,7 +281,43 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Cl return interfaceDiagnosticsFromRPCResult(x), nil } -func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client collector.Client) ([]*interfaceDiagnostics, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*chassisSubSubModule, error) { + var x = chassisHardware{} + err := client.RunCommandAndParse("show chassis hardware", &x) + if err != nil { + return nil, err + } + + return transceiverInfoFromRPCResult(x), nil +} + +func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { + transceiverList := make([]*chassisSubSubModule, 0) + + var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule + for _, module := range chassisModules { + for _, subModule := range module.ChassisSubModule { + for _, subSubModule := range subModule.ChassisSubSubModule { + i := strings.Split(module.Name, " ")[1] + j := strings.Split(subModule.Name, " ")[1] + k := strings.Split(subSubModule.Name, " ")[1] + + id := i + "/" + j + "/" + k + transceiver := &chassisSubSubModule{ + Name: id, + Version: subSubModule.Version, + PartNumber: subSubModule.PartNumber, + SerialNumber: subSubModule.SerialNumber, + Description: subSubModule.Description, + } + transceiverList = append(transceiverList, transceiver) + } + } + } + return transceiverList +} + +func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rpc.Client) ([]*interfaceDiagnostics, error) { var x = result{} // NOTE: Junos is broken and delivers incorrect XML From 22789f59af440a2725a1a6e7db0c80c6bc216bdb Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 5 Jul 2023 10:17:10 +0200 Subject: [PATCH 12/19] only include transceiver if it is an actual transceiver (didnt check before) --- pkg/features/interfacediagnostics/collector.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 0eeae51b..7eeccccf 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -302,6 +302,11 @@ func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSub j := strings.Split(subModule.Name, " ")[1] k := strings.Split(subSubModule.Name, " ")[1] + name := strings.Split(subSubModule.Name, " ")[0] + if name != "Xcvr" { + continue + } + id := i + "/" + j + "/" + k transceiver := &chassisSubSubModule{ Name: id, From 59c20de2d7e63ae3ff1e3a539005c0f212c611b8 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 5 Jul 2023 16:42:09 +0200 Subject: [PATCH 13/19] combined "show chassis hardware" with "interface diagnostics optics" --- .../interfacediagnostics/collector.go | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 7eeccccf..a40d31dc 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -132,7 +132,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "slot", "version", "part_number", "serial_number", "description"} + transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -189,15 +189,6 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan return err } - transceiverInfo, err := c.chassisHardwareInfos(client) - if err != nil { - return err - } - for _, t := range transceiverInfo { - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description) - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) - } - // add satellite details if feature is enabled if client.IsSatelliteEnabled() { diagnosticsSatellite, err := c.interfaceDiagnosticsSatellite(client) @@ -208,7 +199,13 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan diagnostics = append(diagnostics, diagnosticsSatellite...) } + diagnostics_dict := make(map[string]*interfaceDiagnostics) + for _, d := range diagnostics { + + index := strings.Split(d.Name, "-")[1] + diagnostics_dict[index] = d + l := append(labelValues, d.Name) l = append(l, c.labels.ValuesForInterface(client.Device(), d.Name)...) @@ -268,6 +265,24 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan } } + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + + for _, t := range transceiverInfo { + + if diag, hit := diagnostics_dict[t.Name]; hit { + t.Name = diag.Name + continue + } + if t.Description == "SFP-T" { + t.Name = "ge-" + t.Name + continue + } + t.Name = "slot-" + t.Name + } + return nil } From 51dd17750b0c0f7a4d1d759df4756d12d2abf8d0 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Thu, 6 Jul 2023 14:12:39 +0200 Subject: [PATCH 14/19] add show interfaces media info as datatype add port speed from interfaces media to Metric set value of metric to 1 only if both operstatus and adminstatus 1 --- .../interfacediagnostics/collector.go | 76 +++++++++++++++---- .../interfacediagnostics/interface_stats.go | 6 ++ pkg/features/interfacediagnostics/rpc.go | 46 +++++++++++ 3 files changed, 112 insertions(+), 16 deletions(-) create mode 100644 pkg/features/interfacediagnostics/interface_stats.go diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index a40d31dc..04ee331f 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -132,7 +132,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description"} + transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description", "speed"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -195,7 +195,6 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan if err != nil { return err } - diagnostics = append(diagnostics, diagnosticsSatellite...) } @@ -265,22 +264,44 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan } } + ifMediaDict, err := c.interfaceInformation(client) + if err != nil { + return err + } + transceiverInfo, err := c.chassisHardwareInfos(client) if err != nil { return err } - for _, t := range transceiverInfo { + interfaceDictList := make(map[string]*interfaceStatsAggregate) + for _, t := range transceiverInfo { if diag, hit := diagnostics_dict[t.Name]; hit { t.Name = diag.Name - continue - } - if t.Description == "SFP-T" { + } else if t.Description == "SFP-T" { t.Name = "ge-" + t.Name + } else { + t.Name = "slot-" + t.Name + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, "") + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) continue } - t.Name = "slot-" + t.Name + + s := interfaceStatsAggregate{ + ChassisHardwareInfo: t, + InterfacesMediaInfo: (ifMediaDict[t.Name]), + } + + interfaceDictList[t.Name] = &s + transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, s.InterfacesMediaInfo.Speed) + + if s.InterfacesMediaInfo.AdminStatus == "up" && s.InterfacesMediaInfo.OperStatus == "up" { + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } else { + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) + } + } return nil @@ -306,23 +327,46 @@ func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) return transceiverInfoFromRPCResult(x), nil } +func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { + var x = interfacesMediaStruct{} + err := client.RunCommandAndParse("show interfaces media", &x) + if err != nil { + return nil, err + } + + return interfaceMediaInfoFromRPCResult(&x.InterfaceInformation.PhysicalInterface), nil +} + +func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) map[string]*physicalInterface { + + interfaceMediaDict := make(map[string]*physicalInterface) + + for _, i := range *interfaceMediaList { + iface := i + interfaceMediaDict[iface.Name] = &iface + } + + return interfaceMediaDict +} + func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { transceiverList := make([]*chassisSubSubModule, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule for _, module := range chassisModules { + if strings.Split(module.Name, " ")[0] != "FPC" { + continue + } for _, subModule := range module.ChassisSubModule { + if strings.Split(subModule.Name, " ")[0] != "PIC" { + continue + } for _, subSubModule := range subModule.ChassisSubSubModule { - i := strings.Split(module.Name, " ")[1] - j := strings.Split(subModule.Name, " ")[1] - k := strings.Split(subSubModule.Name, " ")[1] - - name := strings.Split(subSubModule.Name, " ")[0] - if name != "Xcvr" { - continue - } + fpc := strings.Split(module.Name, " ")[1] + pic := strings.Split(subModule.Name, " ")[1] + port := strings.Split(subSubModule.Name, " ")[1] - id := i + "/" + j + "/" + k + id := fpc + "/" + pic + "/" + port transceiver := &chassisSubSubModule{ Name: id, Version: subSubModule.Version, diff --git a/pkg/features/interfacediagnostics/interface_stats.go b/pkg/features/interfacediagnostics/interface_stats.go new file mode 100644 index 00000000..7c761ffb --- /dev/null +++ b/pkg/features/interfacediagnostics/interface_stats.go @@ -0,0 +1,6 @@ +package interfacediagnostics + +type interfaceStatsAggregate struct { + ChassisHardwareInfo *chassisSubSubModule + InterfacesMediaInfo *physicalInterface +} diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index 0ade1296..5bd1c00f 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -2,6 +2,52 @@ package interfacediagnostics +type interfacesMediaStruct struct { + InterfaceInformation struct { + PhysicalInterface []physicalInterface `xml:"physical-interface"` + } `xml:"interface-information"` +} + +type physicalInterface struct { + Name string `xml:"name"` + AdminStatus string `xml:"admin-status"` + OperStatus string `xml:"oper-status"` + LocalIndex string `xml:"local-index"` + SnmpIndex string `xml:"snmp-index"` + IfType string `xml:"if-type"` + LinkLevelType string `xml:"link-level-type"` + Mtu string `xml:"mtu"` + Speed string `xml:"speed"` + LinkType string `xml:"link-type"` + InterfaceFlapped struct { + Seconds uint64 `xml:"seconds,attr"` + Value string `xml:",chardata"` + } `xml:"interface-flapped"` + IfDeviceFlags ifDeviceFlags `xml:"if-device-flags"` + Stats trafficStat `xml:"traffic-statistics"` +} + +type trafficStat struct { + InputBytes uint64 `xml:"input-bytes"` + InputPackets uint64 `xml:"input-packets"` + OutputBytes uint64 `xml:"output-bytes"` + OutputPackets uint64 `xml:"output-packets"` + IPv6Traffic ipv6Stat `xml:"ipv6-transit-statistics"` +} +type ipv6Stat struct { + InputBytes uint64 `xml:"input-bytes"` + InputPackets uint64 `xml:"input-packets"` + OutputBytes uint64 `xml:"output-bytes"` + OutputPackets uint64 `xml:"output-packets"` +} + +type ifDeviceFlags struct { + Present bool `xml:"ifdf-present"` + Running bool `xml:"ifdf-running"` + Loopback bool `xml:"ifdf-loopback"` + Down bool `xml:"ifdf-down"` +} + type chassisHardware struct { ChassisInventory chassisInventory `xml:"chassis-inventory"` } From 1c7c4d49827880e9b2a3563ef8053942a727290b Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 19 Jul 2023 16:29:25 +0200 Subject: [PATCH 15/19] add show chassis pic port info --- .../interfacediagnostics/collector.go | 125 ++++++++++-------- .../interfacediagnostics/interface_stats.go | 5 +- pkg/features/interfacediagnostics/rpc.go | 32 +++++ 3 files changed, 104 insertions(+), 58 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 04ee331f..9b4d720e 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -4,6 +4,7 @@ package interfacediagnostics import ( "encoding/xml" + "fmt" "log" "math" "net/rpc" @@ -132,7 +133,7 @@ func (c *interfaceDiagnosticsCollector) init() { c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil) c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil) - transceiver_labels := []string{"target", "name", "version", "part_number", "serial_number", "description", "speed"} + transceiver_labels := []string{"target", "name", "serial_number", "description", "speed", "fiber_type", "vendor_name", "vendor_part_number", "wavelength"} c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil) } @@ -264,46 +265,10 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan } } - ifMediaDict, err := c.interfaceInformation(client) - if err != nil { - return err - } - - transceiverInfo, err := c.chassisHardwareInfos(client) + err = createTransceiverMetrics(c, client, diagnostics_dict, ch, labelValues) if err != nil { return err } - - interfaceDictList := make(map[string]*interfaceStatsAggregate) - - for _, t := range transceiverInfo { - if diag, hit := diagnostics_dict[t.Name]; hit { - t.Name = diag.Name - } else if t.Description == "SFP-T" { - t.Name = "ge-" + t.Name - } else { - t.Name = "slot-" + t.Name - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, "") - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) - continue - } - - s := interfaceStatsAggregate{ - ChassisHardwareInfo: t, - InterfacesMediaInfo: (ifMediaDict[t.Name]), - } - - interfaceDictList[t.Name] = &s - transceiver_labels := append(labelValues, t.Name, t.Version, t.PartNumber, t.SerialNumber, t.Description, s.InterfacesMediaInfo.Speed) - - if s.InterfacesMediaInfo.AdminStatus == "up" && s.InterfacesMediaInfo.OperStatus == "up" { - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) - } else { - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 0, transceiver_labels...) - } - - } - return nil } @@ -317,14 +282,14 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Cl return interfaceDiagnosticsFromRPCResult(x), nil } -func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*chassisSubSubModule, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { var x = chassisHardware{} err := client.RunCommandAndParse("show chassis hardware", &x) if err != nil { return nil, err } - return transceiverInfoFromRPCResult(x), nil + return transceiverInfoFromRPCResult(client, x) } func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { @@ -349,8 +314,8 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma return interfaceMediaDict } -func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSubSubModule { - transceiverList := make([]*chassisSubSubModule, 0) +func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { + transceiverList := make([]*transceiverInformation, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule for _, module := range chassisModules { @@ -361,24 +326,72 @@ func transceiverInfoFromRPCResult(chassisHardware chassisHardware) []*chassisSub if strings.Split(subModule.Name, " ")[0] != "PIC" { continue } - for _, subSubModule := range subModule.ChassisSubSubModule { - fpc := strings.Split(module.Name, " ")[1] - pic := strings.Split(subModule.Name, " ")[1] - port := strings.Split(subSubModule.Name, " ")[1] - - id := fpc + "/" + pic + "/" + port - transceiver := &chassisSubSubModule{ - Name: id, - Version: subSubModule.Version, - PartNumber: subSubModule.PartNumber, - SerialNumber: subSubModule.SerialNumber, - Description: subSubModule.Description, + fpc := strings.Split(module.Name, " ")[1] + pic := strings.Split(subModule.Name, " ")[1] + + picPortsInformation, err := getPicPortsFromRPCResult(client, fpc, pic) + if err != nil { + return nil, err + } + + for port, subSubModule := range subModule.ChassisSubSubModule { + port_name := strings.Split(subSubModule.Name, " ")[1] + + id := fpc + "/" + pic + "/" + port_name + transceiver := transceiverInformation{ + Name: id, + ChassisHardwareInfo: &subSubModule, + PicPort: &picPortsInformation[port], } - transceiverList = append(transceiverList, transceiver) + transceiverList = append(transceiverList, &transceiver) } } } - return transceiverList + return transceiverList, nil +} + +func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { + var x = fPCInformationStruct{} + command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) + err := client.RunCommandAndParse(command, &x) + if err != nil { + return nil, err + } + + return x.FPCInformation.FPC.PicDetail.PicPortInfoList, nil +} + +func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { + + ifMediaDict, err := c.interfaceInformation(client) + if err != nil { + return err + } + + transceiverInfo, err := c.chassisHardwareInfos(client) + if err != nil { + return err + } + + for _, t := range transceiverInfo { + chassisInfo := t.ChassisHardwareInfo + port_speed := "0" + + if diag, hit := diagnostics_dict[t.Name]; hit { + t.Name = diag.Name + port_speed = ifMediaDict[t.Name].Speed + } else if t.ChassisHardwareInfo.Description == "SFP-T" { + t.Name = "ge-" + t.Name + port_speed = ifMediaDict[t.Name].Speed + } else { + t.Name = "slot-" + t.Name + } + + transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength) + + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + } + return nil } func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rpc.Client) ([]*interfaceDiagnostics, error) { diff --git a/pkg/features/interfacediagnostics/interface_stats.go b/pkg/features/interfacediagnostics/interface_stats.go index 7c761ffb..3cfa8fb4 100644 --- a/pkg/features/interfacediagnostics/interface_stats.go +++ b/pkg/features/interfacediagnostics/interface_stats.go @@ -1,6 +1,7 @@ package interfacediagnostics -type interfaceStatsAggregate struct { +type transceiverInformation struct { + Name string ChassisHardwareInfo *chassisSubSubModule - InterfacesMediaInfo *physicalInterface + PicPort *picPort } diff --git a/pkg/features/interfacediagnostics/rpc.go b/pkg/features/interfacediagnostics/rpc.go index 5bd1c00f..8fec7510 100644 --- a/pkg/features/interfacediagnostics/rpc.go +++ b/pkg/features/interfacediagnostics/rpc.go @@ -2,6 +2,38 @@ package interfacediagnostics +type fPCInformationStruct struct { + FPCInformation fPCInformation `xml:"fpc-information"` +} +type fPCInformation struct { + FPC fPC `xml:"fpc"` +} + +type fPC struct { + PicDetail picDetail `xml:"pic-detail"` +} + +type picDetail struct { + Slot int `xml:"slot"` + PicSlot int `xml:"pic-slot"` + PicType string `xml:"pic-type"` + State string `xml:"state"` + PicVersion string `xml:"pic-version"` + UpTime string `xml:"up-time"` + PicPortInfoList []picPort `xml:"port-information>port"` +} + +type picPort struct { + PortNumber int `xml:"port-number"` + CableType string `xml:"cable-type"` + FiberMode string `xml:"fiber-mode"` + SFPVendorName string `xml:"sfp-vendor-name"` + SFPVendorPno string `xml:"sfp-vendor-pno"` + Wavelength string `xml:"wavelength"` + SFPVendorFwVer string `xml:"sfp-vendor-fw-ver"` + SFPJnprVer string `xml:"sfp-jnpr-ver"` +} + type interfacesMediaStruct struct { InterfaceInformation struct { PhysicalInterface []physicalInterface `xml:"physical-interface"` From be5b3e4f365b27838d74267eebae642331d7e8b1 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 19 Jul 2023 18:59:46 +0200 Subject: [PATCH 16/19] fix bug, change transceiver metric so that it uses show interface media for naming --- .../interfacediagnostics/collector.go | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 9b4d720e..5b00a562 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -272,27 +272,7 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan return nil } -func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Client) ([]*interfaceDiagnostics, error) { - var x = result{} - err := client.RunCommandAndParse("show interfaces diagnostics optics", &x) - if err != nil { - return nil, err - } - - return interfaceDiagnosticsFromRPCResult(x), nil -} - -func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { - var x = chassisHardware{} - err := client.RunCommandAndParse("show chassis hardware", &x) - if err != nil { - return nil, err - } - - return transceiverInfoFromRPCResult(client, x) -} - -func (c *interfaceDiagnosticsCollector) interfaceInformation(client *rpc.Client) (map[string]*physicalInterface, error) { +func (c *interfaceDiagnosticsCollector) interfaceMediaInfo(client *rpc.Client) (map[string]*physicalInterface, error) { var x = interfacesMediaStruct{} err := client.RunCommandAndParse("show interfaces media", &x) if err != nil { @@ -307,14 +287,26 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma interfaceMediaDict := make(map[string]*physicalInterface) for _, i := range *interfaceMediaList { - iface := i - interfaceMediaDict[iface.Name] = &iface + if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") { + iface := i + afterThirdIndex := iface.Name[3:] + interfaceMediaDict[afterThirdIndex] = &iface + } } - return interfaceMediaDict } -func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { + var x = chassisHardware{} + err := client.RunCommandAndParse("show chassis hardware", &x) + if err != nil { + return nil, err + } + + return c.transceiverInfoFromRPCResult(client, x) +} + +func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { transceiverList := make([]*transceiverInformation, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule @@ -329,18 +321,18 @@ func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHar fpc := strings.Split(module.Name, " ")[1] pic := strings.Split(subModule.Name, " ")[1] - picPortsInformation, err := getPicPortsFromRPCResult(client, fpc, pic) + picPortsInformation, err := c.getPicPortsFromRPCResult(client, fpc, pic) if err != nil { return nil, err } for port, subSubModule := range subModule.ChassisSubSubModule { port_name := strings.Split(subSubModule.Name, " ")[1] - + subSubModule_pointer := subSubModule id := fpc + "/" + pic + "/" + port_name transceiver := transceiverInformation{ Name: id, - ChassisHardwareInfo: &subSubModule, + ChassisHardwareInfo: &subSubModule_pointer, PicPort: &picPortsInformation[port], } transceiverList = append(transceiverList, &transceiver) @@ -350,7 +342,7 @@ func transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHar return transceiverList, nil } -func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { +func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { var x = fPCInformationStruct{} command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) err := client.RunCommandAndParse(command, &x) @@ -363,7 +355,7 @@ func getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]pic func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { - ifMediaDict, err := c.interfaceInformation(client) + ifMediaDict, err := c.interfaceMediaInfo(client) if err != nil { return err } @@ -376,20 +368,21 @@ func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Clie for _, t := range transceiverInfo { chassisInfo := t.ChassisHardwareInfo port_speed := "0" + oper_status := 0.0 - if diag, hit := diagnostics_dict[t.Name]; hit { - t.Name = diag.Name - port_speed = ifMediaDict[t.Name].Speed - } else if t.ChassisHardwareInfo.Description == "SFP-T" { - t.Name = "ge-" + t.Name - port_speed = ifMediaDict[t.Name].Speed + if media, hit := ifMediaDict[t.Name]; hit { + if media.OperStatus == "up" { + oper_status = 1.0 + } + t.Name = media.Name + port_speed = media.Speed } else { t.Name = "slot-" + t.Name } transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength) - ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, 1, transceiver_labels...) + ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, oper_status, transceiver_labels...) } return nil } @@ -451,6 +444,16 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rp return interfaceDiagnosticsFromRPCResult(x), nil } +func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) ([]*interfaceDiagnostics, error) { + var x = result{} + err := client.RunCommandAndParse("show interfaces diagnostics optics", &x) + if err != nil { + return nil, err + } + + return interfaceDiagnosticsFromRPCResult(x), nil +} + func interfaceDiagnosticsFromRPCResult(res result) []*interfaceDiagnostics { diagnostics := make([]*interfaceDiagnostics, 0) From 7bc9fd201b7dce53c834f716825e691a6d582ec2 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 26 Jul 2023 11:51:24 +0200 Subject: [PATCH 17/19] rename variable to be meaningful --- pkg/features/interfacediagnostics/collector.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index 5b00a562..c87cfa80 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -289,8 +289,8 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma for _, i := range *interfaceMediaList { if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") { iface := i - afterThirdIndex := iface.Name[3:] - interfaceMediaDict[afterThirdIndex] = &iface + slotIndex := iface.Name[3:] + interfaceMediaDict[slotIndex] = &iface } } return interfaceMediaDict From 45988e6ce617adedd95d791d7563e824568cc775 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 14 Jun 2023 11:22:51 +0200 Subject: [PATCH 18/19] make new gauge for interface_transceiver (show chassis hardware) --- pkg/features/interfacediagnostics/collector.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/features/interfacediagnostics/collector.go b/pkg/features/interfacediagnostics/collector.go index c87cfa80..d4ae6289 100644 --- a/pkg/features/interfacediagnostics/collector.go +++ b/pkg/features/interfacediagnostics/collector.go @@ -7,7 +7,6 @@ import ( "fmt" "log" "math" - "net/rpc" "strconv" "strings" @@ -272,7 +271,7 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan return nil } -func (c *interfaceDiagnosticsCollector) interfaceMediaInfo(client *rpc.Client) (map[string]*physicalInterface, error) { +func (c *interfaceDiagnosticsCollector) interfaceMediaInfo(client collector.Client) (map[string]*physicalInterface, error) { var x = interfacesMediaStruct{} err := client.RunCommandAndParse("show interfaces media", &x) if err != nil { @@ -296,7 +295,7 @@ func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) ma return interfaceMediaDict } -func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) ([]*transceiverInformation, error) { +func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client collector.Client) ([]*transceiverInformation, error) { var x = chassisHardware{} err := client.RunCommandAndParse("show chassis hardware", &x) if err != nil { @@ -306,7 +305,7 @@ func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client *rpc.Client) return c.transceiverInfoFromRPCResult(client, x) } -func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client *rpc.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { +func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client collector.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) { transceiverList := make([]*transceiverInformation, 0) var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule @@ -342,7 +341,7 @@ func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client *rpc return transceiverList, nil } -func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client *rpc.Client, fpc string, pic string) ([]picPort, error) { +func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client collector.Client, fpc string, pic string) ([]picPort, error) { var x = fPCInformationStruct{} command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic) err := client.RunCommandAndParse(command, &x) @@ -353,7 +352,7 @@ func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client *rpc.Cli return x.FPCInformation.FPC.PicDetail.PicPortInfoList, nil } -func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { +func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client collector.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error { ifMediaDict, err := c.interfaceMediaInfo(client) if err != nil { @@ -387,7 +386,7 @@ func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client *rpc.Clie return nil } -func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rpc.Client) ([]*interfaceDiagnostics, error) { +func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client collector.Client) ([]*interfaceDiagnostics, error) { var x = result{} // NOTE: Junos is broken and delivers incorrect XML @@ -444,7 +443,7 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client *rp return interfaceDiagnosticsFromRPCResult(x), nil } -func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client *rpc.Client) ([]*interfaceDiagnostics, error) { +func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Client) ([]*interfaceDiagnostics, error) { var x = result{} err := client.RunCommandAndParse("show interfaces diagnostics optics", &x) if err != nil { From a443450085d111bf93f2bc7c2fcb60faaa3032b7 Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Thu, 3 Aug 2023 13:28:05 +0200 Subject: [PATCH 19/19] delete anx-ci.yml --- .github/workflows/anx-ci.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/anx-ci.yml diff --git a/.github/workflows/anx-ci.yml b/.github/workflows/anx-ci.yml deleted file mode 100644 index e69de29b..00000000