func snmp_ip_tree(host, community, oid string) (map[string]interface{}, error) { rows, err := snmp.Walk(host, community, oid) if err != nil { return nil, err } m := make(map[string]interface{}) for rows.Next() { key := "" var a interface{} id, err := rows.Scan(&a) if err != nil { return nil, err } switch t := id.(type) { case []int: key = snmp_combine_ip_int(t) default: return nil, fmt.Errorf("Got wrong type from OID check") } m[key] = a } if err := rows.Err(); err != nil && err != io.EOF { return nil, err } return m, nil }
func keepalived_vrrp_addresses(md *opentsdb.MultiDataPoint, instances map[int]*VRRPInstanceEntry) error { entries := make(map[int]map[int]*VRRPAddressEntry) rows, err := snmp.Walk("localhost", KeepalivedCommunity, VRRPAddressTable) if err != nil { return nil } for rows.Next() { var a interface{} i, err := rows.Scan(&a) if err != nil { return err } id, ok := i.([]int) if !ok || len(id) != 3 { return fmt.Errorf("unexpected type for snmp keepalived index") } if _, ok := entries[id[1]]; !ok { entries[id[1]] = make(map[int]*VRRPAddressEntry) } entry, ok := entries[id[1]][id[2]] if !ok { entries[id[1]][id[2]] = &VRRPAddressEntry{} entry = entries[id[1]][id[2]] } s := reflect.ValueOf(entry) nFields := reflect.ValueOf(*entry).NumField() nonPointerType := reflect.ValueOf(*entry).Type() if id[0]-1 > nFields { return fmt.Errorf("unexpected number of fields for snmp keepalived VRRPAddressTable") } v := s.Elem().Field(id[0] - 1) switch t := a.(type) { case int64: v.SetInt(t) case []uint8: if nonPointerType.Kind() == reflect.Struct && nonPointerType.Field(id[0]-1).Tag.Get("snmp") == "octet" { var s []string for _, runeValue := range t { s = append(s, fmt.Sprintf("%v", runeValue)) } v.SetString(strings.Join(s, ".")) } else { v.SetString(string(t)) } } } for instance_id, instance := range instances { for _, entry := range entries[instance_id] { ts := opentsdb.TagSet{ "instance_name": instance.VInstanceName, "instance_id": fmt.Sprint(instance.VInstanceVirtualRouterId), "address": entry.VRRPAddressValue} Add(md, "keepalived.vrrp.address_status", entry.VRRPAddressStatus-1, ts, metadata.Gauge, metadata.Bool, descVRRPAddressStatus) Add(md, "keepalived.vrrp.address_advertising", entry.VRRPAddressAdvertising-1, ts, metadata.Gauge, metadata.Bool, descVRRPAddressStatus) } } return nil }
func c_snmp_keepalived_vrrp_instances() (opentsdb.MultiDataPoint, error) { if KeepalivedCommunity == "" { return nil, nil } var md opentsdb.MultiDataPoint entries := make(map[int]*VRRPInstanceEntry) rows, err := snmp.Walk("localhost", KeepalivedCommunity, VRRPInstanceTable) if err != nil { return nil, nil } for rows.Next() { var a interface{} i, err := rows.Scan(&a) if err != nil { return nil, err } id, ok := i.([]int) if !ok || len(id) != 2 { return nil, fmt.Errorf("unexpected type for snmp keepalived index") } entry, ok := entries[id[1]] if !ok { entries[id[1]] = &VRRPInstanceEntry{} entry = entries[id[1]] } s := reflect.ValueOf(entry) nFields := reflect.ValueOf(*entry).NumField() if id[0] > nFields { return nil, fmt.Errorf("unexpected number of fields for snmp keepalived VRRPInstanceTable") } v := s.Elem().Field(id[0] - 1) switch t := a.(type) { case int64: v.SetInt(t) case []uint8: v.SetString(string(t)) } } for _, entry := range entries { ts := opentsdb.TagSet{"instance_name": entry.VInstanceName, "instance_id": fmt.Sprint(entry.VInstanceVirtualRouterId)} Add(&md, "keepalived.vrrp.state", entry.VInstanceState, ts, metadata.Gauge, metadata.StatusCode, descVRRPState) Add(&md, "keepalived.vrrp.wanted_state", entry.VInstanceWantedState, ts, metadata.Gauge, metadata.StatusCode, descVRRPState) Add(&md, "keepalived.vrrp.vips_status", entry.VInstanceVipsStatus, ts, metadata.Gauge, metadata.StatusCode, descVRRPVipsStatus) Add(&md, "keepalived.vrrp.base_priority", entry.VInstanceBasePriority, ts, metadata.Gauge, metadata.Priority, descVRRPBasePriority) Add(&md, "keepalived.vrrp.effective_priority", entry.VInstanceEffectivePriority, ts, metadata.Gauge, metadata.Priority, descVRRPEffectivePriority) } if err := keepalived_vrrp_addresses(&md, entries); err != nil { return nil, err } return md, nil }
// snmp_subtree takes an oid and returns all data exactly one level below it. It // produces an error if there is more than one level below. func snmp_subtree(host, community, oid string) (map[string]interface{}, error) { rows, err := snmp.Walk(host, community, oid) if err != nil { return nil, err } m := make(map[string]interface{}) for rows.Next() { key := "" var a interface{} switch oid { case ifHCInBroadcastPkts: a = new(big.Int) id, err := rows.Scan(&a) if err != nil { slog.Errorf("Error scanning oid %v on host %v: %v", oid, host, err) continue } switch t := id.(type) { case int: key = fmt.Sprint(t) default: return nil, fmt.Errorf("snmp subtree: only one level allowed") } default: id, err := rows.Scan(&a) if err != nil { slog.Errorf("Error scanning oid %v on host %v: %v", oid, host, err) continue } switch t := id.(type) { case int: key = fmt.Sprint(t) case []int: key = snmpOidArrayToString(t) default: return nil, fmt.Errorf("Unknown key type: %s", reflect.TypeOf(id).String()) } } m[key] = a } if err := rows.Err(); err != nil && err != io.EOF { return nil, err } return m, nil }