From 00d474b9370c31d46920cba9d14b5de77ce9f7b1 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Thu, 26 Sep 2024 13:29:02 +1000 Subject: [PATCH] add vm cleanup endpoint --- db/queries/query.sql | 5 +++ db/queries/query.sql.go | 16 +++++++ server/handler/vmCleanup.go | 90 +++++++++++++++++++++++++++++++++++++ server/handler/vmImport.go | 2 +- server/router/router.go | 2 + 5 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 server/handler/vmCleanup.go diff --git a/db/queries/query.sql b/db/queries/query.sql index e670912..41803a1 100644 --- a/db/queries/query.sql +++ b/db/queries/query.sql @@ -27,6 +27,11 @@ UPDATE "Inventory" SET "DeletionTime" = sqlc.arg('deletionTime') WHERE "VmId" = sqlc.arg('vmId') AND "Datacenter" = sqlc.arg('datacenterName'); +-- name: InventoryCleanup :exec +DELETE FROM "Inventory" +WHERE "VmId" = sqlc.arg('vmId') AND "Datacenter" = sqlc.arg('datacenterName') +RETURNING *; + -- name: CreateUpdate :one INSERT INTO "Updates" ( "InventoryId", "EventKey", "EventId", "UpdateTime", "UpdateType", "NewVcpus", "NewRam", "NewResourcePool", "NewProvisionedDisk", "UserName" diff --git a/db/queries/query.sql.go b/db/queries/query.sql.go index 1f58c61..098d4c5 100644 --- a/db/queries/query.sql.go +++ b/db/queries/query.sql.go @@ -329,6 +329,22 @@ func (q *Queries) GetInventoryVmId(ctx context.Context, arg GetInventoryVmIdPara return i, err } +const inventoryCleanup = `-- name: InventoryCleanup :exec +DELETE FROM "Inventory" +WHERE "VmId" = ?1 AND "Datacenter" = ?2 +RETURNING Iid, Name, Vcenter, VmId, EventKey, CloudId, CreationTime, DeletionTime, ResourcePool, VmType, Datacenter, Cluster, Folder, ProvisionedDisk, InitialVcpus, InitialRam, SrmPlaceholder, IsTemplate, PowerState +` + +type InventoryCleanupParams struct { + VmId sql.NullString + DatacenterName sql.NullString +} + +func (q *Queries) InventoryCleanup(ctx context.Context, arg InventoryCleanupParams) error { + _, err := q.db.ExecContext(ctx, inventoryCleanup, arg.VmId, arg.DatacenterName) + return err +} + const inventoryMarkDeleted = `-- name: InventoryMarkDeleted :exec UPDATE "Inventory" SET "DeletionTime" = ?1 diff --git a/server/handler/vmCleanup.go b/server/handler/vmCleanup.go new file mode 100644 index 0000000..e78bff4 --- /dev/null +++ b/server/handler/vmCleanup.go @@ -0,0 +1,90 @@ +package handler + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "net/http" + "vctp/db/queries" +) + +// Remove a specified VM from the inventory +func (h *Handler) VmCleanup(w http.ResponseWriter, r *http.Request) { + ctx := context.Background() + + // Get the parameters + vmId := r.URL.Query().Get("vm_id") + datacenterName := r.URL.Query().Get("datacenter_name") + if vmId != "" && datacenterName != "" { + // check that the VM exists in the inventory + invParams := queries.GetInventoryVmIdParams{ + VmId: sql.NullString{String: vmId, Valid: vmId != ""}, + DatacenterName: sql.NullString{String: datacenterName, Valid: datacenterName != ""}, + } + h.Logger.Debug("Checking inventory table for VM record", "params", invParams) + vm, err := h.Database.Queries().GetInventoryVmId(ctx, invParams) + + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + h.Logger.Error("No VM found matching parameters", "vm_id", vmId, "datacenter_name", datacenterName) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("No match to VM details specified. vm_id: '%s', datacenter_name: '%s'", vmId, datacenterName), + }) + return + } else { + h.Logger.Error("Error checking for VM to cleanup", "error", err, "vm_id", vmId, "datacenter_name", datacenterName) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("Error checking for VM to cleanup. error: '%s'", err), + }) + return + } + } else { + // delete the VM + + // create the database parameters + params := queries.InventoryCleanupParams{ + VmId: sql.NullString{String: vmId, Valid: vmId != ""}, + DatacenterName: sql.NullString{String: datacenterName, Valid: datacenterName != ""}, + } + + h.Logger.Debug("database params", "params", params) + err = h.Database.Queries().InventoryCleanup(ctx, params) + if err != nil { + h.Logger.Error("Error cleaning up VM from Inventory table", "error", err, "vm_id", vmId, "datacenter_name", datacenterName) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("Error cleaning up VM from Inventory table. error: '%s'", err), + }) + return + } else { + // Successful cleanup + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{ + "status": "OK", + "message": fmt.Sprintf("VM '%s' removed from Inventory table", vm.Name), + }) + return + } + } + } else { + h.Logger.Error("Parameters not correctly specified", "vm_id", vmId, "datacenter_name", datacenterName) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(map[string]string{ + "status": "ERROR", + "message": fmt.Sprintf("Parameters not correctly specified. vm_id: '%s', datacenter_name: '%s'", vmId, datacenterName), + }) + return + } +} diff --git a/server/handler/vmImport.go b/server/handler/vmImport.go index d616dd7..e2ec188 100644 --- a/server/handler/vmImport.go +++ b/server/handler/vmImport.go @@ -39,7 +39,7 @@ func (h *Handler) VmImport(w http.ResponseWriter, r *http.Request) { ctx := context.Background() - // TODO - query Inventory table for this VM before adding it + // Query Inventory table for this VM before adding it h.Logger.Debug("Checking inventory table for VM record") invParams := queries.GetInventoryVmIdParams{ VmId: sql.NullString{String: inData.VmId, Valid: inData.VmId != ""}, diff --git a/server/router/router.go b/server/router/router.go index 76672b9..a58ce20 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -26,6 +26,8 @@ func New(logger *slog.Logger, database db.Database, buildTime string, sha1ver st mux.HandleFunc("/api/event/vm/modify", h.VmModify) mux.HandleFunc("/api/event/vm/delete", h.VmDelete) mux.HandleFunc("/api/import/vm", h.VmImport) + // Use this when we need to manually remove a VM from the database to clean up + mux.HandleFunc("/api/inventory/vm/delete", h.VmCleanup) // temporary endpoint //mux.HandleFunc("/api/cleanup/updates", h.UpdateCleanup)