]> git.proxmox.com Git - mirror_lxc.git/blame - src/tests/cgpath.c
tests: use busybox in lxc-test-unpriv
[mirror_lxc.git] / src / tests / cgpath.c
CommitLineData
ae5c8b8e
SH
1/* liblxcapi
2 *
8cd80b50
SG
3 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2012 Canonical Ltd.
ae5c8b8e
SH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
948955a2 19#include <lxc/lxccontainer.h>
ae5c8b8e 20
2acf7795 21#include <limits.h>
ae5c8b8e
SH
22#include <unistd.h>
23#include <signal.h>
24#include <stdio.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <stdlib.h>
28#include <errno.h>
95ee490b
SG
29#include <string.h>
30#include <sys/stat.h>
ca1e6c02
CB
31
32#include "cgroup.h"
ca1e6c02 33#include "commands.h"
44322ead
CB
34#include "lxc.h"
35#include "lxctest.h"
36#include "utils.h"
ae5c8b8e 37
18cd4b54
DJ
38#ifndef HAVE_STRLCPY
39#include "include/strlcpy.h"
40#endif
41
ae5c8b8e 42#define MYNAME "lxctest1"
ae5c8b8e 43
2acf7795
DE
44#define TSTERR(fmt, ...) do { \
45 fprintf(stderr, "%s:%d " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
ae5c8b8e
SH
46} while (0)
47
2acf7795
DE
48/*
49 * test_running_container: test cgroup functions against a running container
50 *
2acf7795
DE
51 * @name : name of the container
52 */
fe70edee 53static int test_running_container(const char *lxcpath, const char *name)
2acf7795 54{
44322ead 55 __do_close int fd_log = -EBADF;
b98f7d6e 56 int ret = -1;
2acf7795 57 struct lxc_container *c = NULL;
44322ead
CB
58 struct lxc_log log = {};
59 char template[sizeof(P_tmpdir"/attach_XXXXXX")];
2acf7795 60 char *cgrelpath;
2acf7795 61 char relpath[PATH_MAX+1];
2acf7795 62 char value[NAME_MAX], value_save[NAME_MAX];
5a9fae9e 63 call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
2acf7795 64
44322ead
CB
65 (void)strlcpy(template, P_tmpdir"/attach_XXXXXX", sizeof(template));
66
67 fd_log = lxc_make_tmpfile(template, false);
68 if (fd_log < 0) {
69 lxc_error("Failed to create temporary log file for container %s\n", name);
70 exit(EXIT_FAILURE);
71 }
72 log.name = name;
73 log.file = template;
74 log.level = "TRACE";
75 log.prefix = "cgpath";
76 log.quiet = false;
77 log.lxcpath = NULL;
78 if (lxc_log_init(&log))
79 goto err1;
80
fe70edee 81 sprintf(relpath, DEFAULT_PAYLOAD_CGROUP_PREFIX "%s", name);
2acf7795
DE
82
83 if ((c = lxc_container_new(name, lxcpath)) == NULL) {
84 TSTERR("container %s couldn't instantiate", name);
85 goto err1;
86 }
87 if (!c->is_defined(c)) {
88 TSTERR("container %s does not exist", name);
89 goto err2;
90 }
91
b98f7d6e 92 cgrelpath = lxc_cmd_get_cgroup_path(c->name, c->config_path, "freezer");
2acf7795
DE
93 if (!cgrelpath) {
94 TSTERR("lxc_cmd_get_cgroup_path returned NULL");
95 goto err2;
96 }
97 if (!strstr(cgrelpath, relpath)) {
98 TSTERR("lxc_cmd_get_cgroup_path %s not in %s", relpath, cgrelpath);
99 goto err3;
100 }
101
5a087e05 102 cgroup_ops = cgroup_init(c->lxc_conf);
2202afc9
CB
103 if (!cgroup_ops)
104 goto err3;
105
1f845c39 106 /* test get/set value using memory.soft_limit_in_bytes file */
7d013ccc
CB
107 ret = cgroup_ops->get(cgroup_ops, "pids.max", value, sizeof(value),
108 c->name, c->config_path);
109 if (ret < 0) {
2202afc9 110 TSTERR("cgroup_get failed");
2acf7795 111 goto err3;
ae5c8b8e 112 }
18cd4b54 113 (void)strlcpy(value_save, value, NAME_MAX);
ae5c8b8e 114
7d013ccc 115 ret = cgroup_ops->set(cgroup_ops, "pids.max", "10000",
2202afc9 116 c->name, c->config_path);
2acf7795 117 if (ret < 0) {
2202afc9 118 TSTERR("cgroup_set failed %d %d", ret, errno);
2acf7795 119 goto err3;
ae5c8b8e 120 }
7d013ccc 121 ret = cgroup_ops->get(cgroup_ops, "pids.max", value,
2202afc9 122 sizeof(value), c->name, c->config_path);
2acf7795 123 if (ret < 0) {
2202afc9 124 TSTERR("cgroup_get failed");
2acf7795
DE
125 goto err3;
126 }
7d013ccc 127 if (strcmp(value, "10000\n")) {
2202afc9 128 TSTERR("cgroup_set_bypath failed to set value >%s<", value);
2acf7795
DE
129 goto err3;
130 }
131
132 /* restore original value */
7d013ccc 133 ret = cgroup_ops->set(cgroup_ops, "pids.max",
2202afc9 134 value_save, c->name, c->config_path);
2acf7795 135 if (ret < 0) {
2202afc9 136 TSTERR("cgroup_set failed");
2acf7795
DE
137 goto err3;
138 }
ae5c8b8e 139
2acf7795 140 ret = 0;
4fb3cba5 141
2acf7795
DE
142err3:
143 free(cgrelpath);
144err2:
145 lxc_container_put(c);
146err1:
44322ead
CB
147
148 if (ret != 0) {
149 char buf[4096];
150 ssize_t buflen;
151 while ((buflen = read(fd_log, buf, 1024)) > 0) {
152 buflen = write(STDERR_FILENO, buf, buflen);
153 if (buflen <= 0)
154 break;
155 }
156 }
157 (void)unlink(template);
2acf7795
DE
158 return ret;
159}
160
fe70edee 161static int test_container(const char *lxcpath, const char *name,
2acf7795
DE
162 const char *template)
163{
164 int ret;
165 struct lxc_container *c = NULL;
ae5c8b8e 166
2acf7795
DE
167 if (lxcpath) {
168 ret = mkdir(lxcpath, 0755);
169 if (ret < 0 && errno != EEXIST) {
170 TSTERR("failed to mkdir %s %s", lxcpath, strerror(errno));
171 goto out1;
172 }
173 }
174 ret = -1;
ae5c8b8e 175
2acf7795
DE
176 if ((c = lxc_container_new(name, lxcpath)) == NULL) {
177 TSTERR("instantiating container %s", name);
178 goto out1;
ae5c8b8e
SH
179 }
180 if (c->is_defined(c)) {
181 c->stop(c);
182 c->destroy(c);
f80950ee 183 lxc_container_put(c);
2acf7795 184 c = lxc_container_new(name, lxcpath);
ae5c8b8e 185 }
7fa3f2e9 186 c->set_config_item(c, "lxc.net.0.type", "empty");
dc23c1c8 187 if (!c->createl(c, template, NULL, NULL, 0, NULL)) {
2acf7795
DE
188 TSTERR("creating container %s", name);
189 goto out2;
ae5c8b8e
SH
190 }
191 c->load_config(c, NULL);
540f932a 192 c->want_daemonize(c, true);
ae5c8b8e 193 if (!c->startl(c, 0, NULL)) {
2acf7795
DE
194 TSTERR("starting container %s", name);
195 goto out3;
ae5c8b8e 196 }
ae5c8b8e 197
fe70edee 198 ret = test_running_container(lxcpath, name);
ae5c8b8e 199
2acf7795
DE
200 c->stop(c);
201out3:
202 c->destroy(c);
203out2:
204 lxc_container_put(c);
205out1:
206 return ret;
207}
208
39b72573 209int main(int argc, char *argv[])
2acf7795
DE
210{
211 int ret = EXIT_FAILURE;
212
213 /* won't require privilege necessarily once users are classified by
214 * pam_cgroup */
215 if (geteuid() != 0) {
216 TSTERR("requires privilege");
57017714 217 exit(EXIT_SUCCESS);
ae5c8b8e
SH
218 }
219
2acf7795
DE
220 #if TEST_ALREADY_RUNNING_CT
221
222 /*
223 * This is useful for running with valgrind to test for memory
224 * leaks. The container should already be running, we can't start
225 * the container ourselves because valgrind gets confused by lxc's
226 * internal calls to clone.
227 */
fe70edee 228 if (test_running_container(NULL, "bb01") < 0)
ae5c8b8e 229 goto out;
2acf7795
DE
230 printf("Running container cgroup tests...Passed\n");
231
232 #else
ae5c8b8e 233
fe70edee 234 if (test_container(NULL, MYNAME, "busybox") < 0)
7e1667d7 235 goto out;
2acf7795 236 printf("Container creation tests...Passed\n");
ae5c8b8e 237
fe70edee 238 if (test_container("/var/lib/lxctest2", MYNAME, "busybox") < 0)
ae5c8b8e 239 goto out;
2acf7795 240 printf("Container creation with LXCPATH tests...Passed\n");
ae5c8b8e 241
2acf7795
DE
242 #endif
243
244 ret = EXIT_SUCCESS;
ae5c8b8e 245out:
2acf7795 246 return ret;
ae5c8b8e 247}