github.com/vmware/govmomi@v0.51.0/event/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 event
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"reflect"
    11  	"sync"
    12  
    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  	r types.ManagedObjectReference
    22  	c *vim25.Client
    23  
    24  	eventCategory   map[string]string
    25  	eventCategoryMu *sync.Mutex
    26  	maxObjects      int
    27  }
    28  
    29  func NewManager(c *vim25.Client) *Manager {
    30  	m := Manager{
    31  		r:               c.ServiceContent.EventManager.Reference(),
    32  		c:               c,
    33  		eventCategory:   make(map[string]string),
    34  		eventCategoryMu: new(sync.Mutex),
    35  		maxObjects:      10,
    36  	}
    37  
    38  	return &m
    39  }
    40  
    41  // Reference returns the event.Manager MOID
    42  func (m Manager) Reference() types.ManagedObjectReference {
    43  	return m.r
    44  }
    45  
    46  func (m Manager) Client() *vim25.Client {
    47  	return m.c
    48  }
    49  
    50  func (m Manager) CreateCollectorForEvents(ctx context.Context, filter types.EventFilterSpec) (*HistoryCollector, error) {
    51  	req := types.CreateCollectorForEvents{
    52  		This:   m.r,
    53  		Filter: filter,
    54  	}
    55  
    56  	res, err := methods.CreateCollectorForEvents(ctx, m.c, &req)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	return newHistoryCollector(m.c, res.Returnval), nil
    62  }
    63  
    64  func (m Manager) LogUserEvent(ctx context.Context, entity types.ManagedObjectReference, msg string) error {
    65  	req := types.LogUserEvent{
    66  		This:   m.r,
    67  		Entity: entity,
    68  		Msg:    msg,
    69  	}
    70  
    71  	_, err := methods.LogUserEvent(ctx, m.c, &req)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  func (m Manager) PostEvent(ctx context.Context, eventToPost types.BaseEvent, taskInfo ...types.TaskInfo) error {
    80  	req := types.PostEvent{
    81  		This:        m.r,
    82  		EventToPost: eventToPost,
    83  	}
    84  
    85  	if len(taskInfo) == 1 {
    86  		req.TaskInfo = &taskInfo[0]
    87  	}
    88  
    89  	_, err := methods.PostEvent(ctx, m.c, &req)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  func (m Manager) QueryEvents(ctx context.Context, filter types.EventFilterSpec) ([]types.BaseEvent, error) {
    98  	req := types.QueryEvents{
    99  		This:   m.r,
   100  		Filter: filter,
   101  	}
   102  
   103  	res, err := methods.QueryEvents(ctx, m.c, &req)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	return res.Returnval, nil
   109  }
   110  
   111  func (m Manager) RetrieveArgumentDescription(ctx context.Context, eventTypeID string) ([]types.EventArgDesc, error) {
   112  	req := types.RetrieveArgumentDescription{
   113  		This:        m.r,
   114  		EventTypeId: eventTypeID,
   115  	}
   116  
   117  	res, err := methods.RetrieveArgumentDescription(ctx, m.c, &req)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	return res.Returnval, nil
   123  }
   124  
   125  func (m Manager) eventCategoryMap(ctx context.Context) (map[string]string, error) {
   126  	m.eventCategoryMu.Lock()
   127  	defer m.eventCategoryMu.Unlock()
   128  
   129  	if len(m.eventCategory) != 0 {
   130  		return m.eventCategory, nil
   131  	}
   132  
   133  	var o mo.EventManager
   134  
   135  	ps := []string{"description.eventInfo"}
   136  	err := property.DefaultCollector(m.c).RetrieveOne(ctx, m.r, ps, &o)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	for _, info := range o.Description.EventInfo {
   142  		m.eventCategory[info.Key] = info.Category
   143  	}
   144  
   145  	return m.eventCategory, nil
   146  }
   147  
   148  // EventCategory returns the category for an event, such as "info" or "error" for example.
   149  func (m Manager) EventCategory(ctx context.Context, event types.BaseEvent) (string, error) {
   150  	// Most of the event details are included in the Event.FullFormattedMessage, but the category
   151  	// is only available via the EventManager description.eventInfo property.  The value of this
   152  	// property is static, so we fetch and once and cache.
   153  	eventCategory, err := m.eventCategoryMap(ctx)
   154  	if err != nil {
   155  		return "", err
   156  	}
   157  
   158  	switch e := event.(type) {
   159  	case *types.EventEx:
   160  		if e.Severity == "" {
   161  			return "info", nil
   162  		}
   163  		return e.Severity, nil
   164  	}
   165  
   166  	class := reflect.TypeOf(event).Elem().Name()
   167  
   168  	return eventCategory[class], nil
   169  }
   170  
   171  // Events gets the events from the specified object(s) and optionanlly tail the
   172  // event stream
   173  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 {
   174  	// TODO: deprecated this method and add one that uses a single config struct, so we can extend further without breaking the method signature.
   175  	if len(objects) >= m.maxObjects && !force {
   176  		return fmt.Errorf("maximum number of objects to monitor (%d) exceeded, refine search", m.maxObjects)
   177  	}
   178  
   179  	proc := newEventProcessor(m, pageSize, f, kind)
   180  	for _, o := range objects {
   181  		proc.addObject(ctx, o)
   182  	}
   183  
   184  	defer proc.destroy()
   185  
   186  	return proc.run(ctx, tail)
   187  }