Added EFI for ARM, RunInstances tweak for provisining disks after instance response

This commit is contained in:
benduncan
2025-11-25 19:49:22 +11:00
parent 243463be2b
commit 58d75102ca
3 changed files with 43 additions and 15 deletions
+8
View File
@@ -963,6 +963,14 @@ func (d *Daemon) handleEC2RunInstances(msg *nats.Msg) {
}
msg.Respond(jsonResponse)
// Next, prepare the root volume, cloud-init, EFI drives via NBD (AMI clone to new volume)
err = d.instanceService.GenerateVolumes(runInstancesInput, instance)
if err != nil {
slog.Error("handleEC2RunInstances GenerateVolumes failed", "err", err)
d.resourceMgr.deallocate(instanceType)
return
}
// Launch the instance infrastructure (QEMU, QMP, NATS subscriptions), this can take sometime
err = d.LaunchInstance(instance)
+22 -15
View File
@@ -103,7 +103,6 @@ func NewInstanceServiceImpl(cfg *config.Config, instanceTypes map[string]Instanc
// This prepares all volumes (root, EFI, cloud-init) and returns the instance ready to launch
func (s *InstanceServiceImpl) RunInstances(input *ec2.RunInstancesInput) (*vm.VM, ec2.Reservation, error) {
var reservation ec2.Reservation
var err error
// Validate input (validation is already done in daemon.handleEC2Launch)
// We can skip re-validation here for performance
@@ -114,13 +113,6 @@ func (s *InstanceServiceImpl) RunInstances(input *ec2.RunInstancesInput) (*vm.VM
return nil, reservation, errors.New(awserrors.ErrorInvalidInstanceType)
}
var size int = 4 * 1024 * 1024 * 1024 // 4GB default size
var deviceName string
var volumeType string
var iops int
var imageId string
var snapshotId string
instanceId := vm.GenerateEC2InstanceID()
// Create new instance structure
@@ -156,6 +148,20 @@ func (s *InstanceServiceImpl) RunInstances(input *ec2.RunInstancesInput) (*vm.VM
instance.Reservation = &reservation
instance.Instance = ec2Instance
// Return instance attributes, defer disk preparation to later step
return instance, reservation, nil
}
func (s *InstanceServiceImpl) GenerateVolumes(input *ec2.RunInstancesInput, instance *vm.VM) (err error) {
var size int = 4 * 1024 * 1024 * 1024 // 4GB default size
var deviceName string
var volumeType string
var iops int
var imageId string
var snapshotId string
// Handle block device mappings
if input.BlockDeviceMappings != nil && len(input.BlockDeviceMappings) > 0 {
size = int(*input.BlockDeviceMappings[0].Ebs.VolumeSize)
@@ -188,24 +194,25 @@ func (s *InstanceServiceImpl) RunInstances(input *ec2.RunInstancesInput) (*vm.VM
// Step 1: Create or validate root volume
err = s.prepareRootVolume(input, imageId, size, volumeConfig, instance)
if err != nil {
return nil, reservation, err
return err
}
// Step 2: Create EFI partition
err = s.prepareEFIVolume(imageId, volumeConfig, instance)
if err != nil {
return nil, reservation, err
return err
}
// Step 3: Create cloud-init volume if needed
if input.KeyName != nil && *input.KeyName != "" || (input.UserData != nil && *input.UserData != "") {
err = s.prepareCloudInitVolume(input, imageId, volumeConfig, instance)
if err != nil {
return nil, reservation, err
return err
}
}
return instance, reservation, nil
return nil
}
// prepareRootVolume handles creation/cloning of the root volume
@@ -234,7 +241,7 @@ func (s *InstanceServiceImpl) prepareRootVolume(input *ec2.RunInstancesInput, im
return errors.New(awserrors.ErrorServerInternal)
}
vb.SetDebug(true)
vb.SetDebug(false)
// Initialize the backend
err = vb.Backend.Init()
@@ -412,7 +419,7 @@ func (s *InstanceServiceImpl) prepareEFIVolume(imageId string, volumeConfig vipe
return errors.New(awserrors.ErrorServerInternal)
}
efiVb.SetDebug(true)
efiVb.SetDebug(false)
// Initialize the backend
slog.Debug("Initializing EFI Viperblock store backend")
@@ -503,7 +510,7 @@ func (s *InstanceServiceImpl) prepareCloudInitVolume(input *ec2.RunInstancesInpu
return errors.New(awserrors.ErrorServerInternal)
}
cloudInitVb.SetDebug(true)
cloudInitVb.SetDebug(false)
// Initialize the backend
slog.Debug("Initializing cloud-init Viperblock store backend")
+13
View File
@@ -214,6 +214,19 @@ func (cfg *Config) Execute() (*exec.Cmd, error) {
// Note, require `-M` machine type for ARM (virt) if set to q35 (incompatible)
if cfg.Architecture == "arm64" && cfg.MachineType == "q35" {
args = append(args, "-M", "virt")
// For ARM, when using virt, preload the firmware file
// Note: this requires the `qemu-efi-aarch64` package to be installed on the host
uefiPath := "/usr/share/qemu-efi-aarch64/QEMU_EFI.fd"
// TODO: Use EFI via NBD for state persistence
if _, err := os.Stat(uefiPath); err == nil {
args = append(args, "-bios", uefiPath)
} else {
slog.Warn("UEFI firmware file not found for ARM virt machine. Ensure qemu-efi-aarch64 package is installed.", "path", uefiPath)
return nil, fmt.Errorf("UEFI firmware file not found for ARM virt machine")
}
} else if cfg.MachineType != "" {
args = append(args, "-M", cfg.MachineType)
}