code cleanup
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-21 08:45:46 +11:00
parent d683d23bfc
commit c7c7fd3dc9
5 changed files with 296 additions and 175 deletions

View File

@@ -503,128 +503,6 @@ func normalizeResourcePool(value string) string {
return trimmed
}
// backfillLifecycleDeletionsToday looks for VMs in the lifecycle cache that are not in the current inventory,
// have no DeletedAt, and determines their deletion time from today's hourly snapshots.
func backfillLifecycleDeletionsToday(ctx context.Context, logger *slog.Logger, dbConn *sqlx.DB, vcenter string, snapshotTime time.Time, present map[string]InventorySnapshotRow) error {
dayStart := truncateDate(snapshotTime)
dayEnd := dayStart.Add(24 * time.Hour)
// Lifecycle entries missing DeletedAt.
queryLifecycle := `
SELECT "VmId","VmUuid","Name","Cluster"
FROM vm_lifecycle_cache
WHERE "Vcenter" = ? AND ("DeletedAt" IS NULL OR "DeletedAt" = 0)
`
rows, err := dbConn.QueryxContext(ctx, queryLifecycle, vcenter)
if err != nil {
return err
}
defer rows.Close()
type candidate struct {
vmID string
vmUUID string
name string
cluster string
}
var cands []candidate
for rows.Next() {
var vmID, vmUUID, name, cluster sql.NullString
if scanErr := rows.Scan(&vmID, &vmUUID, &name, &cluster); scanErr != nil {
continue
}
if vmID.String == "" {
continue
}
if _, ok := present[vmID.String]; ok {
continue // still present, skip
}
cands = append(cands, candidate{
vmID: vmID.String,
vmUUID: vmUUID.String,
name: name.String,
cluster: cluster.String,
})
}
if len(cands) == 0 {
return nil
}
// Get today's hourly tables.
query := `
SELECT table_name, snapshot_time
FROM snapshot_registry
WHERE snapshot_type = 'hourly' AND snapshot_time >= ? AND snapshot_time < ?
ORDER BY snapshot_time ASC
`
query = sqlx.Rebind(sqlx.BindType(dbConn.DriverName()), query)
var tables []struct {
Table string `db:"table_name"`
Time int64 `db:"snapshot_time"`
}
rowsTables, err := dbConn.QueryxContext(ctx, query, dayStart.Unix(), dayEnd.Unix())
if err != nil {
return err
}
defer rowsTables.Close()
for rowsTables.Next() {
var t struct {
Table string `db:"table_name"`
Time int64 `db:"snapshot_time"`
}
if err := rowsTables.StructScan(&t); err != nil {
continue
}
tables = append(tables, t)
}
if len(tables) == 0 {
return nil
}
for _, cand := range cands {
var lastSeen int64
var deletion int64
logger.Debug("lifecycle backfill candidate", "vcenter", vcenter, "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "name", cand.name, "cluster", cand.cluster, "tables", len(tables))
for i, tbl := range tables {
if err := db.ValidateTableName(tbl.Table); err != nil {
continue
}
q := fmt.Sprintf(`SELECT "Name","Cluster" FROM %s WHERE "Vcenter" = ? AND "VmId" = ? LIMIT 1`, tbl.Table)
q = sqlx.Rebind(sqlx.BindType(dbConn.DriverName()), q)
var name, cluster sql.NullString
err := dbConn.QueryRowxContext(ctx, q, vcenter, cand.vmID).Scan(&name, &cluster)
if err == nil {
lastSeen = tbl.Time
if cand.name == "" && name.Valid {
cand.name = name.String
}
if cand.cluster == "" && cluster.Valid {
cand.cluster = cluster.String
}
continue
}
// Not found in this table; if previously seen today, mark deletion at this snapshot time.
if lastSeen > 0 {
deletion = tbl.Time
break
}
// If never seen today and we're at the last table, mark deletion at current snapshot time.
if i == len(tables)-1 {
deletion = tbl.Time
}
}
if deletion > 0 {
if err := db.MarkVmDeletedWithDetails(ctx, dbConn, vcenter, cand.vmID, cand.vmUUID, cand.name, cand.cluster, deletion); err != nil {
logger.Warn("lifecycle backfill mark deleted failed", "vcenter", vcenter, "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "name", cand.name, "cluster", cand.cluster, "deletion", deletion, "error", err)
continue
}
logger.Debug("lifecycle backfill applied", "vcenter", vcenter, "vm_id", cand.vmID, "vm_uuid", cand.vmUUID, "name", cand.name, "cluster", cand.cluster, "deletion", deletion)
}
}
return nil
}
func (c *CronTask) reportsDir() string {
if c.Settings != nil && c.Settings.Values != nil {
if dir := strings.TrimSpace(c.Settings.Values.Settings.ReportsDir); dir != "" {
@@ -1099,8 +977,8 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
moreMissing := c.markMissingFromPrevious(ctx, dbConn, prevTableName, url, startTime, presentSnapshots, presentByUuid, presentByName, inventoryByVmID, inventoryByUuid, inventoryByName)
missingCount += moreMissing
// Guard against gaps: if previous snapshot is much older than expected, skip "new" detection to avoid false positives when an hourly run was missed.
snapshotPeriod := durationFromSeconds(c.Settings.Values.Settings.VcenterInventorySnapshotSeconds, time.Hour).Seconds()
if prevSnapshotTime > 0 && startTime.Unix()-prevSnapshotTime > int64(snapshotPeriod*2) {
expectedSeconds := int64(durationFromSeconds(c.Settings.Values.Settings.VcenterInventorySnapshotSeconds, time.Hour).Seconds())
if HasSnapshotGap(prevSnapshotTime, startTime.Unix(), expectedSeconds) {
c.Logger.Info("skipping new-VM detection due to gap between snapshots", "prev_table", prevTableName, "prev_snapshot_unix", prevSnapshotTime, "current_snapshot_unix", startTime.Unix())
} else {
newCount = countNewFromPrevious(ctx, dbConn, prevTableName, url, presentSnapshots)