libvirt/tests/vircgrouptest.c
Daniel P. Berrange 8d1c141a8d Refactor cgroups internal data structures
Currently the virCgroupPtr struct contains 3 pieces of
information

 - path - path of the cgroup, relative to current process'
   cgroup placement
 - placement - current process' placement in each controller
 - mounts - mount point of each controller

When reading/writing cgroup settings, the path & placement
strings are combined to form the file path. This approach
only works if we assume all cgroups will be relative to
the current process' cgroup placement.

To allow support for managing cgroups at any place in the
heirarchy a change is needed. The 'placement' data should
reflect the absolute path to the cgroup, and the 'path'
value should no longer be used to form the paths to the
cgroup attribute files.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-04-15 17:35:31 +01:00

271 lines
8.9 KiB
C

/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
#include <config.h>
#include "testutils.h"
#ifdef __linux__
# include <stdlib.h>
# define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
# include "vircgrouppriv.h"
# include "virutil.h"
# include "virerror.h"
# include "virlog.h"
# include "virfile.h"
# define VIR_FROM_THIS VIR_FROM_NONE
static int validateCgroup(virCgroupPtr cgroup,
const char *expectPath,
const char **expectMountPoint,
const char **expectPlacement)
{
int i;
if (STRNEQ(cgroup->path, expectPath)) {
fprintf(stderr, "Wrong path '%s', expected '%s'\n",
cgroup->path, expectPath);
return -1;
}
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
if (STRNEQ_NULLABLE(expectMountPoint[i],
cgroup->controllers[i].mountPoint)) {
fprintf(stderr, "Wrong mount '%s', expected '%s' for '%s'\n",
cgroup->controllers[i].mountPoint,
expectMountPoint[i],
virCgroupControllerTypeToString(i));
return -1;
}
if (STRNEQ_NULLABLE(expectPlacement[i],
cgroup->controllers[i].placement)) {
fprintf(stderr, "Wrong placement '%s', expected '%s' for '%s'\n",
cgroup->controllers[i].placement,
expectPlacement[i],
virCgroupControllerTypeToString(i));
return -1;
}
}
return 0;
}
const char *mountsSmall[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
[VIR_CGROUP_CONTROLLER_CPUSET] = NULL,
[VIR_CGROUP_CONTROLLER_MEMORY] = "/not/really/sys/fs/cgroup/memory",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
[VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
};
const char *mountsFull[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
[VIR_CGROUP_CONTROLLER_CPUSET] = "/not/really/sys/fs/cgroup/cpuset",
[VIR_CGROUP_CONTROLLER_MEMORY] = "/not/really/sys/fs/cgroup/memory",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = "/not/really/sys/fs/cgroup/freezer",
[VIR_CGROUP_CONTROLLER_BLKIO] = "/not/really/sys/fs/cgroup/blkio",
};
static int testCgroupNewForSelf(const void *args ATTRIBUTE_UNUSED)
{
virCgroupPtr cgroup = NULL;
int ret = -1;
const char *placement[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/system",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/system",
[VIR_CGROUP_CONTROLLER_CPUSET] = "/",
[VIR_CGROUP_CONTROLLER_MEMORY] = "/",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = "/",
[VIR_CGROUP_CONTROLLER_BLKIO] = "/",
};
if (virCgroupNewSelf(&cgroup) < 0) {
fprintf(stderr, "Cannot create cgroup for self\n");
goto cleanup;
}
ret = validateCgroup(cgroup, "", mountsFull, placement);
cleanup:
virCgroupFree(&cgroup);
return ret;
}
static int testCgroupNewForDriver(const void *args ATTRIBUTE_UNUSED)
{
virCgroupPtr cgroup = NULL;
int ret = -1;
int rv;
const char *placementSmall[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/system/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/system/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_CPUSET] = NULL,
[VIR_CGROUP_CONTROLLER_MEMORY] = "/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
[VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
};
const char *placementFull[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/system/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/system/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_CPUSET] = "/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_MEMORY] = "/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = "/libvirt/lxc",
[VIR_CGROUP_CONTROLLER_BLKIO] = "/libvirt/lxc",
};
if ((rv = virCgroupNewDriver("lxc", true, false, -1, &cgroup)) != -ENOENT) {
fprintf(stderr, "Unexpected found LXC cgroup: %d\n", -rv);
goto cleanup;
}
/* Asking for impossible combination since CPU is co-mounted */
if ((rv = virCgroupNewDriver("lxc", true, true,
(1 << VIR_CGROUP_CONTROLLER_CPU),
&cgroup)) != -EINVAL) {
fprintf(stderr, "Should not have created LXC cgroup: %d\n", -rv);
goto cleanup;
}
/* Asking for impossible combination since devices is not mounted */
if ((rv = virCgroupNewDriver("lxc", true, true,
(1 << VIR_CGROUP_CONTROLLER_DEVICES),
&cgroup)) != -ENOENT) {
fprintf(stderr, "Should not have created LXC cgroup: %d\n", -rv);
goto cleanup;
}
/* Asking for small combination since devices is not mounted */
if ((rv = virCgroupNewDriver("lxc", true, true,
(1 << VIR_CGROUP_CONTROLLER_CPU) |
(1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
(1 << VIR_CGROUP_CONTROLLER_MEMORY),
&cgroup)) != 0) {
fprintf(stderr, "Cannot create LXC cgroup: %d\n", -rv);
goto cleanup;
}
ret = validateCgroup(cgroup, "libvirt/lxc", mountsSmall, placementSmall);
virCgroupFree(&cgroup);
if ((rv = virCgroupNewDriver("lxc", true, true, -1, &cgroup)) != 0) {
fprintf(stderr, "Cannot create LXC cgroup: %d\n", -rv);
goto cleanup;
}
ret = validateCgroup(cgroup, "libvirt/lxc", mountsFull, placementFull);
cleanup:
virCgroupFree(&cgroup);
return ret;
}
static int testCgroupNewForDomain(const void *args ATTRIBUTE_UNUSED)
{
virCgroupPtr drivercgroup = NULL;
virCgroupPtr domaincgroup = NULL;
int ret = -1;
int rv;
const char *placement[VIR_CGROUP_CONTROLLER_LAST] = {
[VIR_CGROUP_CONTROLLER_CPU] = "/system/libvirt/lxc/wibble",
[VIR_CGROUP_CONTROLLER_CPUACCT] = "/system/libvirt/lxc/wibble",
[VIR_CGROUP_CONTROLLER_CPUSET] = "/libvirt/lxc/wibble",
[VIR_CGROUP_CONTROLLER_MEMORY] = "/libvirt/lxc/wibble",
[VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
[VIR_CGROUP_CONTROLLER_FREEZER] = "/libvirt/lxc/wibble",
[VIR_CGROUP_CONTROLLER_BLKIO] = "/libvirt/lxc/wibble",
};
if ((rv = virCgroupNewDriver("lxc", true, false, -1, &drivercgroup)) != 0) {
fprintf(stderr, "Cannot find LXC cgroup: %d\n", -rv);
goto cleanup;
}
if ((rv = virCgroupNewDomain(drivercgroup, "wibble", true, &domaincgroup)) != 0) {
fprintf(stderr, "Cannot create LXC cgroup: %d\n", -rv);
goto cleanup;
}
ret = validateCgroup(domaincgroup, "libvirt/lxc/wibble", mountsFull, placement);
cleanup:
virCgroupFree(&drivercgroup);
virCgroupFree(&domaincgroup);
return ret;
}
# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX"
static int
mymain(void)
{
int ret = 0;
char *fakesysfsdir;
if (!(fakesysfsdir = strdup(FAKESYSFSDIRTEMPLATE))) {
fprintf(stderr, "Out of memory\n");
abort();
}
if (!mkdtemp(fakesysfsdir)) {
fprintf(stderr, "Cannot create fakesysfsdir");
abort();
}
setenv("LIBVIRT_FAKE_SYSFS_DIR", fakesysfsdir, 1);
if (virtTestRun("New cgroup for self", 1, testCgroupNewForSelf, NULL) < 0)
ret = -1;
if (virtTestRun("New cgroup for driver", 1, testCgroupNewForDriver, NULL) < 0)
ret = -1;
if (virtTestRun("New cgroup for domain", 1, testCgroupNewForDomain, NULL) < 0)
ret = -1;
if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
virFileDeleteTree(fakesysfsdir);
VIR_FREE(fakesysfsdir);
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/vircgroupmock.so")
#else
int
main(void)
{
return EXIT_AM_SKIP;
}
#endif