mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-14 17:12:14 +00:00
Revert "Refactor lxc-snapshot, lxc-clone, make LXC_CLONE_KEEPNAME work and add option to destroy container with all snapshots to lxc-destroy"
This commit is contained in:
parent
f69d74e359
commit
965ef7f460
@ -94,22 +94,6 @@ struct lxc_arguments {
|
|||||||
int list;
|
int list;
|
||||||
char *groups;
|
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 */
|
/* remaining arguments */
|
||||||
char *const *argv;
|
char *const *argv;
|
||||||
int argc;
|
int argc;
|
||||||
|
@ -146,7 +146,7 @@ static struct lxc_arguments my_args = {
|
|||||||
Execute the specified COMMAND - enter the container NAME\n\
|
Execute the specified COMMAND - enter the container NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-e, --elevated-privileges=PRIVILEGES\n\
|
||||||
Use elevated privileges instead of those of the\n\
|
Use elevated privileges instead of those of the\n\
|
||||||
container. If you don't specify privileges to be\n\
|
container. If you don't specify privileges to be\n\
|
||||||
|
@ -105,7 +105,7 @@ lxc-checkpoint checkpoints and restores a container\n\
|
|||||||
its running state at a later time.\n\
|
its running state at a later time.\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-r, --restore Restore container\n\
|
||||||
-D, --checkpoint-dir=DIR directory to save the checkpoint in\n\
|
-D, --checkpoint-dir=DIR directory to save the checkpoint in\n\
|
||||||
-v, --verbose Enable verbose criu logs\n\
|
-v, --verbose Enable verbose criu logs\n\
|
||||||
|
@ -27,198 +27,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <lxc/lxccontainer.h>
|
#include <lxc/lxccontainer.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "confile.h"
|
#include "config.h"
|
||||||
#include "arguments.h"
|
|
||||||
#include "lxc.h"
|
#include "lxc.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
|
|
||||||
lxc_log_define(lxc_clone_ui, lxc);
|
lxc_log_define(lxc_clone_ui, lxc);
|
||||||
|
|
||||||
static int my_parser(struct lxc_arguments *args, int c, char *arg);
|
|
||||||
|
|
||||||
static const struct option my_longopts[] = {
|
|
||||||
{ "newname", required_argument, 0, 'N'},
|
|
||||||
{ "newpath", required_argument, 0, 'p'},
|
|
||||||
{ "rename", no_argument, 0, 'R'},
|
|
||||||
{ "snapshot", no_argument, 0, 's'},
|
|
||||||
{ "backingstore", required_argument, 0, 'B'},
|
|
||||||
{ "fssize", required_argument, 0, 'L'},
|
|
||||||
{ "keepname", no_argument, 0, 'K'},
|
|
||||||
{ "keepmac", no_argument, 0, 'M'},
|
|
||||||
LXC_COMMON_OPTIONS
|
|
||||||
};
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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 (!my_args.newname) {
|
|
||||||
printf("Error: You must provide a NEWNAME for the clone.\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (!c->is_defined(c)) {
|
|
||||||
fprintf(stderr, "Error: container %s is not defined\n",
|
|
||||||
c->name);
|
|
||||||
lxc_container_put(c);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
clone = c->clone(c, newname, newpath, flags, bdevtype, NULL, fssize,
|
|
||||||
args);
|
|
||||||
if (clone == NULL) {
|
|
||||||
fprintf(stderr, "clone failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
/* we pass fssize in bytes */
|
||||||
static uint64_t get_fssize(char *s)
|
static uint64_t get_fssize(char *s)
|
||||||
{
|
{
|
||||||
@ -226,29 +45,171 @@ static uint64_t get_fssize(char *s)
|
|||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
ret = strtoull(s, &end, 0);
|
ret = strtoull(s, &end, 0);
|
||||||
if (end == s) {
|
if (end == s)
|
||||||
|
{
|
||||||
fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s);
|
fprintf(stderr, "Invalid blockdev size '%s', using default size\n", s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (isblank(*end))
|
while (isblank(*end))
|
||||||
end++;
|
end++;
|
||||||
if (*end == '\0') {
|
if (*end == '\0')
|
||||||
ret *= 1024ULL * 1024ULL; // MB by default
|
ret *= 1024ULL * 1024ULL; // MB by default
|
||||||
} else if (*end == 'b' || *end == 'B') {
|
else if (*end == 'b' || *end == 'B')
|
||||||
ret *= 1ULL;
|
ret *= 1ULL;
|
||||||
} else if (*end == 'k' || *end == 'K') {
|
else if (*end == 'k' || *end == 'K')
|
||||||
ret *= 1024ULL;
|
ret *= 1024ULL;
|
||||||
} else if (*end == 'm' || *end == 'M') {
|
else if (*end == 'm' || *end == 'M')
|
||||||
ret *= 1024ULL * 1024ULL;
|
ret *= 1024ULL * 1024ULL;
|
||||||
} else if (*end == 'g' || *end == 'G') {
|
else if (*end == 'g' || *end == 'G')
|
||||||
ret *= 1024ULL * 1024ULL * 1024ULL;
|
ret *= 1024ULL * 1024ULL * 1024ULL;
|
||||||
} else if (*end == 't' || *end == 'T') {
|
else if (*end == 't' || *end == 'T')
|
||||||
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||||
} else {
|
else
|
||||||
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', " "using default size\n", *end, s);
|
{
|
||||||
|
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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'},
|
||||||
|
{ "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'},
|
||||||
|
{ "lxcpath", required_argument, 0, 'p'},
|
||||||
|
{ "newpath", required_argument, 0, 'P'},
|
||||||
|
{ "fstype", required_argument, 0, 't'},
|
||||||
|
{ "help", no_argument, 0, 'h'},
|
||||||
|
{ 0, 0, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
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 (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 (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 (snapshot) flags |= LXC_CLONE_SNAPSHOT;
|
||||||
|
if (keepname) flags |= LXC_CLONE_KEEPNAME;
|
||||||
|
if (keepmac) flags |= LXC_CLONE_KEEPMACADDR;
|
||||||
|
|
||||||
|
// 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 (fstype) {
|
||||||
|
printf("Error: fstype not supported\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
c1 = lxc_container_new(orig, lxcpath);
|
||||||
|
if (!c1)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
|
if (!c1->may_control(c1)) {
|
||||||
|
fprintf(stderr, "Insufficent privileges to control %s\n", orig);
|
||||||
|
lxc_container_put(c1);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c1->is_defined(c1)) {
|
||||||
|
fprintf(stderr, "Error: container %s is not defined\n", orig);
|
||||||
|
lxc_container_put(c1);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
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);
|
||||||
|
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
@ -78,7 +78,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-console logs on the container with the identifier NAME\n\
|
lxc-console logs on the container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-t, --tty=NUMBER console tty number\n\
|
||||||
-e, --escape=PREFIX prefix for escape command\n",
|
-e, --escape=PREFIX prefix for escape command\n",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
|
@ -61,7 +61,7 @@ static uint64_t get_fssize(char *s)
|
|||||||
else if (*end == 't' || *end == 'T')
|
else if (*end == 't' || *end == 'T')
|
||||||
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s);
|
fprintf(stderr, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-create creates a container\n\
|
lxc-create creates a container\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-f, --config=file Initial configuration file\n\
|
||||||
-t, --template=t Template to use to setup container\n\
|
-t, --template=t Template to use to setup container\n\
|
||||||
-B, --bdev=BDEV Backing store type to use\n\
|
-B, --bdev=BDEV Backing store type to use\n\
|
||||||
|
@ -31,11 +31,16 @@
|
|||||||
|
|
||||||
lxc_log_define(lxc_destroy_ui, lxc);
|
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[] = {
|
static const struct option my_longopts[] = {
|
||||||
{"force", no_argument, 0, 'f'},
|
{"force", no_argument, 0, 'f'},
|
||||||
{"snapshots", no_argument, 0, 's'},
|
|
||||||
LXC_COMMON_OPTIONS
|
LXC_COMMON_OPTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,104 +52,61 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-destroy destroys a container with the identifier NAME\n\
|
lxc-destroy destroys a container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\n\
|
Options :\n\
|
||||||
-n, --name=NAME NAME of the container\n\
|
-n, --name=NAME NAME for name of the container\n\
|
||||||
-s, --snapshots destroy including all snapshots\n\
|
|
||||||
-f, --force wait for the container to shut down\n",
|
-f, --force wait for the container to shut down\n",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
.parser = my_parser,
|
.parser = my_parser,
|
||||||
.checker = NULL,
|
.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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct lxc_container *c;
|
struct lxc_container *c;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (lxc_arguments_parse(&my_args, argc, argv))
|
if (lxc_arguments_parse(&my_args, argc, argv))
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
|
|
||||||
if (!my_args.log_file)
|
if (!my_args.log_file)
|
||||||
my_args.log_file = "none";
|
my_args.log_file = "none";
|
||||||
|
|
||||||
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
|
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]))
|
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
lxc_log_options_no_override();
|
lxc_log_options_no_override();
|
||||||
|
|
||||||
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
|
c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "System error loading container\n");
|
fprintf(stderr, "System error loading container\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->may_control(c)) {
|
if (!c->may_control(c)) {
|
||||||
fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
|
fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c->is_defined(c)) {
|
if (!c->is_defined(c)) {
|
||||||
fprintf(stderr, "Container is not defined\n");
|
fprintf(stderr, "Container is not defined\n");
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->is_running(c)) {
|
if (c->is_running(c)) {
|
||||||
if (!my_args.force) {
|
if (!my_args.force) {
|
||||||
fprintf(stderr, "%s is running\n", my_args.name);
|
fprintf(stderr, "%s is running\n", my_args.name);
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
exit(EXIT_FAILURE);
|
exit(1);
|
||||||
}
|
}
|
||||||
c->stop(c);
|
c->stop(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (my_args.task == SNAP) {
|
if (!c->destroy(c)) {
|
||||||
ret = do_destroy_with_snapshots(c);
|
fprintf(stderr, "Destroying %s failed\n", my_args.name);
|
||||||
} else {
|
lxc_container_put(c);
|
||||||
ret = do_destroy(c);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
|
exit(0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Destroyed container including snapshots %s\n", my_args.name);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-device attach or detach DEV to or from container.\n\
|
lxc-device attach or detach DEV to or from container.\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\n\
|
Options :\n\
|
||||||
-n, --name=NAME NAME of the container",
|
-n, --name=NAME NAME for name of the container",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
.parser = NULL,
|
.parser = NULL,
|
||||||
.checker = NULL,
|
.checker = NULL,
|
||||||
|
@ -79,7 +79,7 @@ lxc-execute creates a container with the identifier NAME\n\
|
|||||||
and execs COMMAND into this container.\n\
|
and execs COMMAND into this container.\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-f, --rcfile=FILE Load configuration file FILE\n\
|
||||||
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n",
|
-s, --define KEY=VAL Assign VAL to configuration variable KEY\n",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
|
@ -47,7 +47,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-freeze freezes a container with the identifier NAME\n\
|
lxc-freeze freezes a container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\n\
|
Options :\n\
|
||||||
-n, --name=NAME NAME of the container",
|
-n, --name=NAME NAME for name of the container",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
.parser = NULL,
|
.parser = NULL,
|
||||||
.checker = NULL,
|
.checker = NULL,
|
||||||
|
@ -87,7 +87,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-info display some information about a container with the identifier NAME\n\
|
lxc-info display some information about a container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-c, --config=KEY show configuration variable KEY from running container\n\
|
||||||
-i, --ips shows the IP addresses\n\
|
-i, --ips shows the IP addresses\n\
|
||||||
-p, --pid shows the process id of the init container\n\
|
-p, --pid shows the process id of the init container\n\
|
||||||
|
@ -61,7 +61,7 @@ static void interrupt_handler(int sig)
|
|||||||
static void usage(void) {
|
static void usage(void) {
|
||||||
fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n"
|
fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n"
|
||||||
"Common options :\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"
|
" -l, --logpriority=LEVEL Set log priority to LEVEL\n"
|
||||||
" -q, --quiet Don't produce any output\n"
|
" -q, --quiet Don't produce any output\n"
|
||||||
" -P, --lxcpath=PATH Use specified container path\n"
|
" -P, --lxcpath=PATH Use specified container path\n"
|
||||||
|
@ -61,7 +61,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-monitor monitors the state of the NAME container\n\
|
lxc-monitor monitors the state of the NAME container\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
NAME may be a regular expression\n\
|
||||||
-Q, --quit tell lxc-monitord to quit\n",
|
-Q, --quit tell lxc-monitord to quit\n",
|
||||||
.name = ".*",
|
.name = ".*",
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include "confile.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -35,149 +35,18 @@
|
|||||||
|
|
||||||
lxc_log_define(lxc_snapshot_ui, lxc);
|
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[] = {
|
#define DO_SNAP 0
|
||||||
{"list", no_argument, 0, 'L'},
|
#define DO_LIST 1
|
||||||
{"restore", required_argument, 0, 'r'},
|
#define DO_RESTORE 2
|
||||||
{"newname", required_argument, 0, 'N'},
|
#define DO_DESTROY 3
|
||||||
{"destroy", required_argument, 0, 'd'},
|
static int action;
|
||||||
{"comment", required_argument, 0, 'c'},
|
static int print_comments;
|
||||||
{"showcomments", no_argument, 0, 'C'},
|
static char *commentfile;
|
||||||
LXC_COMMON_OPTIONS
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct lxc_arguments my_args = {
|
static int do_snapshot(struct lxc_container *c)
|
||||||
.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -188,11 +57,26 @@ static int do_snapshot(struct lxc_container *c, char *commentfile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
INFO("Created snapshot snap%d", ret);
|
INFO("Created snapshot snap%d", ret);
|
||||||
|
|
||||||
return 0;
|
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;
|
struct lxc_snapshot *s;
|
||||||
int i, n;
|
int i, n;
|
||||||
@ -206,69 +90,148 @@ static int do_list_snapshots(struct lxc_container *c, int print_comments)
|
|||||||
printf("No snapshots\n");
|
printf("No snapshots\n");
|
||||||
return 0;
|
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);
|
printf("%s (%s) %s\n", s[i].name, s[i].lxcpath, s[i].timestamp);
|
||||||
if (print_comments)
|
if (print_comments)
|
||||||
print_file(s[i].comment_pathname);
|
print_file(s[i].comment_pathname);
|
||||||
s[i].free(&s[i]);
|
s[i].free(&s[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_restore_snapshots(struct lxc_container *c, char *snapname,
|
static int do_restore_snapshots(struct lxc_container *c)
|
||||||
char *newname)
|
|
||||||
{
|
{
|
||||||
if (!newname) {
|
if (c->snapshot_restore(c, snapshot, newname))
|
||||||
printf("Error: You must provide a NEWNAME for the container\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->snapshot_restore(c, snapname, newname))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ERROR("Error restoring snapshot %s", snapname);
|
ERROR("Error restoring snapshot %s", snapshot);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_destroy_snapshots(struct lxc_container *c, char *snapname)
|
static int do_destroy_snapshots(struct lxc_container *c)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool bret;
|
||||||
|
if (strcmp(snapshot, "ALL") == 0)
|
||||||
if (strcmp(snapname, "ALL") == 0)
|
bret = c->snapshot_destroy_all(c);
|
||||||
ret = c->snapshot_destroy_all(c);
|
|
||||||
else
|
else
|
||||||
ret = c->snapshot_destroy(c, snapname);
|
bret = c->snapshot_destroy(c, snapshot);
|
||||||
|
|
||||||
if (ret)
|
if (bret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ERROR("Error destroying snapshot %s", snapname);
|
ERROR("Error destroying snapshot %s", snapshot);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_file(char *path)
|
static int my_parser(struct lxc_arguments* args, int c, char* arg)
|
||||||
{
|
{
|
||||||
if (!path)
|
switch (c) {
|
||||||
return;
|
case 'L': action = DO_LIST; break;
|
||||||
|
case 'r': snapshot = arg; action = DO_RESTORE; break;
|
||||||
FILE *f = fopen(path, "r");
|
case 'd': snapshot = arg; action = DO_DESTROY; break;
|
||||||
char *line = NULL;
|
case 'c': commentfile = arg; break;
|
||||||
size_t sz = 0;
|
case 'C': print_comments = true; break;
|
||||||
|
|
||||||
if (!f)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (getline(&line, &sz, f) != -1) {
|
|
||||||
printf("%s", line);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
free(line);
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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[])
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
@ -181,7 +181,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-start start COMMAND in specified container NAME\n\
|
lxc-start start COMMAND in specified container NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-d, --daemon Daemonize the container (default)\n\
|
||||||
-F, --foreground Start with the current tty attached to /dev/console\n\
|
-F, --foreground Start with the current tty attached to /dev/console\n\
|
||||||
-p, --pidfile=FILE Create a file with the process id\n\
|
-p, --pidfile=FILE Create a file with the process id\n\
|
||||||
|
@ -69,7 +69,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-stop stops a container with the identifier NAME\n\
|
lxc-stop stops a container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-r, --reboot reboot the container\n\
|
||||||
-W, --nowait don't wait for shutdown or reboot to complete\n\
|
-W, --nowait don't wait for shutdown or reboot to complete\n\
|
||||||
-t, --timeout=T wait T seconds before hard-stopping\n\
|
-t, --timeout=T wait T seconds before hard-stopping\n\
|
||||||
|
@ -45,7 +45,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-unfreeze unfreezes a container with the identifier NAME\n\
|
lxc-unfreeze unfreezes a container with the identifier NAME\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\n\
|
Options :\n\
|
||||||
-n, --name=NAME NAME of the container\n",
|
-n, --name=NAME NAME for name of the container\n",
|
||||||
.options = my_longopts,
|
.options = my_longopts,
|
||||||
.parser = NULL,
|
.parser = NULL,
|
||||||
.checker = NULL,
|
.checker = NULL,
|
||||||
|
@ -68,7 +68,7 @@ static struct lxc_arguments my_args = {
|
|||||||
lxc-wait waits for NAME container state to reach STATE\n\
|
lxc-wait waits for NAME container state to reach STATE\n\
|
||||||
\n\
|
\n\
|
||||||
Options :\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\
|
-s, --state=STATE ORed states to wait for\n\
|
||||||
STOPPED, STARTING, RUNNING, STOPPING,\n\
|
STOPPED, STARTING, RUNNING, STOPPING,\n\
|
||||||
ABORTING, FREEZING, FROZEN, THAWED\n\
|
ABORTING, FREEZING, FROZEN, THAWED\n\
|
||||||
|
@ -2906,15 +2906,12 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
clear_unexp_config_line(c2->lxc_conf, "lxc.utsname", false);
|
||||||
|
|
||||||
// update utsname
|
// update utsname
|
||||||
if (!(flags & LXC_CLONE_KEEPNAME)) {
|
if (!set_config_item_locked(c2, "lxc.utsname", newname)) {
|
||||||
clear_unexp_config_line(c2->lxc_conf, "lxc.utsname", false);
|
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
|
// copy hooks
|
||||||
|
Loading…
Reference in New Issue
Block a user