1 /*
2 * Copyright 2009-2017 Citrix Ltd and other contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14
15 #define _GNU_SOURCE
16
17 #include <fcntl.h>
18 #include <inttypes.h>
19 #include <stdlib.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/utsname.h>
23 #include <time.h>
24 #include <unistd.h>
25
26 #include <libxl.h>
27 #include <libxl_json.h>
28 #include <libxl_utils.h>
29 #include <libxlutil.h>
30
31 #include "xl.h"
32 #include "xl_utils.h"
33
34 /* Possibly select a specific piece of `xl info` to print. */
35 static const char *info_name;
36 static int maybe_printf(const char *fmt, ...) __attribute__((format(printf,1,2)));
maybe_printf(const char * fmt,...)37 static int maybe_printf(const char *fmt, ...)
38 {
39 va_list ap;
40 char *str;
41 int count = 0;
42
43 va_start(ap, fmt);
44 if (vasprintf(&str, fmt, ap) != -1) {
45 if (info_name) {
46 char *s;
47
48 if (!strncmp(str, info_name, strlen(info_name)) &&
49 (s = strchr(str, ':')) && s[1] == ' ')
50 count = fputs(&s[2], stdout);
51 } else
52 count = fputs(str, stdout);
53
54 free(str);
55 }
56 va_end(ap);
57
58 return count;
59 }
60
printf_info_one_json(yajl_gen hand,int domid,libxl_domain_config * d_config)61 static yajl_gen_status printf_info_one_json(yajl_gen hand, int domid,
62 libxl_domain_config *d_config)
63 {
64 yajl_gen_status s;
65
66 s = yajl_gen_map_open(hand);
67 if (s != yajl_gen_status_ok)
68 goto out;
69
70 s = yajl_gen_string(hand, (const unsigned char *)"domid",
71 sizeof("domid")-1);
72 if (s != yajl_gen_status_ok)
73 goto out;
74 if (domid != -1)
75 s = yajl_gen_integer(hand, domid);
76 else
77 s = yajl_gen_null(hand);
78 if (s != yajl_gen_status_ok)
79 goto out;
80
81 s = yajl_gen_string(hand, (const unsigned char *)"config",
82 sizeof("config")-1);
83 if (s != yajl_gen_status_ok)
84 goto out;
85 s = libxl_domain_config_gen_json(hand, d_config);
86 if (s != yajl_gen_status_ok)
87 goto out;
88
89 s = yajl_gen_map_close(hand);
90 if (s != yajl_gen_status_ok)
91 goto out;
92
93 out:
94 return s;
95 }
96
97 void printf_info(enum output_format output_format,
98 int domid,
99 libxl_domain_config *d_config, FILE *fh);
printf_info(enum output_format output_format,int domid,libxl_domain_config * d_config,FILE * fh)100 void printf_info(enum output_format output_format,
101 int domid,
102 libxl_domain_config *d_config, FILE *fh)
103 {
104 if (output_format == OUTPUT_FORMAT_SXP)
105 return printf_info_sexp(domid, d_config, fh);
106
107 const char *buf;
108 libxl_yajl_length len = 0;
109 yajl_gen_status s;
110 yajl_gen hand;
111
112 hand = libxl_yajl_gen_alloc(NULL);
113 if (!hand) {
114 fprintf(stderr, "unable to allocate JSON generator\n");
115 return;
116 }
117
118 s = printf_info_one_json(hand, domid, d_config);
119 if (s != yajl_gen_status_ok)
120 goto out;
121
122 s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &len);
123 if (s != yajl_gen_status_ok)
124 goto out;
125
126 fputs(buf, fh);
127
128 out:
129 yajl_gen_free(hand);
130
131 if (s != yajl_gen_status_ok)
132 fprintf(stderr,
133 "unable to format domain config as JSON (YAJL:%d)\n", s);
134
135 flush_stream(fh);
136 }
137
output_xeninfo(void)138 static void output_xeninfo(void)
139 {
140 const libxl_version_info *info;
141 libxl_scheduler sched;
142 int rc;
143
144 if (!(info = libxl_get_version_info(ctx))) {
145 fprintf(stderr, "libxl_get_version_info failed.\n");
146 return;
147 }
148
149 rc = libxl_get_scheduler(ctx);
150 if (rc < 0) {
151 fprintf(stderr, "get_scheduler sysctl failed.\n");
152 return;
153 }
154 sched = rc;
155
156 maybe_printf("xen_major : %d\n", info->xen_version_major);
157 maybe_printf("xen_minor : %d\n", info->xen_version_minor);
158 maybe_printf("xen_extra : %s\n", info->xen_version_extra);
159 maybe_printf("xen_version : %d.%d%s\n", info->xen_version_major,
160 info->xen_version_minor, info->xen_version_extra);
161 maybe_printf("xen_caps : %s\n", info->capabilities);
162 maybe_printf("xen_scheduler : %s\n", libxl_scheduler_to_string(sched));
163 maybe_printf("xen_pagesize : %u\n", info->pagesize);
164 maybe_printf("platform_params : virt_start=0x%"PRIx64"\n", info->virt_start);
165 maybe_printf("xen_changeset : %s\n", info->changeset);
166 maybe_printf("xen_commandline : %s\n", info->commandline);
167 maybe_printf("cc_compiler : %s\n", info->compiler);
168 maybe_printf("cc_compile_by : %s\n", info->compile_by);
169 maybe_printf("cc_compile_domain : %s\n", info->compile_domain);
170 maybe_printf("cc_compile_date : %s\n", info->compile_date);
171 maybe_printf("build_id : %s\n", info->build_id);
172
173 return;
174 }
175
output_nodeinfo(void)176 static void output_nodeinfo(void)
177 {
178 struct utsname utsbuf;
179
180 if (uname(&utsbuf) < 0)
181 return;
182
183 maybe_printf("host : %s\n", utsbuf.nodename);
184 maybe_printf("release : %s\n", utsbuf.release);
185 maybe_printf("version : %s\n", utsbuf.version);
186 maybe_printf("machine : %s\n", utsbuf.machine);
187 }
188
output_physinfo(void)189 static void output_physinfo(void)
190 {
191 libxl_physinfo info;
192 const libxl_version_info *vinfo;
193 unsigned int i;
194 libxl_bitmap cpumap;
195 int n = 0;
196
197 if (libxl_get_physinfo(ctx, &info) != 0) {
198 fprintf(stderr, "libxl_physinfo failed.\n");
199 return;
200 }
201 maybe_printf("nr_cpus : %d\n", info.nr_cpus);
202 maybe_printf("max_cpu_id : %d\n", info.max_cpu_id);
203 maybe_printf("nr_nodes : %d\n", info.nr_nodes);
204 maybe_printf("cores_per_socket : %d\n", info.cores_per_socket);
205 maybe_printf("threads_per_core : %d\n", info.threads_per_core);
206 maybe_printf("cpu_mhz : %d\n", info.cpu_khz / 1000);
207
208 maybe_printf("hw_caps : %08x:%08x:%08x:%08x:%08x:%08x:%08x:%08x\n",
209 info.hw_cap[0], info.hw_cap[1], info.hw_cap[2], info.hw_cap[3],
210 info.hw_cap[4], info.hw_cap[5], info.hw_cap[6], info.hw_cap[7]
211 );
212
213 maybe_printf("virt_caps :%s%s\n",
214 info.cap_hvm ? " hvm" : "",
215 info.cap_hvm_directio ? " hvm_directio" : ""
216 );
217
218 vinfo = libxl_get_version_info(ctx);
219 if (vinfo) {
220 i = (1 << 20) / vinfo->pagesize;
221 maybe_printf("total_memory : %"PRIu64"\n", info.total_pages / i);
222 maybe_printf("free_memory : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
223 maybe_printf("sharing_freed_memory : %"PRIu64"\n", info.sharing_freed_pages / i);
224 maybe_printf("sharing_used_memory : %"PRIu64"\n", info.sharing_used_frames / i);
225 maybe_printf("outstanding_claims : %"PRIu64"\n", info.outstanding_pages / i);
226 }
227 if (!libxl_get_freecpus(ctx, &cpumap)) {
228 libxl_for_each_bit(i, cpumap)
229 if (libxl_bitmap_test(&cpumap, i))
230 n++;
231 maybe_printf("free_cpus : %d\n", n);
232 free(cpumap.map);
233 }
234 libxl_physinfo_dispose(&info);
235 return;
236 }
237
output_numainfo(void)238 static void output_numainfo(void)
239 {
240 libxl_numainfo *info;
241 int i, j, nr;
242
243 info = libxl_get_numainfo(ctx, &nr);
244 if (info == NULL) {
245 fprintf(stderr, "libxl_get_numainfo failed.\n");
246 return;
247 }
248
249 printf("numa_info :\n");
250 printf("node: memsize memfree distances\n");
251
252 for (i = 0; i < nr; i++) {
253 if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
254 printf("%4d: %6"PRIu64" %6"PRIu64" %d", i,
255 info[i].size >> 20, info[i].free >> 20,
256 info[i].dists[0]);
257 for (j = 1; j < info[i].num_dists; j++)
258 printf(",%d", info[i].dists[j]);
259 printf("\n");
260 }
261 }
262
263 libxl_numainfo_list_free(info, nr);
264
265 return;
266 }
267
output_topologyinfo(void)268 static void output_topologyinfo(void)
269 {
270 libxl_cputopology *cpuinfo;
271 int i, nr;
272 libxl_pcitopology *pciinfo;
273 int valid_devs = 0;
274
275
276 cpuinfo = libxl_get_cpu_topology(ctx, &nr);
277 if (cpuinfo == NULL) {
278 fprintf(stderr, "libxl_get_cpu_topology failed.\n");
279 return;
280 }
281
282 printf("cpu_topology :\n");
283 printf("cpu: core socket node\n");
284
285 for (i = 0; i < nr; i++) {
286 if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
287 printf("%3d: %4d %4d %4d\n", i,
288 cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
289 }
290
291 libxl_cputopology_list_free(cpuinfo, nr);
292
293 pciinfo = libxl_get_pci_topology(ctx, &nr);
294 if (pciinfo == NULL) {
295 fprintf(stderr, "libxl_get_pci_topology failed.\n");
296 return;
297 }
298
299 printf("device topology :\n");
300 printf("device node\n");
301 for (i = 0; i < nr; i++) {
302 if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
303 printf("%04x:%02x:%02x.%01x %d\n", pciinfo[i].seg,
304 pciinfo[i].bus,
305 ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
306 pciinfo[i].node);
307 valid_devs++;
308 }
309 }
310
311 if (valid_devs == 0)
312 printf("No device topology data available\n");
313
314 libxl_pcitopology_list_free(pciinfo, nr);
315
316 return;
317 }
318
print_info(int numa)319 static void print_info(int numa)
320 {
321 output_nodeinfo();
322
323 output_physinfo();
324
325 if (numa) {
326 output_topologyinfo();
327 output_numainfo();
328 }
329 output_xeninfo();
330
331 maybe_printf("xend_config_format : 4\n");
332
333 return;
334 }
335
list_vm(void)336 static void list_vm(void)
337 {
338 libxl_vminfo *info;
339 char *domname;
340 int nb_vm, i;
341
342 info = libxl_list_vm(ctx, &nb_vm);
343
344 if (!info) {
345 fprintf(stderr, "libxl_list_vm failed.\n");
346 exit(EXIT_FAILURE);
347 }
348 printf("UUID ID name\n");
349 for (i = 0; i < nb_vm; i++) {
350 domname = libxl_domid_to_name(ctx, info[i].domid);
351 printf(LIBXL_UUID_FMT " %d %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
352 info[i].domid, domname);
353 free(domname);
354 }
355 libxl_vminfo_list_free(info, nb_vm);
356 }
357
list_domains(bool verbose,bool context,bool claim,bool numa,bool cpupool,const libxl_dominfo * info,int nb_domain)358 static void list_domains(bool verbose, bool context, bool claim, bool numa,
359 bool cpupool, const libxl_dominfo *info, int nb_domain)
360 {
361 int i;
362 static const char shutdown_reason_letters[]= "-rscwS";
363 libxl_bitmap nodemap;
364 libxl_physinfo physinfo;
365
366 libxl_bitmap_init(&nodemap);
367 libxl_physinfo_init(&physinfo);
368
369 printf("Name ID Mem VCPUs\tState\tTime(s)");
370 if (verbose) printf(" UUID Reason-Code\tSecurity Label");
371 if (context && !verbose) printf(" Security Label");
372 if (claim) printf(" Claimed");
373 if (cpupool) printf(" Cpupool");
374 if (numa) {
375 if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
376 fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
377 exit(EXIT_FAILURE);
378 }
379 if (libxl_get_physinfo(ctx, &physinfo) != 0) {
380 fprintf(stderr, "libxl_physinfo failed.\n");
381 libxl_bitmap_dispose(&nodemap);
382 exit(EXIT_FAILURE);
383 }
384
385 printf(" NODE Affinity");
386 }
387 printf("\n");
388 for (i = 0; i < nb_domain; i++) {
389 char *domname;
390 libxl_shutdown_reason shutdown_reason;
391 domname = libxl_domid_to_name(ctx, info[i].domid);
392 shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
393 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
394 domname,
395 info[i].domid,
396 (unsigned long) ((info[i].current_memkb +
397 info[i].outstanding_memkb)/ 1024),
398 info[i].vcpu_online,
399 info[i].running ? 'r' : '-',
400 info[i].blocked ? 'b' : '-',
401 info[i].paused ? 'p' : '-',
402 info[i].shutdown ? 's' : '-',
403 (shutdown_reason >= 0 &&
404 shutdown_reason < sizeof(shutdown_reason_letters)-1
405 ? shutdown_reason_letters[shutdown_reason] : '?'),
406 info[i].dying ? 'd' : '-',
407 ((float)info[i].cpu_time / 1e9));
408 free(domname);
409 if (verbose) {
410 printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
411 if (info[i].shutdown) printf(" %8x", shutdown_reason);
412 else printf(" %8s", "-");
413 }
414 if (claim)
415 printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
416 if (verbose || context)
417 printf(" %16s", info[i].ssid_label ? : "-");
418 if (cpupool) {
419 char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
420 printf("%16s", poolname);
421 free(poolname);
422 }
423 if (numa) {
424 libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
425
426 putchar(' ');
427 print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
428 }
429 putchar('\n');
430 }
431
432 libxl_bitmap_dispose(&nodemap);
433 libxl_physinfo_dispose(&physinfo);
434 }
435
list_domains_details(const libxl_dominfo * info,int nb_domain)436 static void list_domains_details(const libxl_dominfo *info, int nb_domain)
437 {
438 libxl_domain_config d_config;
439
440 int i, rc;
441
442 yajl_gen hand = NULL;
443 yajl_gen_status s;
444 const char *buf;
445 libxl_yajl_length yajl_len = 0;
446
447 if (default_output_format == OUTPUT_FORMAT_JSON) {
448 hand = libxl_yajl_gen_alloc(NULL);
449 if (!hand) {
450 fprintf(stderr, "unable to allocate JSON generator\n");
451 return;
452 }
453
454 s = yajl_gen_array_open(hand);
455 if (s != yajl_gen_status_ok)
456 goto out;
457 } else
458 s = yajl_gen_status_ok;
459
460 for (i = 0; i < nb_domain; i++) {
461 libxl_domain_config_init(&d_config);
462 rc = libxl_retrieve_domain_configuration(ctx, info[i].domid, &d_config);
463 if (rc)
464 continue;
465 if (default_output_format == OUTPUT_FORMAT_JSON)
466 s = printf_info_one_json(hand, info[i].domid, &d_config);
467 else
468 printf_info_sexp(info[i].domid, &d_config, stdout);
469 libxl_domain_config_dispose(&d_config);
470 if (s != yajl_gen_status_ok)
471 goto out;
472 }
473
474 if (default_output_format == OUTPUT_FORMAT_JSON) {
475 s = yajl_gen_array_close(hand);
476 if (s != yajl_gen_status_ok)
477 goto out;
478
479 s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
480 if (s != yajl_gen_status_ok)
481 goto out;
482
483 puts(buf);
484 }
485
486 out:
487 if (default_output_format == OUTPUT_FORMAT_JSON) {
488 yajl_gen_free(hand);
489 if (s != yajl_gen_status_ok)
490 fprintf(stderr,
491 "unable to format domain config as JSON (YAJL:%d)\n", s);
492 }
493 }
494
495
main_list(int argc,char ** argv)496 int main_list(int argc, char **argv)
497 {
498 int opt;
499 bool verbose = false;
500 bool context = false;
501 bool details = false;
502 bool cpupool = false;
503 bool numa = false;
504 static struct option opts[] = {
505 {"long", 0, 0, 'l'},
506 {"verbose", 0, 0, 'v'},
507 {"context", 0, 0, 'Z'},
508 {"cpupool", 0, 0, 'c'},
509 {"numa", 0, 0, 'n'},
510 COMMON_LONG_OPTS
511 };
512
513 libxl_dominfo info_buf;
514 libxl_dominfo *info, *info_free=0;
515 int nb_domain, rc;
516
517 SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
518 case 'l':
519 details = true;
520 break;
521 case 'v':
522 verbose = true;
523 break;
524 case 'Z':
525 context = true;
526 break;
527 case 'c':
528 cpupool = true;
529 break;
530 case 'n':
531 numa = true;
532 break;
533 }
534
535 libxl_dominfo_init(&info_buf);
536
537 if (optind >= argc) {
538 info = libxl_list_domain(ctx, &nb_domain);
539 if (!info) {
540 fprintf(stderr, "libxl_list_domain failed.\n");
541 return EXIT_FAILURE;
542 }
543 info_free = info;
544 } else if (optind == argc-1) {
545 uint32_t domid = find_domain(argv[optind]);
546 rc = libxl_domain_info(ctx, &info_buf, domid);
547 if (rc == ERROR_DOMAIN_NOTFOUND) {
548 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
549 argv[optind]);
550 return EXIT_FAILURE;
551 }
552 if (rc) {
553 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
554 return EXIT_FAILURE;
555 }
556 info = &info_buf;
557 nb_domain = 1;
558 } else {
559 help("list");
560 return EXIT_FAILURE;
561 }
562
563 if (details)
564 list_domains_details(info, nb_domain);
565 else
566 list_domains(verbose, context, false /* claim */, numa, cpupool,
567 info, nb_domain);
568
569 if (info_free)
570 libxl_dominfo_list_free(info, nb_domain);
571
572 libxl_dominfo_dispose(&info_buf);
573
574 return EXIT_SUCCESS;
575 }
576
main_vm_list(int argc,char ** argv)577 int main_vm_list(int argc, char **argv)
578 {
579 int opt;
580
581 SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
582 /* No options */
583 }
584
585 list_vm();
586 return EXIT_SUCCESS;
587 }
588
main_info(int argc,char ** argv)589 int main_info(int argc, char **argv)
590 {
591 int opt;
592 static struct option opts[] = {
593 {"numa", 0, 0, 'n'},
594 COMMON_LONG_OPTS
595 };
596 int numa = 0;
597
598 SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
599 case 'n':
600 numa = 1;
601 break;
602 }
603
604 /*
605 * If an extra argument is provided, filter out a specific piece of
606 * information.
607 */
608 if (numa == 0 && argc > optind)
609 info_name = argv[optind];
610
611 print_info(numa);
612 return 0;
613 }
614
main_domid(int argc,char ** argv)615 int main_domid(int argc, char **argv)
616 {
617 uint32_t domid;
618 int opt;
619 const char *domname = NULL;
620
621 SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
622 /* No options */
623 }
624
625 domname = argv[optind];
626
627 if (libxl_name_to_domid(ctx, domname, &domid)) {
628 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
629 return EXIT_FAILURE;
630 }
631
632 printf("%u\n", domid);
633
634 return EXIT_SUCCESS;
635 }
636
main_domname(int argc,char ** argv)637 int main_domname(int argc, char **argv)
638 {
639 uint32_t domid;
640 int opt;
641 char *domname = NULL;
642 char *endptr = NULL;
643
644 SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
645 /* No options */
646 }
647
648 domid = strtol(argv[optind], &endptr, 10);
649 if (domid == 0 && !strcmp(endptr, argv[optind])) {
650 /*no digits at all*/
651 fprintf(stderr, "Invalid domain id.\n\n");
652 return EXIT_FAILURE;
653 }
654
655 domname = libxl_domid_to_name(ctx, domid);
656 if (!domname) {
657 fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
658 return EXIT_FAILURE;
659 }
660
661 printf("%s\n", domname);
662 free(domname);
663
664 return EXIT_SUCCESS;
665 }
666
uptime_to_string(unsigned long uptime,int short_mode)667 static char *uptime_to_string(unsigned long uptime, int short_mode)
668 {
669 int sec, min, hour, day;
670 char *time_string;
671
672 day = (int)(uptime / 86400);
673 uptime -= (day * 86400);
674 hour = (int)(uptime / 3600);
675 uptime -= (hour * 3600);
676 min = (int)(uptime / 60);
677 uptime -= (min * 60);
678 sec = uptime;
679
680 if (short_mode)
681 if (day > 1)
682 xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
683 else if (day == 1)
684 xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
685 else
686 xasprintf(&time_string, "%2d:%02d", hour, min);
687 else
688 if (day > 1)
689 xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
690 else if (day == 1)
691 xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
692 else
693 xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
694
695 return time_string;
696 }
697
main_claims(int argc,char ** argv)698 int main_claims(int argc, char **argv)
699 {
700 libxl_dominfo *info;
701 int opt;
702 int nb_domain;
703
704 SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
705 /* No options */
706 }
707
708 if (!claim_mode)
709 fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
710
711 info = libxl_list_domain(ctx, &nb_domain);
712 if (!info) {
713 fprintf(stderr, "libxl_list_domain failed.\n");
714 return 1;
715 }
716
717 list_domains(false /* verbose */, false /* context */, true /* claim */,
718 false /* numa */, false /* cpupool */, info, nb_domain);
719
720 libxl_dominfo_list_free(info, nb_domain);
721 return 0;
722 }
723
current_time_to_string(time_t now)724 static char *current_time_to_string(time_t now)
725 {
726 char now_str[100];
727 struct tm *tmp;
728
729 tmp = localtime(&now);
730 if (tmp == NULL) {
731 fprintf(stderr, "Get localtime error");
732 exit(-1);
733 }
734 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
735 fprintf(stderr, "strftime returned 0");
736 exit(-1);
737 }
738 return strdup(now_str);
739 }
740
print_dom0_uptime(int short_mode,time_t now)741 static void print_dom0_uptime(int short_mode, time_t now)
742 {
743 int fd;
744 ssize_t nr;
745 char buf[512];
746 uint32_t uptime = 0;
747 char *uptime_str = NULL;
748 char *now_str = NULL;
749 char *domname;
750
751 fd = open("/proc/uptime", O_RDONLY);
752 if (fd == -1)
753 goto err;
754
755 nr = read(fd, buf, sizeof(buf) - 1);
756 if (nr == -1) {
757 close(fd);
758 goto err;
759 }
760 close(fd);
761
762 buf[nr] = '\0';
763
764 strtok(buf, " ");
765 uptime = strtoul(buf, NULL, 10);
766
767 domname = libxl_domid_to_name(ctx, 0);
768 if (short_mode)
769 {
770 now_str = current_time_to_string(now);
771 uptime_str = uptime_to_string(uptime, 1);
772 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
773 domname, 0);
774 }
775 else
776 {
777 now_str = NULL;
778 uptime_str = uptime_to_string(uptime, 0);
779 printf("%-33s %4d %s\n", domname,
780 0, uptime_str);
781 }
782
783 free(now_str);
784 free(uptime_str);
785 free(domname);
786 return;
787 err:
788 fprintf(stderr, "Can not get Dom0 uptime.\n");
789 exit(-1);
790 }
791
print_domU_uptime(uint32_t domuid,int short_mode,time_t now)792 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
793 {
794 uint32_t s_time = 0;
795 uint32_t uptime = 0;
796 char *uptime_str = NULL;
797 char *now_str = NULL;
798 char *domname;
799
800 s_time = libxl_vm_get_start_time(ctx, domuid);
801 if (s_time == -1)
802 return;
803 uptime = now - s_time;
804 domname = libxl_domid_to_name(ctx, domuid);
805 if (short_mode)
806 {
807 now_str = current_time_to_string(now);
808 uptime_str = uptime_to_string(uptime, 1);
809 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
810 domname, domuid);
811 }
812 else
813 {
814 now_str = NULL;
815 uptime_str = uptime_to_string(uptime, 0);
816 printf("%-33s %4d %s\n", domname,
817 domuid, uptime_str);
818 }
819
820 free(domname);
821 free(now_str);
822 free(uptime_str);
823 return;
824 }
825
print_uptime(int short_mode,uint32_t doms[],int nb_doms)826 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
827 {
828 libxl_vminfo *info;
829 time_t now;
830 int nb_vm, i;
831
832 now = time(NULL);
833
834 if (!short_mode)
835 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
836
837 if (nb_doms == 0) {
838 print_dom0_uptime(short_mode, now);
839 info = libxl_list_vm(ctx, &nb_vm);
840 if (info == NULL) {
841 fprintf(stderr, "Could not list vms.\n");
842 return;
843 }
844 for (i = 0; i < nb_vm; i++) {
845 if (info[i].domid == 0) continue;
846 print_domU_uptime(info[i].domid, short_mode, now);
847 }
848 libxl_vminfo_list_free(info, nb_vm);
849 } else {
850 for (i = 0; i < nb_doms; i++) {
851 if (doms[i] == 0)
852 print_dom0_uptime(short_mode, now);
853 else
854 print_domU_uptime(doms[i], short_mode, now);
855 }
856 }
857 }
858
main_uptime(int argc,char ** argv)859 int main_uptime(int argc, char **argv)
860 {
861 const char *dom;
862 int short_mode = 0;
863 uint32_t domains[100];
864 int nb_doms = 0;
865 int opt;
866
867 SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
868 case 's':
869 short_mode = 1;
870 break;
871 }
872
873 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
874 domains[nb_doms] = find_domain(dom);
875
876 print_uptime(short_mode, domains, nb_doms);
877
878 return 0;
879 }
880
main_dmesg(int argc,char ** argv)881 int main_dmesg(int argc, char **argv)
882 {
883 unsigned int clear = 0;
884 libxl_xen_console_reader *cr;
885 char *line;
886 int opt, ret = 1;
887 static struct option opts[] = {
888 {"clear", 0, 0, 'c'},
889 COMMON_LONG_OPTS
890 };
891
892 SWITCH_FOREACH_OPT(opt, "c", opts, "dmesg", 0) {
893 case 'c':
894 clear = 1;
895 break;
896 }
897
898 cr = libxl_xen_console_read_start(ctx, clear);
899 if (!cr)
900 goto finish;
901
902 while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
903 printf("%s", line);
904
905 finish:
906 if (cr)
907 libxl_xen_console_read_finish(ctx, cr);
908 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
909 }
910
main_top(int argc,char ** argv)911 int main_top(int argc, char **argv)
912 {
913 int opt;
914
915 SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
916 /* No options */
917 }
918
919 return system("xentop");
920 }
921
922
923 /*
924 * Local variables:
925 * mode: C
926 * c-basic-offset: 4
927 * indent-tabs-mode: nil
928 * End:
929 */
930