diff --git a/pkg/internal/checkup/checkup.go b/pkg/internal/checkup/checkup.go index 434c34b..74667fc 100644 --- a/pkg/internal/checkup/checkup.go +++ b/pkg/internal/checkup/checkup.go @@ -231,12 +231,15 @@ func newVMUnderTestConfigMap(checkupConfig config.Config) *corev1.ConfigMap { func newRealtimeVMI(checkupConfig config.Config) *kvcorev1.VirtualMachineInstance { const ( - CPUSocketsCount = 1 - CPUCoresCount = 4 - CPUTreadsCount = 1 - hugePageSize = "1Gi" - guestMemory = "4Gi" - rootDiskName = "rootdisk" + CPUSocketsCount = 1 + CPUCoresCount = 4 + CPUTreadsCount = 1 + hugePageSize = "1Gi" + guestMemory = "4Gi" + rootDiskName = "rootdisk" + configDiskSerial = "DEADBEEF" + cloudInitDiskName = "cloudinitdisk" + configVolumeName = "realtime-config" ) return vmi.New(randomizeName(VMINamePrefix), @@ -253,9 +256,22 @@ func newRealtimeVMI(checkupConfig config.Config) *kvcorev1.VirtualMachineInstanc vmi.WithNodeSelector(checkupConfig.VMUnderTestTargetNodeName), vmi.WithContainerDisk(rootDiskName, checkupConfig.VMUnderTestContainerDiskImage), vmi.WithVirtIODisk(rootDiskName), + vmi.WithConfigMapVolume(configVolumeName, VMUnderTestConfigMapNamePrefix), + vmi.WithConfigMapDisk(configVolumeName, configDiskSerial), + vmi.WithCloudInitNoCloudVolume(cloudInitDiskName, + vmi.CloudInit(realtimeVMIBootCommands(configDiskSerial))), ) } +func realtimeVMIBootCommands(configDiskSerial string) []string { + const configMountDirectory = "/mnt/app-config" + + return []string{ + fmt.Sprintf("mkdir %s", configMountDirectory), + fmt.Sprintf("mount /dev/$(lsblk --nodeps -no name,serial | grep %s | cut -f1 -d' ') %s", configDiskSerial, configMountDirectory), + } +} + func randomizeName(prefix string) string { const randomStringLen = 5 diff --git a/pkg/internal/checkup/vmi/vmi.go b/pkg/internal/checkup/vmi/vmi.go index b342f88..d6d4082 100644 --- a/pkg/internal/checkup/vmi/vmi.go +++ b/pkg/internal/checkup/vmi/vmi.go @@ -20,6 +20,9 @@ package vmi import ( + "fmt" + "strings" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -199,6 +202,31 @@ func WithContainerDisk(volumeName, imageName string) Option { } } +func WithConfigMapVolume(name, configMapName string) Option { + return func(vmi *kvcorev1.VirtualMachineInstance) { + vmi.Spec.Volumes = append(vmi.Spec.Volumes, kvcorev1.Volume{ + Name: name, + VolumeSource: kvcorev1.VolumeSource{ + ConfigMap: &kvcorev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: configMapName}, + Optional: Pointer(false), + }, + }, + }) + } +} + +func WithConfigMapDisk(name, serial string) Option { + return func(vmi *kvcorev1.VirtualMachineInstance) { + vmi.Spec.Domain.Devices.Disks = append(vmi.Spec.Domain.Devices.Disks, + kvcorev1.Disk{ + Name: name, + Serial: serial, + }, + ) + } +} + func WithCloudInitNoCloudVolume(name, userData string) Option { return func(vmi *kvcorev1.VirtualMachineInstance) { newVolume := kvcorev1.Volume{ @@ -214,6 +242,21 @@ func WithCloudInitNoCloudVolume(name, userData string) Option { } } +func CloudInit(bootCommands []string) string { + sb := strings.Builder{} + sb.WriteString("#cloud-config\n") + + if len(bootCommands) != 0 { + sb.WriteString("bootcmd:\n") + + for _, command := range bootCommands { + sb.WriteString(fmt.Sprintf(" - %q\n", command)) + } + } + + return sb.String() +} + func Pointer[T any](v T) *T { return &v }