From cc6601146a8c0168bd079417dc2636b0b4679018 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Mon, 14 Oct 2024 09:24:28 +1100 Subject: [PATCH] vcenter poll job now creates update records for changed VMs --- internal/tasks/monitorVcenter.go | 102 ++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 2 deletions(-) diff --git a/internal/tasks/monitorVcenter.go b/internal/tasks/monitorVcenter.go index 01945e8..e7841ba 100644 --- a/internal/tasks/monitorVcenter.go +++ b/internal/tasks/monitorVcenter.go @@ -31,7 +31,7 @@ func (c *CronTask) RunVcenterPoll(ctx context.Context, logger *slog.Logger) erro vc.Login(url) // Get list of VMs from vcenter - vms, err := vc.GetAllVmReferences() + vcVms, err := vc.GetAllVmReferences() // Get list of VMs from inventory table c.Logger.Debug("Querying inventory table") @@ -47,7 +47,7 @@ func (c *CronTask) RunVcenterPoll(ctx context.Context, logger *slog.Logger) erro } // Iterate VMs from vcenter and see if they were in the database - for _, vm := range vms { + for _, vm := range vcVms { matchFound = false // Skip any vCLS VMs @@ -61,6 +61,25 @@ func (c *CronTask) RunVcenterPoll(ctx context.Context, logger *slog.Logger) erro if dbvm.VmId.String == vm.Reference().Value { c.Logger.Debug("Found match for VM", "vm_name", dbvm.Name, "id", dbvm.VmId.String) matchFound = true + + // Get the full VM object + vmObj, err := vc.ConvertObjToMoVM(vm) + if err != nil { + c.Logger.Error("Failed to find VM in vcenter", "vm_id", dbvm.VmId.String, "error", err) + continue + } + + if vmObj.Config == nil { + c.Logger.Error("VM has no config properties", "vm_id", dbvm.VmId.String, "vm_name", vmObj.Name) + continue + } + + // Check that this is definitely the right VM + if dbvm.VmUuid.String == vmObj.Config.Uuid { + // TODO - compare database against current values, create update record if not matching + err = c.UpdateVmInventory(vmObj, vc, ctx, dbvm) + } + break } } @@ -93,6 +112,82 @@ func (c *CronTask) RunVcenterPoll(ctx context.Context, logger *slog.Logger) erro return nil } +// UpdateVmInventory will compare database against current vcenter values, and create update record if not matching +func (c *CronTask) UpdateVmInventory(vmObj *mo.VirtualMachine, vc *vcenter.Vcenter, ctx context.Context, dbVm queries.Inventory) error { + var ( + err error + numVcpus int32 + numRam int32 + srmPlaceholder string + updateType string + rpName string + ) + params := queries.CreateUpdateParams{ + InventoryId: sql.NullInt64{Int64: dbVm.Iid, Valid: dbVm.Iid > 0}, + } + srmPlaceholder = "FALSE" // default value + updateType = "unknown" // default value + numRam = vmObj.Config.Hardware.MemoryMB + numVcpus = vmObj.Config.Hardware.NumCPU + + if numRam != int32(dbVm.InitialRam.Int64) { + params.NewRam = sql.NullInt64{Int64: int64(numRam), Valid: numRam > 0} + updateType = "reconfigure" + } + + if numVcpus != int32(dbVm.InitialVcpus.Int64) { + params.NewVcpus = sql.NullInt64{Int64: int64(numVcpus), Valid: numVcpus > 0} + updateType = "reconfigure" + } + + // Determine if the VM is a normal VM or an SRM placeholder + if vmObj.Config.ManagedBy != nil && vmObj.Config.ManagedBy.ExtensionKey == "com.vmware.vcDr" { + if vmObj.Config.ManagedBy.Type == "placeholderVm" { + //c.Logger.Debug("VM is a placeholder") + srmPlaceholder = "TRUE" + } else { + //c.Logger.Debug("VM is managed by SRM but not a placeholder", "details", vmObj.Config.ManagedBy) + } + } + + if srmPlaceholder != dbVm.SrmPlaceholder { + params.PlaceholderChange = sql.NullString{String: srmPlaceholder, Valid: srmPlaceholder != ""} + if updateType == "unknown" { + updateType = "srm" + } + } + + rpName, err = vc.GetVmResourcePool(*vmObj) + if err != nil { + c.Logger.Error("Unable to determine resource pool name", "error", err) + } + if rpName != dbVm.ResourcePool.String { + params.NewResourcePool = sql.NullString{String: rpName, Valid: rpName != ""} + if updateType == "unknown" { + updateType = "move" + } + } + + // TODO - should we bother to check if disk space has changed? + + if updateType != "unknown" { + c.Logger.Debug("Detected change in VM, inserting update record into database", "update_type", updateType) + params.UpdateType = updateType + + result, err := c.Database.Queries().CreateUpdate(ctx, params) + if err != nil { + c.Logger.Error("Failed creating database record", "error", err) + return err + } + + c.Logger.Debug("created database record", "insert_result", result) + // add sleep to slow down mass VM additions + utils.SleepWithContext(ctx, (10 * time.Millisecond)) + } + + return nil +} + func (c *CronTask) AddVmToInventory(vmObject *mo.VirtualMachine, vc *vcenter.Vcenter, ctx context.Context) error { var ( numVcpus int32 @@ -194,6 +289,9 @@ func (c *CronTask) AddVmToInventory(vmObject *mo.VirtualMachine, vc *vcenter.Vce } rpName, err := vc.GetVmResourcePool(*vmObject) + if err != nil { + c.Logger.Error("Unable to determine resource pool name", "error", err) + } // Get VM's host and use that to determine cluster //c.Logger.Debug("Checking for VM host by runtime data", "runtime", vmObject.Runtime)