|
9 | 9 | "os/exec"
|
10 | 10 | "os/user"
|
11 | 11 | "path/filepath"
|
| 12 | + "regexp" |
12 | 13 | "runtime"
|
13 | 14 | "strconv"
|
14 | 15 | "strings"
|
@@ -36,6 +37,9 @@ type Config struct {
|
36 | 37 | SSHLocalPort int
|
37 | 38 | }
|
38 | 39 |
|
| 40 | +// MinimumQemuVersion is the minimum supported QEMU version |
| 41 | +const MinimumQemuVersion = "4.0.0" |
| 42 | + |
39 | 43 | // EnsureDisk also ensures the kernel and the initrd
|
40 | 44 | func EnsureDisk(cfg Config) error {
|
41 | 45 | diffDisk := filepath.Join(cfg.InstanceDir, filenames.DiffDisk)
|
@@ -341,6 +345,16 @@ func Cmdline(cfg Config) (string, []string, error) {
|
341 | 345 | return "", nil, err
|
342 | 346 | }
|
343 | 347 |
|
| 348 | + version, err := getQemuVersion(exe) |
| 349 | + if err != nil { |
| 350 | + logrus.WithError(err).Warning("Failed to detect QEMU version") |
| 351 | + } else { |
| 352 | + logrus.Debugf("QEMU version %s detected", version.String()) |
| 353 | + if version.LessThan(*semver.New(MinimumQemuVersion)) { |
| 354 | + logrus.Fatalf("QEMU %v is too old, %v or later required", version, MinimumQemuVersion) |
| 355 | + } |
| 356 | + } |
| 357 | + |
344 | 358 | // Architecture
|
345 | 359 | accel := getAccel(*y.Arch)
|
346 | 360 | if !strings.Contains(string(features.AccelHelp), accel) {
|
@@ -717,6 +731,31 @@ func getAccel(arch limayaml.Arch) string {
|
717 | 731 | return "tcg"
|
718 | 732 | }
|
719 | 733 |
|
| 734 | +func parseQemuVersion(output string) (*semver.Version, error) { |
| 735 | + lines := strings.Split(output, "\n") |
| 736 | + regex := regexp.MustCompile(`^QEMU emulator version (\d+\.\d+\.\d+)`) |
| 737 | + matches := regex.FindStringSubmatch(lines[0]) |
| 738 | + if len(matches) == 2 { |
| 739 | + return semver.New(matches[1]), nil |
| 740 | + } |
| 741 | + return &semver.Version{}, fmt.Errorf("failed to parse %v", output) |
| 742 | +} |
| 743 | + |
| 744 | +func getQemuVersion(qemuExe string) (*semver.Version, error) { |
| 745 | + var ( |
| 746 | + stdout bytes.Buffer |
| 747 | + stderr bytes.Buffer |
| 748 | + ) |
| 749 | + cmd := exec.Command(qemuExe, "--version") |
| 750 | + cmd.Stdout = &stdout |
| 751 | + cmd.Stderr = &stderr |
| 752 | + if err := cmd.Run(); err != nil { |
| 753 | + return nil, fmt.Errorf("failed to run %v: stdout=%q, stderr=%q", cmd.Args, stdout.String(), stderr.String()) |
| 754 | + } |
| 755 | + |
| 756 | + return parseQemuVersion(stdout.String()) |
| 757 | +} |
| 758 | + |
720 | 759 | func getFirmware(qemuExe string, arch limayaml.Arch) (string, error) {
|
721 | 760 | switch arch {
|
722 | 761 | case limayaml.X8664, limayaml.AARCH64:
|
|
0 commit comments