int main() { struct lxc_container *c; const char *p1, *p2; int retval = -1; c = lxc_container_new(MYNAME, NULL); if (!c) { TSTERR("create using default path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (!p1 || !p2 || strncmp(p1, p2, strlen(p1))) { TSTERR("Bad result for path names"); goto err; } #define CPATH "/boo" #define FPATH "/boo/lxctest1/config" if (!c->set_config_path(c, "/boo")) { TSTERR("Error setting custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after set_config_path()"); goto err; } lxc_container_put(c); c = lxc_container_new(MYNAME, CPATH); if (!c) { TSTERR("create using custom path"); goto err; } p1 = c->get_config_path(c); p2 = c->config_file_name(c); if (strcmp(p1, CPATH) || strcmp(p2, FPATH)) { TSTERR("Bad result for path names after create with custom path"); goto err; } retval = 0; err: lxc_container_put(c); return retval; }
static int Container_init(Container *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"name", "config_path", NULL}; char *name = NULL; PyObject *fs_config_path = NULL; char *config_path = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|O&", kwlist, &name, PyUnicode_FSConverter, &fs_config_path)) return -1; if (fs_config_path != NULL) { config_path = PyBytes_AS_STRING(fs_config_path); assert(config_path != NULL); } self->container = lxc_container_new(name, config_path); if (!self->container) { Py_XDECREF(fs_config_path); fprintf(stderr, "%d: error creating container %s\n", __LINE__, name); return -1; } Py_XDECREF(fs_config_path); return 0; }
/* * TODO: this should be re-written to use the get_config_item("lxc.id_map") * cmd api instead of getting the idmap from c->lxc_conf. The reason is * that the id_maps may be different if the container was started with a * -f or -s argument. * The reason I'm punting on that is because we'll need to parse the * idmap results. */ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid) { bool pass = false; char *cgroup = NULL; struct lxc_container *c; c = lxc_container_new(name, lxcpath); if (!c) { ERROR("Could not load container %s:%s", lxcpath, name); return false; } if (!collect_subsytems()) { ERROR("Error collecting cgroup subsystems"); goto out; } // cgm_create makes sure that we have the same cgroup name for all // subsystems, so since this is a slow command over the cmd socket, // just get the cgroup name for the first one. cgroup = lxc_cmd_get_cgroup_path(name, lxcpath, subsystems[0]); if (!cgroup) { ERROR("Failed to get cgroup for controller %s", subsystems[0]); goto out; } if (!(pass = do_cgm_enter(pid, cgroup))) ERROR("Failed to enter group %s", cgroup); out: free(cgroup); lxc_container_put(c); return pass; }
static int pid_from_lxcname(const char *lxcname_or_pid, const char *lxcpath) { char *eptr; int pid = strtol(lxcname_or_pid, &eptr, 10); if (*eptr != '\0' || pid < 1) { struct lxc_container *s; s = lxc_container_new(lxcname_or_pid, lxcpath); if (!s) { SYSERROR("'%s' is not a valid pid nor a container name", lxcname_or_pid); return -1; } if (!s->may_control(s)) { SYSERROR("Insufficient privileges to control container '%s'", s->name); lxc_container_put(s); return -1; } pid = s->init_pid(s); if (pid < 1) { SYSERROR("Is container '%s' running?", s->name); lxc_container_put(s); return -1; } lxc_container_put(s); } if (kill(pid, 0) < 0) { SYSERROR("Can't send signal to pid %d", pid); return -1; } return pid; }
int main(int argc, char *argv[]) { struct lxc_container *c; bool s; int ret = 1; if (lxc_arguments_parse(&my_args, argc, argv)) return 1; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) return 1; /* shortcut - if locking is bogus, we should be able to kill * containers at least */ if (my_args.nolock) return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "Error opening container\n"); goto out; } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (!c->is_running(c)) { fprintf(stderr, "%s is not running\n", c->name); ret = 2; goto out; } if (my_args.hardstop) { ret = c->stop(c) ? 0 : 1; goto out; } if (my_args.reboot) { ret = do_reboot_and_check(&my_args, c); goto out; } if (my_args.shutdown) my_args.timeout = 0; s = c->shutdown(c, my_args.timeout); if (!s) { if (!my_args.shutdown) ret = c->wait(c, "STOPPED", -1) ? 0 : 1; else ret = 1; // fail } else ret = 0; out: lxc_container_put(c); return ret; }
void LxcZone::refresh() { //TODO Consider make LxcZone state-less std::string zoneName = mLxcContainer->name; std::string lxcPath = mLxcContainer->config_path; lxc_container_put(mLxcContainer); mLxcContainer = lxc_container_new(zoneName.c_str(), lxcPath.c_str()); }
int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (create_container()) { fprintf(stderr, "%d: failed to create a container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c->load_config(c, NULL); unlink("/tmp/lxctest1"); if (!c->save_config(c, "/tmp/lxctest1")) { fprintf(stderr, "%d: failed writing config file /tmp/lxctest1\n", __LINE__); goto out; } rename(LXCPATH "/" MYNAME "/config", LXCPATH "/" MYNAME "/config.bak"); if (!c->save_config(c, NULL)) { fprintf(stderr, "%d: failed writing config file\n", __LINE__); goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: lxc_container_put(c); exit(ret); }
static void try_to_remove(void) { struct lxc_container *c; c = lxc_container_new(RESTNAME, NULL); if (c) { c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } c = lxc_container_new(MYNAME2, NULL); if (c) { c->destroy_with_snapshots(c); lxc_container_put(c); } c = lxc_container_new(MYNAME, NULL); if (c) { c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } }
void try_to_remove() { struct lxc_container *c; char snappath[1024]; c = lxc_container_new(RESTNAME, NULL); if (c) { if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } snprintf(snappath, 1024, "%ssnaps/%s", lxc_get_default_config_path(), MYNAME); c = lxc_container_new("snap0", snappath); if (c) { if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } c = lxc_container_new(MYNAME, NULL); if (c) { if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } }
int main(int argc, char *argv[]) { const char *lxcpath = NULL, *name; bool may = false; struct lxc_container *c; if (argc < 2) usage(argv[0]); name = argv[1]; if (argc == 3) lxcpath = argv[2]; c = lxc_container_new(name, lxcpath); if (c) may = c->may_control(c); printf("You may%s control %s\n", may ? "" : " not", name); exit(may ? 0 : 1); }
int main(int argc, char *argv[]) { struct lxc_container *c; bool ret; if (lxc_arguments_parse(&my_args, argc, argv)) exit(1); if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(1); lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "System error loading %s\n", my_args.name); exit(1); } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); exit(1); } if (!c->is_defined(c)) { fprintf(stderr, "%s is not defined\n", my_args.name); lxc_container_put(c); exit(1); } if (do_restore) ret = restore(c); else if (do_pre_checkpoint) ret = pre_checkpoint(c); else ret = checkpoint(c); return !ret; }
static int container_new(lua_State *L) { struct lxc_container *c; const char *name = luaL_checkstring(L, 1); const char *configpath = NULL; int argc = lua_gettop(L); if (argc > 1) configpath = luaL_checkstring(L, 2); c = lxc_container_new(name, configpath); if (c) { lua_boxpointer(L, c); luaL_getmetatable(L, CONTAINER_TYPENAME); lua_setmetatable(L, -2); } else { lua_pushnil(L); } return 1; }
static bool fetch_seccomp(const char *name, const char *lxcpath, struct lxc_proc_context_info *i, lxc_attach_options_t *options) { struct lxc_container *c; if (!(options->namespaces & CLONE_NEWNS) || !(options->attach_flags & LXC_ATTACH_LSM)) return true; c = lxc_container_new(name, lxcpath); if (!c) return false; i->container = c; if (!c->lxc_conf) return false; if (lxc_read_seccomp_config(c->lxc_conf) < 0) { ERROR("Error reading seccomp policy"); return false; } return true; }
static bool fetch_seccomp(const char *name, const char *lxcpath, struct lxc_proc_context_info *i, lxc_attach_options_t *options) { struct lxc_container *c; char *path; if (!(options->namespaces & CLONE_NEWNS) || !(options->attach_flags & LXC_ATTACH_LSM)) return true; c = lxc_container_new(name, lxcpath); if (!c) return false; i->container = c; /* Initialize an empty lxc_conf */ if (!c->set_config_item(c, "lxc.seccomp", "")) { return false; } /* Fetch the current profile path over the cmd interface */ path = c->get_running_config_item(c, "lxc.seccomp"); if (!path) { return true; } /* Copy the value into the new lxc_conf */ if (!c->set_config_item(c, "lxc.seccomp", path)) { free(path); return false; } free(path); /* Attempt to parse the resulting config */ if (lxc_read_seccomp_config(c->lxc_conf) < 0) { ERROR("Error reading seccomp policy"); return false; } return true; }
int main(int argc, char *argv[]) { struct lxc_container *c; int ret; char v1[2], v2[256], v3[2048]; if ((c = lxc_container_new("testxyz", NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (!c->set_config_item(c, "lxc.hook.pre-start", "hi there")) { fprintf(stderr, "%d: failed to set hook.pre-start\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.hook.pre-start", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.hook.pre-start) returned %d\n", __LINE__, ret); ret = 1; goto out; } fprintf(stderr, "lxc.hook.pre-start returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); ret = 1; goto out; } fprintf(stderr, "%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.tty", "4")) { fprintf(stderr, "%d: failed to set tty\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.tty", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.tty) returned %d\n", __LINE__, ret); ret = 1; goto out; } fprintf(stderr, "lxc.tty returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.arch", "x86")) { fprintf(stderr, "%d: failed to set arch\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.arch", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.arch) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("lxc.arch returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init_uid", "100")) { fprintf(stderr, "%d: failed to set init_uid\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.init_uid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_uid) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("lxc.init_uid returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init_gid", "100")) { fprintf(stderr, "%d: failed to set init_gid\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.init_gid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_gid) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("lxc.init_gid returned %d %s\n", ret, v2); #define HNAME "hostname1" // demonstrate proper usage: char *alloced; if (!c->set_config_item(c, "lxc.utsname", HNAME)) { fprintf(stderr, "%d: failed to set utsname\n", __LINE__); ret = 1; goto out; } int len; len = c->get_config_item(c, "lxc.utsname", NULL, 0); // query the size of the string if (len < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, len); ret = 1; goto out; } printf("lxc.utsname returned %d\n", len); // allocate the length of string + 1 for trailing \0 alloced = malloc(len+1); if (!alloced) { fprintf(stderr, "%d: failed to allocate %d bytes for utsname\n", __LINE__, len); ret = 1; goto out; } // now pass in the malloc'd array, and pass in length of string + 1: again // because we need room for the trailing \0 ret = c->get_config_item(c, "lxc.utsname", alloced, len+1); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, ret); ret = 1; goto out; } if (strcmp(alloced, HNAME) != 0 || ret != len) { fprintf(stderr, "lxc.utsname returned wrong value: %d %s not %d %s\n", ret, alloced, len, HNAME); ret = 1; goto out; } printf("lxc.utsname returned %d %s\n", len, alloced); free(alloced); if (!c->set_config_item(c, "lxc.mount.entry", "hi there")) { fprintf(stderr, "%d: failed to set mount.entry\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.mount.entry", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.mount.entry) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("lxc.mount.entry returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.aa_profile", "unconfined")) { fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.aa_profile", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.aa_profile) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("lxc.aa_profile returned %d %s\n", ret, v2); lxc_container_put(c); // new test with real container if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } c->destroy(c); lxc_container_put(c); if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a trusty container\n", __LINE__); ret = 1; goto out; } lxc_container_put(c); /* XXX TODO load_config needs to clear out any old config first */ if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.cap.drop", NULL, 300); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) with NULL returned %d\n", __LINE__, ret); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v1, 1); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d\n", __LINE__, ret); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); ret = 1; goto out; } printf("%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("%d: get_config_item(lxc.network) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.network.ipv4", "10.2.3.4")) { fprintf(stderr, "%d: failed to set ipv4\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.network.0.ipv4 returned %d\n", __LINE__, ret); ret = 1; goto out; } if (!c->clear_config_item(c, "lxc.network.0.ipv4")) { fprintf(stderr, "%d: failed clearing all ipv4 entries\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4 entries get_item(lxc.network.0.ipv4 returned %d\n", __LINE__, ret); ret = 1; goto out; } if (!c->set_config_item(c, "lxc.network.ipv4.gateway", "10.2.3.254")) { fprintf(stderr, "%d: failed to set ipv4.gateway\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret); ret = 1; goto out; } if (!c->set_config_item(c, "lxc.network.0.ipv4.gateway", "")) { fprintf(stderr, "%d: failed clearing ipv4.gateway\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network.0.ipv4.gateway", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4.gateway get_item(lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network.0.link", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("%d: get_config_item (link) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.network.0.name", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("%d: get_config_item (name) returned %d %s\n", __LINE__, ret, v2); if (!c->clear_config_item(c, "lxc.network")) { fprintf(stderr, "%d: clear_config_item failed\n", __LINE__); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.network", v2, 255); if (ret != 0) { fprintf(stderr, "%d: network was not actually cleared (get_network returned %d)\n", __LINE__, ret); ret = 1; goto out; } ret = c->get_config_item(c, "lxc.cgroup", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("%d: get_config_item (cgroup.devices) returned %d %s\n", __LINE__, ret, v3); ret = c->get_config_item(c, "lxc.cgroup.devices.allow", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices.devices.allow) returned %d\n", __LINE__, ret); ret = 1; goto out; } printf("%d: get_config_item (cgroup.devices.devices.allow) returned %d %s\n", __LINE__, ret, v3); if (!c->clear_config_item(c, "lxc.cgroup")) { fprintf(stderr, "%d: failed clearing lxc.cgroup\n", __LINE__); ret = 1; goto out; } if (!c->clear_config_item(c, "lxc.cap.drop")) { fprintf(stderr, "%d: failed clearing lxc.cap.drop\n", __LINE__); ret = 1; goto out; } if (!c->clear_config_item(c, "lxc.mount.entries")) { fprintf(stderr, "%d: failed clearing lxc.mount.entries\n", __LINE__); ret = 1; goto out; } if (!c->clear_config_item(c, "lxc.hook")) { fprintf(stderr, "%d: failed clearing lxc.hook\n", __LINE__); ret = 1; goto out; } c->destroy(c); printf("All get_item tests passed\n"); ret = 0; out: lxc_container_put(c); exit(ret); };
int main(int argc, char *argv[]) { struct lxc_container *c; bool s; int ret = EXIT_FAILURE; if (lxc_arguments_parse(&my_args, argc, argv)) exit(ret); if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) exit(ret); lxc_log_options_no_override(); /* Set default timeout */ if (my_args.timeout == -2) { if (my_args.hardstop) my_args.timeout = 0; else my_args.timeout = 60; } if (my_args.nowait) my_args.timeout = 0; /* some checks */ if (!my_args.hardstop && my_args.timeout < -1) { fprintf(stderr, "invalid timeout\n"); exit(ret); } if (my_args.hardstop && my_args.nokill) { fprintf(stderr, "-k can't be used with --nokill\n"); exit(ret); } if (my_args.hardstop && my_args.reboot) { fprintf(stderr, "-k can't be used with -r\n"); exit(ret); } if (my_args.hardstop && my_args.timeout) { fprintf(stderr, "-k doesn't allow timeouts\n"); exit(ret); } if (my_args.nolock && !my_args.hardstop) { fprintf(stderr, "--nolock may only be used with -k\n"); exit(ret); } /* shortcut - if locking is bogus, we should be able to kill * containers at least */ if (my_args.nolock) { ret = lxc_cmd_stop(my_args.name, my_args.lxcpath[0]); exit(ret); } c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "Error opening container\n"); goto out; } if (my_args.rcfile) { c->clear_config(c); if (!c->load_config(c, my_args.rcfile)) { fprintf(stderr, "Failed to load rcfile\n"); goto out; } c->configfile = strdup(my_args.rcfile); if (!c->configfile) { fprintf(stderr, "Out of memory setting new config filename\n"); goto out; } } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (!c->is_running(c)) { fprintf(stderr, "%s is not running\n", c->name); /* Per our manpage we need to exit with exit code: * 2: The specified container exists but was not running. */ ret = 2; goto out; } /* kill */ if (my_args.hardstop) { ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE; goto out; } /* reboot */ if (my_args.reboot) { ret = do_reboot_and_check(&my_args, c) < 0 ? EXIT_SUCCESS : EXIT_FAILURE; goto out; } /* shutdown */ s = c->shutdown(c, my_args.timeout); if (!s) { if (my_args.timeout == 0) ret = EXIT_SUCCESS; else if (my_args.nokill) ret = EXIT_FAILURE; else ret = c->stop(c) ? EXIT_SUCCESS : EXIT_FAILURE; } else { ret = EXIT_SUCCESS; } out: lxc_container_put(c); exit(ret); }
int main(int argc, char *argv[]) { int ret; struct lxc_container *c; int fd = -1, fret = EXIT_FAILURE; char tmpf[] = "lxc-parse-config-file-XXXXXX"; char retval[4096] = {0}; fd = lxc_make_tmpfile(tmpf, false); if (fd < 0) { lxc_error("%s\n", "Could not create temporary file"); exit(fret); } close(fd); c = lxc_container_new(tmpf, NULL); if (!c) { lxc_error("%s\n", "Failed to create new container"); exit(EXIT_FAILURE); } if (set_get_compare_clear_save_load(c, "lxc.arch", "x86_64", tmpf, true) < 0) { lxc_error("%s\n", "lxc.arch"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.pty.max", "1000", tmpf, true) < 0) { lxc_error("%s\n", "lxc.pty.max"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.tty.max", "4", tmpf, true) < 0) { lxc_error("%s\n", "lxc.tty.max"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.tty.dir", "not-dev", tmpf, true) < 0) { lxc_error("%s\n", "lxc.tty.dir"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.apparmor.profile", "unconfined", tmpf, true) < 0) { lxc_error("%s\n", "lxc.apparmor.profile"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.apparmor.allow_incomplete", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.apparmor.allow_incomplete"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.selinux.context", "system_u:system_r:lxc_t:s0:c22", tmpf, true) < 0) { lxc_error("%s\n", "lxc.selinux.context"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.cgroup.cpuset.cpus", "1-100", tmpf, false) < 0) { lxc_error("%s\n", "lxc.cgroup.cpuset.cpus"); goto non_test_error; } if (!c->set_config_item(c, "lxc.cgroup.cpuset.cpus", "1-100")) { lxc_error("%s\n", "failed to set config item \"lxc.cgroup.cpuset.cpus\" to \"1-100\""); return -1; } if (!c->set_config_item(c, "lxc.cgroup.memory.limit_in_bytes", "123456789")) { lxc_error("%s\n", "failed to set config item \"lxc.cgroup.memory.limit_in_bytes\" to \"123456789\""); return -1; } if (!c->get_config_item(c, "lxc.cgroup", retval, sizeof(retval))) { lxc_error("%s\n", "failed to get config item \"lxc.cgroup\""); return -1; } c->clear_config(c); c->lxc_conf = NULL; /* lxc.idmap * We can't really save the config here since save_config() wants to * chown the container's directory but we haven't created an on-disk * container. So let's test set-get-clear. */ if (set_get_compare_clear_save_load(c, "lxc.idmap", "u 0 100000 1000000000", NULL, false) < 0) { lxc_error("%s\n", "lxc.idmap"); goto non_test_error; } if (!c->set_config_item(c, "lxc.idmap", "u 1 100000 10000000")) { lxc_error("%s\n", "failed to set config item \"lxc.idmap\" to \"u 1 100000 10000000\""); return -1; } if (!c->set_config_item(c, "lxc.idmap", "g 1 100000 10000000")) { lxc_error("%s\n", "failed to set config item \"lxc.idmap\" to \"g 1 100000 10000000\""); return -1; } if (!c->get_config_item(c, "lxc.idmap", retval, sizeof(retval))) { lxc_error("%s\n", "failed to get config item \"lxc.idmap\""); return -1; } c->clear_config(c); c->lxc_conf = NULL; if (set_get_compare_clear_save_load(c, "lxc.log.level", "DEBUG", tmpf, true) < 0) { lxc_error("%s\n", "lxc.log.level"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.log.file", "/some/path", tmpf, true) < 0) { lxc_error("%s\n", "lxc.log.file"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.mount.fstab", "/some/path", NULL, true) < 0) { lxc_error("%s\n", "lxc.mount.fstab"); goto non_test_error; } /* lxc.mount.auto * Note that we cannot compare the values since the getter for * lxc.mount.auto does not preserve ordering. */ if (set_get_compare_clear_save_load(c, "lxc.mount.auto", "proc:rw sys:rw cgroup-full:rw", tmpf, false) < 0) { lxc_error("%s\n", "lxc.mount.auto"); goto non_test_error; } /* lxc.mount.entry * Note that we cannot compare the values since the getter for * lxc.mount.entry appends newlines. */ if (set_get_compare_clear_save_load(c, "lxc.mount.entry", "/dev/dri dev/dri none bind,optional,create=dir", tmpf, false) < 0) { lxc_error("%s\n", "lxc.mount.entry"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.rootfs.path", "/some/path", tmpf, true) < 0) { lxc_error("%s\n", "lxc.rootfs.path"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.rootfs.mount", "/some/path", tmpf, true) < 0) { lxc_error("%s\n", "lxc.rootfs.mount"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.rootfs.options", "ext4,discard", tmpf, true) < 0) { lxc_error("%s\n", "lxc.rootfs.options"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.uts.name", "the-shire", tmpf, true) < 0) { lxc_error("%s\n", "lxc.uts.name"); goto non_test_error; } if (set_get_compare_clear_save_load( c, "lxc.hook.pre-start", "/some/pre-start", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.pre-start"); goto non_test_error; } if (set_get_compare_clear_save_load( c, "lxc.hook.pre-mount", "/some/pre-mount", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.pre-mount"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.mount", "/some/mount", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.mount"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.autodev", "/some/autodev", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.autodev"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.start", "/some/start", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.start"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.stop", "/some/stop", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.stop"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.post-stop", "/some/post-stop", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.post-stop"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.clone", "/some/clone", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.clone"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.hook.destroy", "/some/destroy", tmpf, false) < 0) { lxc_error("%s\n", "lxc.hook.destroy"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.cap.drop", "sys_module mknod setuid net_raw", tmpf, false) < 0) { lxc_error("%s\n", "lxc.cap.drop"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.cap.keep", "sys_module mknod setuid net_raw", tmpf, false) < 0) { lxc_error("%s\n", "lxc.cap.keep"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.console.path", "none", tmpf, true) < 0) { lxc_error("%s\n", "lxc.console.path"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.console.logfile", "/some/logfile", tmpf, true) < 0) { lxc_error("%s\n", "lxc.console.logfile"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.seccomp.profile", "/some/seccomp/file", tmpf, true) < 0) { lxc_error("%s\n", "lxc.seccomp.profile"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.autodev", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.autodev"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.signal.halt", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.signal.halt"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.signal.reboot", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.signal.reboot"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.signal.stop", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.signal.stop"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.start.auto", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.start.auto"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.start.delay", "5", tmpf, true) < 0) { lxc_error("%s\n", "lxc.start.delay"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.start.order", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.start.order"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.log.syslog", "local0", tmpf, true) < 0) { lxc_error("%s\n", "lxc.log.syslog"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.monitor.unshare", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.monitor.unshare"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.group", "some,container,groups", tmpf, false) < 0) { lxc_error("%s\n", "lxc.group"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.environment", "FOO=BAR", tmpf, false) < 0) { lxc_error("%s\n", "lxc.environment"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.init.cmd", "/bin/bash", tmpf, true) < 0) { lxc_error("%s\n", "lxc.init.cmd"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.init.uid", "1000", tmpf, true) < 0) { lxc_error("%s\n", "lxc.init.uid"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.init.gid", "1000", tmpf, true) < 0) { lxc_error("%s\n", "lxc.init.gid"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.ephemeral", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.ephemeral"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.no_new_privs", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.no_new_privs"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.sysctl.net.core.somaxconn", "256", tmpf, true) < 0) { lxc_error("%s\n", "lxc.sysctl.net.core.somaxconn"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.proc.oom_score_adj", "10", tmpf, true) < 0) { lxc_error("%s\n", "lxc.proc.oom_score_adj"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.prlimit.nofile", "65536", tmpf, true) < 0) { lxc_error("%s\n", "lxc.prlimit.nofile"); goto non_test_error; } if (test_idmap_parser() < 0) { lxc_error("%s\n", "failed to test parser for \"lxc.id_map\""); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.type", "veth", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.2.type", "none", tmpf, true)) { lxc_error("%s\n", "lxc.net.2.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.3.type", "empty", tmpf, true)) { lxc_error("%s\n", "lxc.net.3.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.4.type", "vlan", tmpf, true)) { lxc_error("%s\n", "lxc.net.4.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.type", "macvlan", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.type", "ipvlan", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.1000.type", "phys", tmpf, true)) { lxc_error("%s\n", "lxc.net.1000.type"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.flags", "up", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.flags"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.name", "eth0", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.name"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.link", "bla", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.link"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.macvlan.mode", "private", tmpf, true, "macvlan")) { lxc_error("%s\n", "lxc.net.0.macvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.macvlan.mode", "vepa", tmpf, true, "macvlan")) { lxc_error("%s\n", "lxc.net.0.macvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.macvlan.mode", "bridge", tmpf, true, "macvlan")) { lxc_error("%s\n", "lxc.net.0.macvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.mode", "l3", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.mode", "l3s", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.mode", "l2", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.mode"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.isolation", "bridge", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.isolation"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.isolation", "private", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.isolation"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.ipvlan.isolation", "vepa", tmpf, true, "ipvlan")) { lxc_error("%s\n", "lxc.net.0.ipvlan.isolation"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.pair", "clusterfuck", tmpf, true, "veth")) { lxc_error("%s\n", "lxc.net.0.veth.pair"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv4.route", "192.0.2.1/32", tmpf, true, "veth")) { lxc_error("%s\n", "lxc.net.0.veth.ipv4.route"); return -1; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv6.route", "2001:db8::1/128", tmpf, true, "veth")) { lxc_error("%s\n", "lxc.net.0.veth.ipv6.route"); return -1; } if (set_get_compare_clear_save_load(c, "lxc.net.0.script.up", "/some/up/path", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.script.up"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.script.down", "/some/down/path", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.script.down"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.hwaddr", "52:54:00:80:7a:5d", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.hwaddr"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.mtu", "2000", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.mtu"); goto non_test_error; } if (set_get_compare_clear_save_load_network(c, "lxc.net.0.vlan.id", "2", tmpf, true, "vlan")) { lxc_error("%s\n", "lxc.net.0.vlan.id"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv4.gateway", "10.0.2.2", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.ipv4.gateway"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv6.gateway", "2003:db8:1::1", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.ipv6.gateway"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv4.address", "10.0.2.3/24", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.ipv4.address"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv6.address", "2003:db8:1:0:214:1234:fe0b:3596/64", tmpf, true)) { lxc_error("%s\n", "lxc.net.0.ipv6.address"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.cgroup.dir", "lxd", tmpf, true)) { lxc_error("%s\n", "lxc.cgroup.dir"); goto non_test_error; } if (set_and_clear_complete_netdev(c) < 0) { lxc_error("%s\n", "failed to clear whole network"); goto non_test_error; } if (set_invalid_netdev(c) < 0) { lxc_error("%s\n", "failed to reject invalid configuration"); goto non_test_error; } ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "1", tmpf, true); if (ret < 0) { lxc_error("%s\n", "lxc.hook.version"); goto non_test_error; } ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "2", tmpf, true); if (ret == 0) { lxc_error("%s\n", "lxc.hook.version"); goto non_test_error; } ret = set_get_compare_clear_save_load(c, "lxc.monitor.signal.pdeath", "SIGKILL", tmpf, true); if (ret == 0) { lxc_error("%s\n", "lxc.hook.version"); goto non_test_error; } if (set_get_compare_clear_save_load(c, "lxc.rootfs.managed", "1", tmpf, true) < 0) { lxc_error("%s\n", "lxc.rootfs.managed"); goto non_test_error; } if (c->set_config_item(c, "lxc.notaconfigkey", "invalid")) { lxc_error("%s\n", "Managed to set to set invalid config item \"lxc.notaconfigkey\" to \"invalid\""); return -1; } fret = EXIT_SUCCESS; non_test_error: (void)unlink(tmpf); (void)rmdir(dirname(c->configfile)); lxc_container_put(c); exit(fret); }
int main(int argc, char *argv[]) { struct lxc_container *c; bool s; int ret = 1; if (lxc_arguments_parse(&my_args, argc, argv)) return 1; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) return 1; lxc_log_options_no_override(); /* Set default timeout */ if (my_args.timeout == -2) { if (my_args.hardstop) { my_args.timeout = 0; } else { my_args.timeout = 60; } } if (my_args.nowait) { my_args.timeout = 0; } /* some checks */ if (!my_args.hardstop && my_args.timeout < -1) { fprintf(stderr, "invalid timeout\n"); return 1; } if (my_args.hardstop && my_args.nokill) { fprintf(stderr, "-k can't be used with --nokill\n"); return 1; } if (my_args.hardstop && my_args.reboot) { fprintf(stderr, "-k can't be used with -r\n"); return 1; } if (my_args.hardstop && my_args.timeout) { fprintf(stderr, "-k doesn't allow timeouts\n"); return 1; } if (my_args.nolock && !my_args.hardstop) { fprintf(stderr, "--nolock may only be used with -k\n"); return 1; } /* shortcut - if locking is bogus, we should be able to kill * containers at least */ if (my_args.nolock) return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { fprintf(stderr, "Error opening container\n"); goto out; } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", c->name); goto out; } if (!c->is_running(c)) { fprintf(stderr, "%s is not running\n", c->name); ret = 2; goto out; } /* kill */ if (my_args.hardstop) { ret = c->stop(c) ? 0 : 1; goto out; } /* reboot */ if (my_args.reboot) { ret = do_reboot_and_check(&my_args, c); goto out; } /* shutdown */ s = c->shutdown(c, my_args.timeout); if (!s) { if (my_args.timeout == 0) ret = 0; else if (my_args.nokill) ret = 1; else ret = c->stop(c) ? 0 : 1; } else ret = 0; out: lxc_container_put(c); return ret; }
int main(int argc, char *argv[]) { int ret; struct lxc_container *c; int fret = EXIT_FAILURE; char v1[2], v2[256], v3[2048]; if ((c = lxc_container_new("testxyz", NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); exit(EXIT_FAILURE); } /* EXPECT SUCCESS: lxc.log.syslog with valid value. */ if (!c->set_config_item(c, "lxc.log.syslog", "local0")) { lxc_error("%s\n", "Failed to set lxc.log.syslog.\n"); goto out; } ret = c->get_config_item(c, "lxc.log.syslog", v2, 255); if (ret < 0) { lxc_error("Failed to retrieve lxc.log.syslog: %d.\n", ret); goto out; } if (strcmp(v2, "local0") != 0) { lxc_error("Expected: local0 == %s.\n", v2); goto out; } lxc_debug("Retrieving value for lxc.log.syslog correctly returned: %s.\n", v2); /* EXPECT FAILURE: lxc.log.syslog with invalid value. */ if (c->set_config_item(c, "lxc.log.syslog", "NONSENSE")) { lxc_error("%s\n", "Succeeded int setting lxc.log.syslog to invalid value \"NONSENSE\".\n"); goto out; } lxc_debug("%s\n", "Successfully failed to set lxc.log.syslog to invalid value.\n"); if (!c->set_config_item(c, "lxc.hook.pre-start", "hi there")) { fprintf(stderr, "%d: failed to set hook.pre-start\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.hook.pre-start", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.hook.pre-start) returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "lxc.hook.pre-start returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.net", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "%d: get_config_item(lxc.net) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.tty.max", "4")) { fprintf(stderr, "%d: failed to set tty\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.tty.max", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.tty) returned %d\n", __LINE__, ret); goto out; } fprintf(stderr, "lxc.tty returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.arch", "x86")) { fprintf(stderr, "%d: failed to set arch\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.arch", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.arch) returned %d\n", __LINE__, ret); goto out; } printf("lxc.arch returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init.uid", "100")) { fprintf(stderr, "%d: failed to set init_uid\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.init.uid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_uid) returned %d\n", __LINE__, ret); goto out; } printf("lxc.init_uid returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.init.gid", "100")) { fprintf(stderr, "%d: failed to set init_gid\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.init.gid", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.init_gid) returned %d\n", __LINE__, ret); goto out; } printf("lxc.init_gid returned %d %s\n", ret, v2); #define HNAME "hostname1" // demonstrate proper usage: char *alloced; int len; if (!c->set_config_item(c, "lxc.uts.name", HNAME)) { fprintf(stderr, "%d: failed to set utsname\n", __LINE__); goto out; } len = c->get_config_item(c, "lxc.uts.name", NULL, 0); // query the size of the string if (len < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, len); goto out; } printf("lxc.utsname returned %d\n", len); // allocate the length of string + 1 for trailing \0 alloced = malloc(len+1); if (!alloced) { fprintf(stderr, "%d: failed to allocate %d bytes for utsname\n", __LINE__, len); goto out; } // now pass in the malloc'd array, and pass in length of string + 1: again // because we need room for the trailing \0 ret = c->get_config_item(c, "lxc.uts.name", alloced, len+1); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.utsname) returned %d\n", __LINE__, ret); goto out; } if (strcmp(alloced, HNAME) != 0 || ret != len) { fprintf(stderr, "lxc.utsname returned wrong value: %d %s not %d %s\n", ret, alloced, len, HNAME); goto out; } printf("lxc.utsname returned %d %s\n", len, alloced); free(alloced); if (!c->set_config_item(c, "lxc.mount.entry", "hi there")) { fprintf(stderr, "%d: failed to set mount.entry\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.mount.entry", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.mount.entry) returned %d\n", __LINE__, ret); goto out; } printf("lxc.mount.entry returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.prlimit", v3, 2047); if (ret != 0) { fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.prlimit.nofile", "1234:unlimited")) { fprintf(stderr, "%d: failed to set limit.nofile\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.prlimit.nofile", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.prlimit.nofile) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "1234:unlimited")) { fprintf(stderr, "%d: lxc.prlimit.nofile returned wrong value: %d %s not 14 1234:unlimited\n", __LINE__, ret, v2); goto out; } printf("lxc.prlimit.nofile returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.prlimit.stack", "unlimited")) { fprintf(stderr, "%d: failed to set limit.stack\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.prlimit.stack", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.prlimit.stack) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "unlimited")) { fprintf(stderr, "%d: lxc.prlimit.stack returned wrong value: %d %s not 9 unlimited\n", __LINE__, ret, v2); goto out; } printf("lxc.prlimit.stack returned %d %s\n", ret, v2); #define LIMIT_STACK "lxc.prlimit.stack = unlimited\n" #define ALL_LIMITS "lxc.prlimit.nofile = 1234:unlimited\n" LIMIT_STACK ret = c->get_config_item(c, "lxc.prlimit", v3, 2047); if (ret != sizeof(ALL_LIMITS)-1) { fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, ALL_LIMITS)) { fprintf(stderr, "%d: lxc.prlimit returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(ALL_LIMITS)-1, ALL_LIMITS); goto out; } printf("lxc.prlimit returned %d %s\n", ret, v3); if (!c->clear_config_item(c, "lxc.prlimit.nofile")) { fprintf(stderr, "%d: failed clearing limit.nofile\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.prlimit", v3, 2047); if (ret != sizeof(LIMIT_STACK)-1) { fprintf(stderr, "%d: get_config_item(limit) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, LIMIT_STACK)) { fprintf(stderr, "%d: lxc.prlimit returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(LIMIT_STACK)-1, LIMIT_STACK); goto out; } printf("lxc.prlimit returned %d %s\n", ret, v3); #define SYSCTL_SOMAXCONN "lxc.sysctl.net.core.somaxconn = 256\n" #define ALL_SYSCTLS "lxc.sysctl.net.ipv4.ip_forward = 1\n" SYSCTL_SOMAXCONN ret = c->get_config_item(c, "lxc.sysctl", v3, 2047); if (ret != 0) { fprintf(stderr, "%d: get_config_item(sysctl) returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.sysctl.net.ipv4.ip_forward", "1")) { fprintf(stderr, "%d: failed to set lxc.sysctl.net.ipv4.ip_forward\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.sysctl.net.ipv4.ip_forward", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.sysctl.net.ipv4.ip_forward) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "1")) { fprintf(stderr, "%d: lxc.sysctl.net.ipv4.ip_forward returned wrong value: %d %s not 1\n", __LINE__, ret, v2); goto out; } printf("lxc.sysctl.net.ipv4.ip_forward returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.sysctl.net.core.somaxconn", "256")) { fprintf(stderr, "%d: failed to set lxc.sysctl.net.core.somaxconn\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.sysctl.net.core.somaxconn", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.sysctl.net.core.somaxconn) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "256")) { fprintf(stderr, "%d: lxc.sysctl.net.core.somaxconn returned wrong value: %d %s not 256\n", __LINE__, ret, v2); goto out; } printf("lxc.sysctl.net.core.somaxconn returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.sysctl", v3, 2047); if (ret != sizeof(ALL_SYSCTLS)-1) { fprintf(stderr, "%d: get_config_item(sysctl) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, ALL_SYSCTLS)) { fprintf(stderr, "%d: lxc.sysctl returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(ALL_SYSCTLS) - 1, ALL_SYSCTLS); goto out; } printf("lxc.sysctl returned %d %s\n", ret, v3); if (!c->clear_config_item(c, "lxc.sysctl.net.ipv4.ip_forward")) { fprintf(stderr, "%d: failed clearing lxc.sysctl.net.ipv4.ip_forward\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.sysctl", v3, 2047); if (ret != sizeof(SYSCTL_SOMAXCONN) - 1) { fprintf(stderr, "%d: get_config_item(sysctl) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, SYSCTL_SOMAXCONN)) { fprintf(stderr, "%d: lxc.sysctl returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(SYSCTL_SOMAXCONN) - 1, SYSCTL_SOMAXCONN); goto out; } printf("lxc.sysctl returned %d %s\n", ret, v3); #define PROC_OOM_SCORE_ADJ "lxc.proc.oom_score_adj = 10\n" #define ALL_PROCS "lxc.proc.setgroups = allow\n" PROC_OOM_SCORE_ADJ ret = c->get_config_item(c, "lxc.proc", v3, 2047); if (ret != 0) { fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.proc.setgroups", "allow")) { fprintf(stderr, "%d: failed to set lxc.proc.setgroups\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.proc.setgroups", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.proc.setgroups) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "allow")) { fprintf(stderr, "%d: lxc.proc.setgroups returned wrong value: %d %s not 10\n", __LINE__, ret, v2); goto out; } printf("lxc.proc.setgroups returned %d %s\n", ret, v2); if (!c->set_config_item(c, "lxc.proc.oom_score_adj", "10")) { fprintf(stderr, "%d: failed to set lxc.proc.oom_score_adj\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.proc.oom_score_adj", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.proc.oom_score_adj) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v2, "10")) { fprintf(stderr, "%d: lxc.proc.oom_score_adj returned wrong value: %d %s not 10\n", __LINE__, ret, v2); goto out; } printf("lxc.proc.oom_score_adj returned %d %s\n", ret, v2); ret = c->get_config_item(c, "lxc.proc", v3, 2047); if (ret != sizeof(ALL_PROCS)-1) { fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, ALL_PROCS)) { fprintf(stderr, "%d: lxc.proc returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(ALL_PROCS) - 1, ALL_PROCS); goto out; } printf("lxc.proc returned %d %s\n", ret, v3); if (!c->clear_config_item(c, "lxc.proc.setgroups")) { fprintf(stderr, "%d: failed clearing lxc.proc.setgroups\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.proc", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(proc) returned %d\n", __LINE__, ret); goto out; } if (strcmp(v3, PROC_OOM_SCORE_ADJ)) { fprintf(stderr, "%d: lxc.proc returned wrong value: %d %s not %d %s\n", __LINE__, ret, v3, (int)sizeof(PROC_OOM_SCORE_ADJ) - 1, PROC_OOM_SCORE_ADJ); goto out; } printf("lxc.proc returned %d %s\n", ret, v3); if (!c->set_config_item(c, "lxc.apparmor.profile", "unconfined")) { fprintf(stderr, "%d: failed to set aa_profile\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.apparmor.profile", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.aa_profile) returned %d\n", __LINE__, ret); goto out; } printf("lxc.aa_profile returned %d %s\n", ret, v2); lxc_container_put(c); // new test with real container if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } c->destroy(c); lxc_container_put(c); if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { fprintf(stderr, "%d: failed to create a trusty container\n", __LINE__); goto out; } lxc_container_put(c); /* XXX TODO load_config needs to clear out any old config first */ if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", NULL, 300); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) with NULL returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v1, 1); if (ret < 5 || ret > 255) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cap.drop", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); goto out; } printf("%d: get_config_item(lxc.cap.drop) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.net", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item(lxc.net) returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item(lxc.net) returned %d %s\n", __LINE__, ret, v2); if (!c->set_config_item(c, "lxc.net.0.type", "veth")) { fprintf(stderr, "%d: failed to set lxc.net.0.type\n", __LINE__); goto out; } if (!c->set_config_item(c, "lxc.net.0.link", "lxcbr0")) { fprintf(stderr, "%d: failed to set network.link\n", __LINE__); goto out; } if (!c->set_config_item(c, "lxc.net.0.flags", "up")) { fprintf(stderr, "%d: failed to set network.flags\n", __LINE__); goto out; } if (!c->set_config_item(c, "lxc.net.0.hwaddr", "00:16:3e:xx:xx:xx")) { fprintf(stderr, "%d: failed to set network.hwaddr\n", __LINE__); goto out; } if (!c->set_config_item(c, "lxc.net.0.ipv4.address", "10.2.3.4")) { fprintf(stderr, "%d: failed to set ipv4\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.net.0.ipv4.address", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.net.0.ipv4 returned %d\n", __LINE__, ret); goto out; } if (!c->clear_config_item(c, "lxc.net.0.ipv4.address")) { fprintf(stderr, "%d: failed clearing all ipv4 entries\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.net.0.ipv4.address", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4 entries get_item(lxc.network.0.ipv4 returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.net.0.ipv4.gateway", "10.2.3.254")) { fprintf(stderr, "%d: failed to set ipv4.gateway\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.net.0.ipv4.gateway", v2, 255); if (ret <= 0) { fprintf(stderr, "%d: lxc.net.0.ipv4.gateway returned %d\n", __LINE__, ret); goto out; } if (!c->set_config_item(c, "lxc.net.0.ipv4.gateway", "")) { fprintf(stderr, "%d: failed clearing ipv4.gateway\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.net.0.ipv4.gateway", v2, 255); if (ret != 0) { fprintf(stderr, "%d: after clearing ipv4.gateway get_item(lxc.network.0.ipv4.gateway returned %d\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.net.0.link", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (link) returned %d %s\n", __LINE__, ret, v2); ret = c->get_config_item(c, "lxc.net.0.name", v2, 255); if (ret < 0) { fprintf(stderr, "%d: get_config_item returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (name) returned %d %s\n", __LINE__, ret, v2); if (!c->clear_config_item(c, "lxc.net")) { fprintf(stderr, "%d: clear_config_item failed\n", __LINE__); goto out; } ret = c->get_config_item(c, "lxc.net", v2, 255); if (ret != 0) { fprintf(stderr, "%d: network was not actually cleared (get_network returned %d)\n", __LINE__, ret); goto out; } ret = c->get_config_item(c, "lxc.cgroup", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices) returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (cgroup.devices) returned %d %s\n", __LINE__, ret, v3); ret = c->get_config_item(c, "lxc.cgroup.devices.allow", v3, 2047); if (ret < 0) { fprintf(stderr, "%d: get_config_item(cgroup.devices.devices.allow) returned %d\n", __LINE__, ret); goto out; } printf("%d: get_config_item (cgroup.devices.devices.allow) returned %d %s\n", __LINE__, ret, v3); if (!c->clear_config_item(c, "lxc.cgroup")) { fprintf(stderr, "%d: failed clearing lxc.cgroup\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.cap.drop")) { fprintf(stderr, "%d: failed clearing lxc.cap.drop\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.mount.entry")) { fprintf(stderr, "%d: failed clearing lxc.mount.entry\n", __LINE__); goto out; } if (!c->clear_config_item(c, "lxc.hook")) { fprintf(stderr, "%d: failed clearing lxc.hook\n", __LINE__); goto out; } if (!lxc_config_item_is_supported("lxc.arch")) { fprintf(stderr, "%d: failed to report \"lxc.arch\" as supported configuration item\n", __LINE__); goto out; } if (lxc_config_item_is_supported("lxc.nonsense")) { fprintf(stderr, "%d: failed to detect \"lxc.nonsense\" as unsupported configuration item\n", __LINE__); goto out; } if (c->set_config_item(c, "lxc.notaconfigkey", "invalid")) { fprintf(stderr, "%d: Managed to set \"lxc.notaconfigkey\"\n", __LINE__); goto out; } printf("All get_item tests passed\n"); fret = EXIT_SUCCESS; out: if (c) { c->destroy(c); lxc_container_put(c); } exit(fret); }
int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_function, void* exec_payload, lxc_attach_options_t* options, pid_t* attached_process) { int ret, status; pid_t init_pid, pid, attached_pid, expected; struct lxc_proc_context_info *init_ctx; char* cwd; char* new_cwd; int ipc_sockets[2]; signed long personality; if (!options) options = &attach_static_default_options; init_pid = lxc_cmd_get_init_pid(name, lxcpath); if (init_pid < 0) { ERROR("Failed to get init pid."); return -1; } init_ctx = lxc_proc_get_context_info(init_pid); if (!init_ctx) { ERROR("Failed to get context of init process: %ld.", (long)init_pid); return -1; } personality = get_personality(name, lxcpath); if (init_ctx->personality < 0) { ERROR("Failed to get personality of the container."); lxc_proc_put_context_info(init_ctx); return -1; } init_ctx->personality = personality; init_ctx->container = lxc_container_new(name, lxcpath); if (!init_ctx->container) return -1; if (!fetch_seccomp(init_ctx->container, options)) WARN("Failed to get seccomp policy."); if (!no_new_privs(init_ctx->container, options)) WARN("Could not determine whether PR_SET_NO_NEW_PRIVS is set."); cwd = getcwd(NULL, 0); /* Determine which namespaces the container was created with * by asking lxc-start, if necessary. */ if (options->namespaces == -1) { options->namespaces = lxc_cmd_get_clone_flags(name, lxcpath); /* call failed */ if (options->namespaces == -1) { ERROR("Failed to automatically determine the " "namespaces which the container uses."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } } /* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order * to make sure we don't irritate other threads that want to fork+exec * away * * IMPORTANT: if the initial process is multithreaded and another call * just fork()s away without exec'ing directly after, the socket fd will * exist in the forked process from the other thread and any close() in * our own child process will not really cause the socket to close * properly, potentiall causing the parent to hang. * * For this reason, while IPC is still active, we have to use shutdown() * if the child exits prematurely in order to signal that the socket is * closed and cannot assume that the child exiting will automatically do * that. * * IPC mechanism: (X is receiver) * initial process intermediate attached * X <--- send pid of * attached proc, * then exit * send 0 ------------------------------------> X * [do initialization] * X <------------------------------------ send 1 * [add to cgroup, ...] * send 2 ------------------------------------> X * [set LXC_ATTACH_NO_NEW_PRIVS] * X <------------------------------------ send 3 * [open LSM label fd] * send 4 ------------------------------------> X * [set LSM label] * close socket close socket * run program */ ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); if (ret < 0) { SYSERROR("Could not set up required IPC mechanism for attaching."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } /* Create intermediate subprocess, three reasons: * 1. Runs all pthread_atfork handlers and the child will no * longer be threaded (we can't properly setns() in a threaded * process). * 2. We can't setns() in the child itself, since we want to make * sure we are properly attached to the pidns. * 3. Also, the initial thread has to put the attached process * into the cgroup, which we can only do if we didn't already * setns() (otherwise, user namespaces will hate us). */ pid = fork(); if (pid < 0) { SYSERROR("Failed to create first subprocess."); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } if (pid) { int procfd = -1; pid_t to_cleanup_pid = pid; /* Initial thread, we close the socket that is for the * subprocesses. */ close(ipc_sockets[1]); free(cwd); /* Attach to cgroup, if requested. */ if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) { if (!cgroup_attach(name, lxcpath, pid)) goto on_error; } /* Setup resource limits */ if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits) && setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid)) { goto on_error; } /* Open /proc before setns() to the containers namespace so we * don't rely on any information from inside the container. */ procfd = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC); if (procfd < 0) { SYSERROR("Unable to open /proc."); goto on_error; } /* Let the child process know to go ahead. */ status = 0; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 0: %s.", strerror(errno)); goto on_error; } /* Get pid of attached process from intermediate process. */ ret = lxc_read_nointr_expect(ipc_sockets[0], &attached_pid, sizeof(attached_pid), NULL); if (ret <= 0) { if (ret != 0) ERROR("Expected to receive pid: %s.", strerror(errno)); goto on_error; } /* Ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313. */ if (options->stdin_fd == 0) { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); } /* Reap intermediate process. */ ret = wait_for_pid(pid); if (ret < 0) goto on_error; /* We will always have to reap the attached process now. */ to_cleanup_pid = attached_pid; /* Tell attached process it may start initializing. */ status = 0; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 0: %s.", strerror(errno)); goto on_error; } /* Wait for the attached process to finish initializing. */ expected = 1; ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected); if (ret <= 0) { if (ret != 0) ERROR("Expected to receive sequence number 1: %s.", strerror(errno)); goto on_error; } /* Tell attached process we're done. */ status = 2; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); if (ret <= 0) { ERROR("Intended to send sequence number 2: %s.", strerror(errno)); goto on_error; } /* Wait for the (grand)child to tell us that it's ready to set * up its LSM labels. */ expected = 3; ret = lxc_read_nointr_expect(ipc_sockets[0], &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 3: %s.", strerror(errno)); goto on_error; } /* Open LSM fd and send it to child. */ if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) { int on_exec, saved_errno; int labelfd = -1; on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; /* Open fd for the LSM security module. */ labelfd = lsm_openat(procfd, attached_pid, on_exec); if (labelfd < 0) goto on_error; /* Send child fd of the LSM security module to write to. */ ret = lxc_abstract_unix_send_fds(ipc_sockets[0], &labelfd, 1, NULL, 0); saved_errno = errno; close(labelfd); if (ret <= 0) { ERROR("Intended to send file descriptor %d: %s.", labelfd, strerror(saved_errno)); goto on_error; } } if (procfd >= 0) close(procfd); /* Now shut down communication with child, we're done. */ shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); lxc_proc_put_context_info(init_ctx); /* We're done, the child process should now execute whatever it * is that the user requested. The parent can now track it with * waitpid() or similar. */ *attached_process = attached_pid; return 0; on_error: /* First shut down the socket, then wait for the pid, otherwise * the pid we're waiting for may never exit. */ if (procfd >= 0) close(procfd); shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); if (to_cleanup_pid) (void) wait_for_pid(to_cleanup_pid); lxc_proc_put_context_info(init_ctx); return -1; } /* First subprocess begins here, we close the socket that is for the * initial thread. */ close(ipc_sockets[0]); /* Wait for the parent to have setup cgroups. */ expected = 0; status = -1; ret = lxc_read_nointr_expect(ipc_sockets[1], &status, sizeof(status), &expected); if (ret <= 0) { ERROR("Expected to receive sequence number 0: %s.", strerror(errno)); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } if ((options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) && cgns_supported()) options->namespaces |= CLONE_NEWCGROUP; /* Attach now, create another subprocess later, since pid namespaces * only really affect the children of the current process. */ ret = lxc_attach_to_ns(init_pid, options->namespaces); if (ret < 0) { ERROR("Failed to enter namespaces."); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* Attach succeeded, try to cwd. */ if (options->initial_cwd) new_cwd = options->initial_cwd; else new_cwd = cwd; ret = chdir(new_cwd); if (ret < 0) WARN("Could not change directory to \"%s\".", new_cwd); free(cwd); /* Now create the real child process. */ { struct attach_clone_payload payload = { .ipc_socket = ipc_sockets[1], .options = options, .init_ctx = init_ctx, .exec_function = exec_function, .exec_payload = exec_payload, }; /* We use clone_parent here to make this subprocess a direct * child of the initial process. Then this intermediate process * can exit and the parent can directly track the attached * process. */ pid = lxc_clone(attach_child_main, &payload, CLONE_PARENT); } /* Shouldn't happen, clone() should always return positive pid. */ if (pid <= 0) { SYSERROR("Failed to create subprocess."); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* Tell grandparent the pid of the pid of the newly created child. */ ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid)); if (ret != sizeof(pid)) { /* If this really happens here, this is very unfortunate, since * the parent will not know the pid of the attached process and * will not be able to wait for it (and we won't either due to * CLONE_PARENT) so the parent won't be able to reap it and the * attached process will remain a zombie. */ ERROR("Intended to send pid %d: %s.", pid, strerror(errno)); shutdown(ipc_sockets[1], SHUT_RDWR); rexit(-1); } /* The rest is in the hands of the initial and the attached process. */ rexit(0); }
int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 1; if ((c = lxc_container_new(MYNAME, NULL)) == NULL) { fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } if (!c->set_config_item(c, "lxc.network.type", "veth")) { fprintf(stderr, "%d: failed to set network type\n", __LINE__); goto out; } c->set_config_item(c, "lxc.network.link", "lxcbr0"); c->set_config_item(c, "lxc.network.flags", "up"); if (!c->createl(c, "ubuntu", NULL, NULL, "-r", "lucid", NULL)) { fprintf(stderr, "%d: failed to create a lucid container\n", __LINE__); goto out; } if (!c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } c->load_config(c, NULL); c->want_daemonize(c); if (!c->startl(c, 0, NULL)) { fprintf(stderr, "%d: failed to start %s\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "%d: %s started, you have 60 seconds to test a console\n", __LINE__, MYNAME); sleep(60); // wait a minute to let user connect to console if (!c->shutdown(c, 60)) { fprintf(stderr, "%d: failed to shut down %s\n", __LINE__, MYNAME); goto out; } if (!c->destroy(c)) { fprintf(stderr, "%d: error deleting %s\n", __LINE__, MYNAME); goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: lxc_container_put(c); exit(ret); }
int main(int argc, char *argv[]) { int i, j; pthread_attr_t attr; pthread_t threads[10]; struct thread_args args[10]; struct lxc_container *c; int ret = EXIT_FAILURE; c = lxc_container_new("state-server", NULL); if (!c) { lxc_error("%s", "Failed to create container \"state-server\""); exit(ret); } if (c->is_defined(c)) { lxc_error("%s\n", "Container \"state-server\" is defined"); goto on_error_put; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { lxc_error("%s\n", "Failed to create busybox container \"state-server\""); goto on_error_put; } if (!c->is_defined(c)) { lxc_error("%s\n", "Container \"state-server\" is not defined"); goto on_error_put; } c->clear_config(c); if (!c->load_config(c, NULL)) { lxc_error("%s\n", "Failed to load config for container \"state-server\""); goto on_error_stop; } if (!c->want_daemonize(c, true)) { lxc_error("%s\n", "Failed to mark container \"state-server\" daemonized"); goto on_error_stop; } pthread_attr_init(&attr); for (j = 0; j < 10; j++) { lxc_debug("Starting state server test iteration %d\n", j); if (!c->startl(c, 0, NULL)) { lxc_error("%s\n", "Failed to start container \"state-server\" daemonized"); goto on_error_stop; } sleep(5); for (i = 0; i < 10; i++) { int ret; args[i].thread_id = i; args[i].c = c; args[i].timeout = -1; /* test non-blocking shutdown request */ if (i == 0) args[i].timeout = 0; ret = pthread_create(&threads[i], &attr, state_wrapper, (void *) &args[i]); if (ret != 0) goto on_error_stop; } for (i = 0; i < 10; i++) { int ret; ret = pthread_join(threads[i], NULL); if (ret != 0) goto on_error_stop; if (!args[i].success) { lxc_error("State server thread %d failed\n", args[i].thread_id); goto on_error_stop; } } } ret = EXIT_SUCCESS; on_error_stop: if (c->is_running(c) && !c->stop(c)) lxc_error("%s\n", "Failed to stop container \"state-server\""); if (!c->destroy(c)) lxc_error("%s\n", "Failed to destroy container \"state-server\""); on_error_put: lxc_container_put(c); if (ret == EXIT_SUCCESS) lxc_debug("%s\n", "All state server tests passed"); exit(ret); }
int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 0; const char *s; bool b; char buf[201]; int len; ret = 1; /* test a real container */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } ret = create_ubuntu(); if (ret) { fprintf(stderr, "%d: failed to create a ubuntu container\n", __LINE__); goto out; } b = c->is_defined(c); if (!b) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200); if (len >= 0) { fprintf(stderr, "%d: %s not running but had cgroup settings\n", __LINE__, MYNAME); goto out; } sprintf(buf, "0"); b = c->set_cgroup_item(c, "cpuset.cpus", buf); if (b) { fprintf(stderr, "%d: %s not running but coudl set cgroup settings\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (!s || strcmp(s, "STOPPED")) { fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } b = c->load_config(c, NULL); if (!b) { fprintf(stderr, "%d: %s failed to read its config\n", __LINE__, c->name); goto out; } if (!c->set_config_item(c, "lxc.utsname", "bobo")) { fprintf(stderr, "%d: failed setting lxc.utsname\n", __LINE__); goto out; } printf("hit return to start container"); char mychar; ret = scanf("%c", &mychar); if (ret < 0) goto out; if (!lxc_container_get(c)) { fprintf(stderr, "%d: failed to get extra ref to container\n", __LINE__); exit(1); } pid_t pid = fork(); if (pid < 0) { fprintf(stderr, "%d: fork failed\n", __LINE__); goto out; } if (pid == 0) { b = c->startl(c, 0, NULL); if (!b) fprintf(stderr, "%d: %s failed to start\n", __LINE__, c->name); lxc_container_put(c); exit(!b); } sleep(3); s = c->state(c); if (!s || strcmp(s, "RUNNING")) { fprintf(stderr, "%d: %s is in state %s, not in RUNNING.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 0); if (len <= 0) { fprintf(stderr, "%d: not able to get length of cpuset.cpus (ret %d)\n", __LINE__, len); goto out; } len = c->get_cgroup_item(c, "cpuset.cpus", buf, 200); if (len <= 0 || strcmp(buf, "0\n")) { fprintf(stderr, "%d: not able to get cpuset.cpus (len %d buf %s)\n", __LINE__, len, buf); goto out; } sprintf(buf, "FROZEN"); b = c->set_cgroup_item(c, "freezer.state", buf); if (!b) { fprintf(stderr, "%d: not able to set freezer.state.\n", __LINE__); goto out; } sprintf(buf, "XXX"); len = c->get_cgroup_item(c, "freezer.state", buf, 200); if (len <= 0 || (strcmp(buf, "FREEZING\n") && strcmp(buf, "FROZEN\n"))) { fprintf(stderr, "%d: not able to get freezer.state (len %d buf %s)\n", __LINE__, len, buf); goto out; } c->set_cgroup_item(c, "freezer.state", "THAWED"); printf("hit return to finish"); ret = scanf("%c", &mychar); if (ret < 0) goto out; c->stop(c); /* feh - multilib has moved the lxc-init crap */ #if 0 goto ok; ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc"); if (!ret) ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/"); if (!ret) ret = system("cp src/lxc/lxc-init " LXCPATH "/lxctest1/rootfs//usr/local/libexec/lxc"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib/lxc"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib/lxc/liblxc.so.0"); if (!ret) ret = system("cp src/lxc/liblxc.so " LXCPATH "/lxctest1/rootfs/usr/lib"); if (!ret) ret = system("mkdir -p " LXCPATH "/lxctest1/rootfs/dev/shm"); if (!ret) ret = system("chroot " LXCPATH "/lxctest1/rootfs apt-get install --no-install-recommends lxc"); if (ret) { fprintf(stderr, "%d: failed to installing lxc-init in container\n", __LINE__); goto out; } // next write out the config file; does it match? if (!c->startl(c, 1, "/bin/hostname", NULL)) { fprintf(stderr, "%d: failed to lxc-execute /bin/hostname\n", __LINE__); goto out; } // auto-check result? ('bobo' is printed on stdout) ok: #endif fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: if (c) { c->stop(c); destroy_ubuntu(); } lxc_container_put(c); exit(ret); }
int main(int argc, char *argv[]) { struct lxc_container *c; char *cmd, *dev_name, *dst_name; int ret = 1; if (geteuid() != 0) { ERROR("%s must be run as root", argv[0]); exit(1); } if (lxc_arguments_parse(&my_args, argc, argv)) goto err; if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) goto err; lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { ERROR("%s doesn't exist", my_args.name); goto err; } if (!c->is_running(c)) { ERROR("Container %s is not running.", c->name); goto err1; } if (my_args.argc < 2) { ERROR("Error: no command given (Please see --help output)"); goto err1; } cmd = my_args.argv[0]; dev_name = my_args.argv[1]; if (my_args.argc < 3) dst_name = dev_name; else dst_name = my_args.argv[2]; if (strcmp(cmd, "add") == 0) { if (is_interface(dev_name, 1)) { ret = c->attach_interface(c, dev_name, dst_name); } else { ret = c->add_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to add %s to %s.", dev_name, c->name); ret = 1; goto err1; } INFO("Add %s to %s.", dev_name, c->name); } else if (strcmp(cmd, "del") == 0) { if (is_interface(dev_name, c->init_pid(c))) { ret = c->detach_interface(c, dev_name, dst_name); } else { ret = c->remove_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to del %s from %s.", dev_name, c->name); ret = 1; goto err1; } INFO("Delete %s from %s.", dev_name, c->name); } else { ERROR("Error: Please use add or del (Please see --help output)"); goto err1; } exit(0); err1: lxc_container_put(c); err: exit(ret); }
int main(int argc, char *argv[]) { struct lxc_container *c; int ret = 0; const char *s; bool b; char *str; ret = 1; /* test refcounting */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); goto out; } if (!lxc_container_get(c)) { fprintf(stderr, "%d: error getting refcount\n", __LINE__); goto out; } /* peek in, inappropriately, make sure refcount is a we'd like */ if (c->numthreads != 2) { fprintf(stderr, "%d: refcount is %d, not %d\n", __LINE__, c->numthreads, 2); goto out; } if (strcmp(c->name, MYNAME) != 0) { fprintf(stderr, "%d: container has wrong name (%s not %s)\n", __LINE__, c->name, MYNAME); goto out; } str = c->config_file_name(c); #define CONFIGFNAM LXCPATH "/" MYNAME "/config" if (!str || strcmp(str, CONFIGFNAM)) { fprintf(stderr, "%d: got wrong config file name (%s, not %s)\n", __LINE__, str, CONFIGFNAM); goto out; } free(str); free(c->configfile); c->configfile = NULL; str = c->config_file_name(c); if (str) { fprintf(stderr, "%d: config file name was not NULL as it should have been\n", __LINE__); goto out; } if (lxc_container_put(c) != 0) { fprintf(stderr, "%d: c was freed on non-final put\n", __LINE__); goto out; } if (c->numthreads != 1) { fprintf(stderr, "%d: refcount is %d, not %d\n", __LINE__, c->numthreads, 1); goto out; } if (lxc_container_put(c) != 1) { fprintf(stderr, "%d: c was not freed on final put\n", __LINE__); goto out; } /* test a real container */ c = lxc_container_new(MYNAME, NULL); if (!c) { fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); ret = 1; goto out; } b = c->is_defined(c); if (b) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (s && strcmp(s, "STOPPED") != 0) { // liblxc says a container is STOPPED if it doesn't exist. That's because // the container may be an application container - it's not wrong, just // sometimes unintuitive. fprintf(stderr, "%d: %s thinks it is in state %s\n", __LINE__, c->name, s); goto out; } // create a container // the liblxc api does not support creation - it probably will eventually, // but not yet. // So we just call out to lxc-create. We'll create a busybox container. ret = create_busybox(); if (ret) { fprintf(stderr, "%d: failed to create a busybox container\n", __LINE__); goto out; } b = c->is_defined(c); if (!b) { fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME); goto out; } s = c->state(c); if (!s || strcmp(s, "STOPPED")) { fprintf(stderr, "%d: %s is in state %s, not in STOPPED.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } b = c->load_config(c, NULL); if (!b) { fprintf(stderr, "%d: %s failed to read its config\n", __LINE__, c->name); goto out; } // test wait states int numstates = lxc_get_wait_states(NULL); if (numstates != MAX_STATE) { fprintf(stderr, "%d: lxc_get_wait_states gave %d not %d\n", __LINE__, numstates, MAX_STATE); goto out; } const char **sstr = malloc(numstates * sizeof(const char *)); numstates = lxc_get_wait_states(sstr); int i; for (i=0; i<numstates; i++) { fprintf(stderr, "got state %d %s\n", i, sstr[i]); } free(sstr); /* non-daemonized is tested in 'startone' */ c->want_daemonize(c, true); if (!c->startl(c, 0, NULL, NULL)) { fprintf(stderr, "%d: %s failed to start daemonized\n", __LINE__, c->name); goto out; } if (!c->wait(c, "RUNNING", -1)) { fprintf(stderr, "%d: failed waiting for state RUNNING\n", __LINE__); goto out; } sleep(3); s = c->state(c); if (!s || strcmp(s, "RUNNING")) { fprintf(stderr, "%d: %s is in state %s, not in RUNNING.\n", __LINE__, c->name, s ? s : "undefined"); goto out; } fprintf(stderr, "all lxc_container tests passed for %s\n", c->name); ret = 0; out: if (c) { c->stop(c); destroy_busybox(); } lxc_container_put(c); exit(ret); }
/* * test_running_container: test cgroup functions against a running container * * @group : name of the container group or NULL for default "lxc" * @name : name of the container */ static int test_running_container(const char *lxcpath, const char *group, const char *name) { int ret = -1; struct lxc_container *c = NULL; char *cgrelpath; char relpath[PATH_MAX+1]; char value[NAME_MAX], value_save[NAME_MAX]; sprintf(relpath, "%s/%s", group ? group : "lxc", name); if ((c = lxc_container_new(name, lxcpath)) == NULL) { TSTERR("container %s couldn't instantiate", name); goto err1; } if (!c->is_defined(c)) { TSTERR("container %s does not exist", name); goto err2; } cgrelpath = lxc_cmd_get_cgroup_path(c->name, c->config_path, "freezer"); if (!cgrelpath) { TSTERR("lxc_cmd_get_cgroup_path returned NULL"); goto err2; } if (!strstr(cgrelpath, relpath)) { TSTERR("lxc_cmd_get_cgroup_path %s not in %s", relpath, cgrelpath); goto err3; } /* test get/set value using memory.soft_limit_in_bytes file */ ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } strcpy(value_save, value); ret = lxc_cgroup_set("memory.soft_limit_in_bytes", "512M", c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed %d %d", ret, errno); goto err3; } ret = lxc_cgroup_get("memory.soft_limit_in_bytes", value, sizeof(value), c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_get failed"); goto err3; } if (strcmp(value, "536870912\n")) { TSTERR("lxc_cgroup_set_bypath failed to set value >%s<", value); goto err3; } /* restore original value */ ret = lxc_cgroup_set("memory.soft_limit_in_bytes", value_save, c->name, c->config_path); if (ret < 0) { TSTERR("lxc_cgroup_set failed"); goto err3; } ret = 0; err3: free(cgrelpath); err2: lxc_container_put(c); err1: return ret; }
int main(int argc, char *argv[]) { int i, init_pid, j; char proc_ns_path[4096]; char ipc_ns_buf[4096]; char net_ns_buf[4096]; pthread_attr_t attr; pthread_t threads[10]; struct thread_args args[10]; struct lxc_container *c; int ret = EXIT_FAILURE; c = lxc_container_new("owning-ns", NULL); if (!c) { lxc_error("%s", "Failed to create container \"owning-ns\""); exit(ret); } if (c->is_defined(c)) { lxc_error("%s\n", "Container \"owning-ns\" is defined"); goto on_error_put; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { lxc_error("%s\n", "Failed to create busybox container \"owning-ns\""); goto on_error_put; } if (!c->is_defined(c)) { lxc_error("%s\n", "Container \"owning-ns\" is not defined"); goto on_error_put; } c->clear_config(c); if (!c->load_config(c, NULL)) { lxc_error("%s\n", "Failed to load config for container \"owning-ns\""); goto on_error_stop; } if (!c->want_daemonize(c, true)) { lxc_error("%s\n", "Failed to mark container \"owning-ns\" daemonized"); goto on_error_stop; } if (!c->startl(c, 0, NULL)) { lxc_error("%s\n", "Failed to start container \"owning-ns\" daemonized"); goto on_error_stop; } init_pid = c->init_pid(c); if (init_pid < 0) { lxc_error("%s\n", "Failed to retrieve init pid of container \"owning-ns\""); goto on_error_stop; } /* record our ipc namespace */ ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/ipc", init_pid); if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) { lxc_error("%s\n", "Failed to create string for container \"owning-ns\""); goto on_error_stop; } ret = readlink(proc_ns_path, ipc_ns_buf, sizeof(ipc_ns_buf)); if (ret < 0 || (size_t)ret >= sizeof(ipc_ns_buf)) { lxc_error("%s\n", "Failed to retrieve ipc namespace for container \"owning-ns\""); goto on_error_stop; } ipc_ns_buf[ret] = '\0'; /* record our net namespace */ ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/net", init_pid); if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) { lxc_error("%s\n", "Failed to create string for container \"owning-ns\""); goto on_error_stop; } ret = readlink(proc_ns_path, net_ns_buf, sizeof(net_ns_buf)); if (ret < 0 || (size_t)ret >= sizeof(net_ns_buf)) { lxc_error("%s\n", "Failed to retrieve ipc namespace for container \"owning-ns\""); goto on_error_stop; } net_ns_buf[ret] = '\0'; sleep(5); pthread_attr_init(&attr); for (j = 0; j < 10; j++) { lxc_debug("Starting namespace sharing test iteration %d\n", j); for (i = 0; i < 10; i++) { int ret; args[i].thread_id = i; args[i].success = false; args[i].init_pid = init_pid; args[i].inherited_ipc_ns = ipc_ns_buf; args[i].inherited_net_ns = net_ns_buf; ret = pthread_create(&threads[i], &attr, ns_sharing_wrapper, (void *) &args[i]); if (ret != 0) goto on_error_stop; } for (i = 0; i < 10; i++) { int ret; ret = pthread_join(threads[i], NULL); if (ret != 0) goto on_error_stop; if (!args[i].success) { lxc_error("ns sharing thread %d failed\n", args[i].thread_id); goto on_error_stop; } } } ret = EXIT_SUCCESS; on_error_stop: if (c->is_running(c) && !c->stop(c)) lxc_error("%s\n", "Failed to stop container \"owning-ns\""); if (!c->destroy(c)) lxc_error("%s\n", "Failed to destroy container \"owning-ns\""); on_error_put: lxc_container_put(c); if (ret == EXIT_SUCCESS) lxc_debug("%s\n", "All state namespace sharing tests passed"); exit(ret); }
void *ns_sharing_wrapper(void *data) { int init_pid; ssize_t ret; char name[100]; char owning_ns_init_pid[100]; char proc_ns_path[4096]; char ns_buf[4096]; struct lxc_container *c; struct thread_args *args = data; lxc_debug("Starting namespace sharing thread %d\n", args->thread_id); sprintf(name, "share-ns-%d", args->thread_id); c = lxc_container_new(name, NULL); if (!c) { lxc_error("Failed to create container \"%s\"\n", name); return NULL; } if (c->is_defined(c)) { lxc_error("Container \"%s\" is defined\n", name); goto out; } if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { lxc_error("Failed to create busybox container \"%s\"\n", name); goto out; } if (!c->is_defined(c)) { lxc_error("Container \"%s\" is not defined\n", name); goto out; } if (!c->load_config(c, NULL)) { lxc_error("Failed to load config for container \"%s\"\n", name); goto out; } /* share ipc namespace by container name */ if (!c->set_config_item(c, "lxc.namespace.share.ipc", "owning-ns")) { lxc_error("Failed to set \"lxc.namespace.share.ipc=owning-ns\" for container \"%s\"\n", name); goto out; } /* clear all network configuration */ if (!c->set_config_item(c, "lxc.net", "")) { lxc_error("Failed to set \"lxc.namespace.share.ipc=owning-ns\" for container \"%s\"\n", name); goto out; } if (!c->set_config_item(c, "lxc.net.0.type", "empty")) { lxc_error("Failed to set \"lxc.net.0.type=empty\" for container \"%s\"\n", name); goto out; } sprintf(owning_ns_init_pid, "%d", args->init_pid); /* share net namespace by pid */ if (!c->set_config_item(c, "lxc.namespace.share.net", owning_ns_init_pid)) { lxc_error("Failed to set \"lxc.namespace.share.net=%s\" for container \"%s\"\n", owning_ns_init_pid, name); goto out; } if (!c->want_daemonize(c, true)) { lxc_error("Failed to mark container \"%s\" daemonized\n", name); goto out; } if (!c->startl(c, 0, NULL)) { lxc_error("Failed to start container \"%s\" daemonized\n", name); goto out; } init_pid = c->init_pid(c); if (init_pid < 0) { lxc_error("Failed to retrieve init pid of container \"%s\"\n", name); goto out; } /* Check whether we correctly inherited the ipc namespace. */ ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/ipc", init_pid); if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) { lxc_error("Failed to create string for container \"%s\"\n", name); goto out; } ret = readlink(proc_ns_path, ns_buf, sizeof(ns_buf)); if (ret < 0 || (size_t)ret >= sizeof(ns_buf)) { lxc_error("Failed to retrieve ipc namespace for container \"%s\"\n", name); goto out; } ns_buf[ret] = '\0'; if (strcmp(args->inherited_ipc_ns, ns_buf) != 0) { lxc_error("Failed to inherit ipc namespace from container \"owning-ns\": %s != %s\n", args->inherited_ipc_ns, ns_buf); goto out; } lxc_debug("Inherited ipc namespace from container \"owning-ns\": %s == %s\n", args->inherited_ipc_ns, ns_buf); /* Check whether we correctly inherited the net namespace. */ ret = snprintf(proc_ns_path, sizeof(proc_ns_path), "/proc/%d/ns/net", init_pid); if (ret < 0 || (size_t)ret >= sizeof(proc_ns_path)) { lxc_error("Failed to create string for container \"%s\"\n", name); goto out; } ret = readlink(proc_ns_path, ns_buf, sizeof(ns_buf)); if (ret < 0 || (size_t)ret >= sizeof(ns_buf)) { lxc_error("Failed to retrieve ipc namespace for container \"%s\"\n", name); goto out; } ns_buf[ret] = '\0'; if (strcmp(args->inherited_net_ns, ns_buf) != 0) { lxc_error("Failed to inherit net namespace from container \"owning-ns\": %s != %s\n", args->inherited_net_ns, ns_buf); goto out; } lxc_debug("Inherited net namespace from container \"owning-ns\": %s == %s\n", args->inherited_net_ns, ns_buf); args->success = true; out: if (c->is_running(c) && !c->stop(c)) { lxc_error("Failed to stop container \"%s\"\n", name); goto out; } if (!c->destroy(c)) { lxc_error("Failed to destroy container \"%s\"\n", name); goto out; } pthread_exit(NULL); return NULL; }