diff --git a/tools/meson.build b/tools/meson.build index 090179470a5f..7977e3d15253 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -58,6 +58,11 @@ if conf.has('WITH_HOST_VALIDATE') 'virt-host-validate-bhyve.c', ] endif + if conf.has('WITH_CH') + virt_host_validate_sources += [ + 'virt-host-validate-ch.c', + ] + endif executable( 'virt-host-validate', diff --git a/tools/virt-host-validate-ch.c b/tools/virt-host-validate-ch.c new file mode 100644 index 000000000000..568903ad630e --- /dev/null +++ b/tools/virt-host-validate-ch.c @@ -0,0 +1,129 @@ +#include + +#include "virt-host-validate-ch.h" +#include "virt-host-validate-common.h" +#include "virarch.h" +#include "virbitmap.h" + +int validateMinimumChVersion(char* ver_string) +{ + // expected ver_string example: "cloud-hypversor v0.8.1-" + int min_major_version = 0; + int min_minor_version = 9; + char *ptr = strtok(ver_string, " "); + char *last_tok = NULL; + while(ptr != NULL) + { + last_tok = ptr; + ptr = strtok(NULL, " "); + } + if (last_tok == NULL) + return -1; + + // eliminate 'v' + last_tok++; + ptr = strtok(last_tok, "."); + if (ptr == NULL) + return -1; + int majorVer = atoi(ptr); + ptr = strtok(NULL, "."); + if (ptr == NULL) + return -1; + int minorVer = atoi(ptr); + + if (majorVer > min_major_version) + { + return 0; + } + else if (majorVer == min_major_version) + { + if (minorVer >= min_minor_version) + return 0; + else + return -1; + } + else + { + return -1; + } +} + +int virHostValidateCh(void) +{ + int ret = 0; + virBitmapPtr flags; + bool hasHwVirt = false; + bool hasVirtFlag = false; + virArch arch = virArchFromHost(); + const char *kvmhint = _("Check that CPU and firmware supports virtualization " + "and kvm module is loaded"); + + if (!(flags = virHostValidateGetCPUFlags())) + return -1; + + switch ((int)arch) { + case VIR_ARCH_I686: + case VIR_ARCH_X86_64: + hasVirtFlag = true; + kvmhint = _("Check that the 'kvm-intel' or 'kvm-amd' modules are " + "loaded & the BIOS has enabled virtualization"); + if (virBitmapIsBitSet(flags, VIR_HOST_VALIDATE_CPU_FLAG_SVM) || + virBitmapIsBitSet(flags, VIR_HOST_VALIDATE_CPU_FLAG_VMX)) + hasHwVirt = true; + break; + case VIR_ARCH_S390: + case VIR_ARCH_S390X: + hasVirtFlag = true; + if (virBitmapIsBitSet(flags, VIR_HOST_VALIDATE_CPU_FLAG_SIE)) + hasHwVirt = true; + break; + case VIR_ARCH_PPC64: + case VIR_ARCH_PPC64LE: + hasVirtFlag = true; + hasHwVirt = true; + break; + default: + hasHwVirt = false; + } + + if (hasVirtFlag) { + virHostMsgCheck("CH", "%s", _("for hardware virtualization")); + if (hasHwVirt) { + virHostMsgPass(); + } else { + virHostMsgFail(VIR_HOST_VALIDATE_FAIL, + _("Only emulated CPUs are available, performance will be significantly limited")); + ret = -1; + } + } + + if (hasHwVirt || !hasVirtFlag) { + if (virHostValidateDeviceExists("CH", "/dev/kvm", + VIR_HOST_VALIDATE_FAIL, + kvmhint) <0) + ret = -1; + else if (virHostValidateDeviceAccessible("CH", "/dev/kvm", + VIR_HOST_VALIDATE_FAIL, + _("Check /dev/kvm is world writable or you are in " + "a group that is allowed to access it")) < 0) + ret = -1; + } + + char verResult[256]; + virHostMsgCheck("CH", "Cloud-Hypvervisor >= 0.9.0"); + if (virHostValidateCmdOutput("cloud-hypervisor --version", verResult, 256, + VIR_HOST_VALIDATE_FAIL, "Failed to get command output of 'cloud-hypervisor --version'") < 0) + ret = -1; + if (validateMinimumChVersion(verResult) < 0) + { + virHostMsgFail(VIR_HOST_VALIDATE_FAIL, + _("Failed to meet minimum version of cloud-hypervisor (minimum:0.9.0)")); + ret = -1; + } + else + { + virHostMsgPass(); + } + + return ret; +} diff --git a/tools/virt-host-validate-ch.h b/tools/virt-host-validate-ch.h new file mode 100644 index 000000000000..ea4c865d8d39 --- /dev/null +++ b/tools/virt-host-validate-ch.h @@ -0,0 +1,4 @@ +#pragma once + +int validateMinimumChVersion(char* ver_string); +int virHostValidateCh(void); diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index f68c9c7c9699..2099b639b301 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -527,3 +527,31 @@ int virHostValidateSecureGuests(const char *hvname, return 0; } + +int virHostValidateCmdOutput(const char* cmd_name, + char* cmd_output, + int max_output_size, + virHostValidateLevel level, + const char *hint) +{ + int ret = -1; + FILE *restrict fp; + if(!cmd_output) + return ret; + + fp = popen(cmd_name, "r"); + if (fp == NULL) { + pclose(fp); + virHostMsgFail(level, "%s", hint); + return -1; + } + while (fgets(cmd_output, max_output_size, fp) != NULL) { + if (strlen(cmd_output) > 0) { + ret = 0; + break; + } + } + pclose(fp); + return ret; +} + diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h index 3df5ea0c7e72..f4eda12d17c4 100644 --- a/tools/virt-host-validate-common.h +++ b/tools/virt-host-validate-common.h @@ -89,3 +89,9 @@ int virHostValidateSecureGuests(const char *hvname, virHostValidateLevel level); bool virHostKernelModuleIsLoaded(const char *module); + +int virHostValidateCmdOutput(const char* cmd_name, + char* cmd_output, + int max_output_size, + virHostValidateLevel level, + const char *hint); diff --git a/tools/virt-host-validate.c b/tools/virt-host-validate.c index e797e63475d7..8721f26acfab 100644 --- a/tools/virt-host-validate.c +++ b/tools/virt-host-validate.c @@ -39,6 +39,9 @@ #if WITH_BHYVE # include "virt-host-validate-bhyve.h" #endif +#if WITH_CH +# include "virt-host-validate-ch.h" +#endif static void show_help(FILE *out, const char *argv0) @@ -52,6 +55,7 @@ show_help(FILE *out, const char *argv0) " - qemu\n" " - lxc\n" " - bhyve\n" + " - cloud-hypervisor\n" "\n" " Options:\n" " -h, --help Display command line help\n" @@ -142,6 +146,14 @@ main(int argc, char **argv) } #endif +#if WITH_CH + if (!hvname || STREQ(hvname, "ch")) { + usedHvname = true; + if (virHostValidateCh() < 0) + ret = EXIT_FAILURE; + } +#endif + if (hvname && !usedHvname) { fprintf(stderr, _("%s: unsupported hypervisor name %s\n"), argv[0], hvname);