Add vCenter reference cache tables and update related functions
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:
242
db/helpers.go
242
db/helpers.go
@@ -30,6 +30,11 @@ type ColumnDef struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
type VcenterHostCacheEntry struct {
|
||||
Cluster string
|
||||
Datacenter string
|
||||
}
|
||||
|
||||
type ensureOnceKey struct {
|
||||
dbConn *sqlx.DB
|
||||
name string
|
||||
@@ -1107,6 +1112,243 @@ CREATE TABLE IF NOT EXISTS vm_renames (
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnsureVcenterReferenceCacheTables creates lookup caches for vCenter object references.
|
||||
func EnsureVcenterReferenceCacheTables(ctx context.Context, dbConn *sqlx.DB) error {
|
||||
return ensureOncePerDB(dbConn, "vcenter_reference_cache_tables", func() error {
|
||||
ddls := []string{
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS vcenter_folder_cache (
|
||||
"Vcenter" TEXT NOT NULL,
|
||||
"FolderRef" TEXT NOT NULL,
|
||||
"FolderPath" TEXT NOT NULL,
|
||||
"LastSeen" BIGINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY ("Vcenter","FolderRef")
|
||||
)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS vcenter_resource_pool_cache (
|
||||
"Vcenter" TEXT NOT NULL,
|
||||
"ResourcePoolRef" TEXT NOT NULL,
|
||||
"ResourcePoolName" TEXT NOT NULL,
|
||||
"LastSeen" BIGINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY ("Vcenter","ResourcePoolRef")
|
||||
)`,
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS vcenter_host_cache (
|
||||
"Vcenter" TEXT NOT NULL,
|
||||
"HostRef" TEXT NOT NULL,
|
||||
"Cluster" TEXT,
|
||||
"Datacenter" TEXT,
|
||||
"LastSeen" BIGINT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY ("Vcenter","HostRef")
|
||||
)`,
|
||||
}
|
||||
for _, ddl := range ddls {
|
||||
if _, err := execLog(ctx, dbConn, ddl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
indexes := []string{
|
||||
`CREATE INDEX IF NOT EXISTS vcenter_folder_cache_vcenter_idx ON vcenter_folder_cache ("Vcenter")`,
|
||||
`CREATE INDEX IF NOT EXISTS vcenter_resource_pool_cache_vcenter_idx ON vcenter_resource_pool_cache ("Vcenter")`,
|
||||
`CREATE INDEX IF NOT EXISTS vcenter_host_cache_vcenter_idx ON vcenter_host_cache ("Vcenter")`,
|
||||
}
|
||||
for _, idx := range indexes {
|
||||
if _, err := execLog(ctx, dbConn, idx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func LoadVcenterFolderCache(ctx context.Context, dbConn *sqlx.DB, vcenter string) (map[string]string, error) {
|
||||
cache := make(map[string]string)
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
if vcenter == "" {
|
||||
return cache, nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
SELECT "FolderRef","FolderPath"
|
||||
FROM vcenter_folder_cache
|
||||
WHERE "Vcenter" = ?
|
||||
`)
|
||||
rows, err := dbConn.QueryxContext(ctx, query, vcenter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var ref string
|
||||
var pathValue string
|
||||
if err := rows.Scan(&ref, &pathValue); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref = strings.TrimSpace(ref)
|
||||
pathValue = strings.TrimSpace(pathValue)
|
||||
if ref == "" || pathValue == "" {
|
||||
continue
|
||||
}
|
||||
cache[ref] = pathValue
|
||||
}
|
||||
return cache, rows.Err()
|
||||
}
|
||||
|
||||
func LoadVcenterResourcePoolCache(ctx context.Context, dbConn *sqlx.DB, vcenter string) (map[string]string, error) {
|
||||
cache := make(map[string]string)
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
if vcenter == "" {
|
||||
return cache, nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
SELECT "ResourcePoolRef","ResourcePoolName"
|
||||
FROM vcenter_resource_pool_cache
|
||||
WHERE "Vcenter" = ?
|
||||
`)
|
||||
rows, err := dbConn.QueryxContext(ctx, query, vcenter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var ref string
|
||||
var name string
|
||||
if err := rows.Scan(&ref, &name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref = strings.TrimSpace(ref)
|
||||
name = strings.TrimSpace(name)
|
||||
if ref == "" || name == "" {
|
||||
continue
|
||||
}
|
||||
cache[ref] = name
|
||||
}
|
||||
return cache, rows.Err()
|
||||
}
|
||||
|
||||
func LoadVcenterHostCache(ctx context.Context, dbConn *sqlx.DB, vcenter string) (map[string]VcenterHostCacheEntry, error) {
|
||||
cache := make(map[string]VcenterHostCacheEntry)
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
if vcenter == "" {
|
||||
return cache, nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
SELECT "HostRef","Cluster","Datacenter"
|
||||
FROM vcenter_host_cache
|
||||
WHERE "Vcenter" = ?
|
||||
`)
|
||||
rows, err := dbConn.QueryxContext(ctx, query, vcenter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var ref string
|
||||
var cluster sql.NullString
|
||||
var datacenter sql.NullString
|
||||
if err := rows.Scan(&ref, &cluster, &datacenter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ref = strings.TrimSpace(ref)
|
||||
if ref == "" {
|
||||
continue
|
||||
}
|
||||
cache[ref] = VcenterHostCacheEntry{
|
||||
Cluster: strings.TrimSpace(cluster.String),
|
||||
Datacenter: strings.TrimSpace(datacenter.String),
|
||||
}
|
||||
}
|
||||
return cache, rows.Err()
|
||||
}
|
||||
|
||||
func UpsertVcenterFolderCache(ctx context.Context, dbConn *sqlx.DB, vcenter, folderRef, folderPath string, lastSeen int64) error {
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
folderRef = strings.TrimSpace(folderRef)
|
||||
folderPath = strings.TrimSpace(folderPath)
|
||||
if vcenter == "" || folderRef == "" || folderPath == "" {
|
||||
return nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
INSERT INTO vcenter_folder_cache ("Vcenter","FolderRef","FolderPath","LastSeen")
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT ("Vcenter","FolderRef") DO UPDATE SET
|
||||
"FolderPath" = EXCLUDED."FolderPath",
|
||||
"LastSeen" = CASE
|
||||
WHEN EXCLUDED."LastSeen" > vcenter_folder_cache."LastSeen" THEN EXCLUDED."LastSeen"
|
||||
ELSE vcenter_folder_cache."LastSeen"
|
||||
END
|
||||
`)
|
||||
_, err := execLog(ctx, dbConn, query, vcenter, folderRef, folderPath, lastSeen)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpsertVcenterResourcePoolCache(ctx context.Context, dbConn *sqlx.DB, vcenter, resourcePoolRef, resourcePoolName string, lastSeen int64) error {
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
resourcePoolRef = strings.TrimSpace(resourcePoolRef)
|
||||
resourcePoolName = strings.TrimSpace(resourcePoolName)
|
||||
if vcenter == "" || resourcePoolRef == "" || resourcePoolName == "" {
|
||||
return nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
INSERT INTO vcenter_resource_pool_cache ("Vcenter","ResourcePoolRef","ResourcePoolName","LastSeen")
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT ("Vcenter","ResourcePoolRef") DO UPDATE SET
|
||||
"ResourcePoolName" = EXCLUDED."ResourcePoolName",
|
||||
"LastSeen" = CASE
|
||||
WHEN EXCLUDED."LastSeen" > vcenter_resource_pool_cache."LastSeen" THEN EXCLUDED."LastSeen"
|
||||
ELSE vcenter_resource_pool_cache."LastSeen"
|
||||
END
|
||||
`)
|
||||
_, err := execLog(ctx, dbConn, query, vcenter, resourcePoolRef, resourcePoolName, lastSeen)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpsertVcenterHostCache(ctx context.Context, dbConn *sqlx.DB, vcenter, hostRef, cluster, datacenter string, lastSeen int64) error {
|
||||
vcenter = strings.TrimSpace(vcenter)
|
||||
hostRef = strings.TrimSpace(hostRef)
|
||||
cluster = strings.TrimSpace(cluster)
|
||||
datacenter = strings.TrimSpace(datacenter)
|
||||
if vcenter == "" || hostRef == "" {
|
||||
return nil
|
||||
}
|
||||
if cluster == "" && datacenter == "" {
|
||||
return nil
|
||||
}
|
||||
if err := EnsureVcenterReferenceCacheTables(ctx, dbConn); err != nil {
|
||||
return err
|
||||
}
|
||||
query := dbConn.Rebind(`
|
||||
INSERT INTO vcenter_host_cache ("Vcenter","HostRef","Cluster","Datacenter","LastSeen")
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT ("Vcenter","HostRef") DO UPDATE SET
|
||||
"Cluster" = COALESCE(NULLIF(EXCLUDED."Cluster", ''), vcenter_host_cache."Cluster"),
|
||||
"Datacenter" = COALESCE(NULLIF(EXCLUDED."Datacenter", ''), vcenter_host_cache."Datacenter"),
|
||||
"LastSeen" = CASE
|
||||
WHEN EXCLUDED."LastSeen" > vcenter_host_cache."LastSeen" THEN EXCLUDED."LastSeen"
|
||||
ELSE vcenter_host_cache."LastSeen"
|
||||
END
|
||||
`)
|
||||
_, err := execLog(ctx, dbConn, query, vcenter, hostRef, cluster, datacenter, lastSeen)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpsertVmIdentity updates/creates the identity record and records rename events.
|
||||
func UpsertVmIdentity(ctx context.Context, dbConn *sqlx.DB, vcenter string, vmId, vmUuid sql.NullString, name string, cluster sql.NullString, snapshotTime time.Time) error {
|
||||
keyVmID := strings.TrimSpace(vmId.String)
|
||||
|
||||
@@ -180,6 +180,8 @@ func ensureDestinationImportTable(ctx context.Context, destination *sqlx.DB, tab
|
||||
return EnsureVcenterLatestTotalsTable(ctx, destination)
|
||||
case tableName == "vcenter_aggregate_totals":
|
||||
return EnsureVcenterAggregateTotalsTable(ctx, destination)
|
||||
case tableName == "vcenter_folder_cache", tableName == "vcenter_resource_pool_cache", tableName == "vcenter_host_cache":
|
||||
return EnsureVcenterReferenceCacheTables(ctx, destination)
|
||||
default:
|
||||
return fmt.Errorf("source table %q does not exist in postgres and cannot be auto-created", tableName)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user