]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_stop.c
Fix grammar in some of the executables
[mirror_lxc.git] / src / lxc / lxc_stop.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23 #include <stdio.h>
24 #include <libgen.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27
28 #include <lxc/lxccontainer.h>
29
30 #include "lxc.h"
31 #include "log.h"
32 #include "arguments.h"
33 #include "commands.h"
34 #include "utils.h"
35
36 #define OPT_NO_LOCK OPT_USAGE+1
37 #define OPT_NO_KILL OPT_USAGE+2
38
39 lxc_log_define(lxc_stop_ui, lxc);
40
41 static int my_parser(struct lxc_arguments* args, int c, char* arg)
42 {
43 switch (c) {
44 case 'r': args->reboot = 1; break;
45 case 'W': args->nowait = 1; break;
46 case 't': args->timeout = atoi(arg); break;
47 case 'k': args->hardstop = 1; break;
48 case OPT_NO_LOCK: args->nolock = 1; break;
49 case OPT_NO_KILL: args->nokill = 1; break;
50 }
51 return 0;
52 }
53
54 static const struct option my_longopts[] = {
55 {"reboot", no_argument, 0, 'r'},
56 {"nowait", no_argument, 0, 'W'},
57 {"timeout", required_argument, 0, 't'},
58 {"kill", no_argument, 0, 'k'},
59 {"nokill", no_argument, 0, OPT_NO_KILL},
60 {"nolock", no_argument, 0, OPT_NO_LOCK},
61 LXC_COMMON_OPTIONS
62 };
63
64 static struct lxc_arguments my_args = {
65 .progname = "lxc-stop",
66 .help = "\
67 --name=NAME\n\
68 \n\
69 lxc-stop stops a container with the identifier NAME\n\
70 \n\
71 Options :\n\
72 -n, --name=NAME NAME of the container\n\
73 -r, --reboot reboot the container\n\
74 -W, --nowait don't wait for shutdown or reboot to complete\n\
75 -t, --timeout=T wait T seconds before hard-stopping\n\
76 -k, --kill kill container rather than request clean shutdown\n\
77 --nolock Avoid using API locks\n\
78 --nokill Only request clean shutdown, don't force kill after timeout\n",
79 .options = my_longopts,
80 .parser = my_parser,
81 .checker = NULL,
82 .timeout = -2,
83 };
84
85 /* returns -1 on failure, 0 on success */
86 static int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c)
87 {
88 int ret;
89 pid_t pid;
90 pid_t newpid;
91 int timeout = a->timeout;
92
93 pid = c->init_pid(c);
94 if (pid == -1)
95 return -1;
96 if (!c->reboot(c))
97 return -1;
98 if (a->nowait)
99 return 0;
100 if (timeout == 0)
101 goto out;
102
103 for (;;) {
104 /* can we use c-> wait for this, assuming it will
105 * re-enter RUNNING? For now just sleep */
106 int elapsed_time, curtime = 0;
107 struct timeval tv;
108
109 newpid = c->init_pid(c);
110 if (newpid != -1 && newpid != pid)
111 return 0;
112
113 if (timeout != -1) {
114 ret = gettimeofday(&tv, NULL);
115 if (ret)
116 break;
117 curtime = tv.tv_sec;
118 }
119
120 sleep(1);
121 if (timeout != -1) {
122 ret = gettimeofday(&tv, NULL);
123 if (ret)
124 break;
125 elapsed_time = tv.tv_sec - curtime;
126 if (timeout - elapsed_time <= 0)
127 break;
128 timeout -= elapsed_time;
129 }
130 }
131
132 out:
133 newpid = c->init_pid(c);
134 if (newpid == -1 || newpid == pid) {
135 printf("Reboot did not complete before timeout\n");
136 return -1;
137 }
138 return 0;
139 }
140
141 int main(int argc, char *argv[])
142 {
143 struct lxc_container *c;
144 bool s;
145 int ret = 1;
146
147 if (lxc_arguments_parse(&my_args, argc, argv))
148 return 1;
149
150 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
151 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
152 return 1;
153 lxc_log_options_no_override();
154
155 /* Set default timeout */
156 if (my_args.timeout == -2) {
157 if (my_args.hardstop) {
158 my_args.timeout = 0;
159 }
160 else {
161 my_args.timeout = 60;
162 }
163 }
164
165 if (my_args.nowait) {
166 my_args.timeout = 0;
167 }
168
169 /* some checks */
170 if (!my_args.hardstop && my_args.timeout < -1) {
171 fprintf(stderr, "invalid timeout\n");
172 return 1;
173 }
174
175 if (my_args.hardstop && my_args.nokill) {
176 fprintf(stderr, "-k can't be used with --nokill\n");
177 return 1;
178 }
179
180 if (my_args.hardstop && my_args.reboot) {
181 fprintf(stderr, "-k can't be used with -r\n");
182 return 1;
183 }
184
185 if (my_args.hardstop && my_args.timeout) {
186 fprintf(stderr, "-k doesn't allow timeouts\n");
187 return 1;
188 }
189
190 if (my_args.nolock && !my_args.hardstop) {
191 fprintf(stderr, "--nolock may only be used with -k\n");
192 return 1;
193 }
194
195 /* shortcut - if locking is bogus, we should be able to kill
196 * containers at least */
197 if (my_args.nolock)
198 return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
199
200 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
201 if (!c) {
202 fprintf(stderr, "Error opening container\n");
203 goto out;
204 }
205
206 if (!c->may_control(c)) {
207 fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
208 goto out;
209 }
210
211 if (!c->is_running(c)) {
212 fprintf(stderr, "%s is not running\n", c->name);
213 ret = 2;
214 goto out;
215 }
216
217 /* kill */
218 if (my_args.hardstop) {
219 ret = c->stop(c) ? 0 : 1;
220 goto out;
221 }
222
223 /* reboot */
224 if (my_args.reboot) {
225 ret = do_reboot_and_check(&my_args, c);
226 goto out;
227 }
228
229 /* shutdown */
230 s = c->shutdown(c, my_args.timeout);
231 if (!s) {
232 if (my_args.timeout == 0)
233 ret = 0;
234 else if (my_args.nokill)
235 ret = 1;
236 else
237 ret = c->stop(c) ? 0 : 1;
238 } else
239 ret = 0;
240
241 out:
242 lxc_container_put(c);
243 if (ret < 0)
244 return 1;
245 return ret;
246 }