Skip to content

Commit

Permalink
Add preflight check for hardware-assisted virtualization
Browse files Browse the repository at this point in the history
This is pretty quick and dirty, but I hope should not be unreasonable.
https://help.ubuntu.com/community/KVM/Installation tells us that we need
to run `egrep -c '(vmx|svm)' /proc/cpuinfo` to check for hardware-assisted
virtualization on x86_64 systems, but I think we can short-circuit that.

I reviewed the kvm-ok script (https://bazaar.launchpad.net/~cpu-checker-dev/cpu-checker/trunk/view/head:/kvm-ok)
and it first checks for those CPU flags, and then next checks for the
existence of /dev/kvm.  If both succeed, we're good.  But I don't think
we actually need the CPU flag check, at least on SUSE distros.  I did some
testing, and AFAICT if the CPU supports hardware virtualization, the
appropriate kvm kernel module (e.g. kvm_intel) is loaded automatically,
so /dev/kvm will exist.  If not, the module doesn't get loaded and
/dev/kvm doesn't exist.

More recent changes to kvm-ok in Debian-based distros (see
https://sources.debian.org/patches/cpu-checker/0.7-1.3/) add support
for other architectures (aarch64, ppc*, s390x, riscv64), but in all those
cases, the only thing that happens is a check for the existence of /dev/kvm.

Signed-off-by: Tim Serong <[email protected]>
  • Loading branch information
tserong committed Jan 31, 2024
1 parent 885f7bf commit f94d245
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/console/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ func (c *Console) doRun() error {
preflight.CPUCheck{},
preflight.MemoryCheck{},
preflight.VirtCheck{},
preflight.KVMHostCheck{},
}
for _, c := range checks {
msg, err := c.Run()
Expand Down
11 changes: 11 additions & 0 deletions pkg/preflight/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"errors"
"fmt"
"io/fs"
"os"
"os/exec"
"strconv"
Expand All @@ -23,6 +24,7 @@ var (
// So that we can fake this stuff up for unit tests
execCommand = exec.Command
procMemInfo = "/proc/meminfo"
devKvm = "/dev/kvm"
)

// The Run() method of a preflight.Check returns a string. If the string
Expand All @@ -36,6 +38,7 @@ type Check interface {
type CPUCheck struct{}
type MemoryCheck struct{}
type VirtCheck struct{}
type KVMHostCheck struct{}

func (c CPUCheck) Run() (msg string, err error) {
out, err := execCommand("/usr/bin/nproc", "--all").Output()
Expand Down Expand Up @@ -118,3 +121,11 @@ func (c VirtCheck) Run() (msg string, err error) {
msg = fmt.Sprintf("System is virtualized (%s) which is not supported.", virt)
return
}

func (c KVMHostCheck) Run() (msg string, err error) {
if _, err = os.Stat(devKvm); errors.Is(err, fs.ErrNotExist) {
msg = "Harvester requires hardware-assisted virtualization, but /dev/kvm does not exist."
err = nil
}
return
}
18 changes: 18 additions & 0 deletions pkg/preflight/checks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,21 @@ func TestMemoryCheck(t *testing.T) {
assert.Equal(t, expectedOutput, msg)
}
}

func TestKVMHostCheck(t *testing.T) {
defaultDevKvm := devKvm
defer func() { devKvm = defaultDevKvm }()

expectedOutputs := map[string]string{
"./testdata/dev-kvm-does-not-exist": "Harvester requires hardware-assisted virtualization, but /dev/kvm does not exist.",
"./testdata/dev-kvm": "",
}

check := KVMHostCheck{}
for file, expectedOutput := range expectedOutputs {
devKvm = file
msg, err := check.Run()
assert.Nil(t, err)
assert.Equal(t, expectedOutput, msg)
}
}

0 comments on commit f94d245

Please sign in to comment.