-
Notifications
You must be signed in to change notification settings - Fork 0
/
ekinops.go
133 lines (108 loc) · 4.08 KB
/
ekinops.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package codecommunicator
import (
"context"
"fmt"
"github.com/RincewindsHat/thola/internal/device"
"github.com/RincewindsHat/thola/internal/deviceclass/groupproperty"
"github.com/RincewindsHat/thola/internal/network"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"strings"
)
type ekinopsCommunicator struct {
codeCommunicator
}
// GetInterfaces returns the interfaces of ekinops devices.
func (c *ekinopsCommunicator) GetInterfaces(ctx context.Context, filter ...groupproperty.Filter) ([]device.Interface, error) {
con, ok := network.DeviceConnectionFromContext(ctx)
if !ok || con.SNMP == nil {
return nil, errors.New("no device connection available")
}
con.SNMP.SnmpClient.UseCache(false)
interfaces, err := c.deviceClass.GetInterfaces(ctx)
if err != nil {
return nil, err
}
//get used slots
slotResults, err := con.SNMP.SnmpClient.SNMPWalk(ctx, ".1.3.6.1.4.1.20044.7.8.1.1.2")
if err != nil {
log.Fatal().Err(err).Msg("failed to snmpwalk")
}
//get used modules
moduleResults, err := con.SNMP.SnmpClient.SNMPWalk(ctx, ".1.3.6.1.4.1.20044.7.8.1.1.3")
if err != nil {
log.Fatal().Err(err).Msg("failed to snmpwalk")
}
var moduleReaders []ekinopsModuleReader
for k, slotResult := range slotResults {
slotIdentifier, err := slotResult.GetValue()
if err != nil {
return nil, errors.Wrap(err, "failed to get snmp result as string")
}
module, err := moduleResults[k].GetValue()
if err != nil {
return nil, errors.Wrap(err, "failed to get module result as string")
}
moduleReader, err := ekinopsGetModuleReader(slotIdentifier.String(), module.String())
if err != nil {
log.Ctx(ctx).Debug().Err(err).Msgf("no information for reading out ekinops module '%s' available", module)
continue
}
moduleReaders = append(moduleReaders, moduleReader)
}
for _, moduleReader := range moduleReaders {
interfaces, err = moduleReader.readModuleMetrics(ctx, interfaces)
if err != nil {
return nil, errors.Wrapf(err, "failed to read out module specific metrics for module '%s' (slot: %s)", moduleReader.getModuleName(), moduleReader.getSlotIdentifier())
}
}
interfaces, err = c.normalizeInterfaces(interfaces)
if err != nil {
return nil, errors.Wrap(err, "failed to normalize interfaces")
}
return filterInterfaces(ctx, interfaces, filter)
}
func ekinopsInterfacesIfIdentifierToSliceIndex(interfaces []device.Interface) (map[string]int, error) {
m := make(map[string]int)
for k, interf := range interfaces {
if interf.IfName == nil {
return nil, fmt.Errorf("no ifName set for interface ifIndex: `%d`", *interf.IfIndex)
}
identifier := strings.Split(strings.Join(strings.Split(*interf.IfName, "/")[2:], "/"), "(")[0]
if _, ok := m[identifier]; ok {
return nil, fmt.Errorf("interface identifier `%s` exists multiple times", *interf.IfName)
}
m[identifier] = k
}
return m, nil
}
func (c *ekinopsCommunicator) normalizeInterfaces(interfaces []device.Interface) ([]device.Interface, error) {
var res []device.Interface
for _, interf := range interfaces {
if interf.IfDescr == nil {
return nil, fmt.Errorf("no IfDescr set for interface ifIndex: `%d`", *interf.IfIndex)
}
slotNumber := strings.Split(*interf.IfName, "/")[2]
moduleName := strings.Split(*interf.IfDescr, "/")[3]
// change ifType of ports of slots > 0 to "opticalChannel" if ifType equals "other", but not OPM8 interfaces
if slotNumber != "0" && interf.IfType != nil && *interf.IfType == "other" && moduleName != "PM_OPM8" {
opticalChannel := "opticalChannel"
interf.IfType = &opticalChannel
}
// change subType of OPM8 ports
if moduleName == "PM_OPM8" {
subType := "channelMonitoring"
interf.SubType = &subType
}
// change ifDescr and ifName of every interface
// they no longer contain Ekinops/C...
// and are now in the form <slot>-[Description]
*interf.IfDescr = slotNumber + "-" + strings.Split(strings.Split(*interf.IfDescr, "/")[4], "(")[0]
interf.IfName = interf.IfDescr
// remove every port on slot 0 starting with "0-FE_"
if slotNumber != "0" || !strings.HasPrefix(*interf.IfName, "0-FE_") {
res = append(res, interf)
}
}
return res, nil
}