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