]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_stop.c
lxc-stop: don't set timeout if user requested -s
[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/lxc.h>
29 #include <lxc/log.h>
30
31 #include <lxc/lxccontainer.h>
32 #include "arguments.h"
33 #include "commands.h"
34 #include "utils.h"
35
36 #define OPT_NO_LOCK OPT_USAGE+1
37
38 static int my_parser(struct lxc_arguments* args, int c, char* arg)
39 {
40 switch (c) {
41 case 'r': args->reboot = 1; break;
42 case 'W': args->nowait = 1; break;
43 case 't': args->timeout = atoi(arg); break;
44 case 'k': args->hardstop = 1; break;
45 case 's': args->shutdown = 1; break;
46 case OPT_NO_LOCK: args->nolock = 1; break;
47 }
48 return 0;
49 }
50
51 static const struct option my_longopts[] = {
52 {"reboot", no_argument, 0, 'r'},
53 {"nowait", no_argument, 0, 'W'},
54 {"timeout", required_argument, 0, 't'},
55 {"kill", no_argument, 0, 'k'},
56 {"shutdown", no_argument, 0, 's'},
57 {"no-lock", no_argument, 0, OPT_NO_LOCK},
58 LXC_COMMON_OPTIONS
59 };
60
61 static struct lxc_arguments my_args = {
62 .progname = "lxc-stop",
63 .help = "\
64 --name=NAME\n\
65 \n\
66 lxc-stop stops a container with the identifier NAME\n\
67 \n\
68 Options :\n\
69 -n, --name=NAME NAME for name of the container\n\
70 -r, --reboot reboot the container\n\
71 -W, --nowait don't wait for shutdown or reboot to complete\n\
72 -t, --timeout=T wait T seconds before hard-stopping\n\
73 -k, --kill kill container rather than request clean shutdown\n\
74 --nolock Avoid using API locks\n\
75 -s, --shutdown Only request clean shutdown, don't later force kill\n",
76 .options = my_longopts,
77 .parser = my_parser,
78 .checker = NULL,
79 .timeout = 60,
80 };
81
82 /* returns -1 on failure, 0 on success */
83 int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c)
84 {
85 int ret;
86 pid_t pid;
87 pid_t newpid;
88 int timeout = a->timeout;
89
90 pid = c->init_pid(c);
91 if (pid == -1)
92 return -1;
93 if (!c->reboot(c))
94 return -1;
95 if (a->nowait)
96 return 0;
97 if (timeout <= 0)
98 goto out;
99
100 for (;;) {
101 /* can we use c-> wait for this, assuming it will
102 * re-enter RUNNING? For now just sleep */
103 int elapsed_time, curtime = 0;
104 struct timeval tv;
105
106 newpid = c->init_pid(c);
107 if (newpid != -1 && newpid != pid)
108 return 0;
109
110 ret = gettimeofday(&tv, NULL);
111 if (ret)
112 break;
113 curtime = tv.tv_sec;
114
115 sleep(1);
116 ret = gettimeofday(&tv, NULL);
117 if (ret)
118 break;
119 elapsed_time = tv.tv_sec - curtime;
120 if (timeout - elapsed_time <= 0)
121 break;
122 timeout -= elapsed_time;
123 }
124
125 out:
126 newpid = c->init_pid(c);
127 if (newpid == -1 || newpid == pid) {
128 printf("Reboot did not complete before timeout\n");
129 return -1;
130 }
131 return 0;
132 }
133
134 int main(int argc, char *argv[])
135 {
136 struct lxc_container *c;
137 bool s;
138 int ret = 1;
139
140 if (lxc_arguments_parse(&my_args, argc, argv))
141 return 1;
142
143 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
144 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
145 return 1;
146
147 /* shortcut - if locking is bogus, we should be able to kill
148 * containers at least */
149 if (my_args.nolock)
150 return lxc_cmd_stop(my_args.name, my_args.lxcpath[0]);
151
152 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
153 if (!c) {
154 fprintf(stderr, "Error opening container\n");
155 goto out;
156 }
157
158 if (!c->may_control(c)) {
159 fprintf(stderr, "Insufficent privileges to control %s\n", c->name);
160 goto out;
161 }
162
163 if (!c->is_running(c)) {
164 fprintf(stderr, "%s is not running\n", c->name);
165 ret = 2;
166 goto out;
167 }
168
169 if (my_args.hardstop) {
170 ret = c->stop(c) ? 0 : 1;
171 goto out;
172 }
173 if (my_args.reboot) {
174 ret = do_reboot_and_check(&my_args, c);
175 goto out;
176 }
177
178 if (my_args.shutdown)
179 my_args.timeout = 0;
180
181 s = c->shutdown(c, my_args.timeout);
182 if (!s) {
183 if (!my_args.shutdown)
184 ret = c->wait(c, "STOPPED", -1) ? 0 : 1;
185 else
186 ret = 1; // fail
187 } else
188 ret = 0;
189
190 out:
191 lxc_container_put(c);
192 return ret;
193 }