Extend the virt-host-validate checks to see if the required cgroups are compiled into the kernel and that they are mounted on the system. The cgroups are all optional except for 3 that LXC mandates Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- tools/virt-host-validate-common.c | 130 +++++++++++++++++++++++++++++++++++--- tools/virt-host-validate-common.h | 8 ++- tools/virt-host-validate-lxc.c | 30 +++++++++ tools/virt-host-validate-qemu.c | 30 +++++++++ 4 files changed, 188 insertions(+), 10 deletions(-) diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index d646a79..7e8d619 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <unistd.h> #include <sys/utsname.h> +#include <mntent.h> #include "virutil.h" #include "viralloc.h" @@ -104,14 +105,29 @@ static const char *failEscapeCodes[] = { verify(ARRAY_CARDINALITY(failEscapeCodes) == VIR_HOST_VALIDATE_LAST); void virHostMsgFail(virHostValidateLevel level, - const char *hint) + const char *format, + ...) { + va_list args; + char *msg; + + if (quiet) + return; + + va_start(args, format); + if (virVasprintf(&msg, format, args) < 0) { + perror("malloc"); + abort(); + } + va_end(args); + if (virHostMsgWantEscape()) fprintf(stdout, "%s%s\033[0m (%s)\n", - failEscapeCodes[level], _(failMessages[level]), hint); + failEscapeCodes[level], _(failMessages[level]), msg); else fprintf(stdout, "%s (%s)\n", - _(failMessages[level]), hint); + _(failMessages[level]), msg); + free(msg); } @@ -123,7 +139,7 @@ int virHostValidateDeviceExists(const char *hvname, virHostMsgCheck(hvname, "if device %s exists", dev_name); if (access(dev_name, F_OK) < 0) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } @@ -140,7 +156,7 @@ int virHostValidateDeviceAccessible(const char *hvname, virHostMsgCheck(hvname, "if device %s is accessible", dev_name); if (access(dev_name, R_OK|W_OK) < 0) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } @@ -160,7 +176,7 @@ int virHostValidateNamespace(const char *hvname, snprintf(nspath, sizeof(nspath), "/proc/self/ns/%s", ns_name); if (access(nspath, F_OK) < 0) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } @@ -211,20 +227,116 @@ int virHostValidateLinuxKernel(const char *hvname, (version & 0xff)); if (STRNEQ(uts.sysname, "Linux")) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } if (virParseVersionString(uts.release, &thisversion, true) < 0) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } if (thisversion < version) { - virHostMsgFail(level, hint); + virHostMsgFail(level, "%s", hint); return -1; } else { virHostMsgPass(); return 0; } } + + +static int virHostValidateCGroupSupport(const char *hvname, + const char *cg_name, + virHostValidateLevel level, + const char *config_name) +{ + virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name); + FILE *fp = fopen("/proc/self/cgroup", "r"); + size_t len = 0; + char *line = NULL; + ssize_t ret; + bool matched = false; + + if (!fp) + goto error; + + while ((ret = getline(&line, &len, fp)) >= 0 && !matched) { + char *tmp = strstr(line, cg_name); + if (!tmp) + continue; + + tmp += strlen(cg_name); + if (*tmp != ',' && + *tmp != ':') + continue; + + matched = true; + } + free(line); + fclose(fp); + if (!matched) + goto error; + + virHostMsgPass(); + return 0; + + error: + free(line); + virHostMsgFail(level, "Enable CONFIG_%s in kernel Kconfig file", config_name); + return -1; +} + +static int virHostValidateCGroupMount(const char *hvname, + const char *cg_name, + virHostValidateLevel level) +{ + virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name); + FILE *fp = setmntent("/proc/mounts", "r"); + struct mntent *ent; + bool matched = false; + + if (!fp) + goto error; + + while ((ent = getmntent(fp)) && !matched) { + char *tmp = strstr(ent->mnt_opts, cg_name); + if (!tmp) + continue; + + tmp += strlen(cg_name); + if (*tmp != ',' && + *tmp != '\0') + continue; + + matched = true; + } + endmntent(fp); + if (!matched) + goto error; + + virHostMsgPass(); + return 0; + + error: + virHostMsgFail(level, "Mount '%s' cgroup controller (suggested at /sys/fs/cgroup/%s)", + cg_name, cg_name); + return -1; +} + +extern int virHostValidateCGroupController(const char *hvname, + const char *cg_name, + virHostValidateLevel level, + const char *config_name) +{ + if (virHostValidateCGroupSupport(hvname, + cg_name, + level, + config_name) < 0) + return -1; + if (virHostValidateCGroupMount(hvname, + cg_name, + level) < 0) + return -1; + return 0; +} diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h index c25e69c..1547e22 100644 --- a/tools/virt-host-validate-common.h +++ b/tools/virt-host-validate-common.h @@ -40,7 +40,8 @@ extern void virHostMsgCheck(const char *prefix, extern void virHostMsgPass(void); extern void virHostMsgFail(virHostValidateLevel level, - const char *hint); + const char *format, + ...) ATTRIBUTE_FMT_PRINTF(2, 3); extern int virHostValidateDeviceExists(const char *hvname, const char *dev_name, @@ -64,4 +65,9 @@ extern int virHostValidateNamespace(const char *hvname, virHostValidateLevel level, const char *hint); +extern int virHostValidateCGroupController(const char *hvname, + const char *cg_name, + virHostValidateLevel level, + const char *config_name); + #endif /* __VIRT_HOST_VALIDATE_COMMON_H__ */ diff --git a/tools/virt-host-validate-lxc.c b/tools/virt-host-validate-lxc.c index 43c3f5f..48323da 100644 --- a/tools/virt-host-validate-lxc.c +++ b/tools/virt-host-validate-lxc.c @@ -63,5 +63,35 @@ int virHostValidateLXC(void) _("User namespace support is recommended")) < 0) ret = -1; + if (virHostValidateCGroupController("LXC", "memory", + VIR_HOST_VALIDATE_FAIL, + "MEMCG") < 0) + ret = -1; + + if (virHostValidateCGroupController("LXC", "cpu", + VIR_HOST_VALIDATE_FAIL, + "CGROUP_SCHED") < 0) + ret = -1; + + if (virHostValidateCGroupController("LXC", "cpuacct", + VIR_HOST_VALIDATE_FAIL, + "CGROUP_CPUACCT") < 0) + ret = -1; + + if (virHostValidateCGroupController("LXC", "devices", + VIR_HOST_VALIDATE_FAIL, + "CGROUP_DEVICE") < 0) + ret = -1; + + if (virHostValidateCGroupController("LXC", "net_cls", + VIR_HOST_VALIDATE_WARN, + "NET_CLS_CGROUP") < 0) + ret = -1; + + if (virHostValidateCGroupController("LXC", "freezer", + VIR_HOST_VALIDATE_WARN, + "CGROUP_FREEZER") < 0) + ret = -1; + return ret; } diff --git a/tools/virt-host-validate-qemu.c b/tools/virt-host-validate-qemu.c index 9486064..b0ae293 100644 --- a/tools/virt-host-validate-qemu.c +++ b/tools/virt-host-validate-qemu.c @@ -57,5 +57,35 @@ int virHostValidateQEMU(void) _("Load the 'tun' module to enable networking for QEMU guests")) < 0) ret = -1; + if (virHostValidateCGroupController("QEMU", "memory", + VIR_HOST_VALIDATE_WARN, + "MEMCG") < 0) + ret = -1; + + if (virHostValidateCGroupController("QEMU", "cpu", + VIR_HOST_VALIDATE_WARN, + "CGROUP_CPU") < 0) + ret = -1; + + if (virHostValidateCGroupController("QEMU", "cpuacct", + VIR_HOST_VALIDATE_WARN, + "CGROUP_CPUACCT") < 0) + ret = -1; + + if (virHostValidateCGroupController("QEMU", "devices", + VIR_HOST_VALIDATE_WARN, + "CGROUP_DEVICES") < 0) + ret = -1; + + if (virHostValidateCGroupController("QEMU", "net_cls", + VIR_HOST_VALIDATE_WARN, + "NET_CLS_CGROUP") < 0) + ret = -1; + + if (virHostValidateCGroupController("QEMU", "blkio", + VIR_HOST_VALIDATE_WARN, + "BLK_CGROUP") < 0) + ret = -1; + return ret; } -- 2.4.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list