2 * Copyright (C) 2013-2015 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
21 #include "testutils.h"
26 # define LIBVIRT_VIRCGROUPPRIV_H_ALLOW
27 # include "vircgrouppriv.h"
28 # include "virstring.h"
29 # include "virerror.h"
32 # include "virbuffer.h"
33 # include "testutilslxc.h"
34 # include "virhostcpu.h"
36 # define VIR_FROM_THIS VIR_FROM_NONE
38 VIR_LOG_INIT("tests.cgrouptest");
40 static int validateCgroup(virCgroupPtr cgroup
,
41 const char *expectPath
,
42 const char **expectMountPoint
,
43 const char **expectLinkPoint
,
44 const char **expectPlacement
,
45 const char *expectUnifiedMountPoint
,
46 const char *expectUnifiedPlacement
,
47 unsigned int expectUnifiedControllers
)
51 if (STRNEQ(cgroup
->path
, expectPath
)) {
52 fprintf(stderr
, "Wrong path '%s', expected '%s'\n",
53 cgroup
->path
, expectPath
);
57 for (i
= 0; i
< VIR_CGROUP_CONTROLLER_LAST
; i
++) {
58 if (STRNEQ_NULLABLE(expectMountPoint
[i
],
59 cgroup
->legacy
[i
].mountPoint
)) {
60 fprintf(stderr
, "Wrong mount '%s', expected '%s' for '%s'\n",
61 cgroup
->legacy
[i
].mountPoint
,
63 virCgroupControllerTypeToString(i
));
66 if (STRNEQ_NULLABLE(expectLinkPoint
[i
],
67 cgroup
->legacy
[i
].linkPoint
)) {
68 fprintf(stderr
, "Wrong link '%s', expected '%s' for '%s'\n",
69 cgroup
->legacy
[i
].linkPoint
,
71 virCgroupControllerTypeToString(i
));
74 if (STRNEQ_NULLABLE(expectPlacement
[i
],
75 cgroup
->legacy
[i
].placement
)) {
76 fprintf(stderr
, "Wrong placement '%s', expected '%s' for '%s'\n",
77 cgroup
->legacy
[i
].placement
,
79 virCgroupControllerTypeToString(i
));
84 if (STRNEQ_NULLABLE(expectUnifiedMountPoint
,
85 cgroup
->unified
.mountPoint
)) {
86 fprintf(stderr
, "Wrong mount '%s', expected '%s' for 'unified'\n",
87 cgroup
->unified
.mountPoint
,
88 expectUnifiedMountPoint
);
91 if (STRNEQ_NULLABLE(expectUnifiedPlacement
,
92 cgroup
->unified
.placement
)) {
93 fprintf(stderr
, "Wrong placement '%s', expected '%s' for 'unified'\n",
94 cgroup
->unified
.placement
,
95 expectUnifiedPlacement
);
98 if (expectUnifiedControllers
!= cgroup
->unified
.controllers
) {
99 for (i
= 0; i
< VIR_CGROUP_CONTROLLER_LAST
; i
++) {
101 if ((expectUnifiedControllers
& type
) != (cgroup
->unified
.controllers
& type
)) {
102 const char *typeStr
= virCgroupControllerTypeToString(i
);
103 if (expectUnifiedControllers
& type
) {
104 fprintf(stderr
, "expected controller '%s' for 'unified', "
105 "but it's missing\n", typeStr
);
107 fprintf(stderr
, "existing controller '%s' for 'unified', "
108 "but it's not expected\n", typeStr
);
119 const char *mountsSmall
[VIR_CGROUP_CONTROLLER_LAST
] = {
120 [VIR_CGROUP_CONTROLLER_CPU
] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
121 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
122 [VIR_CGROUP_CONTROLLER_CPUSET
] = NULL
,
123 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/not/really/sys/fs/cgroup/memory",
124 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
125 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
126 [VIR_CGROUP_CONTROLLER_BLKIO
] = NULL
,
127 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = NULL
,
129 const char *mountsFull
[VIR_CGROUP_CONTROLLER_LAST
] = {
130 [VIR_CGROUP_CONTROLLER_CPU
] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
131 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/not/really/sys/fs/cgroup/cpu,cpuacct",
132 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/not/really/sys/fs/cgroup/cpuset",
133 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/not/really/sys/fs/cgroup/memory",
134 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
135 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/not/really/sys/fs/cgroup/freezer",
136 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/not/really/sys/fs/cgroup/blkio",
137 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/not/really/sys/fs/cgroup/systemd",
139 const char *mountsAllInOne
[VIR_CGROUP_CONTROLLER_LAST
] = {
140 [VIR_CGROUP_CONTROLLER_CPU
] = "/not/really/sys/fs/cgroup",
141 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/not/really/sys/fs/cgroup",
142 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/not/really/sys/fs/cgroup",
143 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/not/really/sys/fs/cgroup",
144 [VIR_CGROUP_CONTROLLER_DEVICES
] = "/not/really/sys/fs/cgroup",
145 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
146 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/not/really/sys/fs/cgroup",
147 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = NULL
,
150 const char *links
[VIR_CGROUP_CONTROLLER_LAST
] = {
151 [VIR_CGROUP_CONTROLLER_CPU
] = "/not/really/sys/fs/cgroup/cpu",
152 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/not/really/sys/fs/cgroup/cpuacct",
153 [VIR_CGROUP_CONTROLLER_CPUSET
] = NULL
,
154 [VIR_CGROUP_CONTROLLER_MEMORY
] = NULL
,
155 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
156 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
157 [VIR_CGROUP_CONTROLLER_BLKIO
] = NULL
,
158 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = NULL
,
161 const char *linksAllInOne
[VIR_CGROUP_CONTROLLER_LAST
] = {
162 [VIR_CGROUP_CONTROLLER_CPU
] = NULL
,
163 [VIR_CGROUP_CONTROLLER_CPUACCT
] = NULL
,
164 [VIR_CGROUP_CONTROLLER_CPUSET
] = NULL
,
165 [VIR_CGROUP_CONTROLLER_MEMORY
] = NULL
,
166 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
167 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
168 [VIR_CGROUP_CONTROLLER_BLKIO
] = NULL
,
169 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = NULL
,
173 struct _detectMountsData
{
180 testCgroupDetectMounts(const void *args
)
183 const struct _detectMountsData
*data
= args
;
186 virCgroupPtr group
= NULL
;
187 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
190 setenv("VIR_CGROUP_MOCK_FILENAME", data
->file
, 1);
192 if (virAsprintf(&parsed
, "%s/vircgroupdata/%s.parsed",
193 abs_srcdir
, data
->file
) < 0) {
197 if (virCgroupNewSelf(&group
) < 0) {
206 for (i
= 0; i
< VIR_CGROUP_CONTROLLER_LAST
; i
++) {
207 virBufferAsprintf(&buf
, "%-12s %s\n",
208 virCgroupControllerTypeToString(i
),
209 NULLSTR(group
->legacy
[i
].mountPoint
));
211 virBufferAsprintf(&buf
, "%-12s %s\n",
212 "unified", NULLSTR(group
->unified
.mountPoint
));
213 if (virBufferCheckError(&buf
) < 0)
216 actual
= virBufferCurrentContent(&buf
);
217 if (virTestCompareToFile(actual
, parsed
) < 0)
223 unsetenv("VIR_CGROUP_MOCK_FILENAME");
225 virCgroupFree(&group
);
226 virBufferFreeAndReset(&buf
);
231 static int testCgroupNewForSelf(const void *args ATTRIBUTE_UNUSED
)
233 virCgroupPtr cgroup
= NULL
;
235 const char *placement
[VIR_CGROUP_CONTROLLER_LAST
] = {
236 [VIR_CGROUP_CONTROLLER_CPU
] = "/system",
237 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/system",
238 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/",
239 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/",
240 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
241 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/",
242 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/",
243 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
246 if (virCgroupNewSelf(&cgroup
) < 0) {
247 fprintf(stderr
, "Cannot create cgroup for self\n");
251 ret
= validateCgroup(cgroup
, "", mountsFull
, links
, placement
, NULL
, NULL
, 0);
254 virCgroupFree(&cgroup
);
259 # define ENSURE_ERRNO(en) \
261 if (!virLastErrorIsSystemErrno(en)) { \
262 virErrorPtr err = virGetLastError(); \
263 fprintf(stderr, "Did not get " #en " error code: %d:%d\n", \
264 err ? err->code : 0, err ? err->int1 : 0); \
268 /* Asking for impossible combination since CPU is co-mounted */
271 static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED
)
273 virCgroupPtr cgroup
= NULL
;
276 const char *placementSmall
[VIR_CGROUP_CONTROLLER_LAST
] = {
277 [VIR_CGROUP_CONTROLLER_CPU
] = "/virtualmachines.partition",
278 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/virtualmachines.partition",
279 [VIR_CGROUP_CONTROLLER_CPUSET
] = NULL
,
280 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/virtualmachines.partition",
281 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
282 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
283 [VIR_CGROUP_CONTROLLER_BLKIO
] = NULL
,
284 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = NULL
,
286 const char *placementFull
[VIR_CGROUP_CONTROLLER_LAST
] = {
287 [VIR_CGROUP_CONTROLLER_CPU
] = "/virtualmachines.partition",
288 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/virtualmachines.partition",
289 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/virtualmachines.partition",
290 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/virtualmachines.partition",
291 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
292 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/virtualmachines.partition",
293 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/virtualmachines.partition",
294 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
297 if ((rv
= virCgroupNewPartition("/virtualmachines", false, -1, &cgroup
)) != -1) {
298 fprintf(stderr
, "Unexpected found /virtualmachines cgroup: %d\n", -rv
);
301 ENSURE_ERRNO(ENOENT
);
303 /* Asking for impossible combination since CPU is co-mounted */
304 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
305 (1 << VIR_CGROUP_CONTROLLER_CPU
),
307 fprintf(stderr
, "Should not have created /virtualmachines cgroup: %d\n", -rv
);
310 ENSURE_ERRNO(EINVAL
);
312 /* Asking for impossible combination since devices is not mounted */
313 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
314 (1 << VIR_CGROUP_CONTROLLER_DEVICES
),
316 fprintf(stderr
, "Should not have created /virtualmachines cgroup: %d\n", -rv
);
321 /* Asking for small combination since devices is not mounted */
322 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
323 (1 << VIR_CGROUP_CONTROLLER_CPU
) |
324 (1 << VIR_CGROUP_CONTROLLER_CPUACCT
) |
325 (1 << VIR_CGROUP_CONTROLLER_MEMORY
),
327 fprintf(stderr
, "Cannot create /virtualmachines cgroup: %d\n", -rv
);
330 ret
= validateCgroup(cgroup
, "/virtualmachines.partition", mountsSmall
, links
, placementSmall
, NULL
, NULL
, 0);
331 virCgroupFree(&cgroup
);
333 if ((rv
= virCgroupNewPartition("/virtualmachines", true, -1, &cgroup
)) != 0) {
334 fprintf(stderr
, "Cannot create /virtualmachines cgroup: %d\n", -rv
);
337 ret
= validateCgroup(cgroup
, "/virtualmachines.partition", mountsFull
, links
, placementFull
, NULL
, NULL
, 0);
340 virCgroupFree(&cgroup
);
345 static int testCgroupNewForPartitionNested(const void *args ATTRIBUTE_UNUSED
)
347 virCgroupPtr cgroup
= NULL
;
350 const char *placementFull
[VIR_CGROUP_CONTROLLER_LAST
] = {
351 [VIR_CGROUP_CONTROLLER_CPU
] = "/deployment.partition/production.partition",
352 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/deployment.partition/production.partition",
353 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/deployment.partition/production.partition",
354 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/deployment.partition/production.partition",
355 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
356 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/deployment.partition/production.partition",
357 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/deployment.partition/production.partition",
358 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
361 if ((rv
= virCgroupNewPartition("/deployment/production", false, -1, &cgroup
)) != -1) {
362 fprintf(stderr
, "Unexpected found /deployment/production cgroup: %d\n", -rv
);
365 ENSURE_ERRNO(ENOENT
);
367 /* Should not work, since we require /deployment to be pre-created */
368 if ((rv
= virCgroupNewPartition("/deployment/production", true, -1, &cgroup
)) != -1) {
369 fprintf(stderr
, "Unexpected created /deployment/production cgroup: %d\n", -rv
);
372 ENSURE_ERRNO(ENOENT
);
374 if ((rv
= virCgroupNewPartition("/deployment", true, -1, &cgroup
)) != 0) {
375 fprintf(stderr
, "Failed to create /deployment cgroup: %d\n", -rv
);
379 /* Should now work */
380 virCgroupFree(&cgroup
);
381 if ((rv
= virCgroupNewPartition("/deployment/production", true, -1, &cgroup
)) != 0) {
382 fprintf(stderr
, "Failed to create /deployment/production cgroup: %d\n", -rv
);
386 ret
= validateCgroup(cgroup
, "/deployment.partition/production.partition",
387 mountsFull
, links
, placementFull
, NULL
, NULL
, 0);
390 virCgroupFree(&cgroup
);
395 static int testCgroupNewForPartitionNestedDeep(const void *args ATTRIBUTE_UNUSED
)
397 virCgroupPtr cgroup
= NULL
;
400 const char *placementFull
[VIR_CGROUP_CONTROLLER_LAST
] = {
401 [VIR_CGROUP_CONTROLLER_CPU
] = "/user/berrange.user/production.partition",
402 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/user/berrange.user/production.partition",
403 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/user/berrange.user/production.partition",
404 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/user/berrange.user/production.partition",
405 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
406 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/user/berrange.user/production.partition",
407 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/user/berrange.user/production.partition",
408 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
411 if ((rv
= virCgroupNewPartition("/user/berrange.user/production", false, -1, &cgroup
)) != -1) {
412 fprintf(stderr
, "Unexpected found /user/berrange.user/production cgroup: %d\n", -rv
);
415 ENSURE_ERRNO(ENOENT
);
417 /* Should not work, since we require /user/berrange.user to be pre-created */
418 if ((rv
= virCgroupNewPartition("/user/berrange.user/production", true, -1, &cgroup
)) != -1) {
419 fprintf(stderr
, "Unexpected created /user/berrange.user/production cgroup: %d\n", -rv
);
422 ENSURE_ERRNO(ENOENT
);
424 if ((rv
= virCgroupNewPartition("/user", true, -1, &cgroup
)) != 0) {
425 fprintf(stderr
, "Failed to create /user/berrange.user cgroup: %d\n", -rv
);
429 virCgroupFree(&cgroup
);
430 if ((rv
= virCgroupNewPartition("/user/berrange.user", true, -1, &cgroup
)) != 0) {
431 fprintf(stderr
, "Failed to create /user/berrange.user cgroup: %d\n", -rv
);
435 /* Should now work */
436 virCgroupFree(&cgroup
);
437 if ((rv
= virCgroupNewPartition("/user/berrange.user/production", true, -1, &cgroup
)) != 0) {
438 fprintf(stderr
, "Failed to create /user/berrange.user/production cgroup: %d\n", -rv
);
442 ret
= validateCgroup(cgroup
, "/user/berrange.user/production.partition",
443 mountsFull
, links
, placementFull
, NULL
, NULL
, 0);
446 virCgroupFree(&cgroup
);
452 static int testCgroupNewForPartitionDomain(const void *args ATTRIBUTE_UNUSED
)
454 virCgroupPtr partitioncgroup
= NULL
;
455 virCgroupPtr domaincgroup
= NULL
;
458 const char *placement
[VIR_CGROUP_CONTROLLER_LAST
] = {
459 [VIR_CGROUP_CONTROLLER_CPU
] = "/production.partition/foo.libvirt-lxc",
460 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/production.partition/foo.libvirt-lxc",
461 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/production.partition/foo.libvirt-lxc",
462 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/production.partition/foo.libvirt-lxc",
463 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
464 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/production.partition/foo.libvirt-lxc",
465 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/production.partition/foo.libvirt-lxc",
466 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
469 if ((rv
= virCgroupNewPartition("/production", true, -1, &partitioncgroup
)) != 0) {
470 fprintf(stderr
, "Failed to create /production cgroup: %d\n", -rv
);
474 if ((rv
= virCgroupNewDomainPartition(partitioncgroup
, "lxc", "foo", true, &domaincgroup
)) != 0) {
475 fprintf(stderr
, "Cannot create LXC cgroup: %d\n", -rv
);
479 ret
= validateCgroup(domaincgroup
, "/production.partition/foo.libvirt-lxc", mountsFull
, links
, placement
, NULL
, NULL
, 0);
482 virCgroupFree(&partitioncgroup
);
483 virCgroupFree(&domaincgroup
);
487 static int testCgroupNewForPartitionDomainEscaped(const void *args ATTRIBUTE_UNUSED
)
489 virCgroupPtr partitioncgroup1
= NULL
;
490 virCgroupPtr partitioncgroup2
= NULL
;
491 virCgroupPtr partitioncgroup3
= NULL
;
492 virCgroupPtr domaincgroup
= NULL
;
495 const char *placement
[VIR_CGROUP_CONTROLLER_LAST
] = {
496 [VIR_CGROUP_CONTROLLER_CPU
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
497 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
498 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
499 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
500 [VIR_CGROUP_CONTROLLER_DEVICES
] = NULL
,
501 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
502 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc",
503 [VIR_CGROUP_CONTROLLER_SYSTEMD
] = "/user/berrange/123",
506 if ((rv
= virCgroupNewPartition("/cgroup.evil", true, -1, &partitioncgroup1
)) != 0) {
507 fprintf(stderr
, "Failed to create /cgroup.evil cgroup: %d\n", -rv
);
511 if ((rv
= virCgroupNewPartition("/cgroup.evil/net_cls.evil", true, -1, &partitioncgroup2
)) != 0) {
512 fprintf(stderr
, "Failed to create /cgroup.evil/cpu.evil cgroup: %d\n", -rv
);
516 if ((rv
= virCgroupNewPartition("/cgroup.evil/net_cls.evil/_evil.evil", true, -1, &partitioncgroup3
)) != 0) {
517 fprintf(stderr
, "Failed to create /cgroup.evil cgroup: %d\n", -rv
);
521 if ((rv
= virCgroupNewDomainPartition(partitioncgroup3
, "lxc", "cpu.foo", true, &domaincgroup
)) != 0) {
522 fprintf(stderr
, "Cannot create LXC cgroup: %d\n", -rv
);
526 /* NB we're not expecting 'net_cls.evil' to be escaped,
527 * since our fake /proc/cgroups pretends this controller
528 * isn't compiled into the kernel
530 ret
= validateCgroup(domaincgroup
, "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc", mountsFull
, links
, placement
, NULL
, NULL
, 0);
533 virCgroupFree(&partitioncgroup3
);
534 virCgroupFree(&partitioncgroup2
);
535 virCgroupFree(&partitioncgroup1
);
536 virCgroupFree(&domaincgroup
);
540 static int testCgroupNewForSelfAllInOne(const void *args ATTRIBUTE_UNUSED
)
542 virCgroupPtr cgroup
= NULL
;
544 const char *placement
[VIR_CGROUP_CONTROLLER_LAST
] = {
545 [VIR_CGROUP_CONTROLLER_CPU
] = "/",
546 [VIR_CGROUP_CONTROLLER_CPUACCT
] = "/",
547 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/",
548 [VIR_CGROUP_CONTROLLER_MEMORY
] = "/",
549 [VIR_CGROUP_CONTROLLER_DEVICES
] = "/",
550 [VIR_CGROUP_CONTROLLER_FREEZER
] = NULL
,
551 [VIR_CGROUP_CONTROLLER_BLKIO
] = "/",
554 if (virCgroupNewSelf(&cgroup
) < 0) {
555 fprintf(stderr
, "Cannot create cgroup for self\n");
559 ret
= validateCgroup(cgroup
, "", mountsAllInOne
, linksAllInOne
, placement
, NULL
, NULL
, 0);
562 virCgroupFree(&cgroup
);
567 static int testCgroupNewForSelfLogind(const void *args ATTRIBUTE_UNUSED
)
569 virCgroupPtr cgroup
= NULL
;
571 if (virCgroupNewSelf(&cgroup
) >= 0) {
572 fprintf(stderr
, "Expected to fail, only systemd cgroup available.\n");
573 virCgroupFree(&cgroup
);
581 static int testCgroupNewForSelfUnified(const void *args ATTRIBUTE_UNUSED
)
583 virCgroupPtr cgroup
= NULL
;
585 const char *empty
[VIR_CGROUP_CONTROLLER_LAST
] = { 0 };
586 unsigned int controllers
=
587 (1 << VIR_CGROUP_CONTROLLER_CPU
) |
588 (1 << VIR_CGROUP_CONTROLLER_CPUACCT
) |
589 (1 << VIR_CGROUP_CONTROLLER_MEMORY
) |
590 (1 << VIR_CGROUP_CONTROLLER_BLKIO
);
592 if (virCgroupNewSelf(&cgroup
) < 0) {
593 fprintf(stderr
, "Cannot create cgroup for self\n");
597 ret
= validateCgroup(cgroup
, "", empty
, empty
, empty
,
598 "/not/really/sys/fs/cgroup", "/", controllers
);
600 virCgroupFree(&cgroup
);
605 static int testCgroupNewForSelfHybrid(const void *args ATTRIBUTE_UNUSED
)
607 virCgroupPtr cgroup
= NULL
;
609 const char *empty
[VIR_CGROUP_CONTROLLER_LAST
] = { 0 };
610 const char *mounts
[VIR_CGROUP_CONTROLLER_LAST
] = {
611 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/not/really/sys/fs/cgroup/cpuset",
612 [VIR_CGROUP_CONTROLLER_DEVICES
] = "/not/really/sys/fs/cgroup/devices",
613 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/not/really/sys/fs/cgroup/freezer",
614 [VIR_CGROUP_CONTROLLER_NET_CLS
] = "/not/really/sys/fs/cgroup/net_cls",
615 [VIR_CGROUP_CONTROLLER_PERF_EVENT
] = "/not/really/sys/fs/cgroup/perf_event",
617 const char *placement
[VIR_CGROUP_CONTROLLER_LAST
] = {
618 [VIR_CGROUP_CONTROLLER_CPUSET
] = "/",
619 [VIR_CGROUP_CONTROLLER_DEVICES
] = "/",
620 [VIR_CGROUP_CONTROLLER_FREEZER
] = "/",
621 [VIR_CGROUP_CONTROLLER_NET_CLS
] = "/",
622 [VIR_CGROUP_CONTROLLER_PERF_EVENT
] = "/",
624 unsigned int controllers
=
625 (1 << VIR_CGROUP_CONTROLLER_CPU
) |
626 (1 << VIR_CGROUP_CONTROLLER_CPUACCT
) |
627 (1 << VIR_CGROUP_CONTROLLER_MEMORY
) |
628 (1 << VIR_CGROUP_CONTROLLER_BLKIO
);
630 if (virCgroupNewSelf(&cgroup
) < 0) {
631 fprintf(stderr
, "Cannot create cgroup for self\n");
635 ret
= validateCgroup(cgroup
, "", mounts
, empty
, placement
,
636 "/not/really/sys/fs/cgroup/unified", "/", controllers
);
639 virCgroupFree(&cgroup
);
644 static int testCgroupAvailable(const void *args
)
646 bool got
= virCgroupAvailable();
647 bool want
= args
== (void*)0x1;
650 fprintf(stderr
, "Expected cgroup %savailable, but state was wrong\n",
658 static int testCgroupControllerAvailable(const void *args ATTRIBUTE_UNUSED
)
662 # define CHECK_CONTROLLER(c, present) \
663 if ((present && !virCgroupControllerAvailable(c)) || \
664 (!present && virCgroupControllerAvailable(c))) { \
665 fprintf(stderr, present ? \
666 "Expected controller %s not available\n" : \
667 "Unexpected controller %s available\n", #c); \
671 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_CPU
, true)
672 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_CPUACCT
, true)
673 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_CPUSET
, true)
674 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_MEMORY
, true)
675 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_DEVICES
, false)
676 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_FREEZER
, true)
677 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_BLKIO
, true)
678 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_NET_CLS
, false)
679 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_PERF_EVENT
, false)
680 CHECK_CONTROLLER(VIR_CGROUP_CONTROLLER_SYSTEMD
, true)
682 # undef CHECK_CONTROLLER
686 static int testCgroupGetPercpuStats(const void *args ATTRIBUTE_UNUSED
)
688 virCgroupPtr cgroup
= NULL
;
691 virTypedParameterPtr params
= NULL
;
692 # define EXPECTED_NCPUS 160
694 unsigned long long expected
[EXPECTED_NCPUS
] = {
695 0, 0, 0, 0, 0, 0, 0, 0,
696 7059492996ULL, 0, 0, 0, 0, 0, 0, 0,
697 4180532496ULL, 0, 0, 0, 0, 0, 0, 0,
698 0, 0, 0, 0, 0, 0, 0, 0,
699 0, 0, 0, 0, 0, 0, 0, 0,
700 0, 0, 0, 0, 0, 0, 0, 0,
701 1957541268ULL, 0, 0, 0, 0, 0, 0, 0,
702 2065932204ULL, 0, 0, 0, 0, 0, 0, 0,
703 18228689414ULL, 0, 0, 0, 0, 0, 0, 0,
704 4245525148ULL, 0, 0, 0, 0, 0, 0, 0,
705 2911161568ULL, 0, 0, 0, 0, 0, 0, 0,
706 1407758136ULL, 0, 0, 0, 0, 0, 0, 0,
707 1836807700ULL, 0, 0, 0, 0, 0, 0, 0,
708 1065296618ULL, 0, 0, 0, 0, 0, 0, 0,
709 2046213266ULL, 0, 0, 0, 0, 0, 0, 0,
710 747889778ULL, 0, 0, 0, 0, 0, 0, 0,
711 709566900ULL, 0, 0, 0, 0, 0, 0, 0,
712 444777342ULL, 0, 0, 0, 0, 0, 0, 0,
713 5683512916ULL, 0, 0, 0, 0, 0, 0, 0,
714 635751356ULL, 0, 0, 0, 0, 0, 0, 0,
717 if (VIR_ALLOC_N(params
, EXPECTED_NCPUS
) < 0)
720 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
721 (1 << VIR_CGROUP_CONTROLLER_CPU
) |
722 (1 << VIR_CGROUP_CONTROLLER_CPUACCT
),
724 fprintf(stderr
, "Could not create /virtualmachines cgroup: %d\n", -rv
);
728 if (virHostCPUGetCount() != EXPECTED_NCPUS
) {
729 fprintf(stderr
, "Unexpected: virHostCPUGetCount() yields: %d\n", virHostCPUGetCount());
733 if ((rv
= virCgroupGetPercpuStats(cgroup
,
735 1, 0, EXPECTED_NCPUS
, NULL
)) < 0) {
736 fprintf(stderr
, "Failed call to virCgroupGetPercpuStats for /virtualmachines cgroup: %d\n", -rv
);
740 for (i
= 0; i
< EXPECTED_NCPUS
; i
++) {
741 if (STRNEQ(params
[i
].field
, VIR_DOMAIN_CPU_STATS_CPUTIME
)) {
743 "Wrong parameter name value from virCgroupGetPercpuStats at %zu (is: %s)\n",
748 if (params
[i
].type
!= VIR_TYPED_PARAM_ULLONG
) {
750 "Wrong parameter value type from virCgroupGetPercpuStats at %zu (is: %d)\n",
755 if (params
[i
].value
.ul
!= expected
[i
]) {
757 "Wrong value from virCgroupGetPercpuStats at %zu (expected %llu)\n",
758 i
, params
[i
].value
.ul
);
766 virCgroupFree(&cgroup
);
771 static int testCgroupGetMemoryUsage(const void *args ATTRIBUTE_UNUSED
)
773 virCgroupPtr cgroup
= NULL
;
777 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
778 (1 << VIR_CGROUP_CONTROLLER_MEMORY
),
780 fprintf(stderr
, "Could not create /virtualmachines cgroup: %d\n", -rv
);
784 if ((rv
= virCgroupGetMemoryUsage(cgroup
, &kb
)) < 0) {
785 fprintf(stderr
, "Could not retrieve GetMemoryUsage for /virtualmachines cgroup: %d\n", -rv
);
789 if (kb
!= 1421212UL) {
791 "Wrong value from virCgroupGetMemoryUsage (expected %ld)\n",
799 virCgroupFree(&cgroup
);
805 testCgroupGetMemoryStat(const void *args ATTRIBUTE_UNUSED
)
807 virCgroupPtr cgroup
= NULL
;
812 const unsigned long long expected_values
[] = {
820 const char* names
[] = {
828 unsigned long long values
[ARRAY_CARDINALITY(expected_values
)];
830 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
831 (1 << VIR_CGROUP_CONTROLLER_MEMORY
),
833 fprintf(stderr
, "Could not create /virtualmachines cgroup: %d\n", -rv
);
837 if ((rv
= virCgroupGetMemoryStat(cgroup
, &values
[0],
838 &values
[1], &values
[2],
839 &values
[3], &values
[4],
841 fprintf(stderr
, "Could not retrieve GetMemoryStat for /virtualmachines cgroup: %d\n", -rv
);
845 for (i
= 0; i
< ARRAY_CARDINALITY(expected_values
); i
++) {
846 /* NB: virCgroupGetMemoryStat returns a KiB scaled value */
847 if ((expected_values
[i
] >> 10) != values
[i
]) {
849 "Wrong value (%llu) for %s from virCgroupGetMemoryStat "
851 values
[i
], names
[i
], (expected_values
[i
] >> 10));
859 virCgroupFree(&cgroup
);
864 static int testCgroupGetBlkioIoServiced(const void *args ATTRIBUTE_UNUSED
)
866 virCgroupPtr cgroup
= NULL
;
870 const long long expected_values
[] = {
876 const char* names
[] = {
882 long long values
[ARRAY_CARDINALITY(expected_values
)];
884 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
885 (1 << VIR_CGROUP_CONTROLLER_BLKIO
),
887 fprintf(stderr
, "Could not create /virtualmachines cgroup: %d\n", -rv
);
891 if ((rv
= virCgroupGetBlkioIoServiced(cgroup
,
893 &values
[2], &values
[3])) < 0) {
894 fprintf(stderr
, "Could not retrieve BlkioIoServiced for /virtualmachines cgroup: %d\n", -rv
);
898 for (i
= 0; i
< ARRAY_CARDINALITY(expected_values
); i
++) {
899 if (expected_values
[i
] != values
[i
]) {
901 "Wrong value for %s from virCgroupBlkioIoServiced (expected %lld)\n",
902 names
[i
], expected_values
[i
]);
910 virCgroupFree(&cgroup
);
914 static int testCgroupGetBlkioIoDeviceServiced(const void *args ATTRIBUTE_UNUSED
)
916 virCgroupPtr cgroup
= NULL
;
919 const long long expected_values0
[] = {
925 const long long expected_values1
[] = {
931 const char* names
[] = {
937 long long values
[ARRAY_CARDINALITY(expected_values0
)];
939 if ((rv
= virCgroupNewPartition("/virtualmachines", true,
940 (1 << VIR_CGROUP_CONTROLLER_BLKIO
),
942 fprintf(stderr
, "Could not create /virtualmachines cgroup: %d\n", -rv
);
946 if ((rv
= virCgroupGetBlkioIoDeviceServiced(cgroup
,
949 &values
[2], &values
[3])) < 0) {
950 fprintf(stderr
, "Could not retrieve BlkioIoDeviceServiced for /virtualmachines cgroup: %d\n", -rv
);
954 for (i
= 0; i
< ARRAY_CARDINALITY(expected_values0
); i
++) {
955 if (expected_values0
[i
] != values
[i
]) {
957 "Wrong value for %s from virCgroupGetBlkioIoDeviceServiced (expected %lld)\n",
958 names
[i
], expected_values0
[i
]);
963 if ((rv
= virCgroupGetBlkioIoDeviceServiced(cgroup
,
966 &values
[2], &values
[3])) < 0) {
967 fprintf(stderr
, "Could not retrieve BlkioIoDeviceServiced for /virtualmachines cgroup: %d\n", -rv
);
971 for (i
= 0; i
< ARRAY_CARDINALITY(expected_values1
); i
++) {
972 if (expected_values1
[i
] != values
[i
]) {
974 "Wrong value for %s from virCgroupGetBlkioIoDeviceServiced (expected %lld)\n",
975 names
[i
], expected_values1
[i
]);
983 virCgroupFree(&cgroup
);
987 # define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX"
990 initFakeFS(const char *mode
,
991 const char *filename
)
995 if (VIR_STRDUP_QUIET(fakerootdir
, FAKEROOTDIRTEMPLATE
) < 0) {
996 fprintf(stderr
, "Out of memory\n");
1000 if (!mkdtemp(fakerootdir
)) {
1001 fprintf(stderr
, "Cannot create fakerootdir");
1005 setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir
, 1);
1008 setenv("VIR_CGROUP_MOCK_MODE", mode
, 1);
1011 setenv("VIR_CGROUP_MOCK_FILENAME", filename
, 1);
1017 cleanupFakeFS(char *fakerootdir
)
1019 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL
)
1020 virFileDeleteTree(fakerootdir
);
1022 VIR_FREE(fakerootdir
);
1023 unsetenv("LIBVIRT_FAKE_ROOT_DIR");
1024 unsetenv("VIR_CGROUP_MOCK_MODE");
1025 unsetenv("VIR_CGROUP_MOCK_FILENAME");
1034 # define DETECT_MOUNTS_FULL(file, fail) \
1036 struct _detectMountsData data = { file, fail }; \
1037 if (virTestRun("Detect cgroup mounts for " file, \
1038 testCgroupDetectMounts, \
1042 # define DETECT_MOUNTS(file) DETECT_MOUNTS_FULL(file, false);
1043 # define DETECT_MOUNTS_FAIL(file) DETECT_MOUNTS_FULL(file, true);
1045 DETECT_MOUNTS("ovirt-node-6.6");
1046 DETECT_MOUNTS("ovirt-node-7.1");
1047 DETECT_MOUNTS("fedora-18");
1048 DETECT_MOUNTS("fedora-21");
1049 DETECT_MOUNTS("rhel-7.1");
1050 DETECT_MOUNTS("cgroups1");
1051 DETECT_MOUNTS("cgroups2");
1052 DETECT_MOUNTS("cgroups3");
1053 DETECT_MOUNTS("all-in-one");
1054 DETECT_MOUNTS_FAIL("no-cgroups");
1055 DETECT_MOUNTS("kubevirt");
1056 fakerootdir
= initFakeFS("unified", NULL
);
1057 DETECT_MOUNTS("unified");
1058 cleanupFakeFS(fakerootdir
);
1059 fakerootdir
= initFakeFS("hybrid", NULL
);
1060 DETECT_MOUNTS("hybrid");
1061 cleanupFakeFS(fakerootdir
);
1063 fakerootdir
= initFakeFS(NULL
, "systemd");
1064 if (virTestRun("New cgroup for self", testCgroupNewForSelf
, NULL
) < 0)
1067 if (virTestRun("New cgroup for partition", testCgroupNewForPartition
, NULL
) < 0)
1070 if (virTestRun("New cgroup for partition nested", testCgroupNewForPartitionNested
, NULL
) < 0)
1073 if (virTestRun("New cgroup for partition nested deeply", testCgroupNewForPartitionNestedDeep
, NULL
) < 0)
1076 if (virTestRun("New cgroup for domain partition", testCgroupNewForPartitionDomain
, NULL
) < 0)
1079 if (virTestRun("New cgroup for domain partition escaped", testCgroupNewForPartitionDomainEscaped
, NULL
) < 0)
1082 if (virTestRun("Cgroup available", testCgroupAvailable
, (void*)0x1) < 0)
1085 if (virTestRun("Cgroup controller available", testCgroupControllerAvailable
, NULL
) < 0)
1088 if (virTestRun("virCgroupGetBlkioIoServiced works", testCgroupGetBlkioIoServiced
, NULL
) < 0)
1091 if (virTestRun("virCgroupGetBlkioIoDeviceServiced works", testCgroupGetBlkioIoDeviceServiced
, NULL
) < 0)
1094 if (virTestRun("virCgroupGetMemoryUsage works", testCgroupGetMemoryUsage
, NULL
) < 0)
1097 if (virTestRun("virCgroupGetMemoryStat works", testCgroupGetMemoryStat
, NULL
) < 0)
1100 if (virTestRun("virCgroupGetPercpuStats works", testCgroupGetPercpuStats
, NULL
) < 0)
1102 cleanupFakeFS(fakerootdir
);
1104 fakerootdir
= initFakeFS(NULL
, "all-in-one");
1105 if (virTestRun("New cgroup for self (allinone)", testCgroupNewForSelfAllInOne
, NULL
) < 0)
1107 if (virTestRun("Cgroup available", testCgroupAvailable
, (void*)0x1) < 0)
1109 cleanupFakeFS(fakerootdir
);
1111 fakerootdir
= initFakeFS(NULL
, "logind");
1112 if (virTestRun("New cgroup for self (logind)", testCgroupNewForSelfLogind
, NULL
) < 0)
1114 if (virTestRun("Cgroup available", testCgroupAvailable
, (void*)0x0) < 0)
1116 cleanupFakeFS(fakerootdir
);
1118 /* cgroup unified */
1120 fakerootdir
= initFakeFS("unified", "unified");
1121 if (virTestRun("New cgroup for self (unified)", testCgroupNewForSelfUnified
, NULL
) < 0)
1123 if (virTestRun("Cgroup available (unified)", testCgroupAvailable
, (void*)0x1) < 0)
1125 cleanupFakeFS(fakerootdir
);
1129 fakerootdir
= initFakeFS("hybrid", "hybrid");
1130 if (virTestRun("New cgroup for self (hybrid)", testCgroupNewForSelfHybrid
, NULL
) < 0)
1132 if (virTestRun("Cgroup available (hybrid)", testCgroupAvailable
, (void*)0x1) < 0)
1134 cleanupFakeFS(fakerootdir
);
1136 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
1139 VIR_TEST_MAIN_PRELOAD(mymain
, abs_builddir
"/.libs/vircgroupmock.so")
1145 return EXIT_AM_SKIP
;