From 96b3cb407c07915db2cd0542c313a4bff4d1d389 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Wed, 10 Jul 2013 23:29:20 -0500 Subject: [PATCH] lxcapi_create: split out the template execution Make it its own function to make both more readable. Signed-off-by: Serge Hallyn --- src/lxc/lxccontainer.c | 213 ++++++++++++++++++++++------------------- 1 file changed, 117 insertions(+), 96 deletions(-) diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 245d5eba5..596c189a2 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -715,115 +715,34 @@ static struct bdev *do_bdev_create(struct lxc_container *c, const char *type, 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"); @@ -860,7 +779,7 @@ static bool lxcapi_create(struct lxc_container *c, const char *t, 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); @@ -908,9 +827,111 @@ static bool lxcapi_create(struct lxc_container *c, const char *t, 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) -- 2.39.5