]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
virt-host-validate: check for required cgroups
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 7 Oct 2015 16:36:37 +0000 (17:36 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 12 Oct 2015 12:15:00 +0000 (13:15 +0100)
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@redhat.com>
tools/virt-host-validate-common.c
tools/virt-host-validate-common.h
tools/virt-host-validate-lxc.c
tools/virt-host-validate-qemu.c

index d646a79ec1b37a633fe57348a48fc698ce7cae4c..a88fc569633cfec5037d4accb8d3ebc023027746 100644 (file)
@@ -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);
+    VIR_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,117 @@ 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;
+    }
+    VIR_FREE(line);
+    VIR_FORCE_FCLOSE(fp);
+    if (!matched)
+        goto error;
+
+    virHostMsgPass();
+    return 0;
+
+ error:
+    VIR_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;
+    char mntbuf[1024];
+    bool matched = false;
+
+    if (!fp)
+        goto error;
+
+    while (getmntent_r(fp, &ent, mntbuf, sizeof(mntbuf)) && !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;
+}
+
+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;
+}
index c25e69ca6019255f32537ae570682f4fae50d9dd..1547e22897eb51eb2f8f1f695bd694da30071784 100644 (file)
@@ -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__ */
index 43c3f5f08e912f006effae45fb274a8b0e4facae..48323da3b5a76908046fc702403ab530e93fc076 100644 (file)
@@ -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;
 }
index 9486064f8a2946ce842428ebafa33169efc2e862..b0ae293be598cc906c6054875876f4d15c615795 100644 (file)
@@ -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;
 }