...

Source file src/edge-infra.dev/pkg/edge/api/utils/vm_helper.go

Documentation: edge-infra.dev/pkg/edge/api/utils

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"k8s.io/apimachinery/pkg/api/resource"
     8  
     9  	"edge-infra.dev/pkg/edge/api/graph/model"
    10  )
    11  
    12  func CreateVirtualMachineModel(virtualMachineID string, namespace string, clusterEdgeID string, clusterName string, hostname string, targetPowerState bool, cpus int, memory string, machineType model.MachineType) model.VirtualMachine {
    13  	return model.VirtualMachine{
    14  		VirtualMachineID: virtualMachineID,
    15  		Namespace:        namespace,
    16  		ClusterEdgeID:    clusterEdgeID,
    17  		ClusterName:      clusterName,
    18  		Hostname:         hostname,
    19  		TargetPowerState: targetPowerState,
    20  		Cpus:             cpus,
    21  		Memory:           memory,
    22  		MachineType:      machineType,
    23  	}
    24  }
    25  
    26  func CreateVirtualMachineDiskModel(diskID string, virtualMachineID string, diskType model.DiskType, bus model.BusType, bootOrder int, size string, containerImageURL string) model.VirtualMachineDisk {
    27  	return model.VirtualMachineDisk{
    28  		DiskID:            diskID,
    29  		VirtualMachineID:  virtualMachineID,
    30  		Type:              diskType,
    31  		Bus:               bus,
    32  		BootOrder:         bootOrder,
    33  		Size:              size,
    34  		ContainerImageURL: containerImageURL,
    35  	}
    36  }
    37  
    38  // Validate a VirtualMachine
    39  func ValidateVirtualMachine(virtualMachine *model.VirtualMachine) error {
    40  	if !virtualMachine.MachineType.IsValid() {
    41  		return fmt.Errorf("invalid VirtualMachine machine type: %s", virtualMachine.MachineType.String())
    42  	}
    43  	if !validateVirtualMachineMemory(virtualMachine.Memory) {
    44  		return fmt.Errorf("invalid memory format (SI notation (K,M,G,T,P,E) and Binary notation (Ki,Mi,Gi,Ti,Pi,Ei) are accepted): %s", virtualMachine.Memory)
    45  	}
    46  	return nil
    47  }
    48  
    49  func validateVirtualMachineMemory(memory string) bool {
    50  	_, err := resource.ParseQuantity(memory) // use kubernetes quantity parsing to check for valid memory string
    51  	return err == nil
    52  }
    53  
    54  func ValidateVirtualMachineDisk(disk *model.VirtualMachineDisk) error {
    55  	if !disk.Type.IsValid() {
    56  		return fmt.Errorf("invalid VirtualMachineDisk disk type: %s", disk.Type.String())
    57  	}
    58  	if !disk.Bus.IsValid() {
    59  		return fmt.Errorf("invalid VirtualMachineDisk bus type: %s", disk.Bus.String())
    60  	}
    61  	if !validateVirtualMachineContainerImageURL(disk.ContainerImageURL) {
    62  		return fmt.Errorf("invalid container image url format: %s", disk.ContainerImageURL)
    63  	}
    64  	if !validateVirtualMachineMemory(disk.Size) {
    65  		return fmt.Errorf("invalid size format (SI notation (K,M,G,T,P,E) and Binary notation (Ki,Mi,Gi,Ti,Pi,Ei) are accepted): %s", disk.Size)
    66  	}
    67  	return nil
    68  }
    69  
    70  func HasDuplicateDiskBootOrders(disks []*model.VirtualMachineDisk) bool {
    71  	visited := make(map[int]bool, 0)
    72  	for _, disk := range disks {
    73  		bootOrder := disk.BootOrder
    74  		if visited[bootOrder] {
    75  			return true
    76  		}
    77  		visited[bootOrder] = true
    78  	}
    79  	return false
    80  }
    81  
    82  func validateVirtualMachineContainerImageURL(containerImageURL string) bool {
    83  	if containerImageURL == "" {
    84  		return true // can't validate something that's empty
    85  	}
    86  	const pattern = `^docker://us-east1-docker.pkg.dev/ret-edge-pltf-infra/workloads/([^:]+):([^:]+)$|^docker://us-east1-docker.pkg.dev/ret-edge-pltf-infra/thirdparty/quay.io/kubevirt/virtio-container-disk([^:]+):([^:]+)$`
    87  	re := regexp.MustCompile(pattern)
    88  	return re.MatchString(containerImageURL)
    89  }
    90  
    91  // Set the VirtualMachine values that aren't being updated to the current values in the db.
    92  func UpdateVirtualMachine(currentVM *model.VirtualMachine, updateVM *model.VirtualMachineIDInput) *model.VirtualMachine {
    93  	currentVM.TargetPowerState = *AssignNotNil[bool](&currentVM.TargetPowerState, updateVM.VirtualMachineValues.TargetPowerState)
    94  	currentVM.Memory = *AssignNotNil[string](&currentVM.Memory, updateVM.VirtualMachineValues.Memory)
    95  	currentVM.MachineType = *AssignNotNil[model.MachineType](&currentVM.MachineType, updateVM.VirtualMachineValues.MachineType)
    96  	currentVM.Cpus = *AssignNotNil[int](&currentVM.Cpus, updateVM.VirtualMachineValues.Cpus)
    97  	return currentVM
    98  }
    99  
   100  func UpdateVirtualMachineDisk(currentDisk *model.VirtualMachineDisk, updateDisk *model.VirtualMachineDiskUpdateInput) *model.VirtualMachineDisk {
   101  	currentDisk.Type = *AssignNotNil[model.DiskType](&currentDisk.Type, updateDisk.Type)
   102  	currentDisk.Bus = *AssignNotNil[model.BusType](&currentDisk.Bus, updateDisk.Bus)
   103  	currentDisk.BootOrder = *AssignNotNil[int](&currentDisk.BootOrder, updateDisk.BootOrder)
   104  	currentDisk.Size = *AssignNotNil[string](&currentDisk.Size, updateDisk.Size)
   105  	currentDisk.ContainerImageURL = *AssignNotNil[string](&currentDisk.ContainerImageURL, updateDisk.ContainerImageURL)
   106  	return currentDisk
   107  }
   108  
   109  func AssignNotNil[T any](currentValue, newValue *T) *T {
   110  	if newValue != nil {
   111  		return newValue
   112  	}
   113  	return currentValue
   114  }
   115  

View as plain text