package collectors import ( "fmt" "io/ioutil" lp "github.com/ClusterCockpit/cc-metric-collector/internal/ccMetric" "encoding/json" "errors" "path/filepath" "strconv" "strings" "time" ) const IB_BASEPATH = `/sys/class/infiniband/` type InfinibandCollector struct { metricCollector tags map[string]string lids map[string]map[string]string config struct { ExcludeDevices []string `json:"exclude_devices,omitempty"` } } func (m *InfinibandCollector) Help() { fmt.Println("This collector includes all devices that can be found below ", IB_BASEPATH) fmt.Println("and where any of the ports provides a 'lid' file (glob ", IB_BASEPATH, "//ports//lid).") fmt.Println("The devices can be filtered with the 'exclude_devices' option in the configuration.") fmt.Println("For each found LIDs the collector calls the 'perfquery' command") fmt.Println("") fmt.Println("Full configuration object:") fmt.Println("\"ibstat\" : {") fmt.Println(" \"exclude_devices\" : [\"dev1\"]") fmt.Println("}") fmt.Println("") fmt.Println("Metrics:") fmt.Println("- ib_recv") fmt.Println("- ib_xmit") fmt.Println("- ib_recv_pkts") fmt.Println("- ib_xmit_pkts") } func (m *InfinibandCollector) Init(config json.RawMessage) error { var err error m.name = "InfinibandCollector" m.setup() m.meta = map[string]string{"source": m.name, "group": "Network"} m.tags = map[string]string{"type": "node"} if len(config) > 0 { err = json.Unmarshal(config, &m.config) if err != nil { return err } } m.lids = make(map[string]map[string]string) p := fmt.Sprintf("%s/*/ports/*/lid", string(IB_BASEPATH)) files, err := filepath.Glob(p) for _, f := range files { lid, err := ioutil.ReadFile(f) if err == nil { plist := strings.Split(strings.Replace(f, string(IB_BASEPATH), "", -1), "/") skip := false for _, d := range m.config.ExcludeDevices { if d == plist[0] { skip = true } } if !skip { m.lids[plist[0]] = make(map[string]string) m.lids[plist[0]][plist[2]] = string(lid) } } } if len(m.lids) == 0 { return errors.New("No usable IB devices") } m.init = true return nil } func (m *InfinibandCollector) Read(interval time.Duration, output chan lp.CCMetric) { if m.init { for dev, ports := range m.lids { for port, lid := range ports { tags := map[string]string{ "type": "node", "device": dev, "port": port, "lid": lid} path := fmt.Sprintf("%s/%s/ports/%s/counters/", string(IB_BASEPATH), dev, port) buffer, err := ioutil.ReadFile(fmt.Sprintf("%s/port_rcv_data", path)) if err == nil { data := strings.Replace(string(buffer), "\n", "", -1) v, err := strconv.ParseFloat(data, 64) if err == nil { y, err := lp.New("ib_recv", tags, m.meta, map[string]interface{}{"value": float64(v)}, time.Now()) if err == nil { output <- y } } } buffer, err = ioutil.ReadFile(fmt.Sprintf("%s/port_xmit_data", path)) if err == nil { data := strings.Replace(string(buffer), "\n", "", -1) v, err := strconv.ParseFloat(data, 64) if err == nil { y, err := lp.New("ib_xmit", tags, m.meta, map[string]interface{}{"value": float64(v)}, time.Now()) if err == nil { output <- y } } } buffer, err = ioutil.ReadFile(fmt.Sprintf("%s/port_rcv_packets", path)) if err == nil { data := strings.Replace(string(buffer), "\n", "", -1) v, err := strconv.ParseFloat(data, 64) if err == nil { y, err := lp.New("ib_recv_pkts", tags, m.meta, map[string]interface{}{"value": float64(v)}, time.Now()) if err == nil { output <- y } } } buffer, err = ioutil.ReadFile(fmt.Sprintf("%s/port_xmit_packets", path)) if err == nil { data := strings.Replace(string(buffer), "\n", "", -1) v, err := strconv.ParseFloat(data, 64) if err == nil { y, err := lp.New("ib_xmit_pkts", tags, m.meta, map[string]interface{}{"value": float64(v)}, time.Now()) if err == nil { output <- y } } } } } } } func (m *InfinibandCollector) Close() { m.init = false }