github.com/vmware/govmomi@v0.51.0/alarm/manager.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package alarm 6 7 import ( 8 "context" 9 10 "github.com/vmware/govmomi/event" 11 "github.com/vmware/govmomi/find" 12 "github.com/vmware/govmomi/object" 13 "github.com/vmware/govmomi/property" 14 "github.com/vmware/govmomi/vim25" 15 "github.com/vmware/govmomi/vim25/methods" 16 "github.com/vmware/govmomi/vim25/mo" 17 "github.com/vmware/govmomi/vim25/types" 18 ) 19 20 type Manager struct { 21 object.Common 22 23 pc *property.Collector 24 } 25 26 var Severity = map[types.ManagedEntityStatus]string{ 27 types.ManagedEntityStatusGray: "Unknown", 28 types.ManagedEntityStatusGreen: "Normal", 29 types.ManagedEntityStatusYellow: "Warning", 30 types.ManagedEntityStatusRed: "Alert", 31 } 32 33 // GetManager wraps NewManager, returning ErrNotSupported 34 // when the client is not connected to a vCenter instance. 35 func GetManager(c *vim25.Client) (*Manager, error) { 36 if c.ServiceContent.AlarmManager == nil { 37 return nil, object.ErrNotSupported 38 } 39 return NewManager(c), nil 40 } 41 42 func NewManager(c *vim25.Client) *Manager { 43 m := Manager{ 44 Common: object.NewCommon(c, *c.ServiceContent.AlarmManager), 45 pc: property.DefaultCollector(c), 46 } 47 48 return &m 49 } 50 51 func (m Manager) CreateAlarm(ctx context.Context, entity object.Reference, spec types.BaseAlarmSpec) (*types.ManagedObjectReference, error) { 52 req := types.CreateAlarm{ 53 This: m.Reference(), 54 Entity: entity.Reference(), 55 Spec: spec, 56 } 57 58 res, err := methods.CreateAlarm(ctx, m.Client(), &req) 59 if err != nil { 60 return nil, err 61 } 62 return &res.Returnval, err 63 } 64 65 func (m Manager) AcknowledgeAlarm(ctx context.Context, alarm types.ManagedObjectReference, entity object.Reference) error { 66 req := types.AcknowledgeAlarm{ 67 This: m.Reference(), 68 Alarm: alarm, 69 Entity: entity.Reference(), 70 } 71 72 _, err := methods.AcknowledgeAlarm(ctx, m.Client(), &req) 73 74 return err 75 } 76 77 // GetAlarm returns available alarms defined on the entity. 78 func (m Manager) GetAlarm(ctx context.Context, entity object.Reference) ([]mo.Alarm, error) { 79 req := types.GetAlarm{ 80 This: m.Reference(), 81 } 82 83 if entity != nil { 84 req.Entity = types.NewReference(entity.Reference()) 85 } 86 87 res, err := methods.GetAlarm(ctx, m.Client(), &req) 88 if err != nil { 89 return nil, err 90 } 91 92 if len(res.Returnval) == 0 { 93 return nil, nil 94 } 95 96 alarms := make([]mo.Alarm, 0, len(res.Returnval)) 97 98 err = m.pc.Retrieve(ctx, res.Returnval, []string{"info"}, &alarms) 99 if err != nil { 100 return nil, err 101 } 102 103 return alarms, nil 104 } 105 106 // StateInfo combines AlarmState with Alarm.Info 107 type StateInfo struct { 108 types.AlarmState 109 Info *types.AlarmInfo `json:"name,omitempty"` 110 Path string `json:"path,omitempty"` 111 Event types.BaseEvent `json:"event,omitempty"` 112 } 113 114 // StateInfoOptions for the GetStateInfo method 115 type StateInfoOptions struct { 116 Declared bool 117 InventoryPath bool 118 Event bool 119 } 120 121 // GetStateInfo combines AlarmState with Alarm.Info 122 func (m Manager) GetStateInfo(ctx context.Context, entity object.Reference, opts StateInfoOptions) ([]StateInfo, error) { 123 prop := "triggeredAlarmState" 124 if opts.Declared { 125 prop = "declaredAlarmState" 126 opts.Event = false 127 } 128 129 var e mo.ManagedEntity 130 131 err := m.pc.RetrieveOne(ctx, entity.Reference(), []string{prop}, &e) 132 if err != nil { 133 return nil, err 134 } 135 136 var objs []types.ManagedObjectReference 137 alarms := append(e.DeclaredAlarmState, e.TriggeredAlarmState...) 138 if len(alarms) == 0 { 139 return nil, nil 140 } 141 for i := range alarms { 142 objs = append(objs, alarms[i].Alarm) 143 } 144 145 var info []mo.Alarm 146 err = m.pc.Retrieve(ctx, objs, []string{"info"}, &info) 147 if err != nil { 148 return nil, err 149 } 150 151 state := make([]StateInfo, len(alarms)) 152 paths := make(map[types.ManagedObjectReference]string) 153 154 em := event.NewManager(m.Client()) 155 156 for i, a := range alarms { 157 path := paths[a.Entity] 158 if opts.InventoryPath { 159 if path == "" { 160 path, err = find.InventoryPath(ctx, m.Client(), a.Entity) 161 if err != nil { 162 return nil, err 163 } 164 paths[a.Entity] = path 165 } 166 } else { 167 path = a.Entity.String() 168 } 169 170 state[i] = StateInfo{ 171 AlarmState: a, 172 Path: path, 173 } 174 175 for j := range info { 176 if info[j].Self == a.Alarm { 177 state[i].Info = &info[j].Info 178 break 179 } 180 } 181 182 if !opts.Event || a.EventKey == 0 { 183 continue 184 } 185 186 spec := types.EventFilterSpec{ 187 EventChainId: a.EventKey, 188 Entity: &types.EventFilterSpecByEntity{ 189 Entity: a.Entity, 190 Recursion: types.EventFilterSpecRecursionOptionSelf, 191 }, 192 } 193 194 events, err := em.QueryEvents(ctx, spec) 195 if err != nil { 196 return nil, err 197 } 198 199 for j := range events { 200 if events[j].GetEvent().Key == a.EventKey { 201 state[i].Event = events[j] 202 break 203 } 204 } 205 } 206 207 return state, nil 208 }