moxitech-gzb/internal/zabbix/driver.go
2024-10-23 04:51:07 +07:00

159 lines
3.5 KiB
Go

package zabbix
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/gosnmp/gosnmp"
)
type ZabbixSNMP struct {
Target string
Port uint16
Community string
Version gosnmp.SnmpVersion
}
type Sensor struct {
ID string `json:"id"`
TC float64 `json:"tc"`
PA float64 `json:"pa"`
TS int64 `json:"ts"`
}
// NewZabbixSNMP creates a new instance of ZabbixSNMP with default SNMP parameters
func NewZabbixSNMP(target string, community string, version gosnmp.SnmpVersion) *ZabbixSNMP {
return &ZabbixSNMP{
Target: target,
Port: 161,
Community: community,
Version: version,
}
}
// Get retrieves a value from the SNMP target for the specified OID
func (z *ZabbixSNMP) Get(oid string) (interface{}, error) {
snmp := &gosnmp.GoSNMP{
Target: z.Target,
Port: z.Port,
Community: z.Community,
Version: z.Version,
Timeout: time.Duration(2) * time.Second,
Retries: 1,
}
err := snmp.Connect()
if err != nil {
return nil, fmt.Errorf("failed to connect: %v", err)
}
defer snmp.Conn.Close()
response, err := snmp.Get([]string{oid})
if err != nil {
return nil, fmt.Errorf("failed to get oid: %v", err)
}
if len(response.Variables) < 1 {
return nil, fmt.Errorf("no result found for oid: %s", oid)
}
return formatSNMPValue(response.Variables[0]), nil
}
// formatSNMPValue formats the SNMP value based on its type
func formatSNMPValue(pdu gosnmp.SnmpPDU) interface{} {
switch pdu.Type {
case gosnmp.OctetString:
return string(pdu.Value.([]byte))
default:
return pdu.Value
}
}
// Walk retrieves all values under the provided OID prefix
func (z *ZabbixSNMP) Walk(oid string) (map[string]interface{}, error) {
snmp := &gosnmp.GoSNMP{
Target: z.Target,
Port: z.Port,
Community: z.Community,
Version: z.Version,
Timeout: time.Duration(2) * time.Second,
Retries: 1,
}
err := snmp.Connect()
if err != nil {
return nil, fmt.Errorf("failed to connect: %v", err)
}
defer snmp.Conn.Close()
results := make(map[string]interface{})
err = snmp.Walk(oid, func(pdu gosnmp.SnmpPDU) error {
results[pdu.Name] = formatSNMPValue(pdu)
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to walk oid: %v", err)
}
return results, nil
}
// SendSensorData sends sensor data to a remote Zabbix server
func SendSensorData(url string, sensor Sensor) error {
data, err := json.Marshal(sensor)
if err != nil {
return fmt.Errorf("failed to marshal sensor data: %v", err)
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
return fmt.Errorf("failed to send data to Zabbix: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("received non-OK response from Zabbix: %d", resp.StatusCode)
}
return nil
}
// Example usage
func Example() {
snmpClient := NewZabbixSNMP("192.168.1.1", "public", gosnmp.Version2c)
// Get a specific OID value
value, err := snmpClient.Get("1.3.6.1.2.1.1.1.0")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Value: %v\n", value)
// Walk a subtree of OIDs
values, err := snmpClient.Walk("1.3.6.1.2.1.1")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
for k, v := range values {
fmt.Printf("%s: %v\n", k, v)
}
// Send sensor data to Zabbix server
sensor := Sensor{
ID: "sensor123",
TC: 23.5,
PA: 101.3,
TS: time.Now().Unix(),
}
err = SendSensorData("http://zabbix-server/api/sensordata", sensor)
if err != nil {
fmt.Printf("Error sending sensor data: %v\n", err)
}
}