object_manager_dtc_pool.go raw
1 package ibclient
2
3 import (
4 "encoding/json"
5 "fmt"
6 "reflect"
7 )
8
9 type Monitor struct {
10 Name string
11 Type string
12 }
13
14 // Updating Servers in DtcServerLink with reference
15 func updateServerReferences(servers []*DtcServerLink, objMgr *ObjectManager) error {
16 for _, link := range servers {
17 sf := map[string]string{"name": link.Server}
18 queryParams := NewQueryParams(false, sf)
19 var serverResult []DtcServer
20 err := objMgr.connector.GetObject(&DtcServer{}, "dtc:server", queryParams, &serverResult)
21 if err != nil {
22 return fmt.Errorf("error getting Dtc Server %s, err: %s", link.Server, err)
23 }
24 if len(serverResult) > 0 {
25 link.Server = serverResult[0].Ref
26 }
27 }
28 return nil
29 }
30
31 // get the monitor reference
32 func getMonitorReference(monitorName string, monitorType string, objMgr *ObjectManager) (string, error) {
33 if monitorType == "" {
34 return "", nil
35 }
36 fields := map[string]string{"name": monitorName}
37 queryParams := NewQueryParams(false, fields)
38 var monitorResult []DtcMonitorHttp
39
40 monitorTypeKey := fmt.Sprintf("dtc:monitor:%s", monitorType)
41 err := objMgr.connector.GetObject(&DtcMonitorHttp{}, monitorTypeKey, queryParams, &monitorResult)
42 if err != nil {
43 return "", fmt.Errorf("error getting Dtc Monitor object %s, err: %s", monitorName, err)
44 }
45 if len(monitorResult) > 0 {
46 return monitorResult[0].Ref, nil
47 }
48 return "", fmt.Errorf("Dtc Monitor with name %s not found", monitorName)
49 }
50
51 func (cm ConsolidatedMonitorsWrapper) MarshalJSON() ([]byte, error) {
52 if !cm.IsNull {
53 if reflect.DeepEqual(cm.ConsolidatedMonitors, []*DtcPoolConsolidatedMonitorHealth{}) {
54 return []byte("[]"), nil
55 }
56 }
57 return json.Marshal(cm.ConsolidatedMonitors)
58 }
59
60 func (cm *ConsolidatedMonitorsWrapper) UnmarshalJSON(data []byte) error {
61 if string(data) == "null" {
62 cm.IsNull = true
63 cm.ConsolidatedMonitors = nil
64 return nil
65 }
66 cm.IsNull = false
67 return json.Unmarshal(data, &cm.ConsolidatedMonitors)
68 }
69
70 type ConsolidatedMonitorsWrapper struct {
71 ConsolidatedMonitors []*DtcPoolConsolidatedMonitorHealth
72 IsNull bool
73 }
74
75 func (d *DtcPool) MarshalJSON() ([]byte, error) {
76 type Alias DtcPool
77 aux := &struct {
78 Monitors []string `json:"monitors"`
79 Servers []*DtcServerLink `json:"servers"`
80 ConsolidatedMonitors *ConsolidatedMonitorsWrapper `json:"consolidated_monitors,omitempty"`
81 *Alias
82 }{
83 Alias: (*Alias)(d),
84 }
85 // Convert Monitors to a slice of strings
86 if len(d.Monitors) == 0 {
87 aux.Monitors = []string{}
88 } else {
89 for _, monitor := range d.Monitors {
90 if monitor != nil {
91 aux.Monitors = append(aux.Monitors, monitor.Ref)
92 }
93 }
94 }
95
96 // Unsetting Servers if they are empty
97 if len(d.Servers) == 0 {
98 aux.Servers = []*DtcServerLink{}
99 } else {
100 aux.Servers = d.Servers
101 }
102
103 // Conditionally handle ConsolidatedMonitors
104 if d.AutoConsolidatedMonitors != nil {
105 if *d.AutoConsolidatedMonitors {
106 // auto_consolidated_monitors = true
107 if d.ConsolidatedMonitors != nil {
108 // consolidated_monitors is empty, omit it
109 aux.ConsolidatedMonitors = nil
110 }
111 } else {
112 // auto_consolidated_monitors = false
113 if len(d.ConsolidatedMonitors) == 0 {
114 // consolidated_monitors is empty, marshal as "[]"
115 aux.ConsolidatedMonitors = &ConsolidatedMonitorsWrapper{IsNull: false, ConsolidatedMonitors: []*DtcPoolConsolidatedMonitorHealth{}}
116 } else {
117 // consolidated_monitors is non-empty, marshal as is
118 aux.ConsolidatedMonitors = &ConsolidatedMonitorsWrapper{IsNull: false, ConsolidatedMonitors: d.ConsolidatedMonitors}
119 }
120 }
121 }
122
123 return json.Marshal(aux)
124 }
125 func (d *DtcPool) UnmarshalJSON(data []byte) error {
126 type Alias DtcPool
127 aux := &struct {
128 Monitors []string `json:"monitors,omitempty"`
129 *Alias
130 }{
131 Alias: (*Alias)(d),
132 }
133
134 if err := json.Unmarshal(data, &aux); err != nil {
135 return err
136 }
137 // Convert Monitors from []string to []*DtcMonitorHttp
138 for _, ref := range aux.Monitors {
139 d.Monitors = append(d.Monitors, &DtcMonitorHttp{Ref: ref})
140 }
141
142 return nil
143 }
144
145 func NewEmptyDtcPool() *DtcPool {
146 poolDtc := &DtcPool{}
147 poolDtc.SetReturnFields(append(poolDtc.ReturnFields(), "lb_preferred_method", "servers", "lb_dynamic_ratio_preferred", "monitors", "auto_consolidated_monitors", "consolidated_monitors", "disable",
148 "extattrs", "health", "lb_alternate_method", "lb_alternate_topology", "lb_dynamic_ratio_alternate", "lb_preferred_topology", "quorum", "ttl", "use_ttl", "availability"))
149
150 return poolDtc
151 }
152
153 func NewDtcPool(comment string,
154 name string,
155 lbPreferredMethod string,
156 lbDynamicRatioPreferred *SettingDynamicratio,
157 servers []*DtcServerLink,
158 monitors []*DtcMonitorHttp,
159 lbPreferredTopology *string,
160 lbAlternateMethod string,
161 lbAlternateTopology *string,
162 lbDynamicRatioAlternate *SettingDynamicratio,
163 eas EA,
164 autoConsolidatedMonitors bool,
165 availability string,
166 consolidatedMonitors []*DtcPoolConsolidatedMonitorHealth,
167 ttl uint32,
168 useTTL bool,
169 disable bool,
170 quorum uint32) *DtcPool {
171 DtcPool := NewEmptyDtcPool()
172 DtcPool.Comment = &comment
173 DtcPool.Name = &name
174 DtcPool.LbPreferredMethod = lbPreferredMethod
175 DtcPool.Servers = servers
176 DtcPool.LbDynamicRatioPreferred = lbDynamicRatioPreferred
177 DtcPool.Monitors = monitors
178 DtcPool.LbPreferredTopology = lbPreferredTopology
179 DtcPool.LbAlternateMethod = lbAlternateMethod
180 DtcPool.LbAlternateTopology = lbAlternateTopology
181 DtcPool.LbDynamicRatioAlternate = lbDynamicRatioAlternate
182 DtcPool.Ea = eas
183 DtcPool.AutoConsolidatedMonitors = &autoConsolidatedMonitors
184 DtcPool.Availability = availability
185 DtcPool.ConsolidatedMonitors = consolidatedMonitors
186 DtcPool.Ttl = &ttl
187 DtcPool.UseTtl = &useTTL
188 DtcPool.Disable = &disable
189 DtcPool.Quorum = &quorum
190 return DtcPool
191 }
192
193 func (objMgr *ObjectManager) CreateDtcPool(
194 comment string,
195 name string,
196 lbPreferredMethod string,
197 lbDynamicRatioPreferred map[string]interface{},
198 servers []*DtcServerLink,
199 monitors []Monitor,
200 lbPreferredTopology *string,
201 lbAlternateMethod string,
202 lbAlternateTopology *string,
203 lbDynamicRatioAlternate map[string]interface{},
204 eas EA,
205 autoConsolidatedMonitors bool,
206 userMonitors []map[string]interface{},
207 availability string,
208 ttl uint32,
209 useTTL bool,
210 disable bool,
211 quorum uint32) (*DtcPool, error) {
212 if name == "" || lbPreferredMethod == "" {
213 return nil, fmt.Errorf("name and preferred load balancing method must be provided to create a pool")
214 }
215 if lbPreferredMethod == "DYNAMIC_RATIO" && lbDynamicRatioPreferred == nil {
216 return nil, fmt.Errorf("LbDynamicRatioPreferred cannot be nil when the preferred load balancing method is set to DYNAMIC_RATIO")
217 }
218 if lbPreferredMethod == "TOPOLOGY" && lbPreferredTopology == nil {
219 return nil, fmt.Errorf("preferred topology cannot be nil when preferred load balancing method is set to TOPOLOGY")
220 }
221 //update servers with server references
222 err := updateServerReferences(servers, objMgr)
223 if err != nil {
224 return nil, err
225 }
226 // update the monitor in LbDynamicRatioPreferred with reference
227 var lbDynamicRatioPreferredMethod *SettingDynamicratio
228 if lbDynamicRatioPreferred != nil {
229 monitor, _ := lbDynamicRatioPreferred["monitor"].(Monitor)
230 method, _ := lbDynamicRatioPreferred["method"].(string)
231 monitorMetric, _ := lbDynamicRatioPreferred["monitor_metric"].(string)
232 monitorWeighing, _ := lbDynamicRatioPreferred["monitor_weighing"].(string)
233 invertMonitorMetric, _ := lbDynamicRatioPreferred["invert_monitor_metric"].(bool)
234
235 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
236 if err != nil {
237 return nil, err
238 }
239 lbDynamicRatioPreferredMethod = &SettingDynamicratio{
240 Method: method,
241 Monitor: monitorRef,
242 MonitorMetric: monitorMetric,
243 MonitorWeighing: monitorWeighing,
244 InvertMonitorMetric: invertMonitorMetric,
245 }
246 } else {
247 lbDynamicRatioPreferredMethod = nil
248 }
249
250 // Convert monitor names to monitor references
251 var monitorResults []*DtcMonitorHttp
252 for _, monitor := range monitors {
253 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
254 if err != nil {
255 return nil, err
256 }
257 monitorResults = append(monitorResults, &DtcMonitorHttp{Ref: monitorRef})
258 }
259 //Update the topology name with the topology reference
260 if lbPreferredTopology != nil {
261 topology, err := getTopology(*lbPreferredTopology, objMgr)
262 if err != nil {
263 return nil, err
264 }
265 lbPreferredTopology = &topology
266 }
267
268 //Update the topology name with the topology reference
269 if lbAlternateTopology != nil {
270 topologyAlternate, err := getTopology(*lbAlternateTopology, objMgr)
271 if err != nil {
272 return nil, err
273 }
274 lbAlternateTopology = &topologyAlternate
275 }
276 //update the monitor in LbDynamicRatioPreferred with reference
277 var lbDynamicRatioAlternateMethod *SettingDynamicratio
278 if lbDynamicRatioAlternate != nil {
279 monitorAlternate, _ := lbDynamicRatioAlternate["monitor"].(Monitor)
280 methodAlternate, _ := lbDynamicRatioAlternate["method"].(string)
281 monitorMetricAlternate, _ := lbDynamicRatioAlternate["monitor_metric"].(string)
282 monitorWeighingAlternate, _ := lbDynamicRatioAlternate["monitor_weighing"].(string)
283 interferometricAlternate, _ := lbDynamicRatioAlternate["invert_monitor_metric"].(bool)
284
285 monitorRefAlternate, err := getMonitorReference(monitorAlternate.Name, monitorAlternate.Type, objMgr)
286 if err != nil {
287 return nil, err
288 }
289 lbDynamicRatioAlternateMethod = &SettingDynamicratio{
290 Method: methodAlternate,
291 Monitor: monitorRefAlternate,
292 MonitorMetric: monitorMetricAlternate,
293 MonitorWeighing: monitorWeighingAlternate,
294 InvertMonitorMetric: interferometricAlternate,
295 }
296 } else {
297 lbDynamicRatioAlternateMethod = nil
298 }
299
300 var consolidatedMonitors []*DtcPoolConsolidatedMonitorHealth
301 if userMonitors != nil {
302 if len(userMonitors) == 0 {
303 consolidatedMonitors = []*DtcPoolConsolidatedMonitorHealth{}
304 } else {
305 for _, userMonitor := range userMonitors {
306 monitor, okMonitor := userMonitor["monitor"].(Monitor)
307 monitorAvailability, okAvail := userMonitor["availability"].(string)
308 fullHealthComm, _ := userMonitor["full_health_communication"].(bool)
309 members, okMember := userMonitor["members"].([]string)
310 if !okMonitor {
311 return nil, fmt.Errorf("required field missing: monitor")
312 }
313
314 if !okAvail {
315 return nil, fmt.Errorf("required field missing: availability")
316 }
317
318 if !okMember {
319 return nil, fmt.Errorf("required field missing: members")
320 }
321 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
322 if err != nil {
323 return nil, err
324 }
325
326 consolidatedMonitor := &DtcPoolConsolidatedMonitorHealth{
327 Members: members,
328 Monitor: monitorRef,
329 Availability: monitorAvailability,
330 FullHealthCommunication: fullHealthComm,
331 }
332 consolidatedMonitors = append(consolidatedMonitors, consolidatedMonitor)
333 }
334 }
335 }
336 // Create the DtcPool
337 poolDtc := NewDtcPool(comment, name, lbPreferredMethod, lbDynamicRatioPreferredMethod, servers, monitorResults, lbPreferredTopology, lbAlternateMethod, lbAlternateTopology, lbDynamicRatioAlternateMethod, eas, autoConsolidatedMonitors, availability, consolidatedMonitors, ttl, useTTL, disable, quorum)
338 ref, err := objMgr.connector.CreateObject(poolDtc)
339 if err != nil {
340 return nil, err
341 }
342 poolDtc.Ref = ref
343 return poolDtc, nil
344 }
345
346 func (objMgr *ObjectManager) GetAllDtcPool(queryParams *QueryParams) ([]DtcPool, error) {
347 var res []DtcPool
348 pool := NewEmptyDtcPool()
349 err := objMgr.connector.GetObject(pool, "", queryParams, &res)
350 if err != nil {
351 return nil, fmt.Errorf("error getting Dtc Pool object, err: %s", err)
352 }
353 return res, nil
354 }
355
356 func (objMgr *ObjectManager) UpdateDtcPool(
357 ref string,
358 comment string,
359 name string,
360 lbPreferredMethod string,
361 lbDynamicRatioPreferred map[string]interface{},
362 servers []*DtcServerLink,
363 monitors []Monitor,
364 lbPreferredTopology *string,
365 lbAlternateMethod string,
366 lbAlternateTopology *string,
367 lbDynamicRatioAlternate map[string]interface{},
368 eas EA,
369 autoConsolidatedMonitors bool,
370 availability string,
371 userMonitors []map[string]interface{},
372 ttl uint32,
373 useTTL bool,
374 disable bool,
375 quorum uint32) (*DtcPool, error) {
376 if lbPreferredMethod == "DYNAMIC_RATIO" && lbDynamicRatioPreferred == nil {
377 return nil, fmt.Errorf("LbDynamicRatioPreferred cannot be nil when the preferred load balancing method is set to DYNAMIC_RATIO")
378 }
379 if lbPreferredMethod == "TOPOLOGY" && lbPreferredTopology == nil {
380 return nil, fmt.Errorf("preferred topology cannot be nil when preferred load balancing method is set to TOPOLOGY")
381 }
382 if autoConsolidatedMonitors && len(userMonitors) > 0 {
383 return nil, fmt.Errorf("either AutoConsolidatedMonitors or ConsolidatedMonitors should be set.")
384 }
385 //update servers with server references
386 err := updateServerReferences(servers, objMgr)
387 if err != nil {
388 return nil, err
389 }
390 // Convert LbDynamicRatioPreferred to use monitor reference
391 var lbDynamicRatioPreferredMethod *SettingDynamicratio
392 if lbDynamicRatioPreferred != nil {
393 monitor, _ := lbDynamicRatioPreferred["monitor"].(Monitor)
394 method, _ := lbDynamicRatioPreferred["method"].(string)
395 monitorMetric, _ := lbDynamicRatioPreferred["monitor_metric"].(string)
396 monitorWeighing, _ := lbDynamicRatioPreferred["monitor_weighing"].(string)
397 invertMonitorMetric, _ := lbDynamicRatioPreferred["invert_monitor_metric"].(bool)
398
399 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
400 if err != nil {
401 return nil, err
402 }
403 lbDynamicRatioPreferredMethod = &SettingDynamicratio{
404 Method: method,
405 Monitor: monitorRef,
406 MonitorMetric: monitorMetric,
407 MonitorWeighing: monitorWeighing,
408 InvertMonitorMetric: invertMonitorMetric,
409 }
410 } else {
411 lbDynamicRatioPreferredMethod = nil
412 }
413 // Convert monitor names to monitor references
414 var monitorResults []*DtcMonitorHttp
415 for _, monitor := range monitors {
416 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
417 if err != nil {
418 return nil, err
419 }
420 monitorResults = append(monitorResults, &DtcMonitorHttp{Ref: monitorRef})
421 }
422 //Update the topology name with the topology reference
423 if lbPreferredTopology != nil {
424 topology, err := getTopology(*lbPreferredTopology, objMgr)
425 if err != nil {
426 return nil, err
427 }
428 lbPreferredTopology = &topology
429 }
430 //Update the topology name with the topology reference
431 if lbAlternateTopology != nil {
432 topologyAlternate, err := getTopology(*lbAlternateTopology, objMgr)
433 if err != nil {
434 return nil, err
435 }
436 lbAlternateTopology = &topologyAlternate
437 }
438 //Convert LbDynamicRatioAlternate to use monitor reference
439 var lbDynamicRatioAlternateMethod *SettingDynamicratio
440 if lbDynamicRatioAlternate != nil {
441 monitorAlternate, _ := lbDynamicRatioAlternate["monitor"].(Monitor)
442 methodAlternate, _ := lbDynamicRatioAlternate["method"].(string)
443 monitorMetricAlternate, _ := lbDynamicRatioAlternate["monitor_metric"].(string)
444 monitorWeighingAlternate, _ := lbDynamicRatioAlternate["monitor_weighing"].(string)
445 invertMonitorMetricAlternate, _ := lbDynamicRatioAlternate["invert_monitor_metric"].(bool)
446
447 monitorRefAlternate, err := getMonitorReference(monitorAlternate.Name, monitorAlternate.Type, objMgr)
448 if err != nil {
449 return nil, err
450 }
451 lbDynamicRatioAlternateMethod = &SettingDynamicratio{
452 Method: methodAlternate,
453 Monitor: monitorRefAlternate,
454 MonitorMetric: monitorMetricAlternate,
455 MonitorWeighing: monitorWeighingAlternate,
456 InvertMonitorMetric: invertMonitorMetricAlternate,
457 }
458 } else {
459 lbDynamicRatioAlternateMethod = nil
460 }
461 //processing user input to retrieve monitor references and creating a slice of *DtcPoolConsolidatedMonitorHealth structs with updated monitor references.
462 var consolidatedMonitors []*DtcPoolConsolidatedMonitorHealth
463 if userMonitors != nil {
464 if len(userMonitors) == 0 {
465 consolidatedMonitors = []*DtcPoolConsolidatedMonitorHealth{}
466 } else {
467 for _, userMonitor := range userMonitors {
468 monitor, okMonitor := userMonitor["monitor"].(Monitor)
469 monitorAvailability, okAvail := userMonitor["availability"].(string)
470 fullHealthComm, _ := userMonitor["full_health_communication"].(bool)
471 members, okMember := userMonitor["members"].([]string)
472 if !okMonitor {
473 return nil, fmt.Errorf("required field missing: monitor")
474 }
475
476 if !okAvail {
477 return nil, fmt.Errorf("required field missing: availability")
478 }
479
480 if !okMember {
481 return nil, fmt.Errorf("required field missing: members")
482 }
483 monitorRef, err := getMonitorReference(monitor.Name, monitor.Type, objMgr)
484 if err != nil {
485 return nil, err
486 }
487
488 consolidatedMonitor := &DtcPoolConsolidatedMonitorHealth{
489 Members: members,
490 Monitor: monitorRef,
491 Availability: monitorAvailability,
492 FullHealthCommunication: fullHealthComm,
493 }
494 consolidatedMonitors = append(consolidatedMonitors, consolidatedMonitor)
495 }
496 }
497 }
498
499 poolDtc := NewDtcPool(comment, name, lbPreferredMethod, lbDynamicRatioPreferredMethod, servers, monitorResults, lbPreferredTopology, lbAlternateMethod, lbAlternateTopology, lbDynamicRatioAlternateMethod, eas, autoConsolidatedMonitors, availability, consolidatedMonitors, ttl, useTTL, disable, quorum)
500 poolDtc.Ref = ref
501 reference, err := objMgr.connector.UpdateObject(poolDtc, ref)
502 if err != nil {
503 return nil, err
504 }
505 poolDtc.Ref = reference
506
507 poolDtc, err = objMgr.GetDtcPoolByRef(reference)
508 if err != nil {
509 return nil, err
510 }
511
512 return poolDtc, nil
513
514 }
515
516 func (objMgr *ObjectManager) GetDtcPoolByRef(ref string) (*DtcPool, error) {
517 poolDtc := NewEmptyDtcPool()
518 err := objMgr.connector.GetObject(
519 poolDtc, ref, NewQueryParams(false, nil), &poolDtc)
520 return poolDtc, err
521 }
522
523 func (objMgr *ObjectManager) GetDtcPool(name string) (*DtcPool, error) {
524 dtcPool := NewEmptyDtcPool()
525 var res []DtcPool
526 if name == "" {
527 return nil, fmt.Errorf("name of the record is required to retrieve a unique Dtc Pool record")
528 }
529 sf := map[string]string{
530 "name": name,
531 }
532 queryParams := NewQueryParams(false, sf)
533 err := objMgr.connector.GetObject(dtcPool, "", queryParams, &res)
534 if err != nil {
535 return nil, err
536 } else if res == nil || len(res) == 0 {
537 return nil, NewNotFoundError(
538 fmt.Sprintf("Dtc Pool record with name '%s' not found", name))
539 }
540 return &res[0], nil
541 }
542
543 func (objMgr *ObjectManager) DeleteDtcPool(ref string) (string, error) {
544 return objMgr.connector.DeleteObject(ref)
545 }
546