github.com/vmware/govmomi@v0.37.1/event/manager.go (about) 1 /* 2 Copyright (c) 2015 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package event 18 19 import ( 20 "context" 21 "fmt" 22 "reflect" 23 "sync" 24 25 "github.com/vmware/govmomi/property" 26 "github.com/vmware/govmomi/vim25" 27 "github.com/vmware/govmomi/vim25/methods" 28 "github.com/vmware/govmomi/vim25/mo" 29 "github.com/vmware/govmomi/vim25/types" 30 ) 31 32 type Manager struct { 33 r types.ManagedObjectReference 34 c *vim25.Client 35 36 eventCategory map[string]string 37 eventCategoryMu *sync.Mutex 38 maxObjects int 39 } 40 41 func NewManager(c *vim25.Client) *Manager { 42 m := Manager{ 43 r: c.ServiceContent.EventManager.Reference(), 44 c: c, 45 eventCategory: make(map[string]string), 46 eventCategoryMu: new(sync.Mutex), 47 maxObjects: 10, 48 } 49 50 return &m 51 } 52 53 // Reference returns the event.Manager MOID 54 func (m Manager) Reference() types.ManagedObjectReference { 55 return m.r 56 } 57 58 func (m Manager) Client() *vim25.Client { 59 return m.c 60 } 61 62 func (m Manager) CreateCollectorForEvents(ctx context.Context, filter types.EventFilterSpec) (*HistoryCollector, error) { 63 req := types.CreateCollectorForEvents{ 64 This: m.r, 65 Filter: filter, 66 } 67 68 res, err := methods.CreateCollectorForEvents(ctx, m.c, &req) 69 if err != nil { 70 return nil, err 71 } 72 73 return newHistoryCollector(m.c, res.Returnval), nil 74 } 75 76 func (m Manager) LogUserEvent(ctx context.Context, entity types.ManagedObjectReference, msg string) error { 77 req := types.LogUserEvent{ 78 This: m.r, 79 Entity: entity, 80 Msg: msg, 81 } 82 83 _, err := methods.LogUserEvent(ctx, m.c, &req) 84 if err != nil { 85 return err 86 } 87 88 return nil 89 } 90 91 func (m Manager) PostEvent(ctx context.Context, eventToPost types.BaseEvent, taskInfo ...types.TaskInfo) error { 92 req := types.PostEvent{ 93 This: m.r, 94 EventToPost: eventToPost, 95 } 96 97 if len(taskInfo) == 1 { 98 req.TaskInfo = &taskInfo[0] 99 } 100 101 _, err := methods.PostEvent(ctx, m.c, &req) 102 if err != nil { 103 return err 104 } 105 106 return nil 107 } 108 109 func (m Manager) QueryEvents(ctx context.Context, filter types.EventFilterSpec) ([]types.BaseEvent, error) { 110 req := types.QueryEvents{ 111 This: m.r, 112 Filter: filter, 113 } 114 115 res, err := methods.QueryEvents(ctx, m.c, &req) 116 if err != nil { 117 return nil, err 118 } 119 120 return res.Returnval, nil 121 } 122 123 func (m Manager) RetrieveArgumentDescription(ctx context.Context, eventTypeID string) ([]types.EventArgDesc, error) { 124 req := types.RetrieveArgumentDescription{ 125 This: m.r, 126 EventTypeId: eventTypeID, 127 } 128 129 res, err := methods.RetrieveArgumentDescription(ctx, m.c, &req) 130 if err != nil { 131 return nil, err 132 } 133 134 return res.Returnval, nil 135 } 136 137 func (m Manager) eventCategoryMap(ctx context.Context) (map[string]string, error) { 138 m.eventCategoryMu.Lock() 139 defer m.eventCategoryMu.Unlock() 140 141 if len(m.eventCategory) != 0 { 142 return m.eventCategory, nil 143 } 144 145 var o mo.EventManager 146 147 ps := []string{"description.eventInfo"} 148 err := property.DefaultCollector(m.c).RetrieveOne(ctx, m.r, ps, &o) 149 if err != nil { 150 return nil, err 151 } 152 153 for _, info := range o.Description.EventInfo { 154 m.eventCategory[info.Key] = info.Category 155 } 156 157 return m.eventCategory, nil 158 } 159 160 // EventCategory returns the category for an event, such as "info" or "error" for example. 161 func (m Manager) EventCategory(ctx context.Context, event types.BaseEvent) (string, error) { 162 // Most of the event details are included in the Event.FullFormattedMessage, but the category 163 // is only available via the EventManager description.eventInfo property. The value of this 164 // property is static, so we fetch and once and cache. 165 eventCategory, err := m.eventCategoryMap(ctx) 166 if err != nil { 167 return "", err 168 } 169 170 switch e := event.(type) { 171 case *types.EventEx: 172 if e.Severity == "" { 173 return "info", nil 174 } 175 return e.Severity, nil 176 } 177 178 class := reflect.TypeOf(event).Elem().Name() 179 180 return eventCategory[class], nil 181 } 182 183 // Events gets the events from the specified object(s) and optionanlly tail the 184 // event stream 185 func (m Manager) Events(ctx context.Context, objects []types.ManagedObjectReference, pageSize int32, tail bool, force bool, f func(types.ManagedObjectReference, []types.BaseEvent) error, kind ...string) error { 186 // TODO: deprecated this method and add one that uses a single config struct, so we can extend further without breaking the method signature. 187 if len(objects) >= m.maxObjects && !force { 188 return fmt.Errorf("maximum number of objects to monitor (%d) exceeded, refine search", m.maxObjects) 189 } 190 191 proc := newEventProcessor(m, pageSize, f, kind) 192 for _, o := range objects { 193 proc.addObject(ctx, o) 194 } 195 196 defer proc.destroy() 197 198 return proc.run(ctx, tail) 199 }