github.com/netdata/go.d.plugin@v0.58.1/modules/snmp/snmp.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package snmp 4 5 import ( 6 _ "embed" 7 "fmt" 8 "strings" 9 10 "github.com/netdata/go.d.plugin/agent/module" 11 12 "github.com/gosnmp/gosnmp" 13 ) 14 15 const ( 16 defaultUpdateEvery = 10 17 defaultHostname = "127.0.0.1" 18 defaultCommunity = "public" 19 defaultVersion = gosnmp.Version2c 20 defaultPort = 161 21 defaultRetries = 1 22 defaultTimeout = defaultUpdateEvery 23 defaultMaxOIDs = 60 24 ) 25 26 //go:embed "config_schema.json" 27 var configSchema string 28 29 func init() { 30 module.Register("snmp", module.Creator{ 31 JobConfigSchema: configSchema, 32 Defaults: module.Defaults{ 33 UpdateEvery: defaultUpdateEvery, 34 }, 35 Create: func() module.Module { return New() }, 36 }) 37 } 38 39 func New() *SNMP { 40 return &SNMP{ 41 Config: Config{ 42 Hostname: defaultHostname, 43 Community: defaultCommunity, 44 Options: Options{ 45 Port: defaultPort, 46 Retries: defaultRetries, 47 Timeout: defaultUpdateEvery, 48 Version: defaultVersion.String(), 49 MaxOIDs: defaultMaxOIDs, 50 }, 51 }, 52 } 53 } 54 55 type ( 56 Config struct { 57 UpdateEvery int `yaml:"update_every"` 58 Hostname string `yaml:"hostname"` 59 Community string `yaml:"community"` 60 User User `yaml:"user"` 61 Options Options `yaml:"options"` 62 ChartsInput []ChartConfig `yaml:"charts"` 63 } 64 User struct { 65 Name string `yaml:"name"` 66 SecurityLevel string `yaml:"level"` 67 AuthProto string `yaml:"auth_proto"` 68 AuthKey string `yaml:"auth_key"` 69 PrivProto string `yaml:"priv_proto"` 70 PrivKey string `yaml:"priv_key"` 71 } 72 Options struct { 73 Port int `yaml:"port"` 74 Retries int `yaml:"retries"` 75 Timeout int `yaml:"timeout"` 76 Version string `yaml:"version"` 77 MaxOIDs int `yaml:"max_request_size"` 78 } 79 ChartConfig struct { 80 ID string `yaml:"id"` 81 Title string `yaml:"title"` 82 Units string `yaml:"units"` 83 Family string `yaml:"family"` 84 Type string `yaml:"type"` 85 Priority int `yaml:"priority"` 86 IndexRange []int `yaml:"multiply_range"` 87 Dimensions []DimensionConfig `yaml:"dimensions"` 88 } 89 DimensionConfig struct { 90 OID string `yaml:"oid"` 91 Name string `yaml:"name"` 92 Algorithm string `yaml:"algorithm"` 93 Multiplier int `yaml:"multiplier"` 94 Divisor int `yaml:"divisor"` 95 } 96 ) 97 98 type SNMP struct { 99 module.Base 100 Config `yaml:",inline"` 101 102 charts *module.Charts 103 snmpClient gosnmp.Handler 104 oids []string 105 } 106 107 func (s *SNMP) Init() bool { 108 err := s.validateConfig() 109 if err != nil { 110 s.Errorf("config validation: %v", err) 111 return false 112 } 113 114 snmpClient, err := s.initSNMPClient() 115 if err != nil { 116 s.Errorf("SNMP client initialization: %v", err) 117 return false 118 } 119 120 s.Info(snmpClientConnInfo(snmpClient)) 121 122 err = snmpClient.Connect() 123 if err != nil { 124 s.Errorf("SNMP client connect: %v", err) 125 return false 126 } 127 s.snmpClient = snmpClient 128 129 charts, err := newCharts(s.ChartsInput) 130 if err != nil { 131 s.Errorf("Population of charts failed: %v", err) 132 return false 133 } 134 s.charts = charts 135 136 s.oids = s.initOIDs() 137 138 return true 139 } 140 141 func (s *SNMP) Check() bool { 142 return len(s.Collect()) > 0 143 } 144 145 func (s *SNMP) Charts() *module.Charts { 146 return s.charts 147 } 148 149 func (s *SNMP) Collect() map[string]int64 { 150 mx, err := s.collect() 151 if err != nil { 152 s.Error(err) 153 } 154 155 if len(mx) == 0 { 156 return nil 157 } 158 return mx 159 } 160 161 func (s *SNMP) Cleanup() { 162 if s.snmpClient != nil { 163 _ = s.snmpClient.Close() 164 } 165 } 166 167 func snmpClientConnInfo(c gosnmp.Handler) string { 168 var info strings.Builder 169 info.WriteString(fmt.Sprintf("hostname=%s,port=%d,snmp_version=%s", c.Target(), c.Port(), c.Version())) 170 switch c.Version() { 171 case gosnmp.Version1, gosnmp.Version2c: 172 info.WriteString(fmt.Sprintf(",community=%s", c.Community())) 173 case gosnmp.Version3: 174 info.WriteString(fmt.Sprintf(",security_level=%d,%s", c.MsgFlags(), c.SecurityParameters().Description())) 175 } 176 return info.String() 177 }