github.com/vmware/govmomi@v0.37.2/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  }