]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Refactor lxc-snapshot
authorChristian Brauner <christianvanbrauner@gmail.com>
Fri, 14 Aug 2015 18:14:01 +0000 (20:14 +0200)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 27 Aug 2015 20:13:46 +0000 (15:13 -0500)
- 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 <christianvanbrauner@gmail.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/arguments.h
src/lxc/lxc_snapshot.c

index cc85f863f5580400f26354e1e8967bcbe3c1cfd6..30aa06a21f974ea835b63ee24abd2ab802c41ad8 100644 (file)
@@ -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;
index a03c0c09bd97458c46c9f646168ac50d375c5d27..6bfb713645d66f600b87b6dd0e2920cffbe03b5c 100644 (file)
@@ -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 <stdio.h>
 #include <libgen.h>
 #include <unistd.h>
 
 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; i<n; i++) {
+
+       for (i = 0; i < n; i++) {
                printf("%s (%s) %s\n", s[i].name, s[i].lxcpath, s[i].timestamp);
                if (print_comments)
                        print_file(s[i].comment_pathname);
                s[i].free(&s[i]);
        }
-       free(s);
-       return 0;
-}
 
-static int do_restore_snapshots(struct lxc_container *c)
-{
-       if (c->snapshot_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);
 }
+