]>
Commit | Line | Data |
---|---|---|
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> |
0ad19a3f | 29 | #include <sys/types.h> |
30 | #include <sys/param.h> | |
31 | #include <sys/stat.h> | |
32 | #include <sys/file.h> | |
5e97c3fc | 33 | |
36eb9bde | 34 | #include <lxc/log.h> |
00b3c2e2 | 35 | #include <lxc/start.h> |
e98fe68b | 36 | #include "commands.h" |
881450bb | 37 | #include "config.h" |
36eb9bde CLG |
38 | |
39 | lxc_log_define(lxc_state, lxc); | |
0ad19a3f | 40 | |
41 | static char *strstate[] = { | |
42 | "STOPPED", "STARTING", "RUNNING", "STOPPING", | |
fa082227 | 43 | "ABORTING", "FREEZING", "FROZEN", "THAWED", |
0ad19a3f | 44 | }; |
45 | ||
46 | const char *lxc_state2str(lxc_state_t state) | |
47 | { | |
48 | if (state < STOPPED || state > MAX_STATE - 1) | |
49 | return NULL; | |
50 | return strstate[state]; | |
51 | } | |
5e97c3fc | 52 | |
0ad19a3f | 53 | lxc_state_t lxc_str2state(const char *state) |
5e97c3fc | 54 | { |
0ad19a3f | 55 | int i, len; |
56 | len = sizeof(strstate)/sizeof(strstate[0]); | |
57 | for (i = 0; i < len; i++) | |
58 | if (!strcmp(strstate[i], state)) | |
59 | return i; | |
3ab87b66 | 60 | |
439358bf | 61 | ERROR("invalid state '%s'", state); |
0ad19a3f | 62 | return -1; |
5e97c3fc | 63 | } |
64 | ||
0ad19a3f | 65 | int lxc_rmstate(const char *name) |
66 | { | |
67 | char file[MAXPATHLEN]; | |
68 | snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); | |
69 | unlink(file); | |
5e97c3fc | 70 | return 0; |
71 | } | |
72 | ||
0ad19a3f | 73 | static int freezer_state(const char *name) |
74 | { | |
fa082227 | 75 | char *nsgroup; |
0ad19a3f | 76 | char freezer[MAXPATHLEN]; |
77 | char status[MAXPATHLEN]; | |
78 | FILE *file; | |
79 | int err; | |
35d2c3e7 | 80 | |
fa082227 MN |
81 | err = lxc_cgroup_path_get(&nsgroup, name); |
82 | if (err) | |
83 | return -1; | |
84 | ||
85 | snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup); | |
0ad19a3f | 86 | |
87 | file = fopen(freezer, "r"); | |
88 | if (!file) | |
89 | return -1; | |
90 | ||
91 | err = fscanf(file, "%s", status); | |
92 | fclose(file); | |
93 | ||
94 | if (err == EOF) { | |
36eb9bde | 95 | SYSERROR("failed to read %s", freezer); |
0ad19a3f | 96 | return -1; |
97 | } | |
98 | ||
99 | return lxc_str2state(status); | |
100 | } | |
101 | ||
fa082227 | 102 | static lxc_state_t __lxc_getstate(const char *name) |
e98fe68b DL |
103 | { |
104 | struct lxc_command command = { | |
105 | .request = { .type = LXC_COMMAND_STATE }, | |
106 | }; | |
107 | ||
d97b36f8 DL |
108 | int ret, stopped = 0; |
109 | ||
110 | ret = lxc_command(name, &command, &stopped); | |
111 | if (ret < 0 && stopped) | |
112 | return STOPPED; | |
e98fe68b | 113 | |
e98fe68b DL |
114 | if (ret < 0) { |
115 | ERROR("failed to send command"); | |
116 | return -1; | |
117 | } | |
118 | ||
119 | if (!ret) { | |
120 | WARN("'%s' has stopped before sending its state", name); | |
121 | return -1; | |
122 | } | |
123 | ||
124 | if (command.answer.ret < 0) { | |
125 | ERROR("failed to get state for '%s': %s", | |
126 | name, strerror(-command.answer.ret)); | |
127 | return -1; | |
128 | } | |
129 | ||
130 | DEBUG("'%s' is in '%s' state", name, lxc_state2str(command.answer.ret)); | |
131 | ||
132 | return command.answer.ret; | |
133 | } | |
134 | ||
fa082227 | 135 | lxc_state_t lxc_getstate(const char *name) |
0ad19a3f | 136 | { |
137 | int state = freezer_state(name); | |
138 | if (state != FROZEN && state != FREEZING) | |
fa082227 | 139 | state = __lxc_getstate(name); |
0ad19a3f | 140 | return state; |
141 | } | |
e98fe68b DL |
142 | |
143 | /*---------------------------------------------------------------------------- | |
144 | * functions used by lxc-start mainloop | |
145 | * to handle above command request. | |
146 | *--------------------------------------------------------------------------*/ | |
147 | extern int lxc_state_callback(int fd, struct lxc_request *request, | |
148 | struct lxc_handler *handler) | |
149 | { | |
150 | struct lxc_answer answer; | |
151 | int ret; | |
152 | ||
153 | answer.ret = handler->state; | |
154 | ||
155 | ret = send(fd, &answer, sizeof(answer), 0); | |
156 | if (ret < 0) { | |
157 | WARN("failed to send answer to the peer"); | |
158 | goto out; | |
159 | } | |
160 | ||
161 | if (ret != sizeof(answer)) { | |
162 | ERROR("partial answer sent"); | |
163 | goto out; | |
164 | } | |
165 | ||
166 | out: | |
167 | return ret; | |
168 | } | |
169 |