more accurate resource pool data in aggregation reports
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -179,13 +179,46 @@ func querySnapshotRows(ctx context.Context, dbConn *sqlx.DB, table string, colum
|
||||
return dbConn.QueryxContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
func updateDeletionTimeInSnapshot(ctx context.Context, dbConn *sqlx.DB, table, vcenter, vmID, vmUUID, name string, deletionUnix int64) (int64, error) {
|
||||
if err := db.ValidateTableName(table); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
matchColumn := ""
|
||||
matchValue := ""
|
||||
switch {
|
||||
case vmID != "":
|
||||
matchColumn = "VmId"
|
||||
matchValue = vmID
|
||||
case vmUUID != "":
|
||||
matchColumn = "VmUuid"
|
||||
matchValue = vmUUID
|
||||
case name != "":
|
||||
matchColumn = "Name"
|
||||
matchValue = name
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`UPDATE %s SET "DeletionTime" = ? WHERE "Vcenter" = ? AND "%s" = ? AND ("DeletionTime" IS NULL OR "DeletionTime" = 0 OR "DeletionTime" > ?)`, table, matchColumn)
|
||||
query = sqlx.Rebind(sqlx.BindType(dbConn.DriverName()), query)
|
||||
result, err := dbConn.ExecContext(ctx, query, deletionUnix, vcenter, matchValue, deletionUnix)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rowsAffected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return rowsAffected, nil
|
||||
}
|
||||
|
||||
// markMissingFromPrevious marks VMs that were present in the previous snapshot but missing now.
|
||||
func (c *CronTask) markMissingFromPrevious(ctx context.Context, dbConn *sqlx.DB, prevTable string, vcenter string, snapshotTime time.Time,
|
||||
currentByID map[string]InventorySnapshotRow, currentByUuid map[string]struct{}, currentByName map[string]struct{},
|
||||
invByID map[string]queries.Inventory, invByUuid map[string]queries.Inventory, invByName map[string]queries.Inventory) int {
|
||||
invByID map[string]queries.Inventory, invByUuid map[string]queries.Inventory, invByName map[string]queries.Inventory) (int, bool) {
|
||||
|
||||
if err := db.ValidateTableName(prevTable); err != nil {
|
||||
return 0
|
||||
return 0, false
|
||||
}
|
||||
|
||||
type prevRow struct {
|
||||
@@ -200,11 +233,12 @@ func (c *CronTask) markMissingFromPrevious(ctx context.Context, dbConn *sqlx.DB,
|
||||
rows, err := querySnapshotRows(ctx, dbConn, prevTable, []string{"VmId", "VmUuid", "Name", "Cluster", "Datacenter", "DeletionTime"}, `"Vcenter" = ?`, vcenter)
|
||||
if err != nil {
|
||||
c.Logger.Warn("failed to read previous snapshot for deletion detection", "error", err, "table", prevTable, "vcenter", vcenter)
|
||||
return 0
|
||||
return 0, false
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
missing := 0
|
||||
tableUpdated := false
|
||||
for rows.Next() {
|
||||
var r prevRow
|
||||
if err := rows.StructScan(&r); err != nil {
|
||||
@@ -255,18 +289,16 @@ func (c *CronTask) markMissingFromPrevious(ctx context.Context, dbConn *sqlx.DB,
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if inv.DeletionTime.Valid {
|
||||
continue
|
||||
}
|
||||
|
||||
delTime := sql.NullInt64{Int64: snapshotTime.Unix(), Valid: true}
|
||||
if err := c.Database.Queries().InventoryMarkDeleted(ctx, queries.InventoryMarkDeletedParams{
|
||||
DeletionTime: delTime,
|
||||
VmId: inv.VmId,
|
||||
DatacenterName: inv.Datacenter,
|
||||
}); err != nil {
|
||||
c.Logger.Warn("failed to mark inventory record deleted from previous snapshot", "error", err, "vm_id", inv.VmId.String)
|
||||
continue
|
||||
delTime := inv.DeletionTime
|
||||
if !delTime.Valid {
|
||||
delTime = sql.NullInt64{Int64: snapshotTime.Unix(), Valid: true}
|
||||
if err := c.Database.Queries().InventoryMarkDeleted(ctx, queries.InventoryMarkDeletedParams{
|
||||
DeletionTime: delTime,
|
||||
VmId: inv.VmId,
|
||||
DatacenterName: inv.Datacenter,
|
||||
}); err != nil {
|
||||
c.Logger.Warn("failed to mark inventory record deleted from previous snapshot", "error", err, "vm_id", inv.VmId.String)
|
||||
}
|
||||
}
|
||||
// Also update lifecycle cache so deletion time is available for rollups.
|
||||
vmUUID := ""
|
||||
@@ -276,11 +308,17 @@ func (c *CronTask) markMissingFromPrevious(ctx context.Context, dbConn *sqlx.DB,
|
||||
if err := db.MarkVmDeletedWithDetails(ctx, dbConn, vcenter, inv.VmId.String, vmUUID, inv.Name, inv.Cluster.String, delTime.Int64); err != nil {
|
||||
c.Logger.Warn("failed to mark lifecycle cache deleted from previous snapshot", "error", err, "vm_id", inv.VmId.String, "vm_uuid", vmUUID, "vcenter", vcenter)
|
||||
}
|
||||
if rowsAffected, err := updateDeletionTimeInSnapshot(ctx, dbConn, prevTable, vcenter, inv.VmId.String, vmUUID, inv.Name, delTime.Int64); err != nil {
|
||||
c.Logger.Warn("failed to update hourly snapshot deletion time", "error", err, "table", prevTable, "vm_id", inv.VmId.String, "vm_uuid", vmUUID, "vcenter", vcenter)
|
||||
} else if rowsAffected > 0 {
|
||||
tableUpdated = true
|
||||
c.Logger.Debug("updated hourly snapshot deletion time", "table", prevTable, "vm_id", inv.VmId.String, "vm_uuid", vmUUID, "vcenter", vcenter, "deletion_time", delTime.Int64)
|
||||
}
|
||||
c.Logger.Debug("Detected VM missing compared to previous snapshot", "name", inv.Name, "vm_id", inv.VmId.String, "vm_uuid", inv.VmUuid.String, "vcenter", vcenter, "snapshot_time", snapshotTime, "prev_table", prevTable)
|
||||
missing++
|
||||
}
|
||||
|
||||
return missing
|
||||
return missing, tableUpdated
|
||||
}
|
||||
|
||||
// countNewFromPrevious returns how many VMs are present in the current snapshot but not in the previous snapshot.
|
||||
@@ -409,9 +447,9 @@ func listNewFromPrevious(ctx context.Context, dbConn *sqlx.DB, prevTable string,
|
||||
|
||||
// findVMInHourlySnapshots searches recent hourly snapshot tables for a VM by ID for the given vCenter.
|
||||
// extraTables are searched first (e.g., known previous snapshot tables).
|
||||
func findVMInHourlySnapshots(ctx context.Context, dbConn *sqlx.DB, vcenter string, vmID string, extraTables ...string) (InventorySnapshotRow, bool) {
|
||||
func findVMInHourlySnapshots(ctx context.Context, dbConn *sqlx.DB, vcenter string, vmID string, extraTables ...string) (InventorySnapshotRow, string, bool) {
|
||||
if vmID == "" {
|
||||
return InventorySnapshotRow{}, false
|
||||
return InventorySnapshotRow{}, "", false
|
||||
}
|
||||
// Use a short timeout to avoid hanging if the DB is busy.
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
@@ -429,7 +467,7 @@ func findVMInHourlySnapshots(ctx context.Context, dbConn *sqlx.DB, vcenter strin
|
||||
query = sqlx.Rebind(sqlx.BindType(dbConn.DriverName()), query)
|
||||
var row InventorySnapshotRow
|
||||
if err := dbConn.QueryRowxContext(ctx, query, vcenter, vmID).Scan(&row.VmId, &row.VmUuid, &row.Name, &row.Datacenter, &row.Cluster); err == nil {
|
||||
return row, true
|
||||
return row, table, true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +480,7 @@ ORDER BY snapshot_time DESC
|
||||
LIMIT 20
|
||||
`)
|
||||
if err != nil {
|
||||
return InventorySnapshotRow{}, false
|
||||
return InventorySnapshotRow{}, "", false
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@@ -459,12 +497,12 @@ LIMIT 20
|
||||
query = sqlx.Rebind(sqlx.BindType(dbConn.DriverName()), query)
|
||||
var row InventorySnapshotRow
|
||||
if err := dbConn.QueryRowxContext(ctx, query, vcenter, vmID).Scan(&row.VmId, &row.VmUuid, &row.Name, &row.Datacenter, &row.Cluster); err == nil {
|
||||
return row, true
|
||||
return row, table, true
|
||||
}
|
||||
checked++
|
||||
if checked >= 10 { // limit work
|
||||
break
|
||||
}
|
||||
}
|
||||
return InventorySnapshotRow{}, false
|
||||
return InventorySnapshotRow{}, "", false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user