From: Serge Hallyn Date: Fri, 14 Aug 2015 15:59:19 +0000 (-0500) Subject: Revert "Refactor lxc-snapshot, lxc-clone, make LXC_CLONE_KEEPNAME work and add option... X-Git-Tag: lxc-2.0.0.beta1~190^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=965ef7f4600e556a91db4f5ecd3f084a28ede6c1;p=thirdparty%2Flxc.git Revert "Refactor lxc-snapshot, lxc-clone, make LXC_CLONE_KEEPNAME work and add option to destroy container with all snapshots to lxc-destroy" --- diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index 30aa06a21..cc85f863f 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -94,22 +94,6 @@ struct lxc_arguments { int list; char *groups; - /* lxc-snapshot and lxc-clone */ - enum task { - DESTROY, - LIST, - RESTORE, - SNAP, - RENAME, - } task; - int print_comments; - char *commentfile; - char *newname; - char *newpath; - char *snapname; - int keepname; - int keepmac; - /* remaining arguments */ char *const *argv; int argc; diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c index 94f0f7a14..d28b22c7a 100644 --- a/src/lxc/lxc_attach.c +++ b/src/lxc/lxc_attach.c @@ -146,7 +146,7 @@ static struct lxc_arguments my_args = { Execute the specified COMMAND - enter the container NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -e, --elevated-privileges=PRIVILEGES\n\ Use elevated privileges instead of those of the\n\ container. If you don't specify privileges to be\n\ diff --git a/src/lxc/lxc_checkpoint.c b/src/lxc/lxc_checkpoint.c index 3e5de4a3c..2e76c2ec4 100644 --- a/src/lxc/lxc_checkpoint.c +++ b/src/lxc/lxc_checkpoint.c @@ -105,7 +105,7 @@ lxc-checkpoint checkpoints and restores a container\n\ its running state at a later time.\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -r, --restore Restore container\n\ -D, --checkpoint-dir=DIR directory to save the checkpoint in\n\ -v, --verbose Enable verbose criu logs\n\ diff --git a/src/lxc/lxc_clone.c b/src/lxc/lxc_clone.c index 610e316a0..e88c18bc3 100644 --- a/src/lxc/lxc_clone.c +++ b/src/lxc/lxc_clone.c @@ -27,228 +27,189 @@ #include #include #include -#include -#include #include #include "log.h" -#include "confile.h" -#include "arguments.h" +#include "config.h" #include "lxc.h" #include "conf.h" #include "state.h" lxc_log_define(lxc_clone_ui, lxc); -static int my_parser(struct lxc_arguments *args, int c, char *arg); +/* we pass fssize in bytes */ +static uint64_t get_fssize(char *s) +{ + uint64_t ret; + char *end; -static const struct option my_longopts[] = { - { "newname", required_argument, 0, 'N'}, - { "newpath", required_argument, 0, 'p'}, - { "rename", no_argument, 0, 'R'}, + ret = strtoull(s, &end, 0); + if (end == s) + { + fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); + return 0; + } + while (isblank(*end)) + end++; + if (*end == '\0') + ret *= 1024ULL * 1024ULL; // MB by default + else if (*end == 'b' || *end == 'B') + ret *= 1ULL; + else if (*end == 'k' || *end == 'K') + ret *= 1024ULL; + else if (*end == 'm' || *end == 'M') + ret *= 1024ULL * 1024ULL; + else if (*end == 'g' || *end == 'G') + ret *= 1024ULL * 1024ULL * 1024ULL; + else if (*end == 't' || *end == 'T') + ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; + else + { + fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); + return 0; + } + return ret; +} + +static void usage(const char *me) +{ + printf("Usage: %s [-s] [-B backingstore] [-L size[unit]] [-K] [-M] [-H]\n", me); + printf(" [-p lxcpath] [-P newlxcpath] orig new\n"); + printf("\n"); + printf(" -s: snapshot rather than copy\n"); + printf(" -B: use specified new backingstore. Default is the same as\n"); + printf(" the original. Options include aufs, btrfs, lvm, overlayfs, \n"); + printf(" dir and loop\n"); + printf(" -L: for blockdev-backed backingstore, use specified size * specified\n"); + printf(" unit. Default size is the size of the source blockdev, default\n"); + printf(" unit is MB\n"); + printf(" -K: Keep name - do not change the container name\n"); + printf(" -M: Keep macaddr - do not choose a random new mac address\n"); + printf(" -p: use container orig from custom lxcpath\n"); + printf(" -P: create container new in custom lxcpath\n"); + printf(" -R: rename existing container\n"); + exit(1); +} + +static struct option options[] = { { "snapshot", no_argument, 0, 's'}, { "backingstore", required_argument, 0, 'B'}, - { "fssize", required_argument, 0, 'L'}, + { "size", required_argument, 0, 'L'}, + { "orig", required_argument, 0, 'o'}, + { "new", required_argument, 0, 'n'}, + { "vgname", required_argument, 0, 'v'}, + { "rename", no_argument, 0, 'R'}, { "keepname", no_argument, 0, 'K'}, { "keepmac", no_argument, 0, 'M'}, - LXC_COMMON_OPTIONS + { "lxcpath", required_argument, 0, 'p'}, + { "newpath", required_argument, 0, 'P'}, + { "fstype", required_argument, 0, 't'}, + { "help", no_argument, 0, 'h'}, + { 0, 0, 0, 0 }, }; -static struct lxc_arguments my_args = { - .progname = "lxc-clone", - .help = "\ ---name=NAME [-P lxcpath] -N newname [-p newpath] [-B backingstorage] [-s] [-K] [-M] [-L size [unit]]\n\ -\n\ -lxc-lcone clone a container\n\ -\n\ -Options :\n\ - -n, --name=NAME NAME of the container\n\ - -N, --newname=NEWNAME NEWNAME for the restored container\n\ - -p, --newpath=NEWPATH NEWPATH for the container to be stored\n\ - -R, --rename rename container\n\ - -s, --snapshot create snapshot instead of clone\n\ - -B, --backingstorage=TYPE backingstorage type for the container\n\ - -L, --fssize size of the new block device for block device containers\n\ - -K, --keepname keep the hostname of the original container\n\ - -M, --keepmac keep the MAC address of the original container\n", - .options = my_longopts, - .parser = my_parser, - .checker = NULL, -}; - -static int do_clone(struct lxc_container *c, char *newname, char *newpath, - int flags, char *bdevtype, uint64_t fssize, char **args); -static int do_clone_rename(struct lxc_container *c, char *newname); -static uint64_t get_fssize(char *s); - int main(int argc, char *argv[]) { - struct lxc_container *c; - int flags = 0; - int ret; - - if (lxc_arguments_parse(&my_args, argc, argv)) - exit(EXIT_FAILURE); - - 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(EXIT_FAILURE); - lxc_log_options_no_override(); + struct lxc_container *c1 = NULL, *c2 = NULL; + int snapshot = 0, keepname = 0, keepmac = 0, rename = 0; + int flags = 0, option_index; + uint64_t newsize = 0; + char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL; + char *orig = NULL, *new = NULL, *vgname = NULL; + char **args = NULL; + int c; + bool ret; - if (geteuid()) { - if (access(my_args.lxcpath[0], O_RDWR) < 0) { - fprintf(stderr, "You lack access to %s\n", - my_args.lxcpath[0]); - exit(EXIT_FAILURE); + if (argc < 3) + usage(argv[0]); + + while (1) { + c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:Rt:h", options, &option_index); + if (c == -1) + break; + switch (c) { + case 's': snapshot = 1; break; + case 'B': bdevtype = optarg; break; + case 'L': newsize = get_fssize(optarg); break; + case 'o': orig = optarg; break; + case 'n': new = optarg; break; + case 'v': vgname = optarg; break; + case 'K': keepname = 1; break; + case 'M': keepmac = 1; break; + case 'p': lxcpath = optarg; break; + case 'P': newpath = optarg; break; + case 'R': rename = 1; break; + case 't': fstype = optarg; break; + case 'h': usage(argv[0]); + default: break; } } - - if (!my_args.newname) { - printf("Error: You must provide a NEWNAME for the clone.\n"); - exit(EXIT_FAILURE); + if (optind < argc && !orig) + orig = argv[optind++]; + if (optind < argc && !new) + new = argv[optind++]; + if (optind < argc) + /* arguments for the clone hook */ + args = &argv[optind]; + if (!new || !orig) { + printf("Error: you must provide orig and new names\n"); + usage(argv[0]); } - if (my_args.task == SNAP) - flags |= LXC_CLONE_SNAPSHOT; - if (my_args.keepname) - flags |= LXC_CLONE_KEEPNAME; - if (my_args.keepmac) - flags |= LXC_CLONE_KEEPMACADDR; - - c = lxc_container_new(my_args.name, my_args.lxcpath[0]); - if (!c) - exit(EXIT_FAILURE); - - if (!c->may_control(c)) { - fprintf(stderr, "Insufficent privileges to control %s\n", - c->name); - lxc_container_put(c); - exit(EXIT_FAILURE); - } + if (snapshot) flags |= LXC_CLONE_SNAPSHOT; + if (keepname) flags |= LXC_CLONE_KEEPNAME; + if (keepmac) flags |= LXC_CLONE_KEEPMACADDR; - if (!c->is_defined(c)) { - fprintf(stderr, "Error: container %s is not defined\n", - c->name); - lxc_container_put(c); - exit(EXIT_FAILURE); + // vgname and fstype could be supported by sending them through the + // bdevdata. However, they currently are not yet. I'm not convinced + // they are worthwhile. + if (vgname) { + printf("Error: vgname not supported\n"); + usage(argv[0]); } - - if (my_args.task == RENAME) { - ret = do_clone_rename(c, my_args.newname); - } else { - ret = do_clone(c, my_args.newname, my_args.newpath, flags, - my_args.bdevtype, my_args.fssize, &argv[optind]); + if (fstype) { + printf("Error: fstype not supported\n"); + usage(argv[0]); } - lxc_container_put(c); - - if (ret == 0) - exit(EXIT_SUCCESS); - exit(EXIT_FAILURE); -} - -static int my_parser(struct lxc_arguments *args, int c, char *arg) -{ - switch (c) { - case 'N': - args->newname = arg; - break; - case 'p': - args->newpath = arg; - break; - case 'R': - args->task = RENAME; - break; - case 's': - args->task = SNAP; - break; - case 'B': - args->bdevtype = arg; - break; - case 'L': - args->fssize = get_fssize(optarg); - break; - case 'K': - args->keepname = 1; - break; - case 'M': - args->keepmac = 1; - break; - } - - return 0; -} - -static int do_clone_rename(struct lxc_container *c, char *newname) -{ - bool ret; - - ret = c->rename(c, newname); - if (!ret) { - ERROR("Error: Renaming container %s to %s failed\n", c->name, - my_args.newname); - return -1; - } - - INFO("Renamed container %s to %s\n", c->name, newname); - - return 0; -} - -static int do_clone(struct lxc_container *c, char *newname, char *newpath, - int flags, char *bdevtype, uint64_t fssize, char **args) -{ - struct lxc_container *clone; + c1 = lxc_container_new(orig, lxcpath); + if (!c1) + exit(EXIT_FAILURE); - clone = c->clone(c, newname, newpath, flags, bdevtype, NULL, fssize, - args); - if (clone == NULL) { - fprintf(stderr, "clone failed\n"); - return -1; + if (!c1->may_control(c1)) { + fprintf(stderr, "Insufficent privileges to control %s\n", orig); + lxc_container_put(c1); + exit(EXIT_FAILURE); } - INFO("Created container %s as %s of %s\n", newname, - my_args.task ? "snapshot" : "copy", c->name); - - lxc_container_put(clone); - - return 0; -} - -/* we pass fssize in bytes */ -static uint64_t get_fssize(char *s) -{ - uint64_t ret; - char *end; - - ret = strtoull(s, &end, 0); - if (end == s) { - fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s); - return 0; + if (!c1->is_defined(c1)) { + fprintf(stderr, "Error: container %s is not defined\n", orig); + lxc_container_put(c1); + exit(EXIT_FAILURE); } - while (isblank(*end)) - end++; - if (*end == '\0') { - ret *= 1024ULL * 1024ULL; // MB by default - } else if (*end == 'b' || *end == 'B') { - ret *= 1ULL; - } else if (*end == 'k' || *end == 'K') { - ret *= 1024ULL; - } else if (*end == 'm' || *end == 'M') { - ret *= 1024ULL * 1024ULL; - } else if (*end == 'g' || *end == 'G') { - ret *= 1024ULL * 1024ULL * 1024ULL; - } else if (*end == 't' || *end == 'T') { - ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; + if (rename) { + ret = c1->rename(c1, new); + if (!ret) { + fprintf(stderr, + "Error: Renaming container %s to %s failed\n", + c1->name, new); + lxc_container_put(c1); + exit(EXIT_FAILURE); + } } else { - fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', " "using default size\n", *end, s); - return 0; + c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, + args); + if (c2 == NULL) { + lxc_container_put(c1); + fprintf(stderr, "clone failed\n"); + exit(EXIT_FAILURE); + } + printf("Created container %s as %s of %s\n", new, + snapshot ? "snapshot" : "copy", orig); + lxc_container_put(c2); } + lxc_container_put(c1); - return ret; + exit(EXIT_SUCCESS); } - diff --git a/src/lxc/lxc_console.c b/src/lxc/lxc_console.c index adbd7e019..b22322b1e 100644 --- a/src/lxc/lxc_console.c +++ b/src/lxc/lxc_console.c @@ -78,7 +78,7 @@ static struct lxc_arguments my_args = { lxc-console logs on the container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -t, --tty=NUMBER console tty number\n\ -e, --escape=PREFIX prefix for escape command\n", .options = my_longopts, diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c index f1094fba8..8f46db941 100644 --- a/src/lxc/lxc_create.c +++ b/src/lxc/lxc_create.c @@ -61,7 +61,7 @@ static uint64_t get_fssize(char *s) else if (*end == 't' || *end == 'T') ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL; else - { + { fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s); return 0; } @@ -131,7 +131,7 @@ static struct lxc_arguments my_args = { lxc-create creates a container\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -f, --config=file Initial configuration file\n\ -t, --template=t Template to use to setup container\n\ -B, --bdev=BDEV Backing store type to use\n\ diff --git a/src/lxc/lxc_destroy.c b/src/lxc/lxc_destroy.c index 32bd2b42d..955fc23f7 100644 --- a/src/lxc/lxc_destroy.c +++ b/src/lxc/lxc_destroy.c @@ -31,11 +31,16 @@ lxc_log_define(lxc_destroy_ui, lxc); -static int my_parser(struct lxc_arguments* args, int c, char* arg); +static int my_parser(struct lxc_arguments* args, int c, char* arg) +{ + switch (c) { + case 'f': args->force = 1; break; + } + return 0; +} static const struct option my_longopts[] = { {"force", no_argument, 0, 'f'}, - {"snapshots", no_argument, 0, 's'}, LXC_COMMON_OPTIONS }; @@ -47,104 +52,61 @@ static struct lxc_arguments my_args = { lxc-destroy destroys a container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ - -s, --snapshots destroy including all snapshots\n\ + -n, --name=NAME NAME for name of the container\n\ -f, --force wait for the container to shut down\n", .options = my_longopts, .parser = my_parser, .checker = NULL, - .task = DESTROY, }; -static int do_destroy(struct lxc_container *c); -static int do_destroy_with_snapshots(struct lxc_container *c); - int main(int argc, char *argv[]) { struct lxc_container *c; - int ret; if (lxc_arguments_parse(&my_args, argc, argv)) - exit(EXIT_FAILURE); + 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(EXIT_FAILURE); + 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 container\n"); - exit(EXIT_FAILURE); + exit(1); } if (!c->may_control(c)) { fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); lxc_container_put(c); - exit(EXIT_FAILURE); + exit(1); } if (!c->is_defined(c)) { fprintf(stderr, "Container is not defined\n"); lxc_container_put(c); - exit(EXIT_FAILURE); + exit(1); } if (c->is_running(c)) { if (!my_args.force) { fprintf(stderr, "%s is running\n", my_args.name); lxc_container_put(c); - exit(EXIT_FAILURE); + exit(1); } c->stop(c); } - if (my_args.task == SNAP) { - ret = do_destroy_with_snapshots(c); - } else { - ret = do_destroy(c); - } - - lxc_container_put(c); - - if (ret == 0) - exit(EXIT_SUCCESS); - exit(EXIT_FAILURE); -} - -static int my_parser(struct lxc_arguments *args, int c, char *arg) -{ - switch (c) { - case 'f': args->force = 1; break; - case 's': args->task = SNAP; break; - } - return 0; -} - -static int do_destroy(struct lxc_container *c) -{ if (!c->destroy(c)) { fprintf(stderr, "Destroying %s failed\n", my_args.name); - return -1; - } - - printf("Destroyed container %s\n", my_args.name); - - return 0; -} - -static int do_destroy_with_snapshots(struct lxc_container *c) -{ - if (!c->destroy_with_snapshots(c)) { - fprintf(stderr, "Destroying %s failed\n", my_args.name); - return -1; + lxc_container_put(c); + exit(1); } - printf("Destroyed container including snapshots %s\n", my_args.name); - - return 0; + lxc_container_put(c); + exit(0); } - diff --git a/src/lxc/lxc_device.c b/src/lxc/lxc_device.c index 0c9e06648..6d715d36c 100644 --- a/src/lxc/lxc_device.c +++ b/src/lxc/lxc_device.c @@ -53,7 +53,7 @@ static struct lxc_arguments my_args = { lxc-device attach or detach DEV to or from container.\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container", + -n, --name=NAME NAME for name of the container", .options = my_longopts, .parser = NULL, .checker = NULL, diff --git a/src/lxc/lxc_execute.c b/src/lxc/lxc_execute.c index d2c1248cd..4f1e1f674 100644 --- a/src/lxc/lxc_execute.c +++ b/src/lxc/lxc_execute.c @@ -79,7 +79,7 @@ lxc-execute creates a container with the identifier NAME\n\ and execs COMMAND into this container.\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -f, --rcfile=FILE Load configuration file FILE\n\ -s, --define KEY=VAL Assign VAL to configuration variable KEY\n", .options = my_longopts, diff --git a/src/lxc/lxc_freeze.c b/src/lxc/lxc_freeze.c index ea8bd3eae..0744c82ea 100644 --- a/src/lxc/lxc_freeze.c +++ b/src/lxc/lxc_freeze.c @@ -47,7 +47,7 @@ static struct lxc_arguments my_args = { lxc-freeze freezes a container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container", + -n, --name=NAME NAME for name of the container", .options = my_longopts, .parser = NULL, .checker = NULL, diff --git a/src/lxc/lxc_info.c b/src/lxc/lxc_info.c index 9f1c46991..b360aa8f7 100644 --- a/src/lxc/lxc_info.c +++ b/src/lxc/lxc_info.c @@ -87,7 +87,7 @@ static struct lxc_arguments my_args = { lxc-info display some information about a container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -c, --config=KEY show configuration variable KEY from running container\n\ -i, --ips shows the IP addresses\n\ -p, --pid shows the process id of the init container\n\ diff --git a/src/lxc/lxc_init.c b/src/lxc/lxc_init.c index f4b120db0..62ed4ad1b 100644 --- a/src/lxc/lxc_init.c +++ b/src/lxc/lxc_init.c @@ -61,7 +61,7 @@ static void interrupt_handler(int sig) static void usage(void) { fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n" "Common options :\n" - " -n, --name=NAME NAME of the container\n" + " -n, --name=NAME NAME for name of the container\n" " -l, --logpriority=LEVEL Set log priority to LEVEL\n" " -q, --quiet Don't produce any output\n" " -P, --lxcpath=PATH Use specified container path\n" diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index 797ae8bc3..ac34b0e5f 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -61,7 +61,7 @@ static struct lxc_arguments my_args = { lxc-monitor monitors the state of the NAME container\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ NAME may be a regular expression\n\ -Q, --quit tell lxc-monitord to quit\n", .name = ".*", diff --git a/src/lxc/lxc_snapshot.c b/src/lxc/lxc_snapshot.c index 9ffbeb4dd..a03c0c09b 100644 --- a/src/lxc/lxc_snapshot.c +++ b/src/lxc/lxc_snapshot.c @@ -16,8 +16,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" -#include "confile.h" #include #include #include @@ -35,149 +35,18 @@ lxc_log_define(lxc_snapshot_ui, lxc); -static int my_parser(struct lxc_arguments *args, int c, char *arg); +static char *newname; +static char *snapshot; -static const struct option my_longopts[] = { - {"list", no_argument, 0, 'L'}, - {"restore", required_argument, 0, 'r'}, - {"newname", required_argument, 0, 'N'}, - {"destroy", required_argument, 0, 'd'}, - {"comment", required_argument, 0, 'c'}, - {"showcomments", no_argument, 0, 'C'}, - LXC_COMMON_OPTIONS -}; - -static struct lxc_arguments my_args = { - .progname = "lxc-snapshot", - .help = "\ ---name=NAME [-P lxcpath] [-L [-C]] [-c commentfile] [-r snapname [-N newname]]\n\ -\n\ -lxc-snapshot snapshots a container\n\ -\n\ -Options :\n\ - -n, --name=NAME NAME of the container\n\ - -L, --list list all snapshots\n\ - -r, --restore=NAME restore snapshot NAME, e.g. 'snap0'\n\ - -N, --newname=NEWNAME NEWNAME for the restored container\n\ - -d, --destroy=NAME destroy snapshot NAME, e.g. 'snap0'\n\ - use ALL to destroy all snapshots\n\ - -c, --comment=FILE add FILE as a comment\n\ - -C, --showcomments show snapshot comments\n", - .options = my_longopts, - .parser = my_parser, - .checker = NULL, - .task = SNAP, -}; - -static int do_destroy_snapshots(struct lxc_container *c, char *snapname); -static int do_list_snapshots(struct lxc_container *c, int print_comments); -static int do_restore_snapshots(struct lxc_container *c, char *snapname, - char *newname); -static int do_snapshot(struct lxc_container *c, char *commentfile); -static int do_snapshot_task(struct lxc_container *c, enum task task); -static void print_file(char *path); - -int main(int argc, char *argv[]) -{ - struct lxc_container *c; - int ret; - - if (lxc_arguments_parse(&my_args, argc, argv)) - exit(EXIT_FAILURE); - - 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(EXIT_FAILURE); - lxc_log_options_no_override(); - - if (geteuid()) { - if (access(my_args.lxcpath[0], O_RDWR) < 0) { - fprintf(stderr, "You lack access to %s\n", - my_args.lxcpath[0]); - exit(EXIT_FAILURE); - } - } - - c = lxc_container_new(my_args.name, my_args.lxcpath[0]); - if (!c) { - fprintf(stderr, "System error loading container\n"); - exit(EXIT_FAILURE); - } - - if (!c->may_control(c)) { - fprintf(stderr, "Insufficent privileges to control %s\n", - my_args.name); - lxc_container_put(c); - exit(EXIT_FAILURE); - } +#define DO_SNAP 0 +#define DO_LIST 1 +#define DO_RESTORE 2 +#define DO_DESTROY 3 +static int action; +static int print_comments; +static char *commentfile; - ret = do_snapshot_task(c, my_args.task); - - lxc_container_put(c); - - if (ret == 0) - exit(EXIT_SUCCESS); - exit(EXIT_FAILURE); -} - -static int do_snapshot_task(struct lxc_container *c, enum task task) -{ - int ret = 0; - - switch (task) { - case DESTROY: - ret = do_destroy_snapshots(c, my_args.snapname); - break; - case LIST: - ret = do_list_snapshots(c, my_args.print_comments); - break; - case RESTORE: - ret = - do_restore_snapshots(c, my_args.snapname, my_args.newname); - break; - case SNAP: - ret = do_snapshot(c, my_args.commentfile); - break; - default: - ret = 0; - break; - } - - return ret; -} - -static int my_parser(struct lxc_arguments *args, int c, char *arg) -{ - switch (c) { - case 'L': - args->task = LIST; - break; - case 'r': - args->task = RESTORE; - args->snapname = arg; - break; - case 'N': - args->newname = arg; - break; - case 'd': - args->task = DESTROY; - args->snapname = arg; - break; - case 'c': - args->commentfile = arg; - break; - case 'C': - args->print_comments = 1; - break; - } - - return 0; -} - -static int do_snapshot(struct lxc_container *c, char *commentfile) +static int do_snapshot(struct lxc_container *c) { int ret; @@ -188,11 +57,26 @@ static int do_snapshot(struct lxc_container *c, char *commentfile) } INFO("Created snapshot snap%d", ret); - return 0; } -static int do_list_snapshots(struct lxc_container *c, int print_comments) +static void print_file(char *path) +{ + if (!path) + return; + FILE *f = fopen(path, "r"); + char *line = NULL; + size_t sz = 0; + if (!f) + return; + while (getline(&line, &sz, f) != -1) { + printf("%s", line); + } + free(line); + fclose(f); +} + +static int do_list_snapshots(struct lxc_container *c) { struct lxc_snapshot *s; int i, n; @@ -206,69 +90,148 @@ static int do_list_snapshots(struct lxc_container *c, int print_comments) printf("No snapshots\n"); return 0; } - - for (i = 0; i < n; i++) { + for (i=0; isnapshot_restore(c, snapname, newname)) + if (c->snapshot_restore(c, snapshot, newname)) return 0; - ERROR("Error restoring snapshot %s", snapname); - + ERROR("Error restoring snapshot %s", snapshot); return -1; } -static int do_destroy_snapshots(struct lxc_container *c, char *snapname) +static int do_destroy_snapshots(struct lxc_container *c) { - bool ret; - - if (strcmp(snapname, "ALL") == 0) - ret = c->snapshot_destroy_all(c); + bool bret; + if (strcmp(snapshot, "ALL") == 0) + bret = c->snapshot_destroy_all(c); else - ret = c->snapshot_destroy(c, snapname); + bret = c->snapshot_destroy(c, snapshot); - if (ret) + if (bret) return 0; - ERROR("Error destroying snapshot %s", snapname); - + ERROR("Error destroying snapshot %s", snapshot); return -1; } -static void print_file(char *path) +static int my_parser(struct lxc_arguments* args, int c, char* arg) { - if (!path) - return; + switch (c) { + case 'L': action = DO_LIST; break; + case 'r': snapshot = arg; action = DO_RESTORE; break; + case 'd': snapshot = arg; action = DO_DESTROY; break; + case 'c': commentfile = arg; break; + case 'C': print_comments = true; break; + } + return 0; +} - FILE *f = fopen(path, "r"); - char *line = NULL; - size_t sz = 0; +static const struct option my_longopts[] = { + {"list", no_argument, 0, 'L'}, + {"restore", required_argument, 0, 'r'}, + {"destroy", required_argument, 0, 'd'}, + {"comment", required_argument, 0, 'c'}, + {"showcomments", no_argument, 0, 'C'}, + LXC_COMMON_OPTIONS +}; - if (!f) - return; - while (getline(&line, &sz, f) != -1) { - printf("%s", line); +static struct lxc_arguments my_args = { + .progname = "lxc-snapshot", + .help = "\ +--name=NAME [-P lxcpath] [-L [-C]] [-c commentfile] [-r snapname [newname]]\n\ +\n\ +lxc-snapshot snapshots a container\n\ +\n\ +Options :\n\ + -n, --name=NAME NAME for name of the container\n\ + -L, --list list snapshots\n\ + -C, --showcomments show snapshot comments in list\n\ + -c, --comment=file add file as a comment\n\ + -r, --restore=name restore snapshot name, i.e. 'snap0'\n\ + -d, --destroy=name destroy snapshot name, i.e. 'snap0'\n\ + use ALL to destroy all snapshots\n", + .options = my_longopts, + .parser = my_parser, + .checker = NULL, +}; + +/* + * lxc-snapshot -P lxcpath -n container + * lxc-snapshot -P lxcpath -n container -l + * lxc-snapshot -P lxcpath -n container -r snap3 recovered_1 + */ + +int main(int argc, char *argv[]) +{ + struct lxc_container *c; + int ret = 0; + + if (lxc_arguments_parse(&my_args, argc, argv)) + exit(1); + + if (!my_args.log_file) + my_args.log_file = "none"; + + if (my_args.argc > 1) { + ERROR("Too many arguments"); + exit(1); } + if (my_args.argc == 1) + newname = my_args.argv[0]; - free(line); - fclose(f); -} + 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(); + + if (geteuid()) { + if (access(my_args.lxcpath[0], O_RDWR) < 0) { + fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); + exit(1); + } + } + + c = lxc_container_new(my_args.name, my_args.lxcpath[0]); + if (!c) { + fprintf(stderr, "System error loading container\n"); + exit(1); + } + + if (!c->may_control(c)) { + fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); + lxc_container_put(c); + exit(1); + } + + switch(action) { + case DO_SNAP: + ret = do_snapshot(c); + break; + case DO_LIST: + ret = do_list_snapshots(c); + break; + case DO_RESTORE: + ret = do_restore_snapshots(c); + break; + case DO_DESTROY: + ret = do_destroy_snapshots(c); + break; + } + lxc_container_put(c); + + if (ret == 0) + exit(EXIT_SUCCESS); + exit(EXIT_FAILURE); +} diff --git a/src/lxc/lxc_start.c b/src/lxc/lxc_start.c index ec6ee219c..b9d1add19 100644 --- a/src/lxc/lxc_start.c +++ b/src/lxc/lxc_start.c @@ -181,7 +181,7 @@ static struct lxc_arguments my_args = { lxc-start start COMMAND in specified container NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -d, --daemon Daemonize the container (default)\n\ -F, --foreground Start with the current tty attached to /dev/console\n\ -p, --pidfile=FILE Create a file with the process id\n\ diff --git a/src/lxc/lxc_stop.c b/src/lxc/lxc_stop.c index 10ddce6a9..705453266 100644 --- a/src/lxc/lxc_stop.c +++ b/src/lxc/lxc_stop.c @@ -69,7 +69,7 @@ static struct lxc_arguments my_args = { lxc-stop stops a container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -r, --reboot reboot the container\n\ -W, --nowait don't wait for shutdown or reboot to complete\n\ -t, --timeout=T wait T seconds before hard-stopping\n\ diff --git a/src/lxc/lxc_unfreeze.c b/src/lxc/lxc_unfreeze.c index 3a13d3723..6a40ed74d 100644 --- a/src/lxc/lxc_unfreeze.c +++ b/src/lxc/lxc_unfreeze.c @@ -45,7 +45,7 @@ static struct lxc_arguments my_args = { lxc-unfreeze unfreezes a container with the identifier NAME\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n", + -n, --name=NAME NAME for name of the container\n", .options = my_longopts, .parser = NULL, .checker = NULL, diff --git a/src/lxc/lxc_wait.c b/src/lxc/lxc_wait.c index 712ba52d6..897d0ea3d 100644 --- a/src/lxc/lxc_wait.c +++ b/src/lxc/lxc_wait.c @@ -68,7 +68,7 @@ static struct lxc_arguments my_args = { lxc-wait waits for NAME container state to reach STATE\n\ \n\ Options :\n\ - -n, --name=NAME NAME of the container\n\ + -n, --name=NAME NAME for name of the container\n\ -s, --state=STATE ORed states to wait for\n\ STOPPED, STARTING, RUNNING, STOPPING,\n\ ABORTING, FREEZING, FROZEN, THAWED\n\ diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 529163449..4918aabad 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -2906,15 +2906,12 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char if (ret < 0) goto out; + clear_unexp_config_line(c2->lxc_conf, "lxc.utsname", false); // update utsname - if (!(flags & LXC_CLONE_KEEPNAME)) { - clear_unexp_config_line(c2->lxc_conf, "lxc.utsname", false); - - if (!set_config_item_locked(c2, "lxc.utsname", newname)) { - ERROR("Error setting new hostname"); - goto out; - } + if (!set_config_item_locked(c2, "lxc.utsname", newname)) { + ERROR("Error setting new hostname"); + goto out; } // copy hooks