- 新增 pkg/k8sclient 轻量级 K8s REST 客户端(解析 kubeconfig TLS 证书) - ListNodes/Pods/Deployments/Services/Ingresses 改为实时代理 K8s API - 集群同步端点 POST /:id/sync(拉取后仍存 MySQL 用于离线缓存储备) - 前端 k8sApi 新增 syncCluster 方法 - 修复 SNMP MaxRepetitions uint8→uint32 类型错误 - 修复 ServicePort.TargetPort 兼容 int/string 双类型 - 创建 k8s_nodes/pods/deployments/services/ingresses 五张表
622 lines
17 KiB
Go
622 lines
17 KiB
Go
package snmp
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/gosnmp/gosnmp"
|
|
)
|
|
|
|
// ============================================
|
|
// SNMP 采集器
|
|
// ============================================
|
|
|
|
// Collector SNMP采集器
|
|
// 封装 gosnmp 库,提供SNMP设备的OID采集功能
|
|
// 支持 SNMP v1/v2c/v3,支持 Get/Walk/BulkWalk 操作
|
|
type Collector struct {
|
|
config *gosnmp.GoSNMP
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// CollectorConfig 采集器配置
|
|
type CollectorConfig struct {
|
|
IP string // 目标IP地址
|
|
Port uint16 // SNMP端口,默认161
|
|
Version gosnmp.SnmpVersion // SNMP版本
|
|
Community string // 共同体字符串(v1/v2c)
|
|
Timeout time.Duration // 超时时间
|
|
Retries int // 重试次数
|
|
MaxRepetitions uint8 // BulkWalk最大重复数
|
|
|
|
// SNMP v3 参数
|
|
SecurityModel gosnmp.SnmpV3SecurityModel
|
|
MsgFlags gosnmp.SnmpV3MsgFlags
|
|
SecurityParameters *gosnmp.UsmSecurityParameters
|
|
}
|
|
|
|
// WalkResult SNMP Walk结果
|
|
type WalkResult struct {
|
|
OID string `json:"oid"` // OID
|
|
Type gosnmp.Asn1BER `json:"type"` // SNMP数据类型
|
|
TypeName string `json:"type_name"` // 类型名称
|
|
Value interface{} `json:"value"` // 值
|
|
Index string `json:"index"` // 索引后缀
|
|
Timestamp time.Time `json:"timestamp"` // 采集时间
|
|
}
|
|
|
|
// CollectResult 采集结果
|
|
type CollectResult struct {
|
|
DeviceID uint `json:"device_id"`
|
|
DeviceIP string `json:"device_ip"`
|
|
Timestamp int64 `json:"timestamp"`
|
|
Success bool `json:"success"`
|
|
Error string `json:"error,omitempty"`
|
|
Metrics []SNMPMetricValue `json:"metrics"`
|
|
Duration float64 `json:"duration_ms"` // 采集耗时(ms)
|
|
}
|
|
|
|
// SNMPMetricValue SNMP采集指标值
|
|
type SNMPMetricValue struct {
|
|
Name string `json:"name"`
|
|
OID string `json:"oid"`
|
|
Index string `json:"index,omitempty"`
|
|
Value float64 `json:"value"`
|
|
RawValue string `json:"raw_value,omitempty"`
|
|
Unit string `json:"unit,omitempty"`
|
|
DataType string `json:"data_type"`
|
|
}
|
|
|
|
// NewCollector 创建SNMP采集器
|
|
// config: 采集器配置
|
|
// 返回配置好的SNMP采集器实例和错误
|
|
func NewCollector(config *CollectorConfig) (*Collector, error) {
|
|
if config.IP == "" {
|
|
return nil, fmt.Errorf("target IP is required")
|
|
}
|
|
|
|
g := &gosnmp.GoSNMP{
|
|
Target: config.IP,
|
|
Port: config.Port,
|
|
Version: config.Version,
|
|
Timeout: config.Timeout,
|
|
Retries: config.Retries,
|
|
MaxRepetitions: uint32(config.MaxRepetitions),
|
|
ExponentialTimeout: true,
|
|
}
|
|
|
|
// 设置默认值
|
|
if g.Port == 0 {
|
|
g.Port = 161
|
|
}
|
|
if g.Timeout == 0 {
|
|
g.Timeout = 10 * time.Second
|
|
}
|
|
if g.Retries == 0 {
|
|
g.Retries = 3
|
|
}
|
|
if g.MaxRepetitions == 0 {
|
|
g.MaxRepetitions = 25
|
|
}
|
|
|
|
// 根据版本设置认证参数
|
|
switch config.Version {
|
|
case gosnmp.Version1:
|
|
g.Community = config.Community
|
|
if g.Community == "" {
|
|
g.Community = "public"
|
|
}
|
|
|
|
case gosnmp.Version2c:
|
|
g.Community = config.Community
|
|
if g.Community == "" {
|
|
g.Community = "public"
|
|
}
|
|
|
|
case gosnmp.Version3:
|
|
g.SecurityModel = config.SecurityModel
|
|
if g.SecurityModel == 0 {
|
|
g.SecurityModel = gosnmp.UserSecurityModel
|
|
}
|
|
g.MsgFlags = config.MsgFlags
|
|
if config.SecurityParameters != nil {
|
|
g.SecurityParameters = config.SecurityParameters
|
|
}
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unsupported SNMP version: %v", config.Version)
|
|
}
|
|
|
|
return &Collector{
|
|
config: g,
|
|
}, nil
|
|
}
|
|
|
|
// NewCollectorV2c 快速创建SNMPv2c采集器
|
|
// ip: 目标IP
|
|
// community: 共同体字符串
|
|
func NewCollectorV2c(ip, community string) (*Collector, error) {
|
|
if community == "" {
|
|
community = "public"
|
|
}
|
|
return NewCollector(&CollectorConfig{
|
|
IP: ip,
|
|
Port: 161,
|
|
Version: gosnmp.Version2c,
|
|
Community: community,
|
|
Timeout: 10 * time.Second,
|
|
Retries: 3,
|
|
})
|
|
}
|
|
|
|
// NewCollectorV3 快速创建SNMPv3采集器
|
|
// ip: 目标IP
|
|
// username: 用户名
|
|
// authProtocol: 认证协议
|
|
// authPassword: 认证密码
|
|
// privProtocol: 加密协议
|
|
// privPassword: 加密密码
|
|
// securityLevel: 安全级别
|
|
func NewCollectorV3(ip, username string, authProtocol gosnmp.SnmpV3AuthProtocol, authPassword string,
|
|
privProtocol gosnmp.SnmpV3PrivProtocol, privPassword string,
|
|
securityLevel gosnmp.SnmpV3MsgFlags) (*Collector, error) {
|
|
|
|
securityParams := &gosnmp.UsmSecurityParameters{
|
|
UserName: username,
|
|
AuthenticationProtocol: authProtocol,
|
|
AuthenticationPassphrase: authPassword,
|
|
PrivacyProtocol: privProtocol,
|
|
PrivacyPassphrase: privPassword,
|
|
}
|
|
|
|
return NewCollector(&CollectorConfig{
|
|
IP: ip,
|
|
Port: 161,
|
|
Version: gosnmp.Version3,
|
|
Timeout: 10 * time.Second,
|
|
Retries: 3,
|
|
MsgFlags: securityLevel,
|
|
SecurityParameters: securityParams,
|
|
})
|
|
}
|
|
|
|
// Connect 建立SNMP连接
|
|
func (c *Collector) Connect() error {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
if err := c.config.Connect(); err != nil {
|
|
return fmt.Errorf("SNMP connect to %s failed: %w", c.config.Target, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Close 关闭SNMP连接
|
|
func (c *Collector) Close() error {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
return c.config.Conn.Close()
|
|
}
|
|
|
|
// ============================================
|
|
// SNMP Get 操作
|
|
// ============================================
|
|
|
|
// Get 执行SNMP Get操作,获取指定OID的值
|
|
// oids: OID字符串列表
|
|
// 返回OID到值的映射和错误
|
|
func (c *Collector) Get(ctx context.Context, oids []string) (map[string]*WalkResult, error) {
|
|
if len(oids) == 0 {
|
|
return nil, fmt.Errorf("oids are required")
|
|
}
|
|
|
|
// 解析OID
|
|
parsedOIDs := make([]string, 0, len(oids))
|
|
for _, oid := range oids {
|
|
parsedOIDs = append(parsedOIDs, oid)
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
// 确保连接
|
|
if c.config.Conn == nil {
|
|
if err := c.config.Connect(); err != nil {
|
|
return nil, fmt.Errorf("connect failed: %w", err)
|
|
}
|
|
}
|
|
|
|
result, err := c.config.Get(parsedOIDs)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("SNMP Get failed: %w", err)
|
|
}
|
|
|
|
results := make(map[string]*WalkResult)
|
|
for _, v := range result.Variables {
|
|
r := &WalkResult{
|
|
OID: v.Name,
|
|
Type: v.Type,
|
|
TypeName: getSNMPTypeName(v.Type),
|
|
Value: convertSNMPValue(v),
|
|
Timestamp: time.Now(),
|
|
}
|
|
results[v.Name] = r
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// GetSingle 获取单个OID的值
|
|
func (c *Collector) GetSingle(ctx context.Context, oid string) (*WalkResult, error) {
|
|
results, err := c.Get(ctx, []string{oid})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result, ok := results[oid]
|
|
if !ok {
|
|
return nil, fmt.Errorf("OID not found in response: %s", oid)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// ============================================
|
|
// SNMP Walk 操作
|
|
// ============================================
|
|
|
|
// Walk 执行SNMP Walk操作,遍历指定OID下的所有子节点
|
|
// rootOID: 根OID
|
|
// 返回遍历结果列表和错误
|
|
func (c *Collector) Walk(ctx context.Context, rootOID string) ([]*WalkResult, error) {
|
|
if rootOID == "" {
|
|
return nil, fmt.Errorf("root OID is required")
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
// 确保连接
|
|
if c.config.Conn == nil {
|
|
if err := c.config.Connect(); err != nil {
|
|
return nil, fmt.Errorf("connect failed: %w", err)
|
|
}
|
|
}
|
|
|
|
var results []*WalkResult
|
|
walkFn := func(data gosnmp.SnmpPDU) error {
|
|
index := ""
|
|
if strings.HasPrefix(data.Name, rootOID) && len(data.Name) > len(rootOID) {
|
|
suffix := strings.TrimPrefix(data.Name, rootOID)
|
|
index = strings.TrimPrefix(suffix, ".")
|
|
}
|
|
|
|
r := &WalkResult{
|
|
OID: data.Name,
|
|
Type: data.Type,
|
|
TypeName: getSNMPTypeName(data.Type),
|
|
Value: convertSNMPValue(data),
|
|
Index: index,
|
|
Timestamp: time.Now(),
|
|
}
|
|
results = append(results, r)
|
|
return nil
|
|
}
|
|
|
|
if err := c.config.Walk(rootOID, walkFn); err != nil {
|
|
return nil, fmt.Errorf("SNMP Walk failed for OID %s: %w", rootOID, err)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// ============================================
|
|
// SNMP BulkWalk 操作
|
|
// ============================================
|
|
|
|
// BulkWalk 执行SNMP BulkWalk操作,高效遍历指定OID下的所有子节点
|
|
// 相比Walk使用GetBulk请求,效率更高,适合遍历大量数据
|
|
// rootOID: 根OID
|
|
// 返回遍历结果列表和错误
|
|
func (c *Collector) BulkWalk(ctx context.Context, rootOID string) ([]*WalkResult, error) {
|
|
if rootOID == "" {
|
|
return nil, fmt.Errorf("root OID is required")
|
|
}
|
|
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
|
|
// 确保连接
|
|
if c.config.Conn == nil {
|
|
if err := c.config.Connect(); err != nil {
|
|
return nil, fmt.Errorf("connect failed: %w", err)
|
|
}
|
|
}
|
|
|
|
var results []*WalkResult
|
|
walkFn := func(data gosnmp.SnmpPDU) error {
|
|
index := ""
|
|
if strings.HasPrefix(data.Name, rootOID) && len(data.Name) > len(rootOID) {
|
|
suffix := strings.TrimPrefix(data.Name, rootOID)
|
|
index = strings.TrimPrefix(suffix, ".")
|
|
}
|
|
|
|
r := &WalkResult{
|
|
OID: data.Name,
|
|
Type: data.Type,
|
|
TypeName: getSNMPTypeName(data.Type),
|
|
Value: convertSNMPValue(data),
|
|
Index: index,
|
|
Timestamp: time.Now(),
|
|
}
|
|
results = append(results, r)
|
|
return nil
|
|
}
|
|
|
|
if err := c.config.BulkWalk(rootOID, walkFn); err != nil {
|
|
return nil, fmt.Errorf("SNMP BulkWalk failed for OID %s: %w", rootOID, err)
|
|
}
|
|
|
|
return results, nil
|
|
}
|
|
|
|
// ============================================
|
|
// 批量采集
|
|
// ============================================
|
|
|
|
// OIDDefinition OID定义
|
|
type OIDDefinition struct {
|
|
Name string `json:"name"` // 指标名称
|
|
OID string `json:"oid"` // OID
|
|
Unit string `json:"unit"` // 单位
|
|
DataType string `json:"data_type"` // 数据类型
|
|
Conversion string `json:"conversion"` // 转换公式
|
|
IsTable bool `json:"is_table"` // 是否表OID(使用Walk)
|
|
}
|
|
|
|
// Collect 执行批量采集
|
|
// oids: OID定义列表
|
|
// 返回采集结果
|
|
func (c *Collector) Collect(ctx context.Context, oids []OIDDefinition) *CollectResult {
|
|
start := time.Now()
|
|
result := &CollectResult{
|
|
DeviceIP: c.config.Target,
|
|
Timestamp: time.Now().Unix(),
|
|
Metrics: make([]SNMPMetricValue, 0),
|
|
}
|
|
|
|
// 建立连接
|
|
if err := c.Connect(); err != nil {
|
|
result.Success = false
|
|
result.Error = err.Error()
|
|
result.Duration = float64(time.Since(start).Milliseconds())
|
|
return result
|
|
}
|
|
defer c.Close()
|
|
|
|
for _, def := range oids {
|
|
if def.IsTable {
|
|
// 表OID使用Walk/BulkWalk
|
|
walkResults, err := c.BulkWalk(ctx, def.OID)
|
|
if err != nil {
|
|
result.Error += fmt.Sprintf("[%s walk failed: %v]", def.Name, err)
|
|
continue
|
|
}
|
|
for _, wr := range walkResults {
|
|
mv := SNMPMetricValue{
|
|
Name: def.Name,
|
|
OID: wr.OID,
|
|
Index: wr.Index,
|
|
Unit: def.Unit,
|
|
}
|
|
if val, ok := wr.Value.(float64); ok {
|
|
mv.Value = applyConversion(val, def.Conversion)
|
|
mv.RawValue = fmt.Sprintf("%v", wr.Value)
|
|
} else {
|
|
mv.RawValue = fmt.Sprintf("%v", wr.Value)
|
|
if v, err := strconv.ParseFloat(mv.RawValue, 64); err == nil {
|
|
mv.Value = applyConversion(v, def.Conversion)
|
|
}
|
|
}
|
|
mv.DataType = def.DataType
|
|
if mv.DataType == "" {
|
|
mv.DataType = wr.TypeName
|
|
}
|
|
result.Metrics = append(result.Metrics, mv)
|
|
}
|
|
} else {
|
|
// 标量OID使用Get
|
|
wr, err := c.GetSingle(ctx, def.OID)
|
|
if err != nil {
|
|
result.Error += fmt.Sprintf("[%s get failed: %v]", def.Name, err)
|
|
continue
|
|
}
|
|
mv := SNMPMetricValue{
|
|
Name: def.Name,
|
|
OID: wr.OID,
|
|
Unit: def.Unit,
|
|
}
|
|
if val, ok := wr.Value.(float64); ok {
|
|
mv.Value = applyConversion(val, def.Conversion)
|
|
mv.RawValue = fmt.Sprintf("%v", wr.Value)
|
|
} else {
|
|
mv.RawValue = fmt.Sprintf("%v", wr.Value)
|
|
if v, err := strconv.ParseFloat(mv.RawValue, 64); err == nil {
|
|
mv.Value = applyConversion(v, def.Conversion)
|
|
}
|
|
}
|
|
mv.DataType = def.DataType
|
|
if mv.DataType == "" {
|
|
mv.DataType = wr.TypeName
|
|
}
|
|
result.Metrics = append(result.Metrics, mv)
|
|
}
|
|
}
|
|
|
|
result.Success = len(result.Metrics) > 0
|
|
result.Duration = float64(time.Since(start).Milliseconds())
|
|
return result
|
|
}
|
|
|
|
// ============================================
|
|
// 工具方法
|
|
// ============================================
|
|
|
|
// getSNMPTypeName 获取SNMP数据类型名称
|
|
func getSNMPTypeName(t gosnmp.Asn1BER) string {
|
|
switch t {
|
|
case gosnmp.Integer:
|
|
return "integer"
|
|
case gosnmp.OctetString:
|
|
return "string"
|
|
case gosnmp.ObjectIdentifier:
|
|
return "oid"
|
|
case gosnmp.IPAddress:
|
|
return "ipaddress"
|
|
case gosnmp.Counter32:
|
|
return "counter32"
|
|
case gosnmp.Gauge32:
|
|
return "gauge32"
|
|
case gosnmp.TimeTicks:
|
|
return "timeticks"
|
|
case gosnmp.Opaque:
|
|
return "opaque"
|
|
case gosnmp.NsapAddress:
|
|
return "nsapaddress"
|
|
case gosnmp.Counter64:
|
|
return "counter64"
|
|
case gosnmp.Uinteger32:
|
|
return "uinteger32"
|
|
case gosnmp.NoSuchObject:
|
|
return "nosuchobject"
|
|
case gosnmp.NoSuchInstance:
|
|
return "nosuchinstance"
|
|
default:
|
|
return fmt.Sprintf("unknown(%d)", t)
|
|
}
|
|
}
|
|
|
|
// convertSNMPValue 转换SNMP值为Go类型
|
|
func convertSNMPValue(pdu gosnmp.SnmpPDU) interface{} {
|
|
switch pdu.Type {
|
|
case gosnmp.Integer, gosnmp.Counter32, gosnmp.Gauge32, gosnmp.TimeTicks, gosnmp.Counter64, gosnmp.Uinteger32:
|
|
if val, ok := pdu.Value.(int); ok {
|
|
return float64(val)
|
|
}
|
|
if val, ok := pdu.Value.(uint); ok {
|
|
return float64(val)
|
|
}
|
|
if val, ok := pdu.Value.(uint32); ok {
|
|
return float64(val)
|
|
}
|
|
if val, ok := pdu.Value.(uint64); ok {
|
|
return float64(val)
|
|
}
|
|
if val, ok := pdu.Value.(int64); ok {
|
|
return float64(val)
|
|
}
|
|
return pdu.Value
|
|
case gosnmp.OctetString:
|
|
if val, ok := pdu.Value.([]byte); ok {
|
|
return string(val)
|
|
}
|
|
return pdu.Value
|
|
case gosnmp.OpaqueFloat:
|
|
if val, ok := pdu.Value.(float32); ok {
|
|
return float64(val)
|
|
}
|
|
return pdu.Value
|
|
case gosnmp.OpaqueDouble:
|
|
if val, ok := pdu.Value.(float64); ok {
|
|
return val
|
|
}
|
|
return pdu.Value
|
|
default:
|
|
return fmt.Sprintf("%v", pdu.Value)
|
|
}
|
|
}
|
|
|
|
// applyConversion 应用转换公式
|
|
// 支持简单的数学运算: *N, /N, +N, -N
|
|
func applyConversion(value float64, conversion string) float64 {
|
|
if conversion == "" {
|
|
return value
|
|
}
|
|
conversion = strings.TrimSpace(conversion)
|
|
|
|
if strings.HasPrefix(conversion, "*") {
|
|
if f, err := strconv.ParseFloat(strings.TrimPrefix(conversion, "*"), 64); err == nil {
|
|
return value * f
|
|
}
|
|
}
|
|
if strings.HasPrefix(conversion, "/") {
|
|
if f, err := strconv.ParseFloat(strings.TrimPrefix(conversion, "/"), 64); err == nil && f != 0 {
|
|
return value / f
|
|
}
|
|
}
|
|
if strings.HasPrefix(conversion, "+") {
|
|
if f, err := strconv.ParseFloat(strings.TrimPrefix(conversion, "+"), 64); err == nil {
|
|
return value + f
|
|
}
|
|
}
|
|
if strings.HasPrefix(conversion, "-") && len(conversion) > 1 {
|
|
if f, err := strconv.ParseFloat(conversion, 64); err == nil {
|
|
return value + f // f is negative
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
|
|
// GetTargetIP 获取目标IP
|
|
func (c *Collector) GetTargetIP() string {
|
|
return c.config.Target
|
|
}
|
|
|
|
// GetVersion 获取SNMP版本
|
|
func (c *Collector) GetVersion() gosnmp.SnmpVersion {
|
|
return c.config.Version
|
|
}
|
|
|
|
// ============================================
|
|
// 预定义OID常量 (RFC1213-MIB, IF-MIB)
|
|
// ============================================
|
|
|
|
// 系统信息 OID
|
|
const (
|
|
OIDSysDescr = ".1.3.6.1.2.1.1.1.0" // 系统描述
|
|
OIDSysObjectID = ".1.3.6.1.2.1.1.2.0" // 系统对象ID
|
|
OIDSysUptime = ".1.3.6.1.2.1.1.3.0" // 系统运行时间
|
|
OIDSysContact = ".1.3.6.1.2.1.1.4.0" // 系统联系人
|
|
OIDSysName = ".1.3.6.1.2.1.1.5.0" // 系统名称
|
|
OIDSysLocation = ".1.3.6.1.2.1.1.6.0" // 系统位置
|
|
)
|
|
|
|
// 接口信息 OID (IF-MIB)
|
|
const (
|
|
OIDIfNumber = ".1.3.6.1.2.1.2.1.0" // 接口数量
|
|
OIDIfTable = ".1.3.6.1.2.1.2.2" // 接口表
|
|
OIDIfDescr = ".1.3.6.1.2.1.2.2.1.2" // 接口描述
|
|
OIDIfType = ".1.3.6.1.2.1.2.2.1.3" // 接口类型
|
|
OIDIfSpeed = ".1.3.6.1.2.1.2.2.1.5" // 接口速率
|
|
OIDIfPhysAddr = ".1.3.6.1.2.1.2.2.1.6" // 物理地址
|
|
OIDIfAdminStatus = ".1.3.6.1.2.1.2.2.1.7" // 管理状态
|
|
OIDIfOperStatus = ".1.3.6.1.2.1.2.2.1.8" // 操作状态
|
|
OIDIfInOctets = ".1.3.6.1.2.1.2.2.1.10" // 接收字节数
|
|
OIDIfInUcastPkts = ".1.3.6.1.2.1.2.2.1.11" // 接收单播包数
|
|
OIDIfInErrors = ".1.3.6.1.2.1.2.2.1.14" // 接收错误数
|
|
OIDIfOutOctets = ".1.3.6.1.2.1.2.2.1.16" // 发送字节数
|
|
OIDIfOutUcastPkts = ".1.3.6.1.2.1.2.2.1.17" // 发送单播包数
|
|
OIDIfOutErrors = ".1.3.6.1.2.1.2.2.1.20" // 发送错误数
|
|
)
|
|
|
|
// HostResource MIB OID
|
|
const (
|
|
OIDHrSystemUptime = ".1.3.6.1.2.1.25.1.1.0" // 系统运行时间
|
|
OIDHrProcessorLoad = ".1.3.6.1.2.1.25.3.3.1.2" // CPU负载
|
|
OIDHrStorageTable = ".1.3.6.1.2.1.25.2.3" // 存储表
|
|
OIDHrStorageDescr = ".1.3.6.1.2.1.25.2.3.1.3" // 存储描述
|
|
OIDHrStorageSize = ".1.3.6.1.2.1.25.2.3.1.5" // 存储大小
|
|
OIDHrStorageUsed = ".1.3.6.1.2.1.25.2.3.1.6" // 已用存储
|
|
)
|