[CI SKIP] bugfixes for vm deletion tracking

This commit is contained in:
2026-01-20 16:33:31 +11:00
parent a9e522cc84
commit 0517ef88c3
7 changed files with 1016 additions and 398 deletions

View File

@@ -7,8 +7,10 @@ import (
"net/url"
"path"
"strings"
"time"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/event"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/view"
@@ -195,6 +197,90 @@ func (v *Vcenter) GetAllVMsWithProps() ([]mo.VirtualMachine, error) {
return vms, nil
}
// FindVmDeletionEvents returns a map of MoRef (VmId) to the deletion event time within the given window.
func (v *Vcenter) FindVmDeletionEvents(ctx context.Context, begin, end time.Time) (map[string]time.Time, error) {
result := make(map[string]time.Time)
if v.client == nil || !v.client.Valid() {
return result, fmt.Errorf("vcenter client is not valid")
}
// vCenter events are stored in UTC; normalize the query window.
beginUTC := begin.UTC()
endUTC := end.UTC()
mgr := event.NewManager(v.client.Client)
processEvents := func(evts []types.BaseEvent) {
for _, ev := range evts {
switch e := ev.(type) {
case *types.VmRemovedEvent:
if e.Vm != nil {
vmID := e.Vm.Vm.Value
if vmID != "" {
result[vmID] = e.CreatedTime
}
}
case *types.TaskEvent:
// Fallback for destroy task events.
if e.Info.Entity != nil {
vmID := e.Info.Entity.Value
msg := strings.ToLower(e.GetEvent().FullFormattedMessage)
if vmID != "" && (strings.Contains(msg, "destroy") || strings.Contains(msg, "deleted")) {
result[vmID] = e.CreatedTime
}
}
case *types.VmEvent:
if e.Vm != nil {
vmID := e.Vm.Vm.Value
if vmID != "" {
result[vmID] = e.CreatedTime
}
}
}
}
}
// First attempt: specific deletion event types.
filter := types.EventFilterSpec{
Time: &types.EventFilterSpecByTime{
BeginTime: &beginUTC,
EndTime: &endUTC,
},
EventTypeId: []string{
"VmRemovedEvent",
"TaskEvent",
},
}
collector, err := mgr.CreateCollectorForEvents(ctx, filter)
if err != nil {
return result, fmt.Errorf("failed to create event collector: %w", err)
}
defer collector.Destroy(ctx)
events, err := collector.ReadNextEvents(ctx, 500)
if err != nil {
return result, fmt.Errorf("failed to read events: %w", err)
}
processEvents(events)
// If nothing found, widen the filter to all event types in the window as a fallback.
if len(result) == 0 {
fallbackFilter := types.EventFilterSpec{
Time: &types.EventFilterSpecByTime{
BeginTime: &beginUTC,
EndTime: &endUTC,
},
}
fc, err := mgr.CreateCollectorForEvents(ctx, fallbackFilter)
if err == nil {
defer fc.Destroy(ctx)
if evs, readErr := fc.ReadNextEvents(ctx, 500); readErr == nil {
processEvents(evs)
}
}
}
return result, nil
}
func (v *Vcenter) BuildHostLookup() (map[string]HostLookup, error) {
finder := find.NewFinder(v.client.Client, true)
datacenters, err := finder.DatacenterList(v.ctx, "*")
@@ -415,6 +501,10 @@ func (v *Vcenter) GetHostSystemObject(hostRef types.ManagedObjectReference) (*mo
// Function to find the cluster or compute resource from a host reference
func (v *Vcenter) GetClusterFromHost(hostRef *types.ManagedObjectReference) (string, error) {
if hostRef == nil {
v.Logger.Warn("nil hostRef passed to GetClusterFromHost")
return "", nil
}
// Get the host object
host, err := v.GetHostSystemObject(*hostRef)
if err != nil {