return bdev;
}
-static bool lxcapi_destroy(struct lxc_container *c);
-/*
- * lxcapi_create:
- * create a container with the given parameters.
- * @c: container to be created. It has the lxcpath, name, and a starting
- * configuration already set
- * @t: the template to execute to instantiate the root filesystem and
- * adjust the configuration.
- * @bdevtype: backing store type to use. If NULL, dir will be used.
- * @specs: additional parameters for the backing store, i.e. LVM vg to
- * use.
- *
- * @argv: the arguments to pass to the template, terminated by NULL. If no
- * arguments, you can just pass NULL.
- */
-static bool lxcapi_create(struct lxc_container *c, const char *t,
- const char *bdevtype, struct bdev_specs *specs,
- char *const argv[])
+static char *lxcbasename(char *path)
{
- bool bret = false;
- pid_t pid;
- char *tpath = NULL, **newargv;
- int partial_fd, ret, len, nargs = 0;
+ char *p = path + strlen(path) - 1;
+ while (*p != '/' && p > path)
+ p--;
+ return p;
+}
- if (!c)
- return false;
+static bool create_run_template(struct lxc_container *c, char *tpath,
+ char *const argv[])
+{
+ pid_t pid;
- len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
- tpath = malloc(len);
if (!tpath)
- return false;
- ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
- if (ret < 0 || ret >= len)
- goto out;
- if (!valid_template(tpath)) {
- ERROR("bad template: %s\n", t);
- goto out;
- }
-
- if (!c->save_config(c, NULL)) {
- ERROR("failed to save starting configuration for %s\n", c->name);
- goto out;
- }
-
- /* container is already created if we have a config and rootfs.path is accessible */
- if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0)
- goto out;
-
- /* Mark that this container is being created */
- if ((partial_fd = create_partial(c)) < 0)
- goto out;
-
- /* no need to get disk lock bc we have the partial locked */
-
- /*
- * Create the backing store
- * Note we can't do this in the same task as we use to execute the
- * template because of the way zfs works.
- * After you 'zfs create', zfs mounts the fs only in the initial
- * namespace.
- */
- pid = fork();
- if (pid < 0) {
- SYSERROR("failed to fork task for container creation template\n");
- goto out_unlock;
- }
-
- if (pid == 0) { // child
- struct bdev *bdev = NULL;
-
- if (!(bdev = do_bdev_create(c, bdevtype, specs))) {
- ERROR("Error creating backing store type %s for %s",
- bdevtype ? bdevtype : "(none)", c->name);
- exit(1);
- }
-
- /* save config file again to store the new rootfs location */
- if (!c->save_config(c, NULL)) {
- ERROR("failed to save starting configuration for %s\n", c->name);
- // parent task won't see bdev in config so we delete it
- bdev->ops->umount(bdev);
- bdev->ops->destroy(bdev);
- exit(1);
- }
- exit(0);
- }
- if (wait_for_pid(pid) != 0)
- goto out;
-
- /* reload config to get the rootfs */
- if (c->lxc_conf)
- lxc_conf_free(c->lxc_conf);
- c->lxc_conf = NULL;
- if (!load_config_locked(c, c->configfile))
- goto out;
+ return true;
- /*
- * now execute the template
- */
pid = fork();
if (pid < 0) {
SYSERROR("failed to fork task for container creation template\n");
- goto out_unlock;
+ return false;
}
if (pid == 0) { // child
char *patharg, *namearg, *rootfsarg, *src;
struct bdev *bdev = NULL;
int i;
+ int ret, len, nargs = 0;
+ char **newargv;
if (unshare(CLONE_NEWNS) < 0) {
ERROR("error unsharing mounts");
newargv = malloc(nargs * sizeof(*newargv));
if (!newargv)
exit(1);
- newargv[0] = (char *)t;
+ newargv[0] = lxcbasename(tpath);
len = strlen(c->config_path) + strlen(c->name) + strlen("--path=") + 2;
patharg = malloc(len);
if (wait_for_pid(pid) != 0) {
ERROR("container creation template for %s failed\n", c->name);
+ return false;
+ }
+
+ return true;
+}
+
+static bool lxcapi_destroy(struct lxc_container *c);
+/*
+ * lxcapi_create:
+ * create a container with the given parameters.
+ * @c: container to be created. It has the lxcpath, name, and a starting
+ * configuration already set
+ * @t: the template to execute to instantiate the root filesystem and
+ * adjust the configuration.
+ * @bdevtype: backing store type to use. If NULL, dir will be used.
+ * @specs: additional parameters for the backing store, i.e. LVM vg to
+ * use.
+ *
+ * @argv: the arguments to pass to the template, terminated by NULL. If no
+ * arguments, you can just pass NULL.
+ */
+static bool lxcapi_create(struct lxc_container *c, const char *t,
+ const char *bdevtype, struct bdev_specs *specs,
+ char *const argv[])
+{
+ bool bret = false;
+ pid_t pid;
+ char *tpath = NULL;
+ int partial_fd, ret, len;
+
+ if (!c)
+ return false;
+
+ len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
+ tpath = malloc(len);
+ if (!tpath)
+ return false;
+ ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
+ if (ret < 0 || ret >= len)
+ goto out;
+ if (!valid_template(tpath)) {
+ ERROR("bad template: %s\n", t);
+ goto out;
+ }
+
+ if (!c->save_config(c, NULL)) {
+ ERROR("failed to save starting configuration for %s\n", c->name);
+ goto out;
+ }
+
+ /* container is already created if we have a config and rootfs.path is accessible */
+ if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0)
+ goto out;
+
+ /* Mark that this container is being created */
+ if ((partial_fd = create_partial(c)) < 0)
+ goto out;
+
+ /* no need to get disk lock bc we have the partial locked */
+
+ /*
+ * Create the backing store
+ * Note we can't do this in the same task as we use to execute the
+ * template because of the way zfs works.
+ * After you 'zfs create', zfs mounts the fs only in the initial
+ * namespace.
+ */
+ pid = fork();
+ if (pid < 0) {
+ SYSERROR("failed to fork task for container creation template\n");
goto out_unlock;
}
+ if (pid == 0) { // child
+ struct bdev *bdev = NULL;
+
+ if (!(bdev = do_bdev_create(c, bdevtype, specs))) {
+ ERROR("Error creating backing store type %s for %s",
+ bdevtype ? bdevtype : "(none)", c->name);
+ exit(1);
+ }
+
+ /* save config file again to store the new rootfs location */
+ if (!c->save_config(c, NULL)) {
+ ERROR("failed to save starting configuration for %s\n", c->name);
+ // parent task won't see bdev in config so we delete it
+ bdev->ops->umount(bdev);
+ bdev->ops->destroy(bdev);
+ exit(1);
+ }
+ exit(0);
+ }
+ if (wait_for_pid(pid) != 0)
+ goto out;
+
+ /* reload config to get the rootfs */
+ if (c->lxc_conf)
+ lxc_conf_free(c->lxc_conf);
+ c->lxc_conf = NULL;
+ if (!load_config_locked(c, c->configfile))
+ goto out;
+
+ if (!create_run_template(c, tpath, argv))
+ goto out_unlock;
+
// now clear out the lxc_conf we have, reload from the created
// container
if (c->lxc_conf)