]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxc_destroy.c
ovl_rsync: make sure to umount
[mirror_lxc.git] / src / lxc / lxc_destroy.c
CommitLineData
60bf62d4
SH
1/*
2 *
3 * Copyright © 2013 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2013 Canonical Ltd.
5 *
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.
9 *
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.
14 *
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.
18 */
19
19712e04 20#define _GNU_SOURCE
948955a2 21#include <lxc/lxccontainer.h>
60bf62d4
SH
22
23#include <stdio.h>
24#include <libgen.h>
25#include <unistd.h>
26#include <sys/types.h>
27
f2363e38
ÇO
28#include "lxc.h"
29#include "log.h"
60bf62d4
SH
30#include "arguments.h"
31#include "utils.h"
32
6ea518f6 33lxc_log_define(lxc_destroy_ui, lxc);
60bf62d4 34
f29bb5d5 35static int my_parser(struct lxc_arguments* args, int c, char* arg);
60bf62d4
SH
36
37static const struct option my_longopts[] = {
38 {"force", no_argument, 0, 'f'},
f29bb5d5 39 {"snapshots", no_argument, 0, 's'},
60bf62d4
SH
40 LXC_COMMON_OPTIONS
41};
42
43static struct lxc_arguments my_args = {
44 .progname = "lxc-destroy",
45 .help = "\
46--name=NAME [-f] [-P lxcpath]\n\
47\n\
4c1f6b67 48lxc-destroy destroys a container with the identifier NAME\n\
60bf62d4
SH
49\n\
50Options :\n\
f29bb5d5
CB
51 -n, --name=NAME NAME of the container\n\
52 -s, --snapshots destroy including all snapshots\n\
60bf62d4
SH
53 -f, --force wait for the container to shut down\n",
54 .options = my_longopts,
55 .parser = my_parser,
56 .checker = NULL,
f29bb5d5 57 .task = DESTROY,
60bf62d4
SH
58};
59
f29bb5d5
CB
60static int do_destroy(struct lxc_container *c);
61static int do_destroy_with_snapshots(struct lxc_container *c);
62
60bf62d4
SH
63int main(int argc, char *argv[])
64{
65 struct lxc_container *c;
f29bb5d5 66 int ret;
60bf62d4 67
60bf62d4 68 if (lxc_arguments_parse(&my_args, argc, argv))
f29bb5d5 69 exit(EXIT_FAILURE);
60bf62d4 70
f5abd74d
SG
71 if (!my_args.log_file)
72 my_args.log_file = "none";
73
60bf62d4
SH
74 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
75 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
f29bb5d5 76 exit(EXIT_FAILURE);
6edbfc86 77 lxc_log_options_no_override();
60bf62d4
SH
78
79 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
80 if (!c) {
81 fprintf(stderr, "System error loading container\n");
f29bb5d5 82 exit(EXIT_FAILURE);
60bf62d4
SH
83 }
84
f5abd74d
SG
85 if (!c->may_control(c)) {
86 fprintf(stderr, "Insufficent privileges to control %s\n", my_args.name);
f3e52710 87 lxc_container_put(c);
f29bb5d5 88 exit(EXIT_FAILURE);
f5abd74d
SG
89 }
90
01e6b714
SH
91 if (!c->is_defined(c)) {
92 fprintf(stderr, "Container is not defined\n");
93 lxc_container_put(c);
f29bb5d5 94 exit(EXIT_FAILURE);
01e6b714
SH
95 }
96
60bf62d4
SH
97 if (c->is_running(c)) {
98 if (!my_args.force) {
99 fprintf(stderr, "%s is running\n", my_args.name);
01e6b714 100 lxc_container_put(c);
f29bb5d5 101 exit(EXIT_FAILURE);
60bf62d4
SH
102 }
103 c->stop(c);
104 }
105
f29bb5d5
CB
106 if (my_args.task == SNAP) {
107 ret = do_destroy_with_snapshots(c);
108 } else {
109 ret = do_destroy(c);
110 }
111
112 lxc_container_put(c);
113
114 if (ret == 0)
115 exit(EXIT_SUCCESS);
116 exit(EXIT_FAILURE);
117}
118
119static int my_parser(struct lxc_arguments *args, int c, char *arg)
120{
121 switch (c) {
122 case 'f': args->force = 1; break;
123 case 's': args->task = SNAP; break;
124 }
125 return 0;
126}
127
128static int do_destroy(struct lxc_container *c)
129{
93ea85c7
ÇO
130 if (!c->destroy(c)) {
131 fprintf(stderr, "Destroying %s failed\n", my_args.name);
f29bb5d5 132 return -1;
7909bb03
CB
133 }
134
f29bb5d5
CB
135 printf("Destroyed container %s\n", my_args.name);
136
137 return 0;
7909bb03 138}
f29bb5d5
CB
139
140static int do_destroy_with_snapshots(struct lxc_container *c)
141{
19712e04
CB
142 struct lxc_container *c1;
143 struct stat fbuf;
144 char path[MAXPATHLEN];
145 char *buf = NULL;
146 char *lxcpath = NULL;
147 char *lxcname = NULL;
148 char *scratch = NULL;
149 int fd;
150 int ret;
151 int counter = 0;
152
153 /* Destroy snapshots created with lxc-clone listed in lxc-snapshots. */
154 ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name);
155
156 fd = open(path, O_RDONLY | O_CLOEXEC);
c01859e8 157 if (fd >= 0) {
19712e04
CB
158 ret = fstat(fd, &fbuf);
159 if (ret < 0) {
160 close(fd);
161 return -1;
162 }
163
164 /* Make sure that the string is \0 terminated. */
165 buf = calloc(fbuf.st_size + 1, sizeof(char));
166 if (!buf) {
167 SYSERROR("failed to allocate memory");
168 close(fd);
169 free(buf);
170 return -1;
171 }
172
173 ret = read(fd, buf, fbuf.st_size);
174 if (ret < 0) {
175 ERROR("could not read %s", path);
176 close(fd);
177 free(buf);
178 return -1;
179 }
180 close(fd);
181
182 while ((lxcpath = strtok_r(!counter ? buf : NULL, "\n", &scratch))) {
183 if (!(lxcname = strtok_r(NULL, "\n", &scratch)))
184 break;
185 c1 = lxc_container_new(lxcname, lxcpath);
61111832
SH
186 if (!c1)
187 goto next;
19712e04
CB
188 if (!c1->destroy(c1)) {
189 fprintf(stderr, "Destroying snapshot %s of %s failed\n", lxcname, my_args.name);
190 lxc_container_put(c1);
191 free(buf);
192 return -1;
193 }
194 lxc_container_put(c1);
61111832 195next:
19712e04
CB
196 counter++;
197 }
198 free(buf);
199 }
200
201 /* Destroy snapshots located in the containers snap/ folder. */
202 ret = snprintf(path, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name);
203 if (ret < 0 || ret >= MAXPATHLEN)
f29bb5d5 204 return -1;
19712e04
CB
205 if (dir_exists(path)) {
206 if (!c->destroy_with_snapshots(c)) {
207 fprintf(stderr, "Destroying %s failed\n", my_args.name);
208 return -1;
209 }
210 } else {
211 if (!c->destroy(c)) {
212 fprintf(stderr, "Destroying %s failed\n", my_args.name);
213 return -1;
214 }
f29bb5d5
CB
215 }
216
19712e04 217 printf("Destroyed container %s including snapshots \n", my_args.name);
f29bb5d5
CB
218
219 return 0;
220}
221