]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/state.c
lxc-ssh: fix message about ssh key insertion
[mirror_lxc.git] / src / lxc / state.c
CommitLineData
5e97c3fc 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <stdio.h>
0ad19a3f 24#include <string.h>
25#include <fcntl.h>
26#include <errno.h>
5e97c3fc 27#include <unistd.h>
5e97c3fc 28#include <sys/types.h>
90b59fd0 29#include <sys/socket.h>
0ad19a3f 30#include <sys/param.h>
31#include <sys/stat.h>
32#include <sys/file.h>
5e97c3fc 33
72d0e1cb 34#include <lxc/lxc.h>
36eb9bde 35#include <lxc/log.h>
00b3c2e2 36#include <lxc/start.h>
108ed092 37#include <lxc/cgroup.h>
72d0e1cb 38#include <lxc/monitor.h>
e98fe68b 39#include "commands.h"
881450bb 40#include "config.h"
36eb9bde
CLG
41
42lxc_log_define(lxc_state, lxc);
0ad19a3f 43
44static char *strstate[] = {
45 "STOPPED", "STARTING", "RUNNING", "STOPPING",
fa082227 46 "ABORTING", "FREEZING", "FROZEN", "THAWED",
0ad19a3f 47};
48
49const char *lxc_state2str(lxc_state_t state)
50{
51 if (state < STOPPED || state > MAX_STATE - 1)
52 return NULL;
53 return strstate[state];
54}
5e97c3fc 55
0ad19a3f 56lxc_state_t lxc_str2state(const char *state)
5e97c3fc 57{
0ad19a3f 58 int i, len;
59 len = sizeof(strstate)/sizeof(strstate[0]);
60 for (i = 0; i < len; i++)
61 if (!strcmp(strstate[i], state))
62 return i;
3ab87b66 63
439358bf 64 ERROR("invalid state '%s'", state);
0ad19a3f 65 return -1;
5e97c3fc 66}
67
0ad19a3f 68static int freezer_state(const char *name)
69{
fa082227 70 char *nsgroup;
0ad19a3f 71 char freezer[MAXPATHLEN];
72 char status[MAXPATHLEN];
73 FILE *file;
74 int err;
35d2c3e7 75
bcbd102c 76 err = lxc_cgroup_path_get(&nsgroup, "freezer", name);
fa082227
MN
77 if (err)
78 return -1;
79
9ba8130c
SH
80 err = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
81 if (err < 0 || err >= MAXPATHLEN)
82 return -1;
0ad19a3f 83
84 file = fopen(freezer, "r");
85 if (!file)
86 return -1;
87
88 err = fscanf(file, "%s", status);
89 fclose(file);
90
91 if (err == EOF) {
36eb9bde 92 SYSERROR("failed to read %s", freezer);
0ad19a3f 93 return -1;
94 }
95
96 return lxc_str2state(status);
97}
98
fa082227 99static lxc_state_t __lxc_getstate(const char *name)
e98fe68b
DL
100{
101 struct lxc_command command = {
102 .request = { .type = LXC_COMMAND_STATE },
103 };
104
d97b36f8
DL
105 int ret, stopped = 0;
106
107 ret = lxc_command(name, &command, &stopped);
108 if (ret < 0 && stopped)
109 return STOPPED;
e98fe68b 110
e98fe68b
DL
111 if (ret < 0) {
112 ERROR("failed to send command");
113 return -1;
114 }
115
116 if (!ret) {
117 WARN("'%s' has stopped before sending its state", name);
118 return -1;
119 }
120
121 if (command.answer.ret < 0) {
122 ERROR("failed to get state for '%s': %s",
123 name, strerror(-command.answer.ret));
124 return -1;
125 }
126
127 DEBUG("'%s' is in '%s' state", name, lxc_state2str(command.answer.ret));
128
129 return command.answer.ret;
130}
131
fa082227 132lxc_state_t lxc_getstate(const char *name)
0ad19a3f 133{
134 int state = freezer_state(name);
135 if (state != FROZEN && state != FREEZING)
fa082227 136 state = __lxc_getstate(name);
0ad19a3f 137 return state;
138}
e98fe68b
DL
139
140/*----------------------------------------------------------------------------
141 * functions used by lxc-start mainloop
142 * to handle above command request.
143 *--------------------------------------------------------------------------*/
144extern int lxc_state_callback(int fd, struct lxc_request *request,
145 struct lxc_handler *handler)
146{
147 struct lxc_answer answer;
148 int ret;
149
150 answer.ret = handler->state;
151
152 ret = send(fd, &answer, sizeof(answer), 0);
153 if (ret < 0) {
154 WARN("failed to send answer to the peer");
155 goto out;
156 }
157
158 if (ret != sizeof(answer)) {
159 ERROR("partial answer sent");
160 goto out;
161 }
162
163out:
164 return ret;
165}
166
72d0e1cb
SG
167static int fillwaitedstates(char *strstates, int *states)
168{
169 char *token, *saveptr = NULL;
170 int state;
171
172 token = strtok_r(strstates, "|", &saveptr);
173 while (token) {
174
175 state = lxc_str2state(token);
176 if (state < 0)
177 return -1;
178
179 states[state] = 1;
180
181 token = strtok_r(NULL, "|", &saveptr);
182 }
183 return 0;
184}
185
186extern int lxc_wait(char *lxcname, char *states, int timeout)
187{
188 struct lxc_msg msg;
189 int state, ret;
190 int s[MAX_STATE] = { }, fd;
191
192 if (fillwaitedstates(states, s))
193 return -1;
194
195 fd = lxc_monitor_open();
196 if (fd < 0)
197 return -1;
198
199 /*
200 * if container present,
201 * then check if already in requested state
202 */
203 ret = -1;
204 state = lxc_getstate(lxcname);
205 if (state < 0) {
206 goto out_close;
207 } else if ((state >= 0) && (s[state])) {
208 ret = 0;
209 goto out_close;
210 }
211
212 for (;;) {
213 int elapsed_time, curtime;
214 struct timeval tv;
215 int stop = 0;
216 int retval;
217
218 if (timeout != -1) {
219 retval = gettimeofday(&tv, NULL);
220 if (retval)
221 goto out_close;
222 curtime = tv.tv_sec;
223 }
224 if (lxc_monitor_read_timeout(fd, &msg, timeout) < 0)
225 goto out_close;
226
227 if (timeout != -1) {
228 retval = gettimeofday(&tv, NULL);
229 if (retval)
230 goto out_close;
231 elapsed_time = tv.tv_sec - curtime;
232 if (timeout - elapsed_time <= 0)
233 stop = 1;
234 timeout -= elapsed_time;
235 }
236
237 if (strcmp(lxcname, msg.name)) {
238 if (stop) {
239 ret = -2;
240 goto out_close;
241 }
242 continue;
243 }
244
245 switch (msg.type) {
246 case lxc_msg_state:
247 if (msg.value < 0 || msg.value >= MAX_STATE) {
248 ERROR("Receive an invalid state number '%d'",
249 msg.value);
250 goto out_close;
251 }
252
253 if (s[msg.value]) {
254 ret = 0;
255 goto out_close;
256 }
257 break;
258 default:
259 if (stop) {
260 ret = -2;
261 goto out_close;
262 }
263 /* just ignore garbage */
264 break;
265 }
266 }
267
268out_close:
269 lxc_monitor_close(fd);
270 return ret;
271}