master
go 157 lines 3.41 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package powerstore
4
5 import (
6 "sync"
7 "time"
8
9 "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/powerstore/client"
10 )
11
12 const discoveryEvery = 5
13
14 func (c *Collector) collect() error {
15 c.runs++
16 if !c.lastDiscoveryOK || c.runs%discoveryEvery == 0 {
17 if err := c.discovery(); err != nil {
18 if !c.lastDiscoveryOK {
19 return err
20 }
21 c.Warningf("discovery refresh failed, using previous data: %v", err)
22 }
23 }
24
25 // Collect metrics from API concurrently, bounded by semaphore.
26 var wg sync.WaitGroup
27 for _, fn := range []func(){
28 c.collectClusterSpace,
29 c.collectAppliances,
30 c.collectVolumes,
31 c.collectNodes,
32 c.collectFcPorts,
33 c.collectEthPorts,
34 c.collectFileSystems,
35 c.collectAlerts,
36 c.collectDriveWear,
37 c.collectReplication,
38 } {
39 wg.Add(1)
40 go func(f func()) {
41 defer wg.Done()
42 f()
43 }(fn)
44 }
45 wg.Wait()
46
47 // These use cached discovery data, no API calls.
48 c.collectHardwareHealth()
49 c.collectNASStatus()
50
51 return nil
52 }
53
54 func (c *Collector) discovery() error {
55 start := time.Now()
56 c.Debugf("starting discovery")
57
58 // Build results in a temp struct; only swap on full success.
59 var d discovered
60
61 clusters, err := c.client.Clusters()
62 if err != nil {
63 c.lastDiscoveryOK = false
64 return err
65 }
66 d.clusters = clusters
67
68 appliances, err := c.client.Appliances()
69 if err != nil {
70 c.lastDiscoveryOK = false
71 return err
72 }
73 d.appliances = make(map[string]client.Appliance, len(appliances))
74 for _, a := range appliances {
75 d.appliances[a.ID] = a
76 }
77
78 volumes, err := c.client.Volumes()
79 if err != nil {
80 c.lastDiscoveryOK = false
81 return err
82 }
83 d.volumes = make(map[string]client.Volume, len(volumes))
84 for _, v := range volumes {
85 if c.volumeMatches(v.Name) {
86 d.volumes[v.ID] = v
87 }
88 }
89
90 allHW, err := c.client.AllHardware()
91 if err != nil {
92 c.lastDiscoveryOK = false
93 return err
94 }
95 d.hardware = allHW
96 d.nodes = make(map[string]client.Node)
97 d.drives = make(map[string]client.Hardware)
98 for _, h := range allHW {
99 switch h.Type {
100 case "Node":
101 d.nodes[h.ID] = client.Node{ID: h.ID, Name: h.Name, ApplianceID: h.ApplianceID}
102 case "Drive":
103 d.drives[h.ID] = h
104 }
105 }
106
107 fcPorts, err := c.client.FcPorts()
108 if err != nil {
109 c.lastDiscoveryOK = false
110 return err
111 }
112 d.fcPorts = make(map[string]client.FcPort, len(fcPorts))
113 for _, p := range fcPorts {
114 d.fcPorts[p.ID] = p
115 }
116
117 ethPorts, err := c.client.EthPorts()
118 if err != nil {
119 c.lastDiscoveryOK = false
120 return err
121 }
122 d.ethPorts = make(map[string]client.EthPort, len(ethPorts))
123 for _, p := range ethPorts {
124 d.ethPorts[p.ID] = p
125 }
126
127 fileSystems, err := c.client.FileSystems()
128 if err != nil {
129 c.lastDiscoveryOK = false
130 return err
131 }
132 d.fileSystems = make(map[string]client.FileSystem, len(fileSystems))
133 for _, fs := range fileSystems {
134 d.fileSystems[fs.ID] = fs
135 }
136
137 nas, err := c.client.NASServers()
138 if err != nil {
139 c.lastDiscoveryOK = false
140 return err
141 }
142 d.nasServers = make(map[string]client.NAS, len(nas))
143 for _, n := range nas {
144 d.nasServers[n.ID] = n
145 }
146
147 // All API calls succeeded — atomic swap.
148 c.discovered = d
149 c.lastDiscoveryOK = true
150
151 c.Debugf("discovery: %d clusters, %d appliances, %d volumes, %d nodes, %d FC ports, %d ETH ports, %d file systems, %d NAS servers, %d drives (took %s)",
152 len(d.clusters), len(d.appliances), len(d.volumes), len(d.nodes),
153 len(d.fcPorts), len(d.ethPorts), len(d.fileSystems), len(d.nasServers), len(d.drives),
154 time.Since(start))
155
156 return nil
157 }