Files
vctp2/internal/tasks/processEvents.go
Nathan Coad 57980a860a
Some checks are pending
CI / Lint (push) Waiting to run
CI / Test (push) Waiting to run
CI / End-to-End (push) Waiting to run
CI / Publish Docker (push) Blocked by required conditions
continuous-integration/drone/push Build is passing
add vm power state and template
2024-09-16 10:14:46 +10:00

161 lines
5.3 KiB
Go

package tasks
import (
"context"
"database/sql"
"log/slog"
"time"
"vctp/db"
"vctp/db/queries"
"vctp/internal/vcenter"
"github.com/vmware/govmomi/vim25/types"
)
// Handler handles requests.
type CronTask struct {
Logger *slog.Logger
Database db.Database
}
// use gocron to check events in the Events table
func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
var (
numVcpus int32
numRam int32
totalDiskGB float64
srmPlaceholder int
foundVm bool
isTemplate int
poweredOn int
)
logger.Debug("Started Events processing", "time", time.Now())
// Query events table
events, err := c.Database.Queries().ListUnprocessedEvents(ctx)
if err != nil {
logger.Error("Unable to query for unprocessed events", "error", err)
return nil // TODO - what to do with this error?
}
for _, evt := range events {
logger.Debug("Checking event", "event", evt)
// TODO - get a list of unique vcenters, then process each event in batches
// to avoid doing unnecessary login/logout of vcenter
c.Logger.Debug("connecting to vcenter")
vc := vcenter.New(c.Logger)
vc.Login(evt.Source)
//datacenter = evt.DatacenterName.String
vmObject, err := vc.FindVMByIDWithDatacenter(evt.VmId.String, evt.DatacenterId.String)
if err != nil {
c.Logger.Error("Can't locate vm in vCenter", "vmID", evt.VmId.String, "error", err)
} else if vmObject == nil {
c.Logger.Debug("didn't find VM", "vm_id", evt.VmId.String)
numRam = 0
numVcpus = 0
totalDiskGB = 0
isTemplate = 0
} else {
c.Logger.Debug("found VM")
srmPlaceholder = 0 // Default assumption
//prettyPrint(vmObject)
// calculate VM properties we want to store
if vmObject.Vm.Config != nil {
numRam = vmObject.Vm.Config.Hardware.MemoryMB
numVcpus = vmObject.Vm.Config.Hardware.NumCPU
// Calculate the total disk allocated in GB
for _, device := range vmObject.Vm.Config.Hardware.Device {
if disk, ok := device.(*types.VirtualDisk); ok {
totalDiskGB += float64(disk.CapacityInBytes / 1024 / 1024 / 1024) // Convert from bytes to GB
}
}
// Determine if the VM is a normal VM or an SRM placeholder
if vmObject.Vm.Config.ManagedBy != nil && vmObject.Vm.Config.ManagedBy.Type == "com.vmware.vcDr" {
c.Logger.Debug("VM ManagedBy indicates managed by SRM")
srmPlaceholder = 1
}
if vmObject.Vm.Config.Template {
isTemplate = 1
} else {
isTemplate = 0
}
foundVm = true
} else {
c.Logger.Error("Empty VM config")
}
//if (types.VirtualMachineRuntimeInfo{}) != vmObject.Vm.Runtime {
//if runtime, ok := vmObject.Vm.Runtime.(types.VirtualMachineRuntimeInfo); ok {
c.Logger.Debug("VM has runtime data", "power_state", vmObject.Vm.Runtime.PowerState)
if vmObject.Vm.Runtime.PowerState == "" {
poweredOn = 0
} else {
poweredOn = 1
}
//}
}
err = vc.Logout()
if err != nil {
c.Logger.Error("unable to logout of vcenter", "error", err)
}
if foundVm {
c.Logger.Debug("Adding to Inventory table", "vm_name", evt.VmName.String, "vcpus", numVcpus, "ram", numRam, "dc", evt.DatacenterId.String)
params := queries.CreateInventoryParams{
Name: vmObject.Vm.Name,
Vcenter: evt.Source,
EventId: sql.NullString{String: evt.CloudId, Valid: evt.CloudId != ""},
EventKey: sql.NullString{String: evt.EventKey.String, Valid: evt.EventKey.Valid},
VmId: sql.NullString{String: evt.VmId.String, Valid: evt.VmId.Valid},
Datacenter: sql.NullString{String: evt.DatacenterName.String, Valid: evt.DatacenterName.Valid},
Cluster: sql.NullString{String: evt.ComputeResourceName.String, Valid: evt.ComputeResourceName.Valid},
CreationTime: sql.NullInt64{Int64: evt.EventTime.Int64, Valid: evt.EventTime.Valid},
InitialVcpus: sql.NullInt64{Int64: int64(numVcpus), Valid: numVcpus > 0},
InitialRam: sql.NullInt64{Int64: int64(numRam), Valid: numRam > 0},
ProvisionedDisk: sql.NullFloat64{Float64: totalDiskGB, Valid: totalDiskGB > 0},
Folder: sql.NullString{String: vmObject.FolderPath, Valid: vmObject.FolderPath != ""},
ResourcePool: sql.NullString{String: vmObject.ResourcePool, Valid: vmObject.ResourcePool != ""},
SrmPlaceholder: sql.NullInt64{Int64: int64(srmPlaceholder), Valid: true},
IsTemplate: sql.NullInt64{Int64: int64(isTemplate), Valid: true},
PowerState: sql.NullInt64{Int64: int64(poweredOn), Valid: true},
}
c.Logger.Debug("database params", "params", params)
// Insert the new inventory record into the database
result, err := c.Database.Queries().CreateInventory(ctx, params)
if err != nil {
c.Logger.Error("unable to perform database insert", "error", err)
} else {
c.Logger.Debug("created database record", "insert_result", result)
// mark this event as processed
err = c.Database.Queries().UpdateEventsProcessed(ctx, evt.Eid)
if err != nil {
c.Logger.Error("Unable to mark this event as processed", "event_id", evt.Eid, "error", err)
} else {
c.Logger.Debug("Marked event as processed", "event_id", evt.Eid)
}
}
} else {
c.Logger.Debug("Not adding to Inventory due to missing vcenter config property", "vm_name", evt.VmName.String)
}
}
//fmt.Printf("processing at %s", time.Now())
return nil
}