From: Christian Brauner Date: Fri, 14 Aug 2015 18:14:01 +0000 (+0200) Subject: Refactor lxc-snapshot X-Git-Tag: lxc-2.0.0.beta1~184 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=513f23df5c0ebdb36954dc75d7bf293a7ec800aa;p=thirdparty%2Flxc.git Refactor lxc-snapshot - lxc_snapshot.c lacked necessary members in the associated lxc_arguments struct in arguments.h. This commit extends the lxc_arguments struct to include several parameters used by lxc-snapshot which allows a rewrite that is more consistent with the rest of the lxc-* executables. - All tests have been moved beyond the call to lxc_log_init() to allow for the messages to be printed or saved. - Some small changes to the my_args struct. (The enum task is set to SNAP (for snapshot) per default and variables illustrating the usage of the command line flags are written in all caps.) - arguments.h has been extended to accommodate a future rewrite of lxc-clone - Traditional behaviour of the executable has been retained in this commit. Signed-off-by: Christian Brauner Acked-by: Serge E. Hallyn --- diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index cc85f863f..30aa06a21 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -94,6 +94,22 @@ 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_snapshot.c b/src/lxc/lxc_snapshot.c index a03c0c09b..6bfb71364 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,18 +35,148 @@ lxc_log_define(lxc_snapshot_ui, lxc); -static char *newname; -static char *snapshot; +static int my_parser(struct lxc_arguments *args, int c, char *arg); -#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; +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_snapshot(struct lxc_container *c, char *commentfile); +static int do_snapshot_destroy(struct lxc_container *c, char *snapname); +static int do_snapshot_list(struct lxc_container *c, int print_comments); +static int do_snapshot_restore(struct lxc_container *c, + struct lxc_arguments *args); +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); + } + + ret = do_snapshot_task(c, my_args.task); -static int do_snapshot(struct lxc_container *c) + 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_snapshot_destroy(c, my_args.snapname); + break; + case LIST: + ret = do_snapshot_list(c, my_args.print_comments); + break; + case RESTORE: + ret = do_snapshot_restore(c, &my_args); + 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) { int ret; @@ -57,26 +187,28 @@ static int do_snapshot(struct lxc_container *c) } INFO("Created snapshot snap%d", ret); + return 0; } -static void print_file(char *path) +static int do_snapshot_destroy(struct lxc_container *c, char *snapname) { - 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); + bool ret; + + if (strcmp(snapname, "ALL") == 0) + ret = c->snapshot_destroy_all(c); + else + ret = c->snapshot_destroy(c, snapname); + + if (!ret) { + ERROR("Error destroying snapshot %s", snapname); + return -1; } - free(line); - fclose(f); + + return 0; } -static int do_list_snapshots(struct lxc_container *c) +static int do_snapshot_list(struct lxc_container *c, int print_comments) { struct lxc_snapshot *s; int i, n; @@ -90,148 +222,63 @@ static int do_list_snapshots(struct lxc_container *c) printf("No snapshots\n"); return 0; } - for (i=0; isnapshot_restore(c, snapshot, newname)) - return 0; + free(s); - ERROR("Error restoring snapshot %s", snapshot); - return -1; + return 0; } -static int do_destroy_snapshots(struct lxc_container *c) +static int do_snapshot_restore(struct lxc_container *c, + struct lxc_arguments *args) { - bool bret; - if (strcmp(snapshot, "ALL") == 0) - bret = c->snapshot_destroy_all(c); - else - bret = c->snapshot_destroy(c, snapshot); + int bret; + + /* When restoring a snapshot, the last optional argument if not given + * explicitly via the corresponding command line option is the name to + * use for the restored container. If no name is given, then the + * original container will be destroyed and the restored container will + * take its place. */ + if ((!args->newname) && (args->argc > 1)) { + lxc_error(args, "Too many arguments"); + return -1; + } - if (bret) - return 0; + if ((!args->newname) && (args->argc == 1)) + args->newname = args->argv[0]; - ERROR("Error destroying snapshot %s", snapshot); - return -1; -} - -static int my_parser(struct lxc_arguments* args, int c, char* arg) -{ - 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; + bret = c->snapshot_restore(c, args->snapname, args->newname); + if (!bret) { + ERROR("Error restoring snapshot %s", args->snapname); + return -1; } + return 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 -}; - - -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[]) +static void print_file(char *path) { - 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]; - - 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); - } - } + if (!path) + return; - c = lxc_container_new(my_args.name, my_args.lxcpath[0]); - if (!c) { - fprintf(stderr, "System error loading container\n"); - exit(1); - } + FILE *f = fopen(path, "r"); + char *line = NULL; + size_t sz = 0; - if (!c->may_control(c)) { - fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name); - lxc_container_put(c); - exit(1); - } + if (!f) + return; - 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; + while (getline(&line, &sz, f) != -1) { + printf("%s", line); } - lxc_container_put(c); - - if (ret == 0) - exit(EXIT_SUCCESS); - exit(EXIT_FAILURE); + free(line); + fclose(f); } +