]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_snapshot.c
3 * Copyright © 2013 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2013 Canonical Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <sys/types.h>
32 #include <lxc/lxccontainer.h>
34 #include "arguments.h"
38 lxc_log_define(lxc_snapshot
, lxc
);
40 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
);
42 static const struct option my_longopts
[] = {
43 {"list", no_argument
, 0, 'L'},
44 {"restore", required_argument
, 0, 'r'},
45 {"newname", required_argument
, 0, 'N'},
46 {"destroy", required_argument
, 0, 'd'},
47 {"comment", required_argument
, 0, 'c'},
48 {"showcomments", no_argument
, 0, 'C'},
52 static struct lxc_arguments my_args
= {
53 .progname
= "lxc-snapshot",
55 --name=NAME [-P lxcpath] [-L [-C]] [-c commentfile] [-r snapname [-N newname]]\n\
57 lxc-snapshot snapshots a container\n\
60 -n, --name=NAME NAME of the container\n\
61 -L, --list list all snapshots\n\
62 -r, --restore=NAME restore snapshot NAME, e.g. 'snap0'\n\
63 -N, --newname=NEWNAME NEWNAME for the restored container\n\
64 -d, --destroy=NAME destroy snapshot NAME, e.g. 'snap0'\n\
65 use ALL to destroy all snapshots\n\
66 -c, --comment=FILE add FILE as a comment\n\
67 -C, --showcomments show snapshot comments\n\
68 --rcfile=FILE Load configuration file FILE\n",
69 .options
= my_longopts
,
75 static int do_snapshot(struct lxc_container
*c
, char *commentfile
);
76 static int do_snapshot_destroy(struct lxc_container
*c
, char *snapname
);
77 static int do_snapshot_list(struct lxc_container
*c
, int print_comments
);
78 static int do_snapshot_restore(struct lxc_container
*c
,
79 struct lxc_arguments
*args
);
80 static int do_snapshot_task(struct lxc_container
*c
, enum task task
);
81 static void print_file(char *path
);
83 int main(int argc
, char *argv
[])
85 struct lxc_container
*c
;
89 if (lxc_arguments_parse(&my_args
, argc
, argv
))
92 /* Only create log if explicitly instructed */
93 if (my_args
.log_file
|| my_args
.log_priority
) {
94 log
.name
= my_args
.name
;
95 log
.file
= my_args
.log_file
;
96 log
.level
= my_args
.log_priority
;
97 log
.prefix
= my_args
.progname
;
98 log
.quiet
= my_args
.quiet
;
99 log
.lxcpath
= my_args
.lxcpath
[0];
101 if (lxc_log_init(&log
))
106 if (access(my_args
.lxcpath
[0], O_RDONLY
) < 0) {
107 ERROR("You lack access to %s", my_args
.lxcpath
[0]);
112 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
114 ERROR("System error loading container");
118 if (my_args
.rcfile
) {
121 if (!c
->load_config(c
, my_args
.rcfile
)) {
122 ERROR("Failed to load rcfile");
123 lxc_container_put(c
);
127 c
->configfile
= strdup(my_args
.rcfile
);
128 if (!c
->configfile
) {
129 ERROR("Out of memory setting new config filename");
130 lxc_container_put(c
);
136 ERROR("No container config specified");
137 lxc_container_put(c
);
141 if (!c
->may_control(c
)) {
142 ERROR("Insufficent privileges to control %s", my_args
.name
);
143 lxc_container_put(c
);
147 ret
= do_snapshot_task(c
, my_args
.task
);
149 lxc_container_put(c
);
157 static int do_snapshot_task(struct lxc_container
*c
, enum task task
)
163 ret
= do_snapshot_destroy(c
, my_args
.snapname
);
166 ret
= do_snapshot_list(c
, my_args
.print_comments
);
169 ret
= do_snapshot_restore(c
, &my_args
);
172 ret
= do_snapshot(c
, my_args
.commentfile
);
182 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
189 args
->task
= RESTORE
;
190 args
->snapname
= arg
;
196 args
->task
= DESTROY
;
197 args
->snapname
= arg
;
200 args
->commentfile
= arg
;
203 args
->print_comments
= 1;
210 static int do_snapshot(struct lxc_container
*c
, char *commentfile
)
214 ret
= c
->snapshot(c
, commentfile
);
216 ERROR("Error creating a snapshot");
223 static int do_snapshot_destroy(struct lxc_container
*c
, char *snapname
)
227 if (strncmp(snapname
, "ALL", strlen(snapname
)) == 0)
228 ret
= c
->snapshot_destroy_all(c
);
230 ret
= c
->snapshot_destroy(c
, snapname
);
233 ERROR("Error destroying snapshot %s", snapname
);
240 static int do_snapshot_list(struct lxc_container
*c
, int print_comments
)
242 struct lxc_snapshot
*s
;
245 n
= c
->snapshot_list(c
, &s
);
247 ERROR("Error listing snapshots");
252 printf("No snapshots\n");
256 for (i
= 0; i
< n
; i
++) {
257 printf("%s (%s) %s\n", s
[i
].name
, s
[i
].lxcpath
, s
[i
].timestamp
);
260 print_file(s
[i
].comment_pathname
);
270 static int do_snapshot_restore(struct lxc_container
*c
,
271 struct lxc_arguments
*args
)
275 /* When restoring a snapshot, the last optional argument if not given
276 * explicitly via the corresponding command line option is the name to
277 * use for the restored container. If no name is given, then the
278 * original container will be destroyed and the restored container will
280 if ((!args
->newname
) && (args
->argc
> 1)) {
281 ERROR("Too many arguments");
285 if ((!args
->newname
) && (args
->argc
== 1))
286 args
->newname
= args
->argv
[0];
288 bret
= c
->snapshot_restore(c
, args
->snapname
, args
->newname
);
290 ERROR("Error restoring snapshot %s", args
->snapname
);
297 static void print_file(char *path
)
306 f
= fopen(path
, "r");
310 while (getline(&line
, &sz
, f
) != -1)