/* * Test creation of container with cgroup controller with subgroups and mount namespaces */ #define _XOPEN_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "test.h" #define CPUS "0" #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #define MEMLIMIT 134217728 //128 MB #define MEMLIMIT_STR STR(MEMLIMIT) #define LOWER_THAN_LIMIT 104857600 //100 MB #define LOWER_THAN_LIMIT_STR STR(LOWER_THAN_LIMIT) #define FS_ROOT "libct_test_root_ns" #define FS_PRIVATE "libct_test_private_ns" #define FS_CG "cg" // External directories that will be bind mounted in the container #define FS_EXT_BIN "/usr/bin" #define FS_EXT_LIB "/lib" #define FS_EXT_LIB64 "/lib64" #define FS_CT_BIN "bin" #define FS_CT_LIB "lib" #define FS_CT_LIB64 "lib64" #ifndef CLONE_NEWNS #define CLONE_NEWNS 0x00020000 #endif // For testing Define STRESS_MEM_STR to either LOWER_THAN_LIMIT_STR or MEMLIMIT_STR #define STRESS_MEM_STR LOWER_THAN_LIMIT_STR //#define STRESS_MEM_STR MEMLIMIT_STR int is_memory_limit_correct(const char *expected_limit) { int ret = 0; FILE *f = NULL; char buf[1024] = {'\0'}; f = fopen("/sys/fs/cgroup/memory/test1/memory.limit_in_bytes", "r"); if (!f) { fprintf(stderr, "Unable to open memory limit file !\n"); goto err; } if (fscanf(f, "%s", buf) != 1) { fprintf(stderr, "fscanf failed!\n"); goto err; } printf(" /sys/fs/cgroup/memory/test1/memory.limit_in_bytes now contains %s \n",buf); ret = !strcmp(buf, expected_limit); err: fclose(f); return ret; } static int check_cgroup(void *a) { FILE *f = NULL; char buf[1024] = {'\0'}; mkdir("/"FS_CG"/memory/x", 0600); f = fopen("/"FS_CG"/memory/x/memory.limit_in_bytes", "r"); if (!f) { fprintf(stderr, "Unable to open memory limit file !\n"); goto err; } if (fscanf(f, "%s", buf) != 1) { fprintf(stderr, "fscanf failed!\n"); goto err; } printf(" /"FS_CG"/memory/x/memory.limit_in_bytes now contains %s \n",buf); if (access("/"FS_CT_BIN"/stress", F_OK) == 0) printf (" Stress program is accessible in the CT \n"); else printf (" Stress program is NOT available !! \n"); // rmdir("/"FS_CG"/memory/x"); err: fclose(f); return 0; } int main(int argc, char **argv) { libct_session_t s; ct_handler_t ct; ct_process_desc_t p; ct_process_t pr; int ret = 0; int state = 0; int fs_err = 0; mkdir(FS_ROOT, 0600); mkdir(FS_ROOT "/" FS_CT_BIN, 0600); mkdir(FS_ROOT "/" FS_CT_LIB, 0600); mkdir(FS_ROOT "/" FS_CT_LIB64, 0600); mkdir(FS_PRIVATE, 0600); mkdir(FS_PRIVATE "/" FS_CG, 0600); s = libct_session_open_local(); ct = libct_container_create(s, "test1"); p = libct_process_desc_create(s); libct_container_set_nsmask(ct, CLONE_NEWNS); libct_controller_add(ct, CTL_MEMORY); ret = libct_controller_configure(ct, CTL_MEMORY, "memory.limit_in_bytes", MEMLIMIT_STR); printf("\n libct_controller_configure returned %d \n", ret); ret = libct_controller_configure(ct, CTL_MEMORY, "memory.memsw.limit_in_bytes", MEMLIMIT_STR); printf("\n libct_controller_configure returned %d \n", ret); libct_fs_set_root(ct, FS_ROOT); libct_fs_add_bind_mount(ct, FS_EXT_BIN, FS_CT_BIN, 0); libct_fs_add_bind_mount(ct, FS_EXT_LIB, FS_CT_LIB, 0); libct_fs_add_bind_mount(ct, FS_EXT_LIB64, FS_CT_LIB64, 0); libct_fs_set_private(ct, CT_FS_SUBDIR, FS_PRIVATE); libct_container_set_option(ct, LIBCT_OPT_CGROUP_SUBMOUNT, FS_CG); #if 0 pr = libct_container_spawn_cb(ct, p, check_cgroup, NULL); if (libct_handle_is_err(pr)) { printf("\n lbct_container_spawn_cb failed with value = %ld \n",libct_handle_to_err(pr)); return fail("Unable to spawn stress program into CT"); } #endif state = libct_container_state(ct); printf(" Before : state of the container is %d \n",state); char *stress_a[8]; stress_a[0] = "/"FS_CT_BIN"/stress"; stress_a[1] = "--vm"; stress_a[2] = "1"; stress_a[3] = "--vm-bytes"; stress_a[4] = STRESS_MEM_STR; stress_a[5] = "--vm-hang"; stress_a[6] = "0"; stress_a[7]= NULL; printf ("Stress path is %s \n ",stress_a[0]); pr = libct_container_spawn_execv(ct,p, "/"FS_CT_BIN"/stress",stress_a); if (libct_handle_is_err(pr)) { printf("\n libct_container_spawn_execv failed with value = %ld \n",libct_handle_to_err(pr)); return fail("Unable to spawn stress program into CT"); } // This is not working . pr = libct_container_enter_cb(ct, p, check_cgroup, NULL); if (libct_handle_is_err(pr)) { printf("\n lbct_container_enter_cb failed with value = %ld \n",libct_handle_to_err(pr)); return fail("Unable to enter callback into CT"); } #if 0 // This is not working either . //pr = libct_container_enter_execv(ct,p, "/"FS_CT_BIN"/stress",stress_a); stress_a[0] = "/usr/bin/stress"; printf ("Stress path is %s \n ",stress_a[0]); pr = libct_container_enter_execv(ct,p, "/usr/bin/stress",stress_a); if (libct_handle_is_err(pr)) { printf("\n libct_container_enter_execv failed with value = %ld \n",libct_handle_to_err(pr)); return fail("Unable to enter stress program into CT"); } #endif state = libct_container_state(ct); printf("\n After spawn_exec state of the container is %d \n",state); if (!is_memory_limit_correct(MEMLIMIT_STR)) return fail("Memory settings dont match to the expected value"); if (libct_container_wait(ct) < 0) goto err; libct_container_destroy(ct); libct_session_close(s); if (rmdir(FS_PRIVATE "/" FS_CG) < 0) fs_err |= 1; if (rmdir(FS_ROOT "/" FS_CT_BIN) < 0) fs_err |= 2; if (rmdir(FS_ROOT "/" FS_CT_LIB) < 0) fs_err |= 4; if (rmdir(FS_ROOT "/" FS_CT_LIB64) < 0) fs_err |= 8; if (rmdir(FS_ROOT) < 0) fs_err |= 3; if (rmdir(FS_PRIVATE) < 0) fs_err |= 16; if (fs_err) { printf("FS remove failed %x %d \n", fs_err,fs_err); return fail("FS broken"); } return pass("Memory limited CT is OK"); err: return fail("Something wrong"); }