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;
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\
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\
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <lxc/lxccontainer.h>
#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);
}
-
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,
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;
}
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\
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
};
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);
}
-
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,
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,
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,
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\
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"
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 = ".*",
* 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 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;
}
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;
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, char *snapname,
- char *newname)
+static int do_restore_snapshots(struct lxc_container *c)
{
- if (!newname) {
- printf("Error: You must provide a NEWNAME for the container\n");
- return -1;
- }
-
- if (c->snapshot_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);
+}
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\
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\
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,
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\
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