]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxc_stop.c
licensing: Add missing headers and FSF address
[mirror_lxc.git] / src / lxc / lxc_stop.c
CommitLineData
5e97c3fc 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
5e97c3fc 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
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5e97c3fc 22 */
23#include <stdio.h>
24#include <libgen.h>
25#include <unistd.h>
26#include <sys/types.h>
27
b113348e 28#include <lxc/lxc.h>
00b3c2e2
CLG
29#include <lxc/log.h>
30
3e625e2d 31#include <lxc/lxccontainer.h>
4237c6ca 32#include "arguments.h"
ef6e34ee 33#include "commands.h"
67e571de 34#include "utils.h"
5e97c3fc 35
3e625e2d
SH
36static int my_parser(struct lxc_arguments* args, int c, char* arg)
37{
38 switch (c) {
39 case 'r': args->reboot = 1; break;
40 case 'W': args->nowait = 1; break;
41 case 't': args->timeout = atoi(arg); break;
42 case 'k': args->hardstop = 1; break;
43 case 's': args->shutdown = 1; break;
44 }
45 return 0;
46}
47
4237c6ca 48static const struct option my_longopts[] = {
3e625e2d
SH
49 {"reboot", no_argument, 0, 'r'},
50 {"nowait", no_argument, 0, 'W'},
51 {"timeout", required_argument, 0, 't'},
52 {"kill", no_argument, 0, 'k'},
53 {"shutdown", no_argument, 0, 's'},
4237c6ca
MN
54 LXC_COMMON_OPTIONS
55};
56
57static struct lxc_arguments my_args = {
58 .progname = "lxc-stop",
59 .help = "\
60--name=NAME\n\
61\n\
62lxc-stop stops a container with the identifier NAME\n\
63\n\
64Options :\n\
3e625e2d
SH
65 -n, --name=NAME NAME for name of the container\n\
66 -r, --reboot reboot the container\n\
67 -W, --nowait don't wait for shutdown or reboot to complete\n\
68 -t, --timeout=T wait T seconds before hard-stopping\n\
69 -k, --kill kill container rather than request clean shutdown\n\
70 -s, --shutdown Only request clean shutdown, don't later force kill\n",
4237c6ca 71 .options = my_longopts,
3e625e2d 72 .parser = my_parser,
4237c6ca 73 .checker = NULL,
3e625e2d 74 .timeout = 60,
4237c6ca 75};
5e97c3fc 76
3e625e2d
SH
77/* returns -1 on failure, 0 on success */
78int do_reboot_and_check(struct lxc_arguments *a, struct lxc_container *c)
79{
80 int ret;
81 pid_t pid;
82 pid_t newpid;
83 int timeout = a->timeout;
84
85 pid = c->init_pid(c);
86 if (pid == -1)
87 return -1;
88 if (!c->reboot(c))
89 return -1;
90 if (a->nowait)
91 return 0;
92 if (timeout <= 0)
93 goto out;
94
95 for (;;) {
96 /* can we use c-> wait for this, assuming it will
97 * re-enter RUNNING? For now just sleep */
98 int elapsed_time, curtime = 0;
99 struct timeval tv;
100
101 newpid = c->init_pid(c);
102 if (newpid != -1 && newpid != pid)
103 return 0;
104
105 ret = gettimeofday(&tv, NULL);
106 if (ret)
107 break;
108 curtime = tv.tv_sec;
109
110 sleep(1);
111 ret = gettimeofday(&tv, NULL);
112 if (ret)
113 break;
114 elapsed_time = tv.tv_sec - curtime;
115 if (timeout - elapsed_time <= 0)
116 break;
117 timeout -= elapsed_time;
118 }
119
120out:
121 newpid = c->init_pid(c);
122 if (newpid == -1 || newpid == pid) {
123 printf("Reboot did not complete before timeout\n");
124 return -1;
125 }
126 return 0;
127}
128
5e97c3fc 129int main(int argc, char *argv[])
130{
3e625e2d
SH
131 struct lxc_container *c;
132 bool s;
b93aac46 133 int ret = 1;
3e625e2d 134
23075e69 135 if (lxc_arguments_parse(&my_args, argc, argv))
b93aac46 136 return 1;
5e97c3fc 137
5e1e7aaf 138 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
8d06bd13 139 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
b93aac46 140 return 1;
5e97c3fc 141
3e625e2d
SH
142 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
143 if (!c) {
144 fprintf(stderr, "Error opening container\n");
145 goto out;
146 }
147
148 if (!c->is_running(c)) {
149 fprintf(stderr, "%s is not running\n", c->name);
b93aac46 150 ret = 2;
3e625e2d
SH
151 goto out;
152 }
153
154 if (my_args.hardstop) {
b93aac46 155 ret = c->stop(c) ? 0 : 1;
3e625e2d
SH
156 goto out;
157 }
158 if (my_args.reboot) {
159 ret = do_reboot_and_check(&my_args, c);
160 goto out;
161 }
162
163 s = c->shutdown(c, my_args.timeout);
164 if (!s) {
165 if (!my_args.shutdown)
b93aac46 166 ret = c->wait(c, "STOPPED", -1) ? 0 : 1;
3e625e2d 167 else
b93aac46 168 ret = 1; // fail
54b79829
SH
169 } else
170 ret = 0;
3e625e2d
SH
171
172out:
173 lxc_container_put(c);
174 return ret;
5e97c3fc 175}