master
go 80 lines 2.53 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package panos
4
5 import (
6 "context"
7 "fmt"
8 "strings"
9 )
10
11 type systemInfo struct {
12 Hostname string `xml:"hostname"`
13 DeviceName string `xml:"devicename"`
14 Model string `xml:"model"`
15 Serial string `xml:"serial"`
16 SWVersion string `xml:"sw-version"`
17 Uptime string `xml:"uptime"`
18 CertificateStatus string `xml:"device-certificate-status"`
19 OperationalMode string `xml:"operational-mode"`
20 }
21
22 type systemInfoResult struct {
23 System systemInfo `xml:"system"`
24 }
25
26 func (c *Collector) collectSystemMetrics(ctx context.Context) (bool, error) {
27 info, err := c.querySystemInfo(ctx)
28 if err != nil {
29 return false, fmt.Errorf("system metricset: %w", err)
30 }
31
32 uptime, err := parseRequiredPANOSDurationField("system uptime", info.Uptime)
33 if err != nil {
34 return false, fmt.Errorf("system metricset: %s response: %w", panosCommandName(systemInfoCommand), err)
35 }
36
37 labels := systemLabelValues(info)
38 c.metrics.system.uptime.WithLabelValues(labels...).Observe(float64(uptime))
39
40 certStatus := strings.TrimSpace(info.CertificateStatus)
41 if certStatus != "" {
42 certValid := strings.EqualFold(certStatus, "valid")
43 observeStateSetVec(c.metrics.system.certStatus, boolState(certValid, "valid", "invalid"), labels...)
44 }
45
46 operationalMode := strings.TrimSpace(info.OperationalMode)
47 if operationalMode != "" {
48 normalMode := strings.EqualFold(operationalMode, "normal")
49 observeStateSetVec(c.metrics.system.operationalMode, boolState(normalMode, "normal", "other"), labels...)
50 }
51 return true, nil
52 }
53
54 func (c *Collector) querySystemInfo(ctx context.Context) (systemInfo, error) {
55 body, err := c.apiClient.op(ctx, systemInfoCommand)
56 if err != nil {
57 return systemInfo{}, fmt.Errorf("%s API call: %w", panosCommandName(systemInfoCommand), err)
58 }
59
60 info, err := parseSystemInfo(body)
61 if err != nil {
62 return systemInfo{}, fmt.Errorf("%s response: %w", panosCommandName(systemInfoCommand), err)
63 }
64 if !info.hasData() {
65 return systemInfo{}, fmt.Errorf("%s response: %w", panosCommandName(systemInfoCommand), missingPANOSResultError{expected: "<system>"})
66 }
67 return info, nil
68 }
69
70 func parseSystemInfo(body []byte) (systemInfo, error) {
71 var result systemInfoResult
72 if err := decodePANOSResult(body, "PAN-OS system info response", &result); err != nil {
73 return systemInfo{}, err
74 }
75 return result.System, nil
76 }
77
78 func (i systemInfo) hasData() bool {
79 return firstNonEmpty(i.Hostname, i.DeviceName, i.Model, i.Serial, i.SWVersion, i.Uptime, i.CertificateStatus, i.OperationalMode) != ""
80 }