optimise vcenter collection [CI SKIP]

This commit is contained in:
2026-01-14 21:18:45 +11:00
parent 8df1d145f8
commit 877b65f10b
2 changed files with 71 additions and 13 deletions

View File

@@ -601,7 +601,7 @@ func normalizeResourcePool(value string) string {
}
}
func snapshotFromVM(vmObject *mo.VirtualMachine, vc *vcenter.Vcenter, snapshotTime time.Time, inv *queries.Inventory, hostLookup map[string]vcenter.HostLookup, folderLookup vcenter.FolderLookup) (inventorySnapshotRow, error) {
func snapshotFromVM(vmObject *mo.VirtualMachine, vc *vcenter.Vcenter, snapshotTime time.Time, inv *queries.Inventory, hostLookup map[string]vcenter.HostLookup, folderLookup vcenter.FolderLookup, rpLookup map[string]string) (inventorySnapshotRow, error) {
if vmObject == nil {
return inventorySnapshotRow{}, fmt.Errorf("missing VM object")
}
@@ -690,11 +690,18 @@ func snapshotFromVM(vmObject *mo.VirtualMachine, vc *vcenter.Vcenter, snapshotTi
}
}
if row.ResourcePool.String == "" {
if row.ResourcePool.String == "" && vmObject.ResourcePool != nil {
if rpLookup != nil {
if rpName, ok := rpLookup[vmObject.ResourcePool.Value]; ok {
row.ResourcePool = sql.NullString{String: normalizeResourcePool(rpName), Valid: rpName != ""}
}
}
if !row.ResourcePool.Valid {
if rpName, err := vc.GetVmResourcePool(*vmObject); err == nil {
row.ResourcePool = sql.NullString{String: normalizeResourcePool(rpName), Valid: rpName != ""}
}
}
}
if row.Folder.String == "" {
if folderPath, ok := vc.GetVMFolderPathFromLookup(*vmObject, folderLookup); ok {
@@ -805,7 +812,7 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
}
}()
vcVms, err := vc.GetAllVmReferences()
vcVms, err := vc.GetAllVMsWithProps()
if err != nil {
return fmt.Errorf("unable to get VMs from vcenter: %w", err)
}
@@ -827,6 +834,13 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
} else {
c.Logger.Debug("built folder lookup", "url", url, "folders", len(folderLookup))
}
rpLookup, err := vc.BuildResourcePoolLookup()
if err != nil {
c.Logger.Warn("failed to build resource pool lookup", "url", url, "error", err)
rpLookup = nil
} else {
c.Logger.Debug("built resource pool lookup", "url", url, "pools", len(rpLookup))
}
inventoryRows, err := c.Database.Queries().GetInventoryByVcenter(ctx, url)
if err != nil {
@@ -844,16 +858,11 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
presentSnapshots := make(map[string]inventorySnapshotRow, len(vcVms))
totals := snapshotTotals{}
for _, vm := range vcVms {
if strings.HasPrefix(vm.Name(), "vCLS-") {
if strings.HasPrefix(vm.Name, "vCLS-") {
continue
}
vmObj, err := vc.ConvertObjToMoVM(vm)
if err != nil {
c.Logger.Error("failed to read VM details", "vm_id", vm.Reference().Value, "error", err)
continue
}
if vmObj.Config != nil && vmObj.Config.Template {
if vm.Config != nil && vm.Config.Template {
continue
}
@@ -863,7 +872,7 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
inv = &existingCopy
}
row, err := snapshotFromVM(vmObj, vc, startTime, inv, hostLookup, folderLookup)
row, err := snapshotFromVM(&vm, vc, startTime, inv, hostLookup, folderLookup, rpLookup)
if err != nil {
c.Logger.Error("unable to build snapshot for VM", "vm_id", vm.Reference().Value, "error", err)
continue

View File

@@ -150,6 +150,34 @@ func (v *Vcenter) GetAllVmReferences() ([]*object.VirtualMachine, error) {
return results, err
}
// GetAllVMsWithProps returns all VMs with the properties needed for snapshotting in a single property-collector call.
func (v *Vcenter) GetAllVMsWithProps() ([]mo.VirtualMachine, error) {
m := view.NewManager(v.client.Client)
cv, err := m.CreateContainerView(v.ctx, v.client.ServiceContent.RootFolder, []string{"VirtualMachine"}, true)
if err != nil {
return nil, fmt.Errorf("failed to create VM container view: %w", err)
}
defer cv.Destroy(v.ctx)
var vms []mo.VirtualMachine
props := []string{
"name",
"parent",
"config.uuid",
"config.createDate",
"config.hardware",
"config.managedBy",
"config.template",
"runtime.powerState",
"runtime.host",
"resourcePool",
}
if err := cv.Retrieve(v.ctx, []string{"VirtualMachine"}, props, &vms); err != nil {
return nil, fmt.Errorf("failed to retrieve VMs: %w", err)
}
return vms, nil
}
func (v *Vcenter) BuildHostLookup() (map[string]HostLookup, error) {
finder := find.NewFinder(v.client.Client, true)
datacenters, err := finder.DatacenterList(v.ctx, "*")
@@ -586,6 +614,27 @@ func (v *Vcenter) GetVmResourcePool(vm mo.VirtualMachine) (string, error) {
return resourcePool, nil
}
// BuildResourcePoolLookup creates a cache of resource pool MoRef -> name for fast lookups.
func (v *Vcenter) BuildResourcePoolLookup() (map[string]string, error) {
m := view.NewManager(v.client.Client)
cv, err := m.CreateContainerView(v.ctx, v.client.ServiceContent.RootFolder, []string{"ResourcePool"}, true)
if err != nil {
return nil, fmt.Errorf("failed to create resource pool view: %w", err)
}
defer cv.Destroy(v.ctx)
var pools []mo.ResourcePool
if err := cv.Retrieve(v.ctx, []string{"ResourcePool"}, []string{"name"}, &pools); err != nil {
return nil, fmt.Errorf("failed to retrieve resource pools: %w", err)
}
lookup := make(map[string]string, len(pools))
for _, pool := range pools {
lookup[pool.Reference().Value] = pool.Name
}
return lookup, nil
}
// Helper function to retrieve the full folder path for the VM
func (v *Vcenter) GetVMFolderPath(vm mo.VirtualMachine) (string, error) {
//finder := find.NewFinder(v.client.Client, true)