]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_destroy.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.
21 #include <lxc/lxccontainer.h>
26 #include <sys/types.h>
30 #include "arguments.h"
33 lxc_log_define(lxc_destroy_ui
, lxc
);
35 static int my_parser(struct lxc_arguments
* args
, int c
, char* arg
);
38 static const struct option my_longopts
[] = {
39 {"force", no_argument
, 0, 'f'},
40 {"snapshots", no_argument
, 0, 's'},
44 static struct lxc_arguments my_args
= {
45 .progname
= "lxc-destroy",
47 --name=NAME [-f] [-P lxcpath]\n\
49 lxc-destroy destroys a container with the identifier NAME\n\
52 -n, --name=NAME NAME of the container\n\
53 -s, --snapshots destroy including all snapshots\n\
54 -f, --force wait for the container to shut down\n",
55 .options
= my_longopts
,
61 static bool do_destroy(struct lxc_container
*c
);
62 static bool do_destroy_with_snapshots(struct lxc_container
*c
);
64 int main(int argc
, char *argv
[])
66 struct lxc_container
*c
;
69 if (lxc_arguments_parse(&my_args
, argc
, argv
))
72 if (!my_args
.log_file
)
73 my_args
.log_file
= "none";
75 if (lxc_log_init(my_args
.name
, my_args
.log_file
, my_args
.log_priority
,
76 my_args
.progname
, my_args
.quiet
, my_args
.lxcpath
[0]))
78 lxc_log_options_no_override();
82 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
85 fprintf(stderr
, "System error loading container\n");
89 if (!c
->may_control(c
)) {
91 fprintf(stderr
, "Insufficent privileges to control %s\n", my_args
.name
);
96 if (!c
->is_defined(c
)) {
98 fprintf(stderr
, "Container is not defined\n");
103 if (my_args
.task
== SNAP
) {
104 bret
= do_destroy_with_snapshots(c
);
106 printf("Destroyed container %s including snapshots \n", my_args
.name
);
108 bret
= do_destroy(c
);
110 printf("Destroyed container %s\n", my_args
.name
);
113 lxc_container_put(c
);
120 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
123 case 'f': args
->force
= 1; break;
124 case 's': args
->task
= SNAP
; break;
129 static bool do_destroy(struct lxc_container
*c
)
132 char path
[MAXPATHLEN
];
134 /* First check whether the container has dependent clones or snapshots. */
135 int ret
= snprintf(path
, MAXPATHLEN
, "%s/%s/lxc_snapshots", c
->config_path
, c
->name
);
136 if (ret
< 0 || ret
>= MAXPATHLEN
)
139 if (file_exists(path
)) {
141 fprintf(stdout
, "Destroying %s failed: %s has clones.\n", c
->name
, c
->name
);
145 ret
= snprintf(path
, MAXPATHLEN
, "%s/%s/snaps", c
->config_path
, c
->name
);
146 if (ret
< 0 || ret
>= MAXPATHLEN
)
149 if (dir_exists(path
)) {
151 fprintf(stdout
, "Destroying %s failed: %s has snapshots.\n", c
->name
, c
->name
);
155 if (c
->is_running(c
)) {
156 if (!my_args
.force
&& !quiet
) {
157 fprintf(stderr
, "%s is running\n", my_args
.name
);
160 /* If the container was ephemeral it will be removed on shutdown. */
164 /* If the container was ephemeral we have already removed it when we
166 if (c
->is_defined(c
) && !c
->lxc_conf
->ephemeral
)
167 bret
= c
->destroy(c
);
171 fprintf(stderr
, "Destroying %s failed\n", my_args
.name
);
178 static bool do_destroy_with_snapshots(struct lxc_container
*c
)
180 struct lxc_container
*c1
;
183 char path
[MAXPATHLEN
];
185 char *lxcpath
= NULL
;
186 char *lxcname
= NULL
;
187 char *scratch
= NULL
;
192 /* Destroy clones. */
193 ret
= snprintf(path
, MAXPATHLEN
, "%s/%s/lxc_snapshots", c
->config_path
, c
->name
);
194 if (ret
< 0 || ret
>= MAXPATHLEN
)
197 fd
= open(path
, O_RDONLY
| O_CLOEXEC
);
199 ret
= fstat(fd
, &fbuf
);
205 /* Make sure that the string is \0 terminated. */
206 buf
= calloc(fbuf
.st_size
+ 1, sizeof(char));
208 SYSERROR("failed to allocate memory");
213 ret
= read(fd
, buf
, fbuf
.st_size
);
215 ERROR("could not read %s", path
);
222 while ((lxcpath
= strtok_r(!counter
? buf
: NULL
, "\n", &scratch
))) {
223 if (!(lxcname
= strtok_r(NULL
, "\n", &scratch
)))
225 c1
= lxc_container_new(lxcname
, lxcpath
);
230 /* We do not destroy recursively. If a clone of a clone
231 * has clones or snapshots the user should remove it
233 if (!do_destroy(c1
)) {
234 lxc_container_put(c1
);
238 lxc_container_put(c1
);
244 /* Destroy snapshots located in the containers snap/ folder. */
245 ret
= snprintf(path
, MAXPATHLEN
, "%s/%s/snaps", c
->config_path
, c
->name
);
246 if (ret
< 0 || ret
>= MAXPATHLEN
)
249 if (dir_exists(path
))
250 bret
= c
->destroy_with_snapshots(c
);
252 bret
= do_destroy(c
);
255 printf("Destroyed container %s including snapshots \n", my_args
.name
);