Skip to content

Commit 2ff7d99

Browse files
committed
Check qemu version in hostagent so not too old
This is mostly to give better error messages, when failing. The old error would just say that it exited unexpectedly... If the version can't be parsed, show a warning and continue. We only want to warn about the versions known not to work. Signed-off-by: Anders F Björklund <[email protected]>
1 parent a4fdc5d commit 2ff7d99

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

pkg/qemu/qemu.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os/exec"
1010
"os/user"
1111
"path/filepath"
12+
"regexp"
1213
"runtime"
1314
"strconv"
1415
"strings"
@@ -36,6 +37,9 @@ type Config struct {
3637
SSHLocalPort int
3738
}
3839

40+
// MinimumQemuVersion is the minimum supported QEMU version
41+
const MinimumQemuVersion = "4.0.0"
42+
3943
// EnsureDisk also ensures the kernel and the initrd
4044
func EnsureDisk(cfg Config) error {
4145
diffDisk := filepath.Join(cfg.InstanceDir, filenames.DiffDisk)
@@ -341,6 +345,16 @@ func Cmdline(cfg Config) (string, []string, error) {
341345
return "", nil, err
342346
}
343347

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+
344358
// Architecture
345359
accel := getAccel(*y.Arch)
346360
if !strings.Contains(string(features.AccelHelp), accel) {
@@ -717,6 +731,31 @@ func getAccel(arch limayaml.Arch) string {
717731
return "tcg"
718732
}
719733

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+
720759
func getFirmware(qemuExe string, arch limayaml.Arch) (string, error) {
721760
switch arch {
722761
case limayaml.X8664, limayaml.AARCH64:

pkg/qemu/qemu_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,42 @@ func TestArgValue(t *testing.T) {
4747
assert.Equal(t, tc.expectedOK, ok)
4848
}
4949
}
50+
51+
func TestParseQemuVersion(t *testing.T) {
52+
type testCase struct {
53+
versionOutput string
54+
expectedValue string
55+
expectedError string
56+
}
57+
testCases := []testCase{
58+
{
59+
// old one line version
60+
versionOutput: "QEMU emulator version 1.5.3 (qemu-kvm-1.5.3-175.el7_9.6), " +
61+
"Copyright (c) 2003-2008 Fabrice Bellard\n",
62+
expectedValue: "1.5.3",
63+
expectedError: "",
64+
},
65+
{
66+
// new two line version
67+
versionOutput: "QEMU emulator version 8.0.0 (v8.0.0)\n" +
68+
"Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers\n",
69+
expectedValue: "8.0.0",
70+
expectedError: "",
71+
},
72+
{
73+
versionOutput: "foobar",
74+
expectedValue: "0.0.0",
75+
expectedError: "failed to parse",
76+
},
77+
}
78+
79+
for _, tc := range testCases {
80+
v, err := parseQemuVersion(tc.versionOutput)
81+
if tc.expectedError == "" {
82+
assert.NilError(t, err)
83+
} else {
84+
assert.ErrorContains(t, err, tc.expectedError)
85+
}
86+
assert.Equal(t, tc.expectedValue, v.String())
87+
}
88+
}

0 commit comments

Comments
 (0)