bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/keepalived_linux.go (about)

     1  package collectors
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  
     8  	"bosun.org/metadata"
     9  	"bosun.org/opentsdb"
    10  	"bosun.org/snmp"
    11  )
    12  
    13  type VRRPInstanceEntry struct {
    14  	VInstanceIndex             int64
    15  	VInstanceName              string
    16  	VInstanceVirtualRouterId   int64
    17  	VInstanceState             int64
    18  	VInstanceInitialState      int64
    19  	VInstanceWantedState       int64
    20  	VInstanceBasePriority      int64
    21  	VInstanceEffectivePriority int64
    22  	VInstanceVipsStatus        int64
    23  	VInstancePrimaryInterface  string
    24  	VInstanceTrackPrimaryIf    int64
    25  	VInstanceAdvertisementsInt int64
    26  	VInstancePreempt           int64
    27  	VInstancePreemptDelay      int64
    28  	VInstanceAuthType          int64
    29  	VInstanceLvsSyncDaemon     int64
    30  	VInstanceLvsSyncInterface  string
    31  	VInstanceSyncGroup         string
    32  	VInstanceGarpDelay         int64
    33  	VInstanceSmtpAlert         int64
    34  	VInstanceNotifyExec        int64
    35  	VInstanceScriptMaster      string
    36  	VInstanceScriptBackup      string
    37  	VInstanceScriptFault       string
    38  	VInstanceScriptStop        string
    39  	VInstanceScript            string
    40  	VInstanceAccept            int64
    41  }
    42  
    43  const (
    44  	VRRPInstanceTable = ".1.3.6.1.4.1.9586.100.5.2.3.1"
    45  	VRRPAddressTable  = ".1.3.6.1.4.1.9586.100.5.2.6.1"
    46  )
    47  
    48  const (
    49  	descVRRPState              = "VRRP Can be in one of the following states: init(0), backup(1), master(2), fault(3), unknown(4)."
    50  	descVRRPVipsStatus         = "Indicates if all the VIPs of this VRRP instance are enabled."
    51  	descVRRPBasePriority       = "Base priority (as defined in the configuration file) for this VRRP instance. This value can be modified to force the virtual router instance to become backup or master."
    52  	descVRRPEffectivePriority  = "Effective priority for this VRRP instance. Status of interfaces and script results are used to compute this value from the base priority."
    53  	descVRRPAddressStatus      = "Indicates if the IP address is set or not."
    54  	descVRRPAddressAdvertising = "Indicates if the IP address is being advertised or not."
    55  )
    56  
    57  func init() {
    58  	collectors = append(collectors, &IntervalCollector{F: c_snmp_keepalived_vrrp_instances})
    59  }
    60  
    61  func c_snmp_keepalived_vrrp_instances() (opentsdb.MultiDataPoint, error) {
    62  	if KeepalivedCommunity == "" {
    63  		return nil, nil
    64  	}
    65  	var md opentsdb.MultiDataPoint
    66  	entries := make(map[int]*VRRPInstanceEntry)
    67  	rows, err := snmp.Walk("localhost", KeepalivedCommunity, VRRPInstanceTable)
    68  	if err != nil {
    69  		return nil, nil
    70  	}
    71  	for rows.Next() {
    72  		var a interface{}
    73  		i, err := rows.Scan(&a)
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  		id, ok := i.([]int)
    78  		if !ok || len(id) != 2 {
    79  			return nil, fmt.Errorf("unexpected type for snmp keepalived index")
    80  		}
    81  		entry, ok := entries[id[1]]
    82  		if !ok {
    83  			entries[id[1]] = &VRRPInstanceEntry{}
    84  			entry = entries[id[1]]
    85  		}
    86  		s := reflect.ValueOf(entry)
    87  		nFields := reflect.ValueOf(*entry).NumField()
    88  		if id[0] > nFields {
    89  			return nil, fmt.Errorf("unexpected number of fields for snmp keepalived VRRPInstanceTable")
    90  		}
    91  		v := s.Elem().Field(id[0] - 1)
    92  		switch t := a.(type) {
    93  		case int64:
    94  			v.SetInt(t)
    95  		case []uint8:
    96  			v.SetString(string(t))
    97  		}
    98  	}
    99  	for _, entry := range entries {
   100  		ts := opentsdb.TagSet{"instance_name": entry.VInstanceName, "instance_id": fmt.Sprint(entry.VInstanceVirtualRouterId)}
   101  		Add(&md, "keepalived.vrrp.state", entry.VInstanceState, ts, metadata.Gauge, metadata.StatusCode, descVRRPState)
   102  		Add(&md, "keepalived.vrrp.wanted_state", entry.VInstanceWantedState, ts, metadata.Gauge, metadata.StatusCode, descVRRPState)
   103  		Add(&md, "keepalived.vrrp.vips_status", entry.VInstanceVipsStatus, ts, metadata.Gauge, metadata.StatusCode, descVRRPVipsStatus)
   104  		Add(&md, "keepalived.vrrp.base_priority", entry.VInstanceBasePriority, ts, metadata.Gauge, metadata.Priority, descVRRPBasePriority)
   105  		Add(&md, "keepalived.vrrp.effective_priority", entry.VInstanceEffectivePriority, ts, metadata.Gauge, metadata.Priority, descVRRPEffectivePriority)
   106  	}
   107  	if err := keepalived_vrrp_addresses(&md, entries); err != nil {
   108  		return nil, err
   109  	}
   110  	return md, nil
   111  }
   112  
   113  type VRRPAddressEntry struct {
   114  	VRRPAddressIndex       int64
   115  	VRRPAddressType        int64
   116  	VRRPAddressValue       string `snmp:"octet"`
   117  	VRRPAddressBroadcast   string `snmp:"octet"`
   118  	VRRPAddressMask        int64
   119  	VRRPAddressScope       int64
   120  	VRRPAddressIfIndex     int64
   121  	VRRPAddressIfName      string
   122  	VRRPAddressIfAlias     string
   123  	VRRPAddressStatus      int64
   124  	VRRPAddressAdvertising int64
   125  }
   126  
   127  // Field (i.e Vrrp address type), Instance Index, Identifer
   128  
   129  func keepalived_vrrp_addresses(md *opentsdb.MultiDataPoint, instances map[int]*VRRPInstanceEntry) error {
   130  	entries := make(map[int]map[int]*VRRPAddressEntry)
   131  	rows, err := snmp.Walk("localhost", KeepalivedCommunity, VRRPAddressTable)
   132  	if err != nil {
   133  		return nil
   134  	}
   135  	for rows.Next() {
   136  		var a interface{}
   137  		i, err := rows.Scan(&a)
   138  		if err != nil {
   139  			return err
   140  		}
   141  		id, ok := i.([]int)
   142  		if !ok || len(id) != 3 {
   143  			return fmt.Errorf("unexpected type for snmp keepalived index")
   144  		}
   145  		if _, ok := entries[id[1]]; !ok {
   146  			entries[id[1]] = make(map[int]*VRRPAddressEntry)
   147  		}
   148  		entry, ok := entries[id[1]][id[2]]
   149  		if !ok {
   150  			entries[id[1]][id[2]] = &VRRPAddressEntry{}
   151  			entry = entries[id[1]][id[2]]
   152  		}
   153  		s := reflect.ValueOf(entry)
   154  		nFields := reflect.ValueOf(*entry).NumField()
   155  		nonPointerType := reflect.ValueOf(*entry).Type()
   156  		if id[0]-1 > nFields {
   157  			return fmt.Errorf("unexpected number of fields for snmp keepalived VRRPAddressTable")
   158  		}
   159  		v := s.Elem().Field(id[0] - 1)
   160  		switch t := a.(type) {
   161  		case int64:
   162  			v.SetInt(t)
   163  		case []uint8:
   164  			if nonPointerType.Kind() == reflect.Struct && nonPointerType.Field(id[0]-1).Tag.Get("snmp") == "octet" {
   165  				var s []string
   166  				for _, runeValue := range t {
   167  					s = append(s, fmt.Sprintf("%v", runeValue))
   168  				}
   169  				v.SetString(strings.Join(s, "."))
   170  			} else {
   171  				v.SetString(string(t))
   172  			}
   173  		}
   174  	}
   175  	for instance_id, instance := range instances {
   176  		for _, entry := range entries[instance_id] {
   177  			ts := opentsdb.TagSet{
   178  				"instance_name": instance.VInstanceName,
   179  				"instance_id":   fmt.Sprint(instance.VInstanceVirtualRouterId),
   180  				"address":       entry.VRRPAddressValue}
   181  			Add(md, "keepalived.vrrp.address_status", entry.VRRPAddressStatus-1, ts, metadata.Gauge, metadata.Bool, descVRRPAddressStatus)
   182  			Add(md, "keepalived.vrrp.address_advertising", entry.VRRPAddressAdvertising-1, ts, metadata.Gauge, metadata.Bool, descVRRPAddressStatus)
   183  		}
   184  	}
   185  	return nil
   186  }