]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/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"
40 lxc_log_define(lxc_info_ui
, lxc
);
46 static bool humanize
= true;
47 static char **key
= NULL
;
49 static int filter_count
= 0;
51 static int my_parser(struct lxc_arguments
* args
, int c
, char* arg
)
56 newk
= realloc(key
, (keys
+ 1) * sizeof(key
[0]));
63 case 'i': ips
= true; filter_count
+= 1; break;
64 case 's': state
= true; filter_count
+= 1; break;
65 case 'p': pid
= true; filter_count
+= 1; break;
66 case 'S': stats
= true; filter_count
+= 5; break;
67 case 'H': humanize
= false; break;
72 static const struct option my_longopts
[] = {
73 {"config", required_argument
, 0, 'c'},
74 {"ips", no_argument
, 0, 'i'},
75 {"state", no_argument
, 0, 's'},
76 {"pid", no_argument
, 0, 'p'},
77 {"stats", no_argument
, 0, 'S'},
78 {"no-humanize", no_argument
, 0, 'H'},
82 static struct lxc_arguments my_args
= {
83 .progname
= "lxc-info",
87 lxc-info display some information about a container with the identifier NAME\n\
90 -n, --name=NAME NAME of the container\n\
91 -c, --config=KEY show configuration variable KEY from running container\n\
92 -i, --ips shows the IP addresses\n\
93 -p, --pid shows the process id of the init container\n\
94 -S, --stats shows usage stats\n\
95 -H, --no-humanize shows stats as raw numbers, not humanized\n\
96 -s, --state shows the state of the container\n\
97 --rcfile=FILE Load configuration file FILE\n",
99 .options
= my_longopts
,
104 static void str_chomp(char *buf
)
108 /* remove trailing whitespace from buf */
109 for(ch
= &buf
[strlen(buf
)-1];
110 ch
>= buf
&& (*ch
== '\t' || *ch
== '\n' || *ch
== ' ');
115 static void size_humanize(unsigned long long val
, char *buf
, size_t bufsz
)
118 snprintf(buf
, bufsz
, "%u.%2.2u GiB",
120 (int)(val
& ((1 << 30) - 1)) / 10737419);
121 } else if (val
> 1 << 20) {
122 int x
= val
+ 5243; /* for rounding */
123 snprintf(buf
, bufsz
, "%u.%2.2u MiB",
124 x
>> 20, ((x
& ((1 << 20) - 1)) * 100) >> 20);
125 } else if (val
> 1 << 10) {
126 int x
= val
+ 5; /* for rounding */
127 snprintf(buf
, bufsz
, "%u.%2.2u KiB",
128 x
>> 10, ((x
& ((1 << 10) - 1)) * 100) >> 10);
130 snprintf(buf
, bufsz
, "%u bytes", (int)val
);
134 static unsigned long long str_size_humanize(char *iobuf
, size_t iobufsz
)
136 unsigned long long val
;
139 val
= strtoull(iobuf
, &end
, 0);
141 if (*end
== '\0' || *end
== '\n')
142 size_humanize(val
, iobuf
, iobufsz
);
149 static void print_net_stats(struct lxc_container
*c
)
152 unsigned long long rx_bytes
= 0, tx_bytes
= 0;
157 for(netnr
= 0; ;netnr
++) {
158 sprintf(buf
, "lxc.network.%d.type", netnr
);
159 type
= c
->get_running_config_item(c
, buf
);
163 if (!strcmp(type
, "veth")) {
164 sprintf(buf
, "lxc.network.%d.veth.pair", netnr
);
166 sprintf(buf
, "lxc.network.%d.link", netnr
);
169 ifname
= c
->get_running_config_item(c
, buf
);
172 printf("%-15s %s\n", "Link:", ifname
);
175 /* XXX: tx and rx are reversed from the host vs container
176 * perspective, print them from the container perspective
178 snprintf(path
, sizeof(path
), "/sys/class/net/%s/statistics/rx_bytes", ifname
);
179 rc
= lxc_read_from_file(path
, buf
, sizeof(buf
));
182 rx_bytes
= str_size_humanize(buf
, sizeof(buf
));
183 printf("%-15s %s\n", " TX bytes:", buf
);
187 snprintf(path
, sizeof(path
), "/sys/class/net/%s/statistics/tx_bytes", ifname
);
188 rc
= lxc_read_from_file(path
, buf
, sizeof(buf
));
191 tx_bytes
= str_size_humanize(buf
, sizeof(buf
));
192 printf("%-15s %s\n", " RX bytes:", buf
);
196 sprintf(buf
, "%llu", rx_bytes
+ tx_bytes
);
197 str_size_humanize(buf
, sizeof(buf
));
198 printf("%-15s %s\n", " Total bytes:", buf
);
204 static void print_stats(struct lxc_container
*c
)
209 ret
= c
->get_cgroup_item(c
, "cpuacct.usage", buf
, sizeof(buf
));
210 if (ret
> 0 && ret
< sizeof(buf
)) {
213 float seconds
= strtof(buf
, NULL
) / 1000000000.0;
214 printf("%-15s %.2f seconds\n", "CPU use:", seconds
);
216 printf("%-15s %s\n", "CPU use:", buf
);
221 ret
= c
->get_cgroup_item(c
, "blkio.throttle.io_service_bytes", buf
, sizeof(buf
));
222 if (ret
> 0 && ret
< sizeof(buf
)) {
225 /* put ch on last "Total" line */
227 for(ch
= &buf
[strlen(buf
)-1]; ch
> buf
&& *ch
!= '\n'; ch
--)
232 if (strncmp(ch
, "Total", 5) == 0) {
234 memmove(buf
, ch
, strlen(ch
)+1);
235 str_size_humanize(buf
, sizeof(buf
));
236 printf("%-15s %s\n", "BlkIO use:", buf
);
241 static const struct {
245 { "Memory use:", "memory.usage_in_bytes" },
246 { "KMem use:", "memory.kmem.usage_in_bytes" },
250 for (i
= 0; lxstat
[i
].name
; i
++) {
251 ret
= c
->get_cgroup_item(c
, lxstat
[i
].file
, buf
, sizeof(buf
));
252 if (ret
> 0 && ret
< sizeof(buf
)) {
254 str_size_humanize(buf
, sizeof(buf
));
255 printf("%-15s %s\n", lxstat
[i
].name
, buf
);
261 static void print_info_msg_int(const char *key
, int value
)
264 printf("%-15s %d\n", key
, value
);
266 if (filter_count
== 1)
267 printf("%d\n", value
);
269 printf("%-15s %d\n", key
, value
);
274 static void print_info_msg_str(const char *key
, const char *value
)
277 printf("%-15s %s\n", key
, value
);
279 if (filter_count
== 1)
280 printf("%s\n", value
);
282 printf("%-15s %s\n", key
, value
);
287 static int print_info(const char *name
, const char *lxcpath
)
290 struct lxc_container
*c
;
292 c
= lxc_container_new(name
, lxcpath
);
294 fprintf(stderr
, "Failure to retrieve information on %s:%s\n", lxcpath
? lxcpath
: "null",
295 name
? name
: "null");
299 if (my_args
.rcfile
) {
301 if (!c
->load_config(c
, my_args
.rcfile
)) {
302 fprintf(stderr
, "Failed to load rcfile\n");
303 lxc_container_put(c
);
306 c
->configfile
= strdup(my_args
.rcfile
);
307 if (!c
->configfile
) {
308 fprintf(stderr
, "Out of memory setting new config filename\n");
309 lxc_container_put(c
);
314 if (!c
->may_control(c
)) {
315 fprintf(stderr
, "Insufficent privileges to control %s\n", c
->name
);
316 lxc_container_put(c
);
320 if (!c
->is_running(c
) && !c
->is_defined(c
)) {
321 fprintf(stderr
, "%s doesn't exist\n", c
->name
);
322 lxc_container_put(c
);
326 if (!state
&& !pid
&& !ips
&& !stats
&& keys
<= 0) {
327 state
= pid
= ips
= stats
= true;
328 print_info_msg_str("Name:", c
->name
);
332 print_info_msg_str("State:", c
->state(c
));
335 if (c
->is_running(c
)) {
339 initpid
= c
->init_pid(c
);
341 print_info_msg_int("PID:", initpid
);
346 char **addresses
= c
->get_ips(c
, NULL
, NULL
, 0);
350 while (addresses
[i
]) {
351 address
= addresses
[i
];
352 print_info_msg_str("IP:", address
);
364 for(i
= 0; i
< keys
; i
++) {
365 int len
= c
->get_config_item(c
, key
[i
], NULL
, 0);
368 char *val
= (char*) malloc(sizeof(char)*len
+ 1);
370 if (c
->get_config_item(c
, key
[i
], val
, len
+ 1) != len
) {
371 fprintf(stderr
, "unable to read %s from configuration\n", key
[i
]);
373 if (!humanize
&& keys
== 1)
376 printf("%s = %s\n", key
[i
], val
);
379 } else if (len
== 0) {
380 if (!humanize
&& keys
== 1)
383 printf("%s =\n", key
[i
]);
385 fprintf(stderr
, "%s invalid\n", key
[i
]);
390 lxc_container_put(c
);
394 int main(int argc
, char *argv
[])
396 int ret
= EXIT_FAILURE
;
398 if (lxc_arguments_parse(&my_args
, argc
, argv
))
401 if (!my_args
.log_file
)
402 my_args
.log_file
= "none";
404 if (lxc_log_init(my_args
.name
, my_args
.log_file
, my_args
.log_priority
,
405 my_args
.progname
, my_args
.quiet
, my_args
.lxcpath
[0]))
407 lxc_log_options_no_override();
409 if (print_info(my_args
.name
, my_args
.lxcpath
[0]) == 0)