github.com/vmware/govmomi@v0.51.0/cli/alarm/state.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  	"encoding/json"
    10  	"flag"
    11  	"fmt"
    12  	"io"
    13  	"text/tabwriter"
    14  	"time"
    15  
    16  	"github.com/vmware/govmomi/alarm"
    17  	"github.com/vmware/govmomi/cli"
    18  	"github.com/vmware/govmomi/cli/flags"
    19  	"github.com/vmware/govmomi/vim25/types"
    20  )
    21  
    22  type state struct {
    23  	*flags.DatacenterFlag
    24  	*flags.OutputFlag
    25  
    26  	ack  bool
    27  	name string
    28  	alarm.StateInfoOptions
    29  }
    30  
    31  func init() {
    32  	cli.Register("alarms", &state{})
    33  }
    34  
    35  func (cmd *state) Register(ctx context.Context, f *flag.FlagSet) {
    36  	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
    37  	cmd.DatacenterFlag.Register(ctx, f)
    38  
    39  	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
    40  	cmd.OutputFlag.Register(ctx, f)
    41  
    42  	f.BoolVar(&cmd.ack, "ack", false, "Acknowledge alarms")
    43  	f.StringVar(&cmd.name, "n", "", "Filter by alarm name")
    44  	f.BoolVar(&cmd.Declared, "d", false, "Show declared alarms")
    45  	f.BoolVar(&cmd.InventoryPath, "l", false, "Long listing output")
    46  }
    47  
    48  func (cmd *state) Usage() string {
    49  	return "[PATH]"
    50  }
    51  
    52  func (cmd *state) Description() string {
    53  	return `Show triggered or declared alarms.
    54  
    55  Triggered alarms: alarms triggered by this entity or by its descendants.
    56  Triggered alarms are propagated up the inventory hierarchy so that a user
    57  can readily tell when a descendant has triggered an alarm.
    58  
    59  Declared alarms: alarms that apply to this managed entity.
    60  Includes alarms defined on this entity and alarms inherited from the parent
    61  entity, or from any ancestors in the inventory hierarchy.
    62  
    63  PATH defaults to the root folder '/'.
    64  When PATH is provided it should be an absolute inventory path or relative
    65  to GOVC_DATACENTER. See also:
    66    govc find -h
    67    govc tree -h
    68  
    69  Examples:
    70    govc alarms
    71    govc alarms vm/folder/vm-name
    72    govc alarms /dc1/host/cluster1
    73    govc alarms /dc1/host/cluster1 -d
    74  
    75    govc alarms -n alarm.WCPRegisterVMFailedAlarm
    76    govc alarms -ack /dc1/host/cluster1
    77    govc alarms -ack -n alarm.WCPRegisterVMFailedAlarm vm/vm-name`
    78  }
    79  
    80  func (cmd *state) Process(ctx context.Context) error {
    81  	if err := cmd.DatacenterFlag.Process(ctx); err != nil {
    82  		return err
    83  	}
    84  	return cmd.OutputFlag.Process(ctx)
    85  }
    86  
    87  func (cmd *state) filterAlarms(ctx context.Context, m *alarm.Manager, obj types.ManagedObjectReference) ([]alarm.StateInfo, error) {
    88  	alarms, err := m.GetStateInfo(ctx, obj, cmd.StateInfoOptions)
    89  	if err != nil || cmd.name == "" {
    90  		return alarms, err
    91  	}
    92  
    93  	var match []alarm.StateInfo
    94  	for _, alarm := range alarms {
    95  		if alarm.Info.SystemName == cmd.name || alarm.Info.Name == cmd.name {
    96  			match = append(match, alarm)
    97  		}
    98  	}
    99  
   100  	return match, nil
   101  }
   102  
   103  type stateResult struct {
   104  	info []alarm.StateInfo
   105  	cmd  *state
   106  }
   107  
   108  func (r *stateResult) Dump() any {
   109  	return r.info
   110  }
   111  
   112  func (r *stateResult) MarshalJSON() ([]byte, error) {
   113  	return json.Marshal(r.info)
   114  }
   115  
   116  func (r *stateResult) Write(w io.Writer) error {
   117  	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
   118  
   119  	fmt.Fprintf(tw, "Alarm Name\tObject\tSeverity\tTriggered Time\tAcknowledged Time\tAcknowledged By\n")
   120  
   121  	for _, a := range r.info {
   122  		name := a.Info.Name
   123  		tt := a.Time.Format(time.Stamp)
   124  		at := ""
   125  		by := a.AcknowledgedByUser
   126  		if a.AcknowledgedTime != nil {
   127  			at = a.AcknowledgedTime.Format(time.Stamp)
   128  		}
   129  		fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\t%s\n", name, a.Path, alarm.Severity[a.OverallStatus], tt, at, by)
   130  	}
   131  
   132  	return tw.Flush()
   133  }
   134  
   135  func (cmd *state) Run(ctx context.Context, f *flag.FlagSet) error {
   136  	if f.NArg() > 1 {
   137  		return flag.ErrHelp
   138  	}
   139  	if cmd.ack && cmd.Declared {
   140  		return flag.ErrHelp
   141  	}
   142  
   143  	c, err := cmd.Client()
   144  	if err != nil {
   145  		return err
   146  	}
   147  
   148  	obj := c.ServiceContent.RootFolder
   149  	if f.NArg() == 1 {
   150  		obj, err = cmd.ManagedObject(ctx, f.Arg(0))
   151  		if err != nil {
   152  			return err
   153  		}
   154  	}
   155  
   156  	cmd.StateInfoOptions.Event = cmd.All()
   157  
   158  	m, err := alarm.GetManager(c)
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	alarms, err := cmd.filterAlarms(ctx, m, obj)
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	if cmd.ack {
   169  		for _, alarm := range alarms {
   170  			if alarm.Acknowledged != nil && *alarm.Acknowledged {
   171  				continue
   172  			}
   173  			if err := m.AcknowledgeAlarm(ctx, alarm.Alarm, alarm.Entity); err != nil {
   174  				return err
   175  			}
   176  		}
   177  
   178  		alarms, err = cmd.filterAlarms(ctx, m, obj)
   179  		if err != nil {
   180  			return err
   181  		}
   182  	}
   183  
   184  	return cmd.WriteResult(&stateResult{alarms, cmd})
   185  }