add repair functionality
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:
@@ -1287,7 +1287,7 @@ WITH snapshots AS (
|
||||
INSERT INTO %s (
|
||||
"InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId", "CreationTime", "DeletionTime",
|
||||
"ResourcePool", "Datacenter", "Cluster", "Folder", "ProvisionedDisk", "VcpuCount",
|
||||
"RamGB", "IsTemplate", "PoweredOn", "SrmPlaceholder", "VmUuid",
|
||||
"RamGB", "IsTemplate", "PoweredOn", "SrmPlaceholder", "VmUuid", "SnapshotTime",
|
||||
"SamplesPresent", "AvgVcpuCount", "AvgRamGB", "AvgProvisionedDisk", "AvgIsPresent",
|
||||
"PoolTinPct", "PoolBronzePct", "PoolSilverPct", "PoolGoldPct",
|
||||
"Tin", "Bronze", "Silver", "Gold"
|
||||
@@ -1339,6 +1339,7 @@ SELECT
|
||||
LIMIT 1
|
||||
) AS "RamGB",
|
||||
agg."IsTemplate", agg."PoweredOn", agg."SrmPlaceholder", agg."VmUuid",
|
||||
agg.last_present AS "SnapshotTime",
|
||||
agg.samples_present AS "SamplesPresent",
|
||||
CASE WHEN totals.total_samples > 0
|
||||
THEN 1.0 * agg.sum_vcpu / totals.total_samples
|
||||
@@ -1382,7 +1383,7 @@ GROUP BY
|
||||
agg."InventoryId", agg."Name", agg."Vcenter", agg."VmId", agg."EventKey", agg."CloudId",
|
||||
agg."Datacenter", agg."Cluster", agg."Folder",
|
||||
agg."IsTemplate", agg."PoweredOn", agg."SrmPlaceholder", agg."VmUuid",
|
||||
agg.any_creation, agg.any_deletion, agg.first_present, agg.last_present,
|
||||
agg.any_creation, agg.any_deletion, agg.first_present, agg.last_present,
|
||||
totals.total_samples;
|
||||
`, unionQuery, tableName)
|
||||
return insert, nil
|
||||
@@ -1660,6 +1661,7 @@ func EnsureSummaryTable(ctx context.Context, dbConn *sqlx.DB, tableName string)
|
||||
"PoolBronzePct" REAL,
|
||||
"PoolSilverPct" REAL,
|
||||
"PoolGoldPct" REAL,
|
||||
"SnapshotTime" BIGINT,
|
||||
"Tin" REAL,
|
||||
"Bronze" REAL,
|
||||
"Silver" REAL,
|
||||
@@ -1690,12 +1692,13 @@ func EnsureSummaryTable(ctx context.Context, dbConn *sqlx.DB, tableName string)
|
||||
"SamplesPresent" BIGINT NOT NULL,
|
||||
"AvgVcpuCount" REAL,
|
||||
"AvgRamGB" REAL,
|
||||
"AvgProvisionedDisk" REAL,
|
||||
"AvgIsPresent" REAL,
|
||||
"PoolTinPct" REAL,
|
||||
"PoolBronzePct" REAL,
|
||||
"PoolSilverPct" REAL,
|
||||
"PoolGoldPct" REAL,
|
||||
"AvgProvisionedDisk" REAL,
|
||||
"AvgIsPresent" REAL,
|
||||
"PoolTinPct" REAL,
|
||||
"PoolBronzePct" REAL,
|
||||
"PoolSilverPct" REAL,
|
||||
"PoolGoldPct" REAL,
|
||||
"SnapshotTime" BIGINT,
|
||||
"Tin" REAL,
|
||||
"Bronze" REAL,
|
||||
"Silver" REAL,
|
||||
@@ -1711,6 +1714,10 @@ func EnsureSummaryTable(ctx context.Context, dbConn *sqlx.DB, tableName string)
|
||||
if hasIsPresent, err := ColumnExists(ctx, dbConn, tableName, "IsPresent"); err == nil && hasIsPresent {
|
||||
_, _ = execLog(ctx, dbConn, fmt.Sprintf(`ALTER TABLE %s DROP COLUMN "IsPresent"`, tableName))
|
||||
}
|
||||
// Ensure SnapshotTime exists for lifecycle refinement.
|
||||
if hasSnapshot, err := ColumnExists(ctx, dbConn, tableName, "SnapshotTime"); err == nil && !hasSnapshot {
|
||||
_, _ = execLog(ctx, dbConn, fmt.Sprintf(`ALTER TABLE %s ADD COLUMN "SnapshotTime" BIGINT`, tableName))
|
||||
}
|
||||
|
||||
indexes := []string{
|
||||
fmt.Sprintf(`CREATE INDEX IF NOT EXISTS %s_vm_vcenter_idx ON %s ("VmId","Vcenter")`, tableName, tableName),
|
||||
@@ -1730,6 +1737,64 @@ func EnsureSummaryTable(ctx context.Context, dbConn *sqlx.DB, tableName string)
|
||||
return nil
|
||||
}
|
||||
|
||||
// BackfillSnapshotTimeFromUnion sets SnapshotTime in a summary table using the max snapshot time per VM from a union query.
|
||||
func BackfillSnapshotTimeFromUnion(ctx context.Context, dbConn *sqlx.DB, summaryTable, unionQuery string) error {
|
||||
if unionQuery == "" {
|
||||
return fmt.Errorf("union query is empty")
|
||||
}
|
||||
if _, err := SafeTableName(summaryTable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
driver := strings.ToLower(dbConn.DriverName())
|
||||
var sql string
|
||||
switch driver {
|
||||
case "pgx", "postgres":
|
||||
sql = fmt.Sprintf(`
|
||||
WITH snapshots AS (
|
||||
%s
|
||||
)
|
||||
UPDATE %s dst
|
||||
SET "SnapshotTime" = sub.max_time
|
||||
FROM (
|
||||
SELECT s."Vcenter", s."VmId", s."VmUuid", s."Name", MAX(s."SnapshotTime") AS max_time
|
||||
FROM snapshots s
|
||||
GROUP BY s."Vcenter", s."VmId", s."VmUuid", s."Name"
|
||||
) sub
|
||||
WHERE (dst."SnapshotTime" IS NULL OR dst."SnapshotTime" = 0)
|
||||
AND dst."Vcenter" = sub."Vcenter"
|
||||
AND (
|
||||
(dst."VmId" IS NOT DISTINCT FROM sub."VmId")
|
||||
OR (dst."VmUuid" IS NOT DISTINCT FROM sub."VmUuid")
|
||||
OR (dst."Name" IS NOT DISTINCT FROM sub."Name")
|
||||
);
|
||||
`, unionQuery, summaryTable)
|
||||
default:
|
||||
sql = fmt.Sprintf(`
|
||||
WITH snapshots AS (
|
||||
%[1]s
|
||||
), grouped AS (
|
||||
SELECT s."Vcenter", s."VmId", s."VmUuid", s."Name", MAX(s."SnapshotTime") AS max_time
|
||||
FROM snapshots s
|
||||
GROUP BY s."Vcenter", s."VmId", s."VmUuid", s."Name"
|
||||
)
|
||||
UPDATE %[2]s
|
||||
SET "SnapshotTime" = (
|
||||
SELECT max_time FROM grouped g
|
||||
WHERE %[2]s."Vcenter" = g."Vcenter"
|
||||
AND (
|
||||
(%[2]s."VmId" IS NOT NULL AND g."VmId" IS NOT NULL AND %[2]s."VmId" = g."VmId")
|
||||
OR (%[2]s."VmUuid" IS NOT NULL AND g."VmUuid" IS NOT NULL AND %[2]s."VmUuid" = g."VmUuid")
|
||||
OR (%[2]s."Name" IS NOT NULL AND g."Name" IS NOT NULL AND %[2]s."Name" = g."Name")
|
||||
)
|
||||
)
|
||||
WHERE "SnapshotTime" IS NULL OR "SnapshotTime" = 0;
|
||||
`, unionQuery, summaryTable)
|
||||
}
|
||||
_, err := execLog(ctx, dbConn, sql)
|
||||
return err
|
||||
}
|
||||
|
||||
// EnsureSnapshotRunTable creates a table to track per-vCenter hourly snapshot attempts.
|
||||
func EnsureSnapshotRunTable(ctx context.Context, dbConn *sqlx.DB) error {
|
||||
ddl := `
|
||||
|
||||
Reference in New Issue
Block a user