github.com/vmware/govmomi@v0.37.1/govc/events/command.go (about) 1 /* 2 Copyright (c) 2015-2023 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 events 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "io" 24 "os" 25 "reflect" 26 "strings" 27 "time" 28 29 "github.com/vmware/govmomi/event" 30 "github.com/vmware/govmomi/govc/cli" 31 "github.com/vmware/govmomi/govc/flags" 32 "github.com/vmware/govmomi/vim25/types" 33 ) 34 35 type events struct { 36 *flags.DatacenterFlag 37 38 Max int32 39 Tail bool 40 Force bool 41 Long bool 42 Kind kinds 43 } 44 45 type kinds []string 46 47 func (e *kinds) String() string { 48 return fmt.Sprint(*e) 49 } 50 51 func (e *kinds) Set(value string) error { 52 *e = append(*e, value) 53 return nil 54 } 55 56 func init() { 57 // initialize with the maximum allowed objects set 58 cli.Register("events", &events{}) 59 } 60 61 func (cmd *events) Register(ctx context.Context, f *flag.FlagSet) { 62 cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx) 63 cmd.DatacenterFlag.Register(ctx, f) 64 65 cmd.Max = 25 // default 66 f.Var(flags.NewInt32(&cmd.Max), "n", "Output the last N events") 67 f.BoolVar(&cmd.Tail, "f", false, "Follow event stream") 68 f.BoolVar(&cmd.Force, "force", false, "Disable number objects to monitor limit") 69 f.BoolVar(&cmd.Long, "l", false, "Long listing format") 70 f.Var(&cmd.Kind, "type", "Include only the specified event types") 71 } 72 73 func (cmd *events) Description() string { 74 return `Display events. 75 76 Examples: 77 govc events vm/my-vm1 vm/my-vm2 78 govc events /dc1/vm/* /dc2/vm/* 79 govc events -type VmPoweredOffEvent -type VmPoweredOnEvent 80 govc ls -t HostSystem host/* | xargs govc events | grep -i vsan` 81 } 82 83 func (cmd *events) Usage() string { 84 return "[PATH]..." 85 } 86 87 func (cmd *events) printEvents(ctx context.Context, obj *types.ManagedObjectReference, page []types.BaseEvent, m *event.Manager) error { 88 event.Sort(page) 89 source := "" 90 if obj != nil { 91 source = obj.String() 92 if !cmd.JSON { 93 // print the object reference 94 fmt.Fprintf(os.Stdout, "\n==> %s <==\n", source) 95 } 96 } 97 for _, e := range page { 98 cat, err := m.EventCategory(ctx, e) 99 if err != nil { 100 return err 101 } 102 103 event := e.GetEvent() 104 r := &record{ 105 Object: source, 106 CreatedTime: event.CreatedTime, 107 Category: cat, 108 Message: strings.TrimSpace(event.FullFormattedMessage), 109 event: e, 110 } 111 112 if cmd.Long { 113 r.Type = reflect.TypeOf(e).Elem().Name() 114 } 115 116 if cmd.Long { 117 r.Key = event.Key 118 } 119 120 // if this is a TaskEvent gather a little more information 121 if t, ok := e.(*types.TaskEvent); ok { 122 // some tasks won't have this information, so just use the event message 123 if t.Info.Entity != nil { 124 r.Message = fmt.Sprintf("%s (target=%s %s)", r.Message, t.Info.Entity.Type, t.Info.EntityName) 125 } 126 } 127 128 if err = cmd.WriteResult(r); err != nil { 129 return err 130 } 131 } 132 return nil 133 } 134 135 type record struct { 136 Object string `json:"object,omitempty"` 137 Type string `json:"type,omitempty"` 138 CreatedTime time.Time `json:"createdTime"` 139 Category string `json:"category"` 140 Message string `json:"message"` 141 Key int32 `json:"key,omitempty"` 142 143 event types.BaseEvent 144 } 145 146 // Dump the raw Event rather than the record struct. 147 func (r *record) Dump() interface{} { 148 return r.event 149 } 150 151 func (r *record) Write(w io.Writer) error { 152 when := r.CreatedTime.Local().Format(time.ANSIC) 153 var kind, key string 154 if r.Type != "" { 155 kind = fmt.Sprintf(" [%s]", r.Type) 156 } 157 if r.Key != 0 { 158 key = fmt.Sprintf(" [%d]", r.Key) 159 } 160 _, err := fmt.Fprintf(w, "[%s] [%s]%s%s %s\n", when, r.Category, key, kind, r.Message) 161 return err 162 } 163 164 func (cmd *events) Run(ctx context.Context, f *flag.FlagSet) error { 165 c, err := cmd.Client() 166 if err != nil { 167 return err 168 } 169 170 objs, err := cmd.ManagedObjects(ctx, f.Args()) 171 if err != nil { 172 return err 173 } 174 175 m := event.NewManager(c) 176 177 return cmd.WithCancel(ctx, func(wctx context.Context) error { 178 return m.Events(wctx, objs, cmd.Max, cmd.Tail, cmd.Force, 179 func(obj types.ManagedObjectReference, ee []types.BaseEvent) error { 180 var o *types.ManagedObjectReference 181 if len(objs) > 1 { 182 o = &obj 183 } 184 185 return cmd.printEvents(ctx, o, ee, m) 186 }, cmd.Kind...) 187 }) 188 }