master
go 240 lines 5.55 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package discover
4
5 import (
6 "time"
7
8 rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources"
9 )
10
11 const maxHierarchyParentDepth = 64
12
13 func (d Discoverer) setHierarchy(res *rs.Resources) error {
14 d.Debug("discovering : hierarchy : start setting resources hierarchy process")
15 t := time.Now()
16
17 c := d.setClustersHierarchy(res)
18 h := d.setHostsHierarchy(res)
19 v := d.setVMsHierarchy(res)
20 ds := d.setDatastoresHierarchy(res)
21 nw := d.setNetworksHierarchy(res)
22 sp := d.setStoragePodsHierarchy(res)
23 rp := d.setResourcePoolsHierarchy(res)
24
25 d.Infof("discovering : hierarchy : set %d/%d clusters, %d/%d hosts, %d/%d vms, %d/%d datastores, %d/%d networks, %d/%d datastore clusters, %d/%d resource pools, process took %s",
26 c, len(res.Clusters),
27 h, len(res.Hosts),
28 v, len(res.VMs),
29 ds, len(res.Datastores),
30 nw, len(res.Networks),
31 sp, len(res.StoragePods),
32 rp, len(res.ResourcePools),
33 time.Since(t),
34 )
35
36 return nil
37 }
38
39 func (d Discoverer) setClustersHierarchy(res *rs.Resources) (set int) {
40 for _, cluster := range res.Clusters {
41 if setClusterHierarchy(cluster, res) {
42 set++
43 }
44 }
45 return set
46 }
47
48 func (d Discoverer) setHostsHierarchy(res *rs.Resources) (set int) {
49 for _, host := range res.Hosts {
50 if setHostHierarchy(host, res) {
51 set++
52 }
53 }
54 return set
55 }
56
57 func (d Discoverer) setVMsHierarchy(res *rs.Resources) (set int) {
58 for _, vm := range res.VMs {
59 if setVMHierarchy(vm, res) {
60 set++
61 }
62 }
63 return set
64 }
65
66 func setClusterHierarchy(cluster *rs.Cluster, res *rs.Resources) bool {
67 dc := res.DataCenters.Get(cluster.ParentID)
68 if dc == nil {
69 return false
70 }
71 cluster.Hier.DC.Set(dc.ID, dc.Name)
72 return cluster.Hier.IsSet()
73 }
74
75 func setHostHierarchy(host *rs.Host, res *rs.Resources) bool {
76 cr := res.Clusters.Get(host.ParentID)
77 if cr == nil {
78 return false
79 }
80 host.Hier.Cluster.Set(cr.ID, cr.Name)
81
82 dc := res.DataCenters.Get(cr.ParentID)
83 if dc == nil {
84 return false
85 }
86 host.Hier.DC.Set(dc.ID, dc.Name)
87 return host.Hier.IsSet()
88 }
89
90 func setVMHierarchy(vm *rs.VM, res *rs.Resources) bool {
91 if setVMHostHierarchy(vm, res) {
92 return true
93 }
94 return setVMFolderHierarchy(vm, res)
95 }
96
97 func setVMHostHierarchy(vm *rs.VM, res *rs.Resources) bool {
98 h := res.Hosts.Get(vm.ParentID)
99 if h == nil {
100 return false
101 }
102 vm.Hier.Host.Set(h.ID, h.Name)
103
104 cr := res.Clusters.Get(h.ParentID)
105 if cr == nil {
106 return false
107 }
108 vm.Hier.Cluster.Set(cr.ID, cr.Name)
109
110 dc := res.DataCenters.Get(cr.ParentID)
111 if dc == nil {
112 return false
113 }
114 vm.Hier.DC.Set(dc.ID, dc.Name)
115 return vm.Hier.IsSet()
116 }
117
118 func setVMFolderHierarchy(vm *rs.VM, res *rs.Resources) bool {
119 dcID := findVMDcID(vm.FolderParentID, res.Folders)
120 dc := res.DataCenters.Get(dcID)
121 if dc == nil {
122 return false
123 }
124 vm.Hier.DC.Set(dc.ID, dc.Name)
125 return vm.Hier.DC.IsSet()
126 }
127
128 func findVMDcID(parentID string, folders rs.Folders) string {
129 return findFolderRootID(parentID, folders)
130 }
131
132 func (d Discoverer) setDatastoresHierarchy(res *rs.Resources) (set int) {
133 for _, ds := range res.Datastores {
134 if setDatastoreHierarchy(ds, res) {
135 set++
136 }
137 }
138 return set
139 }
140
141 // Datastore parent is a folder (group-s*) which resolves to a datacenter.
142 func setDatastoreHierarchy(ds *rs.Datastore, res *rs.Resources) bool {
143 dcID := findDatastoreDcID(ds.ParentID, res.Folders)
144 dc := res.DataCenters.Get(dcID)
145 if dc == nil {
146 return false
147 }
148 ds.Hier.DC.Set(dc.ID, dc.Name)
149 return ds.Hier.IsSet()
150 }
151
152 func findDatastoreDcID(parentID string, folders rs.Folders) string {
153 return findFolderRootID(parentID, folders)
154 }
155
156 func (d Discoverer) setNetworksHierarchy(res *rs.Resources) (set int) {
157 for _, network := range res.Networks {
158 if setNetworkHierarchy(network, res) {
159 set++
160 }
161 }
162 return set
163 }
164
165 // Network parent is normally a network folder (group-n*) which resolves to a datacenter.
166 func setNetworkHierarchy(network *rs.Network, res *rs.Resources) bool {
167 dcID := findNetworkDcID(network.ParentID, res.Folders)
168 dc := res.DataCenters.Get(dcID)
169 if dc == nil {
170 return false
171 }
172 network.Hier.DC.Set(dc.ID, dc.Name)
173 return network.Hier.IsSet()
174 }
175
176 func findNetworkDcID(parentID string, folders rs.Folders) string {
177 return findFolderRootID(parentID, folders)
178 }
179
180 func findFolderRootID(parentID string, folders rs.Folders) string {
181 seen := make(map[string]struct{})
182 for depth := 0; parentID != "" && depth < maxHierarchyParentDepth; depth++ {
183 if _, ok := seen[parentID]; ok {
184 return ""
185 }
186 seen[parentID] = struct{}{}
187
188 f := folders.Get(parentID)
189 if f == nil {
190 return parentID
191 }
192 parentID = f.ParentID
193 }
194 return parentID
195 }
196
197 func (d Discoverer) setStoragePodsHierarchy(res *rs.Resources) (set int) {
198 for _, pod := range res.StoragePods {
199 if setStoragePodHierarchy(pod, res) {
200 set++
201 }
202 }
203 return set
204 }
205
206 // StoragePod parent is a folder (group-s*) which resolves to a datacenter.
207 func setStoragePodHierarchy(pod *rs.StoragePod, res *rs.Resources) bool {
208 dcID := findDatastoreDcID(pod.ParentID, res.Folders)
209 dc := res.DataCenters.Get(dcID)
210 if dc == nil {
211 return false
212 }
213 pod.Hier.DC.Set(dc.ID, dc.Name)
214 return pod.Hier.IsSet()
215 }
216
217 func (d Discoverer) setResourcePoolsHierarchy(res *rs.Resources) (set int) {
218 for _, rp := range res.ResourcePools {
219 if setResourcePoolHierarchy(rp, res) {
220 set++
221 }
222 }
223 return set
224 }
225
226 // Resource pool owner is a cluster. Resolve DC from the cluster.
227 func setResourcePoolHierarchy(rp *rs.ResourcePool, res *rs.Resources) bool {
228 cr := res.Clusters.Get(rp.ParentID)
229 if cr == nil {
230 return false
231 }
232 rp.Hier.Cluster.Set(cr.ID, cr.Name)
233
234 dc := res.DataCenters.Get(cr.ParentID)
235 if dc == nil {
236 return false
237 }
238 rp.Hier.DC.Set(dc.ID, dc.Name)
239 return rp.Hier.IsSet()
240 }