]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_info.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
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.
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.
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
30 #include <sys/types.h>
32 #include <lxc/lxccontainer.h>
38 #include "arguments.h"
44 static bool humanize
= true;
45 static char **key
= NULL
;
47 static int filter_count
= 0;
49 static int my_parser(struct lxc_arguments
* args
, int c
, char* arg
)
53 key
= realloc(key
, keys
+1 * sizeof(key
[0]));
57 case 'i': ips
= true; filter_count
+= 1; break;
58 case 's': state
= true; filter_count
+= 1; break;
59 case 'p': pid
= true; filter_count
+= 1; break;
60 case 'S': stats
= true; filter_count
+= 5; break;
61 case 'H': humanize
= false; break;
66 static const struct option my_longopts
[] = {
67 {"config", required_argument
, 0, 'c'},
68 {"ips", no_argument
, 0, 'i'},
69 {"state", no_argument
, 0, 's'},
70 {"pid", no_argument
, 0, 'p'},
71 {"stats", no_argument
, 0, 'S'},
72 {"no-humanize", no_argument
, 0, 'H'},
76 static struct lxc_arguments my_args
= {
77 .progname
= "lxc-info",
81 lxc-info display some information about a container with the identifier NAME\n\
84 -n, --name=NAME NAME for name of the container\n\
85 -c, --config=KEY show configuration variable KEY from running container\n\
86 -i, --ips shows the IP addresses\n\
87 -p, --pid shows the process id of the init container\n\
88 -S, --stats shows usage stats\n\
89 -H, --no-humanize shows stats as raw numbers, not humanized\n\
90 -s, --state shows the state of the container\n",
92 .options
= my_longopts
,
97 static void str_chomp(char *buf
)
101 /* remove trailing whitespace from buf */
102 for(ch
= &buf
[strlen(buf
)-1];
103 ch
>= buf
&& (*ch
== '\t' || *ch
== '\n' || *ch
== ' ');
108 static void size_humanize(unsigned long long val
, char *buf
, size_t bufsz
)
111 snprintf(buf
, bufsz
, "%u.%2.2u GiB",
113 (int)(val
& ((1 << 30) - 1)) / 10737419);
114 } else if (val
> 1 << 20) {
115 int x
= val
+ 5243; /* for rounding */
116 snprintf(buf
, bufsz
, "%u.%2.2u MiB",
117 x
>> 20, ((x
& ((1 << 20) - 1)) * 100) >> 20);
118 } else if (val
> 1 << 10) {
119 int x
= val
+ 5; /* for rounding */
120 snprintf(buf
, bufsz
, "%u.%2.2u KiB",
121 x
>> 10, ((x
& ((1 << 10) - 1)) * 100) >> 10);
123 snprintf(buf
, bufsz
, "%u bytes", (int)val
);
127 static unsigned long long str_size_humanize(char *iobuf
, size_t iobufsz
)
129 unsigned long long val
;
132 val
= strtoull(iobuf
, &end
, 0);
134 if (*end
== '\0' || *end
== '\n')
135 size_humanize(val
, iobuf
, iobufsz
);
142 static void print_net_stats(const char *name
, const char *lxcpath
)
145 unsigned long long rx_bytes
= 0, tx_bytes
= 0;
150 for(netnr
= 0; ;netnr
++) {
151 sprintf(buf
, "lxc.network.%d.type", netnr
);
152 type
= lxc_cmd_get_config_item(name
, buf
, lxcpath
);
156 if (!strcmp(type
, "veth")) {
157 sprintf(buf
, "lxc.network.%d.veth.pair", netnr
);
159 sprintf(buf
, "lxc.network.%d.link", netnr
);
162 ifname
= lxc_cmd_get_config_item(name
, buf
, lxcpath
);
165 printf("%-15s %s\n", "Link:", ifname
);
167 /* XXX: tx and rx are reversed from the host vs container
168 * perspective, print them from the container perspective
170 snprintf(path
, sizeof(path
), "/sys/class/net/%s/statistics/rx_bytes", ifname
);
171 rc
= lxc_read_from_file(path
, buf
, sizeof(buf
));
174 rx_bytes
= str_size_humanize(buf
, sizeof(buf
));
175 printf("%-15s %s\n", " TX bytes:", buf
);
178 snprintf(path
, sizeof(path
), "/sys/class/net/%s/statistics/tx_bytes", ifname
);
179 rc
= lxc_read_from_file(path
, buf
, sizeof(buf
));
182 tx_bytes
= str_size_humanize(buf
, sizeof(buf
));
183 printf("%-15s %s\n", " RX bytes:", buf
);
186 sprintf(buf
, "%llu", rx_bytes
+ tx_bytes
);
187 str_size_humanize(buf
, sizeof(buf
));
188 printf("%-15s %s\n", " Total bytes:", buf
);
193 static void print_stats(struct lxc_container
*c
)
198 ret
= c
->get_cgroup_item(c
, "cpuacct.usage", buf
, sizeof(buf
));
199 if (ret
> 0 && ret
< sizeof(buf
)) {
202 float seconds
= strtof(buf
, NULL
) / 1000000000.0;
203 printf("%-15s %.2f seconds\n", "CPU use:", seconds
);
205 printf("%-15s %s\n", "CPU use:", buf
);
209 ret
= c
->get_cgroup_item(c
, "blkio.throttle.io_service_bytes", buf
, sizeof(buf
));
210 if (ret
> 0 && ret
< sizeof(buf
)) {
213 /* put ch on last "Total" line */
215 for(ch
= &buf
[strlen(buf
)-1]; ch
> buf
&& *ch
!= '\n'; ch
--)
220 if (strncmp(ch
, "Total", 5) == 0) {
222 memmove(buf
, ch
, strlen(ch
)+1);
223 str_size_humanize(buf
, sizeof(buf
));
224 printf("%-15s %s\n", "BlkIO use:", buf
);
228 static const struct {
232 { "Memory use:", "memory.usage_in_bytes" },
233 { "KMem use:", "memory.kmem.usage_in_bytes" },
237 for (i
= 0; lxstat
[i
].name
; i
++) {
238 ret
= c
->get_cgroup_item(c
, lxstat
[i
].file
, buf
, sizeof(buf
));
239 if (ret
> 0 && ret
< sizeof(buf
)) {
241 str_size_humanize(buf
, sizeof(buf
));
242 printf("%-15s %s\n", lxstat
[i
].name
, buf
);
247 static void print_info_msg_int(const char *key
, int value
)
250 printf("%-15s %d\n", key
, value
);
252 if (filter_count
== 1)
253 printf("%d\n", value
);
255 printf("%-15s %d\n", key
, value
);
259 static void print_info_msg_str(const char *key
, const char *value
)
262 printf("%-15s %s\n", key
, value
);
264 if (filter_count
== 1)
265 printf("%s\n", value
);
267 printf("%-15s %s\n", key
, value
);
271 static int print_info(const char *name
, const char *lxcpath
)
274 struct lxc_container
*c
;
276 c
= lxc_container_new(name
, lxcpath
);
278 fprintf(stderr
, "Failure to retrieve information on %s:%s\n", lxcpath
? lxcpath
: "null",
279 name
? name
: "null");
283 if (!c
->may_control(c
)) {
284 fprintf(stderr
, "Insufficent privileges to control %s\n", c
->name
);
285 lxc_container_put(c
);
289 if (!c
->is_running(c
) && !c
->is_defined(c
)) {
290 fprintf(stderr
, "%s doesn't exist\n", c
->name
);
291 lxc_container_put(c
);
295 if (!state
&& !pid
&& !ips
&& !stats
&& keys
<= 0) {
296 state
= pid
= ips
= stats
= true;
297 print_info_msg_str("Name:", c
->name
);
301 print_info_msg_str("State:", c
->state(c
));
307 initpid
= c
->init_pid(c
);
309 print_info_msg_int("PID:", initpid
);
313 char **addresses
= c
->get_ips(c
, NULL
, NULL
, 0);
317 while (addresses
[i
]) {
318 address
= addresses
[i
];
319 print_info_msg_str("IP:", address
);
327 print_net_stats(name
, lxcpath
);
330 for(i
= 0; i
< keys
; i
++) {
331 int len
= c
->get_config_item(c
, key
[i
], NULL
, 0);
334 char *val
= (char*) malloc(sizeof(char)*len
+ 1);
336 if (c
->get_config_item(c
, key
[i
], val
, len
+ 1) != len
) {
337 fprintf(stderr
, "unable to read %s from configuration\n", key
[i
]);
339 printf("%s = %s\n", key
[i
], val
);
343 fprintf(stderr
, "%s unset or invalid\n", key
[i
]);
347 lxc_container_put(c
);
351 int main(int argc
, char *argv
[])
353 int ret
= EXIT_FAILURE
;
355 if (lxc_arguments_parse(&my_args
, argc
, argv
))
358 if (!my_args
.log_file
)
359 my_args
.log_file
= "none";
361 if (lxc_log_init(my_args
.name
, my_args
.log_file
, my_args
.log_priority
,
362 my_args
.progname
, my_args
.quiet
, my_args
.lxcpath
[0]))
365 if (print_info(my_args
.name
, my_args
.lxcpath
[0]) == 0)