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.%03d\n", info.cpu_khz / 1000, 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%s%s%s%s%s\n",
214 info.cap_pv ? " pv" : "",
215 info.cap_hvm ? " hvm" : "",
216 info.cap_hvm && info.cap_hvm_directio ? " hvm_directio" : "",
217 info.cap_pv && info.cap_hvm_directio ? " pv_directio" : "",
218 info.cap_hap ? " hap" : "",
219 info.cap_shadow ? " shadow" : "",
220 info.cap_iommu_hap_pt_share ? " iommu_hap_pt_share" : ""
221 );
222
223 vinfo = libxl_get_version_info(ctx);
224 if (vinfo) {
225 i = (1 << 20) / vinfo->pagesize;
226 maybe_printf("total_memory : %"PRIu64"\n", info.total_pages / i);
227 maybe_printf("free_memory : %"PRIu64"\n", (info.free_pages - info.outstanding_pages) / i);
228 maybe_printf("sharing_freed_memory : %"PRIu64"\n", info.sharing_freed_pages / i);
229 maybe_printf("sharing_used_memory : %"PRIu64"\n", info.sharing_used_frames / i);
230 maybe_printf("outstanding_claims : %"PRIu64"\n", info.outstanding_pages / i);
231 }
232 if (!libxl_get_freecpus(ctx, &cpumap)) {
233 libxl_for_each_bit(i, cpumap)
234 if (libxl_bitmap_test(&cpumap, i))
235 n++;
236 maybe_printf("free_cpus : %d\n", n);
237 free(cpumap.map);
238 }
239 libxl_physinfo_dispose(&info);
240 return;
241 }
242
output_numainfo(void)243 static void output_numainfo(void)
244 {
245 libxl_numainfo *info;
246 int i, j, nr;
247
248 info = libxl_get_numainfo(ctx, &nr);
249 if (info == NULL) {
250 fprintf(stderr, "libxl_get_numainfo failed.\n");
251 return;
252 }
253
254 printf("numa_info :\n");
255 printf("node: memsize memfree distances\n");
256
257 for (i = 0; i < nr; i++) {
258 if (info[i].size != LIBXL_NUMAINFO_INVALID_ENTRY) {
259 printf("%4d: %6"PRIu64" %6"PRIu64" %d", i,
260 info[i].size >> 20, info[i].free >> 20,
261 info[i].dists[0]);
262 for (j = 1; j < info[i].num_dists; j++)
263 printf(",%d", info[i].dists[j]);
264 printf("\n");
265 }
266 }
267
268 libxl_numainfo_list_free(info, nr);
269
270 return;
271 }
272
output_topologyinfo(void)273 static void output_topologyinfo(void)
274 {
275 libxl_cputopology *cpuinfo;
276 int i, nr;
277 libxl_pcitopology *pciinfo;
278 int valid_devs = 0;
279
280
281 cpuinfo = libxl_get_cpu_topology(ctx, &nr);
282 if (cpuinfo == NULL) {
283 fprintf(stderr, "libxl_get_cpu_topology failed.\n");
284 return;
285 }
286
287 printf("cpu_topology :\n");
288 printf("cpu: core socket node\n");
289
290 for (i = 0; i < nr; i++) {
291 if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
292 printf("%3d: %4d %4d %4d\n", i,
293 cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
294 }
295
296 libxl_cputopology_list_free(cpuinfo, nr);
297
298 pciinfo = libxl_get_pci_topology(ctx, &nr);
299 if (pciinfo == NULL) {
300 fprintf(stderr, "libxl_get_pci_topology failed.\n");
301 return;
302 }
303
304 printf("device topology :\n");
305 printf("device node\n");
306 for (i = 0; i < nr; i++) {
307 if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
308 printf("%04x:%02x:%02x.%01x %d\n", pciinfo[i].seg,
309 pciinfo[i].bus,
310 ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
311 pciinfo[i].node);
312 valid_devs++;
313 }
314 }
315
316 if (valid_devs == 0)
317 printf("No device topology data available\n");
318
319 libxl_pcitopology_list_free(pciinfo, nr);
320
321 return;
322 }
323
print_info(int numa)324 static void print_info(int numa)
325 {
326 output_nodeinfo();
327
328 output_physinfo();
329
330 if (numa) {
331 output_topologyinfo();
332 output_numainfo();
333 }
334 output_xeninfo();
335
336 maybe_printf("xend_config_format : 4\n");
337
338 return;
339 }
340
list_vm(void)341 static void list_vm(void)
342 {
343 libxl_vminfo *info;
344 char *domname;
345 int nb_vm, i;
346
347 info = libxl_list_vm(ctx, &nb_vm);
348
349 if (!info) {
350 fprintf(stderr, "libxl_list_vm failed.\n");
351 exit(EXIT_FAILURE);
352 }
353 printf("UUID ID name\n");
354 for (i = 0; i < nb_vm; i++) {
355 domname = libxl_domid_to_name(ctx, info[i].domid);
356 printf(LIBXL_UUID_FMT " %d %-30s\n", LIBXL_UUID_BYTES(info[i].uuid),
357 info[i].domid, domname);
358 free(domname);
359 }
360 libxl_vminfo_list_free(info, nb_vm);
361 }
362
list_domains(bool verbose,bool context,bool claim,bool numa,bool cpupool,const libxl_dominfo * info,int nb_domain)363 static void list_domains(bool verbose, bool context, bool claim, bool numa,
364 bool cpupool, const libxl_dominfo *info, int nb_domain)
365 {
366 int i;
367 static const char shutdown_reason_letters[]= "-rscwS";
368 libxl_bitmap nodemap;
369 libxl_physinfo physinfo;
370
371 libxl_bitmap_init(&nodemap);
372 libxl_physinfo_init(&physinfo);
373
374 printf("Name ID Mem VCPUs\tState\tTime(s)");
375 if (verbose) printf(" UUID Reason-Code\tSecurity Label");
376 if (context && !verbose) printf(" Security Label");
377 if (claim) printf(" Claimed");
378 if (cpupool) printf(" Cpupool");
379 if (numa) {
380 if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) {
381 fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n");
382 exit(EXIT_FAILURE);
383 }
384 if (libxl_get_physinfo(ctx, &physinfo) != 0) {
385 fprintf(stderr, "libxl_physinfo failed.\n");
386 libxl_bitmap_dispose(&nodemap);
387 exit(EXIT_FAILURE);
388 }
389
390 printf(" NODE Affinity");
391 }
392 printf("\n");
393 for (i = 0; i < nb_domain; i++) {
394 char *domname;
395 libxl_shutdown_reason shutdown_reason;
396 domname = libxl_domid_to_name(ctx, info[i].domid);
397 shutdown_reason = info[i].shutdown ? info[i].shutdown_reason : 0;
398 printf("%-40s %5d %5lu %5d %c%c%c%c%c%c %8.1f",
399 domname,
400 info[i].domid,
401 (unsigned long) ((info[i].current_memkb +
402 info[i].outstanding_memkb)/ 1024),
403 info[i].vcpu_online,
404 info[i].running ? 'r' : '-',
405 info[i].blocked ? 'b' : '-',
406 info[i].paused ? 'p' : '-',
407 info[i].shutdown ? 's' : '-',
408 (shutdown_reason >= 0 &&
409 shutdown_reason < sizeof(shutdown_reason_letters)-1
410 ? shutdown_reason_letters[shutdown_reason] : '?'),
411 info[i].dying ? 'd' : '-',
412 ((float)info[i].cpu_time / 1e9));
413 free(domname);
414 if (verbose) {
415 printf(" " LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info[i].uuid));
416 if (info[i].shutdown) printf(" %8x", shutdown_reason);
417 else printf(" %8s", "-");
418 }
419 if (claim)
420 printf(" %5lu", (unsigned long)info[i].outstanding_memkb / 1024);
421 if (verbose || context)
422 printf(" %16s", info[i].ssid_label ? : "-");
423 if (cpupool) {
424 char *poolname = libxl_cpupoolid_to_name(ctx, info[i].cpupool);
425 printf("%16s", poolname);
426 free(poolname);
427 }
428 if (numa) {
429 libxl_domain_get_nodeaffinity(ctx, info[i].domid, &nodemap);
430
431 putchar(' ');
432 print_bitmap(nodemap.map, physinfo.nr_nodes, stdout);
433 }
434 putchar('\n');
435 }
436
437 libxl_bitmap_dispose(&nodemap);
438 libxl_physinfo_dispose(&physinfo);
439 }
440
list_domains_details(const libxl_dominfo * info,int nb_domain)441 static void list_domains_details(const libxl_dominfo *info, int nb_domain)
442 {
443 libxl_domain_config d_config;
444
445 int i, rc;
446
447 yajl_gen hand = NULL;
448 yajl_gen_status s;
449 const char *buf;
450 libxl_yajl_length yajl_len = 0;
451
452 if (default_output_format == OUTPUT_FORMAT_JSON) {
453 hand = libxl_yajl_gen_alloc(NULL);
454 if (!hand) {
455 fprintf(stderr, "unable to allocate JSON generator\n");
456 return;
457 }
458
459 s = yajl_gen_array_open(hand);
460 if (s != yajl_gen_status_ok)
461 goto out;
462 } else
463 s = yajl_gen_status_ok;
464
465 for (i = 0; i < nb_domain; i++) {
466 libxl_domain_config_init(&d_config);
467 rc = libxl_retrieve_domain_configuration(ctx, info[i].domid,
468 &d_config, NULL);
469 if (rc)
470 continue;
471 if (default_output_format == OUTPUT_FORMAT_JSON)
472 s = printf_info_one_json(hand, info[i].domid, &d_config);
473 else
474 printf_info_sexp(info[i].domid, &d_config, stdout);
475 libxl_domain_config_dispose(&d_config);
476 if (s != yajl_gen_status_ok)
477 goto out;
478 }
479
480 if (default_output_format == OUTPUT_FORMAT_JSON) {
481 s = yajl_gen_array_close(hand);
482 if (s != yajl_gen_status_ok)
483 goto out;
484
485 s = yajl_gen_get_buf(hand, (const unsigned char **)&buf, &yajl_len);
486 if (s != yajl_gen_status_ok)
487 goto out;
488
489 puts(buf);
490 }
491
492 out:
493 if (default_output_format == OUTPUT_FORMAT_JSON) {
494 yajl_gen_free(hand);
495 if (s != yajl_gen_status_ok)
496 fprintf(stderr,
497 "unable to format domain config as JSON (YAJL:%d)\n", s);
498 }
499 }
500
501
main_list(int argc,char ** argv)502 int main_list(int argc, char **argv)
503 {
504 int opt;
505 bool verbose = false;
506 bool context = false;
507 bool details = false;
508 bool cpupool = false;
509 bool numa = false;
510 static struct option opts[] = {
511 {"long", 0, 0, 'l'},
512 {"verbose", 0, 0, 'v'},
513 {"context", 0, 0, 'Z'},
514 {"cpupool", 0, 0, 'c'},
515 {"numa", 0, 0, 'n'},
516 COMMON_LONG_OPTS
517 };
518
519 libxl_dominfo info_buf;
520 libxl_dominfo *info, *info_free=0;
521 int nb_domain, rc;
522
523 SWITCH_FOREACH_OPT(opt, "lvhZcn", opts, "list", 0) {
524 case 'l':
525 details = true;
526 break;
527 case 'v':
528 verbose = true;
529 break;
530 case 'Z':
531 context = true;
532 break;
533 case 'c':
534 cpupool = true;
535 break;
536 case 'n':
537 numa = true;
538 break;
539 }
540
541 libxl_dominfo_init(&info_buf);
542
543 if (optind >= argc) {
544 info = libxl_list_domain(ctx, &nb_domain);
545 if (!info) {
546 fprintf(stderr, "libxl_list_domain failed.\n");
547 return EXIT_FAILURE;
548 }
549 info_free = info;
550 } else if (optind == argc-1) {
551 uint32_t domid = find_domain(argv[optind]);
552 rc = libxl_domain_info(ctx, &info_buf, domid);
553 if (rc == ERROR_DOMAIN_NOTFOUND) {
554 fprintf(stderr, "Error: Domain \'%s\' does not exist.\n",
555 argv[optind]);
556 return EXIT_FAILURE;
557 }
558 if (rc) {
559 fprintf(stderr, "libxl_domain_info failed (code %d).\n", rc);
560 return EXIT_FAILURE;
561 }
562 info = &info_buf;
563 nb_domain = 1;
564 } else {
565 help("list");
566 return EXIT_FAILURE;
567 }
568
569 if (details)
570 list_domains_details(info, nb_domain);
571 else
572 list_domains(verbose, context, false /* claim */, numa, cpupool,
573 info, nb_domain);
574
575 if (info_free)
576 libxl_dominfo_list_free(info, nb_domain);
577
578 libxl_dominfo_dispose(&info_buf);
579
580 return EXIT_SUCCESS;
581 }
582
main_vm_list(int argc,char ** argv)583 int main_vm_list(int argc, char **argv)
584 {
585 int opt;
586
587 SWITCH_FOREACH_OPT(opt, "", NULL, "vm-list", 0) {
588 /* No options */
589 }
590
591 list_vm();
592 return EXIT_SUCCESS;
593 }
594
main_info(int argc,char ** argv)595 int main_info(int argc, char **argv)
596 {
597 int opt;
598 static struct option opts[] = {
599 {"numa", 0, 0, 'n'},
600 COMMON_LONG_OPTS
601 };
602 int numa = 0;
603
604 SWITCH_FOREACH_OPT(opt, "n", opts, "info", 0) {
605 case 'n':
606 numa = 1;
607 break;
608 }
609
610 /*
611 * If an extra argument is provided, filter out a specific piece of
612 * information.
613 */
614 if (numa == 0 && argc > optind)
615 info_name = argv[optind];
616
617 print_info(numa);
618 return 0;
619 }
620
main_domid(int argc,char ** argv)621 int main_domid(int argc, char **argv)
622 {
623 uint32_t domid;
624 int opt;
625 const char *domname = NULL;
626
627 SWITCH_FOREACH_OPT(opt, "", NULL, "domid", 1) {
628 /* No options */
629 }
630
631 domname = argv[optind];
632
633 if (libxl_name_to_domid(ctx, domname, &domid)) {
634 fprintf(stderr, "Can't get domid of domain name '%s', maybe this domain does not exist.\n", domname);
635 return EXIT_FAILURE;
636 }
637
638 printf("%u\n", domid);
639
640 return EXIT_SUCCESS;
641 }
642
main_domname(int argc,char ** argv)643 int main_domname(int argc, char **argv)
644 {
645 uint32_t domid;
646 int opt;
647 char *domname = NULL;
648 char *endptr = NULL;
649
650 SWITCH_FOREACH_OPT(opt, "", NULL, "domname", 1) {
651 /* No options */
652 }
653
654 domid = strtol(argv[optind], &endptr, 10);
655 if (domid == 0 && !strcmp(endptr, argv[optind])) {
656 /*no digits at all*/
657 fprintf(stderr, "Invalid domain id.\n\n");
658 return EXIT_FAILURE;
659 }
660
661 domname = libxl_domid_to_name(ctx, domid);
662 if (!domname) {
663 fprintf(stderr, "Can't get domain name of domain id '%u', maybe this domain does not exist.\n", domid);
664 return EXIT_FAILURE;
665 }
666
667 printf("%s\n", domname);
668 free(domname);
669
670 return EXIT_SUCCESS;
671 }
672
uptime_to_string(unsigned long uptime,int short_mode)673 static char *uptime_to_string(unsigned long uptime, int short_mode)
674 {
675 int sec, min, hour, day;
676 char *time_string;
677
678 day = (int)(uptime / 86400);
679 uptime -= (day * 86400);
680 hour = (int)(uptime / 3600);
681 uptime -= (hour * 3600);
682 min = (int)(uptime / 60);
683 uptime -= (min * 60);
684 sec = uptime;
685
686 if (short_mode)
687 if (day > 1)
688 xasprintf(&time_string, "%d days, %2d:%02d", day, hour, min);
689 else if (day == 1)
690 xasprintf(&time_string, "%d day, %2d:%02d", day, hour, min);
691 else
692 xasprintf(&time_string, "%2d:%02d", hour, min);
693 else
694 if (day > 1)
695 xasprintf(&time_string, "%d days, %2d:%02d:%02d", day, hour, min, sec);
696 else if (day == 1)
697 xasprintf(&time_string, "%d day, %2d:%02d:%02d", day, hour, min, sec);
698 else
699 xasprintf(&time_string, "%2d:%02d:%02d", hour, min, sec);
700
701 return time_string;
702 }
703
main_claims(int argc,char ** argv)704 int main_claims(int argc, char **argv)
705 {
706 libxl_dominfo *info;
707 int opt;
708 int nb_domain;
709
710 SWITCH_FOREACH_OPT(opt, "", NULL, "claims", 0) {
711 /* No options */
712 }
713
714 if (!claim_mode)
715 fprintf(stderr, "claim_mode not enabled (see man xl.conf).\n");
716
717 info = libxl_list_domain(ctx, &nb_domain);
718 if (!info) {
719 fprintf(stderr, "libxl_list_domain failed.\n");
720 return 1;
721 }
722
723 list_domains(false /* verbose */, false /* context */, true /* claim */,
724 false /* numa */, false /* cpupool */, info, nb_domain);
725
726 libxl_dominfo_list_free(info, nb_domain);
727 return 0;
728 }
729
current_time_to_string(time_t now)730 static char *current_time_to_string(time_t now)
731 {
732 char now_str[100];
733 struct tm *tmp;
734
735 tmp = localtime(&now);
736 if (tmp == NULL) {
737 fprintf(stderr, "Get localtime error");
738 exit(-1);
739 }
740 if (strftime(now_str, sizeof(now_str), "%H:%M:%S", tmp) == 0) {
741 fprintf(stderr, "strftime returned 0");
742 exit(-1);
743 }
744 return strdup(now_str);
745 }
746
print_dom0_uptime(int short_mode,time_t now)747 static void print_dom0_uptime(int short_mode, time_t now)
748 {
749 int fd;
750 ssize_t nr;
751 char buf[512];
752 uint32_t uptime = 0;
753 char *uptime_str = NULL;
754 char *now_str = NULL;
755 char *domname;
756
757 fd = open("/proc/uptime", O_RDONLY);
758 if (fd == -1)
759 goto err;
760
761 nr = read(fd, buf, sizeof(buf) - 1);
762 if (nr == -1) {
763 close(fd);
764 goto err;
765 }
766 close(fd);
767
768 buf[nr] = '\0';
769
770 strtok(buf, " ");
771 uptime = strtoul(buf, NULL, 10);
772
773 domname = libxl_domid_to_name(ctx, 0);
774 if (short_mode)
775 {
776 now_str = current_time_to_string(now);
777 uptime_str = uptime_to_string(uptime, 1);
778 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
779 domname, 0);
780 }
781 else
782 {
783 now_str = NULL;
784 uptime_str = uptime_to_string(uptime, 0);
785 printf("%-33s %4d %s\n", domname,
786 0, uptime_str);
787 }
788
789 free(now_str);
790 free(uptime_str);
791 free(domname);
792 return;
793 err:
794 fprintf(stderr, "Can not get Dom0 uptime.\n");
795 exit(-1);
796 }
797
print_domU_uptime(uint32_t domuid,int short_mode,time_t now)798 static void print_domU_uptime(uint32_t domuid, int short_mode, time_t now)
799 {
800 uint32_t s_time = 0;
801 uint32_t uptime = 0;
802 char *uptime_str = NULL;
803 char *now_str = NULL;
804 char *domname;
805
806 s_time = libxl_vm_get_start_time(ctx, domuid);
807 if (s_time == -1)
808 return;
809 uptime = now - s_time;
810 domname = libxl_domid_to_name(ctx, domuid);
811 if (short_mode)
812 {
813 now_str = current_time_to_string(now);
814 uptime_str = uptime_to_string(uptime, 1);
815 printf(" %s up %s, %s (%d)\n", now_str, uptime_str,
816 domname, domuid);
817 }
818 else
819 {
820 now_str = NULL;
821 uptime_str = uptime_to_string(uptime, 0);
822 printf("%-33s %4d %s\n", domname,
823 domuid, uptime_str);
824 }
825
826 free(domname);
827 free(now_str);
828 free(uptime_str);
829 return;
830 }
831
print_uptime(int short_mode,uint32_t doms[],int nb_doms)832 static void print_uptime(int short_mode, uint32_t doms[], int nb_doms)
833 {
834 libxl_vminfo *info;
835 time_t now;
836 int nb_vm, i;
837
838 now = time(NULL);
839
840 if (!short_mode)
841 printf("%-33s %4s %s\n", "Name", "ID", "Uptime");
842
843 if (nb_doms == 0) {
844 print_dom0_uptime(short_mode, now);
845 info = libxl_list_vm(ctx, &nb_vm);
846 if (info == NULL) {
847 fprintf(stderr, "Could not list vms.\n");
848 return;
849 }
850 for (i = 0; i < nb_vm; i++) {
851 if (info[i].domid == 0) continue;
852 print_domU_uptime(info[i].domid, short_mode, now);
853 }
854 libxl_vminfo_list_free(info, nb_vm);
855 } else {
856 for (i = 0; i < nb_doms; i++) {
857 if (doms[i] == 0)
858 print_dom0_uptime(short_mode, now);
859 else
860 print_domU_uptime(doms[i], short_mode, now);
861 }
862 }
863 }
864
main_uptime(int argc,char ** argv)865 int main_uptime(int argc, char **argv)
866 {
867 const char *dom;
868 int short_mode = 0;
869 uint32_t domains[100];
870 int nb_doms = 0;
871 int opt;
872
873 SWITCH_FOREACH_OPT(opt, "s", NULL, "uptime", 0) {
874 case 's':
875 short_mode = 1;
876 break;
877 }
878
879 for (;(dom = argv[optind]) != NULL; nb_doms++,optind++)
880 domains[nb_doms] = find_domain(dom);
881
882 print_uptime(short_mode, domains, nb_doms);
883
884 return 0;
885 }
886
main_dmesg(int argc,char ** argv)887 int main_dmesg(int argc, char **argv)
888 {
889 unsigned int clear = 0;
890 libxl_xen_console_reader *cr;
891 char *line;
892 int opt, ret = 1;
893 static struct option opts[] = {
894 {"clear", 0, 0, 'c'},
895 COMMON_LONG_OPTS
896 };
897
898 SWITCH_FOREACH_OPT(opt, "c", opts, "dmesg", 0) {
899 case 'c':
900 clear = 1;
901 break;
902 }
903
904 cr = libxl_xen_console_read_start(ctx, clear);
905 if (!cr)
906 goto finish;
907
908 while ((ret = libxl_xen_console_read_line(ctx, cr, &line)) > 0)
909 printf("%s", line);
910
911 finish:
912 if (cr)
913 libxl_xen_console_read_finish(ctx, cr);
914 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
915 }
916
main_top(int argc,char ** argv)917 int main_top(int argc, char **argv)
918 {
919 int opt;
920
921 SWITCH_FOREACH_OPT(opt, "", NULL, "top", 0) {
922 /* No options */
923 }
924
925 return system("xentop");
926 }
927
928
929 /*
930 * Local variables:
931 * mode: C
932 * c-basic-offset: 4
933 * indent-tabs-mode: nil
934 * End:
935 */
936