two/internal/qemu/start_linux.go
GnomeZworc c3f26836cd
All checks were successful
Pre Release Workflow / set-release-target (push) Successful in 1s
Pre Release Workflow / upload-scripts (run-dnsmasq-in-netns.sh) (push) Successful in 6s
Pre Release Workflow / build (agent, amd64, linux) (push) Successful in 1m34s
Pre Release Workflow / build (metadata, amd64, linux) (push) Successful in 1m31s
Pre Release Workflow / prerelease (push) Successful in 10s
f-32: fix: update boot order
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-05-24 16:47:49 +02:00

106 lines
2.7 KiB
Go

//go:build linux
package qemu
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
)
func Start(cfg Config) error {
memory := cfg.Memory
if memory == 0 {
memory = 512
}
cpus := cfg.CPUs
if cpus == 0 {
cpus = 1
}
for _, dir := range []string{cfg.SerialDir, cfg.MonitorDir, cfg.QMPDir} {
if dir != "" {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("mkdir %s: %w", dir, err)
}
}
}
serialSock := filepath.Join(cfg.SerialDir, cfg.Name+".sock")
monitorSock := filepath.Join(cfg.MonitorDir, cfg.Name+".sock")
qmpSock := filepath.Join(cfg.QMPDir, cfg.Name+".sock")
args := []string{
"-enable-kvm",
"-cpu", "host",
"-m", fmt.Sprintf("%d", memory),
"-smp", fmt.Sprintf("%d", cpus),
"-serial", fmt.Sprintf("unix:%s,server,nowait", serialSock),
"-monitor", fmt.Sprintf("unix:%s,server,nowait", monitorSock),
"-qmp", fmt.Sprintf("unix:%s,server,nowait", qmpSock),
"-display", "none",
}
if cfg.UEFICodePath != "" && cfg.UEFIVarsPath != "" {
args = append(args,
"-drive", fmt.Sprintf("if=pflash,format=raw,readonly=on,file=%s", cfg.UEFICodePath),
"-drive", fmt.Sprintf("if=pflash,format=raw,file=%s", cfg.UEFIVarsPath),
)
}
hasScsi := false
for _, d := range cfg.Disks {
if strings.HasPrefix(d.Dev, "sd") {
hasScsi = true
break
}
}
if hasScsi {
args = append(args, "-device", "virtio-scsi-pci,id=scsi0")
}
sorted := make([]DiskConfig, len(cfg.Disks))
copy(sorted, cfg.Disks)
// vd* avant sd* : les disques virtio-blk bootent en premier.
// À lettre égale de type, ordre alphabétique.
sort.Slice(sorted, func(i, j int) bool {
iVirtio := strings.HasPrefix(sorted[i].Dev, "vd")
jVirtio := strings.HasPrefix(sorted[j].Dev, "vd")
if iVirtio != jVirtio {
return iVirtio
}
return sorted[i].Dev < sorted[j].Dev
})
for idx, d := range sorted {
bootindex := idx + 1
if strings.HasPrefix(d.Dev, "sd") {
scsiID := int(d.Dev[2] - 'a')
args = append(args,
"-drive", fmt.Sprintf("file=%s,if=none,id=%s", d.Path, d.Dev),
"-device", fmt.Sprintf("scsi-hd,drive=%s,bus=scsi0.0,scsi-id=%d,bootindex=%d", d.Dev, scsiID, bootindex),
)
} else {
args = append(args,
"-drive", fmt.Sprintf("file=%s,if=none,id=%s", d.Path, d.Dev),
"-device", fmt.Sprintf("virtio-blk-pci,drive=%s,bootindex=%d", d.Dev, bootindex),
)
}
}
args = append(args,
"-netdev", fmt.Sprintf("tap,id=net0,ifname=tap%d,script=no,downscript=no", cfg.TapID),
"-device", fmt.Sprintf("virtio-net-pci,netdev=net0,mac=%s", cfg.Mac),
"-daemonize",
)
cmd := exec.Command("qemu-system-x86_64", args...)
if err := cmd.Run(); err != nil {
return fmt.Errorf("qemu-system-x86_64: %w", err)
}
return nil
}