qemu: tpm: do not update profile name for transient domains
[libvirt.git] / tools / virsh-host.c
blob2fe64e415f79825e3a8437004663ccba05519fce
1 /*
2 * virsh-host.c: Commands in "Host and Hypervisor" group.
4 * Copyright (C) 2005, 2007-2014 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include "virsh-host.h"
23 #include "virsh.h"
25 #include <libxml/parser.h>
26 #include <libxml/xpath.h>
28 #include "internal.h"
29 #include "virbitmap.h"
30 #include "viralloc.h"
31 #include "virxml.h"
32 #include "virstring.h"
33 #include "virfile.h"
34 #include "virenum.h"
35 #include "virsh-util.h"
38 * "capabilities" command
40 static const vshCmdInfo info_capabilities = {
41 .help = N_("capabilities"),
42 .desc = N_("Returns capabilities of hypervisor/driver."),
45 static const vshCmdOptDef opts_capabilities[] = {
46 {.name = "xpath",
47 .type = VSH_OT_STRING,
48 .completer = virshCompleteEmpty,
49 .help = N_("xpath expression to filter the XML document")
51 {.name = "wrap",
52 .type = VSH_OT_BOOL,
53 .help = N_("wrap xpath results in an common root element"),
55 {.name = NULL}
58 static bool
59 cmdCapabilities(vshControl *ctl, const vshCmd *cmd)
61 g_autofree char *caps = NULL;
62 virshControl *priv = ctl->privData;
63 bool wrap = vshCommandOptBool(cmd, "wrap");
64 const char *xpath = NULL;
66 if (vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0)
67 return false;
69 if ((caps = virConnectGetCapabilities(priv->conn)) == NULL) {
70 vshError(ctl, "%s", _("failed to get capabilities"));
71 return false;
74 return virshDumpXML(ctl, caps, "capabilities", xpath, wrap);
78 * "domcapabilities" command
80 static const vshCmdInfo info_domcapabilities = {
81 .help = N_("domain capabilities"),
82 .desc = N_("Returns capabilities of emulator with respect to host and libvirt."),
85 static const vshCmdOptDef opts_domcapabilities[] = {
86 {.name = "virttype",
87 .type = VSH_OT_STRING,
88 .unwanted_positional = true,
89 .completer = virshDomainVirtTypeCompleter,
90 .help = N_("virtualization type (/domain/@type)"),
92 {.name = "emulatorbin",
93 .type = VSH_OT_STRING,
94 .unwanted_positional = true,
95 .help = N_("path to emulator binary (/domain/devices/emulator)"),
97 {.name = "arch",
98 .type = VSH_OT_STRING,
99 .unwanted_positional = true,
100 .completer = virshArchCompleter,
101 .help = N_("domain architecture (/domain/os/type/@arch)"),
103 {.name = "machine",
104 .type = VSH_OT_STRING,
105 .unwanted_positional = true,
106 .help = N_("machine type (/domain/os/type/@machine)"),
108 {.name = "xpath",
109 .type = VSH_OT_STRING,
110 .completer = virshCompleteEmpty,
111 .help = N_("xpath expression to filter the XML document")
113 {.name = "wrap",
114 .type = VSH_OT_BOOL,
115 .help = N_("wrap xpath results in an common root element"),
117 {.name = NULL}
120 static bool
121 cmdDomCapabilities(vshControl *ctl, const vshCmd *cmd)
123 g_autofree char *caps = NULL;
124 const char *virttype = NULL;
125 const char *emulatorbin = NULL;
126 const char *arch = NULL;
127 const char *machine = NULL;
128 const char *xpath = NULL;
129 const unsigned int flags = 0; /* No flags so far */
130 bool wrap = vshCommandOptBool(cmd, "wrap");
131 virshControl *priv = ctl->privData;
133 if (vshCommandOptString(ctl, cmd, "virttype", &virttype) < 0 ||
134 vshCommandOptString(ctl, cmd, "emulatorbin", &emulatorbin) < 0 ||
135 vshCommandOptString(ctl, cmd, "arch", &arch) < 0 ||
136 vshCommandOptString(ctl, cmd, "machine", &machine) < 0 ||
137 vshCommandOptStringQuiet(ctl, cmd, "xpath", &xpath) < 0)
138 return false;
140 caps = virConnectGetDomainCapabilities(priv->conn, emulatorbin,
141 arch, machine, virttype, flags);
142 if (!caps) {
143 vshError(ctl, "%s", _("failed to get emulator capabilities"));
144 return false;
147 return virshDumpXML(ctl, caps, "domcapabilities", xpath, wrap);
151 * "freecell" command
153 static const vshCmdInfo info_freecell = {
154 .help = N_("NUMA free memory"),
155 .desc = N_("display available free memory for the NUMA cell."),
158 static const vshCmdOptDef opts_freecell[] = {
159 {.name = "cellno",
160 .type = VSH_OT_INT,
161 .unwanted_positional = true,
162 .completer = virshCellnoCompleter,
163 .help = N_("NUMA cell number")
165 {.name = "all",
166 .type = VSH_OT_BOOL,
167 .help = N_("show free memory for all NUMA cells")
169 {.name = NULL}
172 static bool
173 cmdFreecell(vshControl *ctl, const vshCmd *cmd)
175 int cell = -1;
176 unsigned long long memory = 0;
177 g_autofree xmlNodePtr *nodes = NULL;
178 unsigned long nodes_cnt;
179 g_autofree unsigned long *nodes_id = NULL;
180 g_autofree unsigned long long *nodes_free = NULL;
181 bool all = vshCommandOptBool(cmd, "all");
182 bool cellno = vshCommandOptBool(cmd, "cellno");
183 size_t i;
184 g_autofree char *cap_xml = NULL;
185 g_autoptr(xmlXPathContext) ctxt = NULL;
186 virshControl *priv = ctl->privData;
188 VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
190 if (cellno && vshCommandOptInt(ctl, cmd, "cellno", &cell) < 0)
191 return false;
193 if (!all) {
194 if (cellno) {
195 if (virNodeGetCellsFreeMemory(priv->conn, &memory, cell, 1) != 1)
196 return false;
198 vshPrint(ctl, "%d: %llu KiB\n", cell, (memory/1024));
199 return true;
202 if ((memory = virNodeGetFreeMemory(priv->conn)) == 0)
203 return false;
205 vshPrint(ctl, "%s: %llu KiB\n", _("Total"), (memory/1024));
206 return true;
209 if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
210 vshError(ctl, "%s", _("unable to get node capabilities"));
211 return false;
214 if (!virXMLParseStringCtxt(cap_xml, _("(capabilities)"), &ctxt)) {
215 vshError(ctl, "%s", _("unable to get node capabilities"));
216 return false;
219 nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell",
220 ctxt, &nodes);
222 if (nodes_cnt == -1) {
223 vshError(ctl, "%s", _("could not get information about NUMA topology"));
224 return false;
227 nodes_free = g_new0(unsigned long long, nodes_cnt);
228 nodes_id = g_new0(unsigned long, nodes_cnt);
230 for (i = 0; i < nodes_cnt; i++) {
231 unsigned long id;
232 g_autofree char *val = virXMLPropString(nodes[i], "id");
233 if (virStrToLong_ulp(val, NULL, 10, &id)) {
234 vshError(ctl, "%s", _("conversion from string failed"));
235 return false;
237 nodes_id[i] = id;
238 if (virNodeGetCellsFreeMemory(priv->conn, &(nodes_free[i]),
239 id, 1) != 1) {
240 vshError(ctl, _("failed to get free memory for NUMA node number: %1$lu"),
241 id);
242 return false;
246 for (cell = 0; cell < nodes_cnt; cell++) {
247 vshPrint(ctl, "%5lu: %10llu KiB\n", nodes_id[cell],
248 (nodes_free[cell]/1024));
249 memory += nodes_free[cell];
252 vshPrintExtra(ctl, "--------------------\n");
253 vshPrintExtra(ctl, "%5s: %10llu KiB\n", _("Total"), memory/1024);
255 return true;
260 * "freepages" command
262 static const vshCmdInfo info_freepages = {
263 .help = N_("NUMA free pages"),
264 .desc = N_("display available free pages for the NUMA cell."),
267 static const vshCmdOptDef opts_freepages[] = {
268 {.name = "cellno",
269 .type = VSH_OT_INT,
270 .unwanted_positional = true,
271 .completer = virshCellnoCompleter,
272 .help = N_("NUMA cell number")
274 {.name = "pagesize",
275 .type = VSH_OT_INT,
276 .unwanted_positional = true,
277 .completer = virshAllocpagesPagesizeCompleter,
278 .help = N_("page size (in kibibytes)")
280 {.name = "all",
281 .type = VSH_OT_BOOL,
282 .help = N_("show free pages for all NUMA cells")
284 {.name = NULL}
287 static int
288 vshPageSizeSorter(const void *a,
289 const void *b,
290 void *opaque G_GNUC_UNUSED)
292 unsigned int pa = *(unsigned int *)a;
293 unsigned int pb = *(unsigned int *)b;
295 return pa - pb;
298 static bool
299 cmdFreepages(vshControl *ctl, const vshCmd *cmd)
301 bool ret = false;
302 unsigned int npages;
303 g_autofree unsigned int *pagesize = NULL;
304 unsigned long long bytes = 0;
305 unsigned int kibibytes = 0;
306 int cell;
307 g_autofree unsigned long long *counts = NULL;
308 size_t i, j;
309 xmlNodePtr *nodes = NULL;
310 int nodes_cnt;
311 g_autofree char *cap_xml = NULL;
312 g_autoptr(xmlDoc) doc = NULL;
313 g_autoptr(xmlXPathContext) ctxt = NULL;
314 bool all = vshCommandOptBool(cmd, "all");
315 bool cellno = vshCommandOptBool(cmd, "cellno");
316 bool pagesz = vshCommandOptBool(cmd, "pagesize");
317 virshControl *priv = ctl->privData;
318 bool pagesize_missing = false;
319 int rv = -1;
321 VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
323 if (vshCommandOptScaledInt(ctl, cmd, "pagesize", &bytes,
324 1024, UINT_MAX * 1024ULL) < 0) {
325 goto cleanup;
327 kibibytes = VIR_DIV_UP(bytes, 1024);
329 if (all) {
330 if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
331 vshError(ctl, "%s", _("unable to get node capabilities"));
332 goto cleanup;
335 if (!(doc = virXMLParseStringCtxt(cap_xml, _("capabilities"), &ctxt))) {
336 vshError(ctl, "%s", _("unable to parse node capabilities"));
337 goto cleanup;
340 if (!pagesz) {
341 nodes_cnt = virXPathNodeSet("/capabilities/host/cpu/pages", ctxt, &nodes);
343 if (nodes_cnt <= 0) {
344 /* Some drivers don't export page sizes under the
345 * XPath above. Do another trick to get them. */
346 nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell/pages",
347 ctxt, &nodes);
348 if (nodes_cnt <= 0) {
349 vshError(ctl, "%s", _("could not get information about supported page sizes"));
350 goto cleanup;
354 pagesize = g_new0(unsigned int, nodes_cnt);
356 for (i = 0; i < nodes_cnt; i++) {
357 g_autofree char *val = virXMLPropString(nodes[i], "size");
359 if (virStrToLong_uip(val, NULL, 10, &pagesize[i]) < 0) {
360 vshError(ctl, _("unable to parse page size: %1$s"), val);
361 goto cleanup;
365 /* Here, if we've done the trick few lines above,
366 * @pagesize array will contain duplicates. We should
367 * remove them otherwise not very nice output will be
368 * produced. */
369 g_qsort_with_data(pagesize, nodes_cnt,
370 sizeof(*pagesize), vshPageSizeSorter, NULL);
372 for (i = 0; i < nodes_cnt - 1;) {
373 if (pagesize[i] == pagesize[i + 1]) {
374 memmove(pagesize + i, pagesize + i + 1,
375 (nodes_cnt - i + 1) * sizeof(*pagesize));
376 nodes_cnt--;
377 } else {
378 i++;
382 npages = nodes_cnt;
383 VIR_FREE(nodes);
384 } else {
385 pagesize = g_new0(unsigned int, 1);
386 pagesize[0] = kibibytes;
387 npages = 1;
390 counts = g_new0(unsigned long long, npages);
392 nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell",
393 ctxt, &nodes);
394 for (i = 0; i < nodes_cnt; i++) {
395 g_autofree char *val = virXMLPropString(nodes[i], "id");
397 if (virStrToLong_i(val, NULL, 10, &cell) < 0) {
398 vshError(ctl, _("unable to parse numa node id: %1$s"), val);
399 goto cleanup;
402 rv = virNodeGetFreePages(priv->conn, npages, pagesize,
403 cell, 1, counts, 0);
404 if (rv < 0)
405 goto cleanup;
407 if (rv < npages) {
408 pagesize_missing = true;
409 vshError(ctl, _("Did not get all free page data for node %1$d"), cell);
410 continue;
413 vshPrint(ctl, _("Node %1$d:\n"), cell);
414 for (j = 0; j < npages; j++)
415 vshPrint(ctl, "%uKiB: %lld\n", pagesize[j], counts[j]);
416 vshPrint(ctl, "%c", '\n');
418 } else {
419 if (!cellno) {
420 vshError(ctl, "%s", _("missing cellno argument"));
421 goto cleanup;
424 if (vshCommandOptInt(ctl, cmd, "cellno", &cell) < 0)
425 goto cleanup;
427 if (cell < -1) {
428 vshError(ctl, "%s",
429 _("cell number must be non-negative integer or -1"));
430 goto cleanup;
433 if (!pagesz) {
434 vshError(ctl, "%s", _("missing pagesize argument"));
435 goto cleanup;
438 /* page size is expected in kibibytes */
439 pagesize = g_new0(unsigned int, 1);
440 pagesize[0] = kibibytes;
442 counts = g_new0(unsigned long long, 1);
444 rv = virNodeGetFreePages(priv->conn, 1, pagesize,
445 cell, 1, counts, 0);
446 if (rv < 0)
447 goto cleanup;
449 if (rv == 0) {
450 vshError(ctl,
451 "Could not get count of free %uKiB pages, no data returned",
452 *pagesize);
453 goto cleanup;
456 vshPrint(ctl, "%uKiB: %lld\n", *pagesize, counts[0]);
459 ret = !pagesize_missing;
460 cleanup:
461 VIR_FREE(nodes);
462 return ret;
467 * "allocpages" command
469 static const vshCmdInfo info_allocpages = {
470 .help = N_("Manipulate pages pool size"),
471 .desc = N_("Allocate or free some pages in the pool for NUMA cell."),
473 static const vshCmdOptDef opts_allocpages[] = {
474 {.name = "pagesize",
475 .type = VSH_OT_INT,
476 .positional = true,
477 .required = true,
478 .completer = virshAllocpagesPagesizeCompleter,
479 .help = N_("page size (in kibibytes)")
481 {.name = "pagecount",
482 .type = VSH_OT_INT,
483 .positional = true,
484 .required = true,
485 .help = N_("page count")
487 {.name = "cellno",
488 .type = VSH_OT_INT,
489 .unwanted_positional = true,
490 .completer = virshCellnoCompleter,
491 .help = N_("NUMA cell number")
493 {.name = "add",
494 .type = VSH_OT_BOOL,
495 .help = N_("instead of setting new pool size add pages to it")
497 {.name = "all",
498 .type = VSH_OT_BOOL,
499 .help = N_("set on all NUMA cells")
501 {.name = NULL}
504 static bool
505 cmdAllocpages(vshControl *ctl, const vshCmd *cmd)
507 bool add = vshCommandOptBool(cmd, "add");
508 bool all = vshCommandOptBool(cmd, "all");
509 bool cellno = vshCommandOptBool(cmd, "cellno");
510 int startCell = -1;
511 int cellCount = 1;
512 unsigned int pageSizes[1];
513 unsigned long long pageCounts[1], tmp;
514 unsigned int flags = 0;
515 g_autofree char *cap_xml = NULL;
516 g_autoptr(xmlDoc) xml = NULL;
517 g_autoptr(xmlXPathContext) ctxt = NULL;
518 g_autofree xmlNodePtr *nodes = NULL;
519 virshControl *priv = ctl->privData;
521 VSH_EXCLUSIVE_OPTIONS_VAR(all, cellno);
523 if (cellno && vshCommandOptInt(ctl, cmd, "cellno", &startCell) < 0)
524 return false;
526 if (vshCommandOptScaledInt(ctl, cmd, "pagesize", &tmp, 1024, UINT_MAX * 1024ULL) < 0)
527 return false;
528 pageSizes[0] = VIR_DIV_UP(tmp, 1024);
530 if (vshCommandOptULongLong(ctl, cmd, "pagecount", &pageCounts[0]) < 0)
531 return false;
533 flags |= add ? VIR_NODE_ALLOC_PAGES_ADD : VIR_NODE_ALLOC_PAGES_SET;
535 if (all) {
536 unsigned long nodes_cnt;
537 size_t i;
539 if (!(cap_xml = virConnectGetCapabilities(priv->conn))) {
540 vshError(ctl, "%s", _("unable to get node capabilities"));
541 return false;
544 xml = virXMLParseStringCtxt(cap_xml, _("(capabilities)"), &ctxt);
545 if (!xml) {
546 vshError(ctl, "%s", _("unable to get node capabilities"));
547 return false;
550 nodes_cnt = virXPathNodeSet("/capabilities/host/topology/cells/cell",
551 ctxt, &nodes);
553 if (nodes_cnt == -1) {
554 vshError(ctl, "%s", _("could not get information about NUMA topology"));
555 return false;
558 for (i = 0; i < nodes_cnt; i++) {
559 unsigned long id;
560 g_autofree char *val = virXMLPropString(nodes[i], "id");
561 if (virStrToLong_ulp(val, NULL, 10, &id)) {
562 vshError(ctl, "%s", _("conversion from string failed"));
563 return false;
566 if (virNodeAllocPages(priv->conn, 1, pageSizes,
567 pageCounts, id, 1, flags) < 0)
568 return false;
570 } else {
571 if (virNodeAllocPages(priv->conn, 1, pageSizes, pageCounts,
572 startCell, cellCount, flags) < 0)
573 return false;
576 return true;
581 * "maxvcpus" command
583 static const vshCmdInfo info_maxvcpus = {
584 .help = N_("connection vcpu maximum"),
585 .desc = N_("Show maximum number of virtual CPUs for guests on this connection."),
588 static const vshCmdOptDef opts_maxvcpus[] = {
589 {.name = "type",
590 .type = VSH_OT_STRING,
591 .unwanted_positional = true,
592 .completer = virshDomainVirtTypeCompleter,
593 .help = N_("domain type")
595 {.name = NULL}
598 static bool
599 cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd)
601 const char *type = NULL;
602 int vcpus = -1;
603 g_autofree char *caps = NULL;
604 g_autoptr(xmlDoc) xml = NULL;
605 g_autoptr(xmlXPathContext) ctxt = NULL;
606 virshControl *priv = ctl->privData;
608 if (vshCommandOptString(ctl, cmd, "type", &type) < 0)
609 return false;
611 if ((caps = virConnectGetDomainCapabilities(priv->conn, NULL, NULL, NULL,
612 type, 0))) {
613 if (!(xml = virXMLParseStringCtxt(caps, _("(domainCapabilities)"), &ctxt)))
614 return false;
616 ignore_value(virXPathInt("string(./vcpu[1]/@max)", ctxt, &vcpus));
617 } else {
618 vshResetLibvirtError();
621 if (vcpus < 0 && (vcpus = virConnectGetMaxVcpus(priv->conn, type)) < 0)
622 return false;
624 vshPrint(ctl, "%d\n", vcpus);
626 return true;
630 * "nodeinfo" command
632 static const vshCmdInfo info_nodeinfo = {
633 .help = N_("node information"),
634 .desc = N_("Returns basic information about the node."),
637 static bool
638 cmdNodeinfo(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
640 virNodeInfo info;
641 virshControl *priv = ctl->privData;
643 if (virNodeGetInfo(priv->conn, &info) < 0) {
644 vshError(ctl, "%s", _("failed to get node information"));
645 return false;
647 vshPrint(ctl, "%-20s %s\n", _("CPU model:"), info.model);
648 vshPrint(ctl, "%-20s %d\n", _("CPU(s):"), info.cpus);
649 if (info.mhz)
650 vshPrint(ctl, "%-20s %d MHz\n", _("CPU frequency:"), info.mhz);
651 vshPrint(ctl, "%-20s %d\n", _("CPU socket(s):"), info.sockets);
652 vshPrint(ctl, "%-20s %d\n", _("Core(s) per socket:"), info.cores);
653 vshPrint(ctl, "%-20s %d\n", _("Thread(s) per core:"), info.threads);
654 vshPrint(ctl, "%-20s %d\n", _("NUMA cell(s):"), info.nodes);
655 vshPrint(ctl, "%-20s %lu KiB\n", _("Memory size:"), info.memory);
657 return true;
661 * "nodecpumap" command
663 static const vshCmdInfo info_node_cpumap = {
664 .help = N_("node cpu map"),
665 .desc = N_("Displays the node's total number of CPUs, the number of"
666 " online CPUs and the list of online CPUs."),
669 static const vshCmdOptDef opts_node_cpumap[] = {
670 {.name = "pretty",
671 .type = VSH_OT_BOOL,
672 .help = N_("return human readable output")
674 {.name = NULL}
677 static bool
678 cmdNodeCpuMap(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
680 int cpu, cpunum;
681 g_autofree unsigned char *cpumap = NULL;
682 unsigned int online;
683 bool pretty = vshCommandOptBool(cmd, "pretty");
684 virshControl *priv = ctl->privData;
686 cpunum = virNodeGetCPUMap(priv->conn, &cpumap, &online, 0);
687 if (cpunum < 0) {
688 vshError(ctl, "%s", _("Unable to get cpu map"));
689 return false;
692 vshPrint(ctl, "%-15s %d\n", _("CPUs present:"), cpunum);
693 vshPrint(ctl, "%-15s %d\n", _("CPUs online:"), online);
695 vshPrint(ctl, "%-15s ", _("CPU map:"));
696 if (pretty) {
697 g_autofree char *str = virBitmapDataFormat(cpumap, VIR_CPU_MAPLEN(cpunum));
699 if (!str)
700 return false;
701 vshPrint(ctl, "%s", str);
702 } else {
703 for (cpu = 0; cpu < cpunum; cpu++)
704 vshPrint(ctl, "%c", VIR_CPU_USED(cpumap, cpu) ? 'y' : '-');
706 vshPrint(ctl, "\n");
708 return true;
712 * "nodecpustats" command
714 static const vshCmdInfo info_nodecpustats = {
715 .help = N_("Prints cpu stats of the node."),
716 .desc = N_("Returns cpu stats of the node, in nanoseconds."),
719 static const vshCmdOptDef opts_node_cpustats[] = {
720 {.name = "cpu",
721 .type = VSH_OT_INT,
722 .unwanted_positional = true,
723 .completer = virshNodeCpuCompleter,
724 .help = N_("prints specified cpu statistics only.")
726 {.name = "percent",
727 .type = VSH_OT_BOOL,
728 .help = N_("prints by percentage during 1 second.")
730 {.name = NULL}
733 typedef enum {
734 VIRSH_CPU_USER,
735 VIRSH_CPU_SYSTEM,
736 VIRSH_CPU_IDLE,
737 VIRSH_CPU_IOWAIT,
738 VIRSH_CPU_INTR,
739 VIRSH_CPU_USAGE,
740 VIRSH_CPU_LAST
741 } virshCPUStats;
743 VIR_ENUM_DECL(virshCPUStats);
744 VIR_ENUM_IMPL(virshCPUStats,
745 VIRSH_CPU_LAST,
746 VIR_NODE_CPU_STATS_USER,
747 VIR_NODE_CPU_STATS_KERNEL,
748 VIR_NODE_CPU_STATS_IDLE,
749 VIR_NODE_CPU_STATS_IOWAIT,
750 VIR_NODE_CPU_STATS_INTR,
751 VIR_NODE_CPU_STATS_UTILIZATION);
753 const char *virshCPUOutput[] = {
754 N_("user:"),
755 N_("system:"),
756 N_("idle:"),
757 N_("iowait:"),
758 N_("intr:"),
759 N_("usage:")
762 static bool
763 cmdNodeCpuStats(vshControl *ctl, const vshCmd *cmd)
765 size_t i, j;
766 bool flag_percent = vshCommandOptBool(cmd, "percent");
767 int cpuNum = VIR_NODE_CPU_STATS_ALL_CPUS;
768 g_autofree virNodeCPUStatsPtr params = NULL;
769 int nparams = 0;
770 unsigned long long cpu_stats[VIRSH_CPU_LAST] = { 0 };
771 bool present[VIRSH_CPU_LAST] = { false };
772 virshControl *priv = ctl->privData;
774 if (vshCommandOptInt(ctl, cmd, "cpu", &cpuNum) < 0)
775 return false;
777 if (virNodeGetCPUStats(priv->conn, cpuNum, NULL, &nparams, 0) != 0) {
778 vshError(ctl, "%s",
779 _("Unable to get number of cpu stats"));
780 return false;
782 if (nparams == 0) {
783 /* nothing to output */
784 return true;
787 memset(cpu_stats, 0, sizeof(cpu_stats));
788 params = g_new0(virNodeCPUStats, nparams);
790 for (i = 0; i < 2; i++) {
791 if (virNodeGetCPUStats(priv->conn, cpuNum, params, &nparams, 0) != 0) {
792 vshError(ctl, "%s", _("Unable to get node cpu stats"));
793 return false;
796 for (j = 0; j < nparams; j++) {
797 int field = virshCPUStatsTypeFromString(params[j].field);
799 if (field < 0)
800 continue;
802 if (i == 0) {
803 cpu_stats[field] = params[j].value;
804 present[field] = true;
805 } else if (present[field]) {
806 cpu_stats[field] = params[j].value - cpu_stats[field];
810 if (present[VIRSH_CPU_USAGE] || !flag_percent)
811 break;
813 sleep(1);
816 if (!flag_percent) {
817 for (i = 0; i < VIRSH_CPU_USAGE; i++) {
818 if (present[i]) {
819 vshPrint(ctl, "%-15s %20llu\n", _(virshCPUOutput[i]),
820 cpu_stats[i]);
823 return true;
826 if (present[VIRSH_CPU_USAGE]) {
827 vshPrint(ctl, "%-15s %5.1llu%%\n",
828 _("usage:"), cpu_stats[VIRSH_CPU_USAGE]);
829 vshPrint(ctl, "%-15s %5.1llu%%\n",
830 _("idle:"), 100 - cpu_stats[VIRSH_CPU_USAGE]);
831 } else {
832 double usage, total_time = 0;
833 for (i = 0; i < VIRSH_CPU_USAGE; i++)
834 total_time += cpu_stats[i];
836 usage = (cpu_stats[VIRSH_CPU_USER] + cpu_stats[VIRSH_CPU_SYSTEM])
837 / total_time * 100;
839 vshPrint(ctl, "%-15s %5.1lf%%\n", _("usage:"), usage);
840 for (i = 0; i < VIRSH_CPU_USAGE; i++) {
841 if (present[i]) {
842 vshPrint(ctl, "%-15s %5.1lf%%\n", _(virshCPUOutput[i]),
843 cpu_stats[i] / total_time * 100);
847 return true;
851 * "nodememstats" command
853 static const vshCmdInfo info_nodememstats = {
854 .help = N_("Prints memory stats of the node."),
855 .desc = N_("Returns memory stats of the node, in kilobytes."),
858 static const vshCmdOptDef opts_node_memstats[] = {
859 {.name = "cell",
860 .type = VSH_OT_INT,
861 .unwanted_positional = true,
862 .help = N_("prints specified cell statistics only.")
864 {.name = NULL}
867 static bool
868 cmdNodeMemStats(vshControl *ctl, const vshCmd *cmd)
870 int nparams = 0;
871 size_t i;
872 int cellNum = VIR_NODE_MEMORY_STATS_ALL_CELLS;
873 g_autofree virNodeMemoryStatsPtr params = NULL;
874 virshControl *priv = ctl->privData;
876 if (vshCommandOptInt(ctl, cmd, "cell", &cellNum) < 0)
877 return false;
879 /* get the number of memory parameters */
880 if (virNodeGetMemoryStats(priv->conn, cellNum, NULL, &nparams, 0) != 0) {
881 vshError(ctl, "%s",
882 _("Unable to get number of memory stats"));
883 return false;
886 if (nparams == 0) {
887 /* nothing to output */
888 return true;
891 /* now go get all the memory parameters */
892 params = g_new0(virNodeMemoryStats, nparams);
893 if (virNodeGetMemoryStats(priv->conn, cellNum, params, &nparams, 0) != 0) {
894 vshError(ctl, "%s", _("Unable to get memory stats"));
895 return false;
898 for (i = 0; i < nparams; i++)
899 vshPrint(ctl, "%-7s: %20llu KiB\n", params[i].field, params[i].value);
901 return true;
905 * "nodesevinfo" command
907 static const vshCmdInfo info_nodesevinfo = {
908 .help = N_("node SEV information"),
909 .desc = N_("Returns basic SEV information about the node."),
912 static bool
913 cmdNodeSEVInfo(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
915 virshControl *priv = ctl->privData;
916 size_t i;
917 int nparams = 0;
918 virTypedParameterPtr params = NULL;
919 bool ret = false;
921 if (virNodeGetSEVInfo(priv->conn, &params, &nparams, 0) != 0) {
922 vshError(ctl, "%s", _("Unable to get host SEV information"));
923 goto cleanup;
926 for (i = 0; i < nparams; i++) {
927 g_autofree char *str = vshGetTypedParamValue(ctl, &params[i]);
928 vshPrint(ctl, "%-18s: %s\n", params[i].field, str);
931 ret = true;
933 cleanup:
934 virTypedParamsFree(params, nparams);
935 return ret;
939 * "nodesuspend" command
942 VIR_ENUM_IMPL(virshNodeSuspendTarget,
943 VIR_NODE_SUSPEND_TARGET_LAST,
944 "mem",
945 "disk",
946 "hybrid");
948 static const vshCmdInfo info_nodesuspend = {
949 .help = N_("suspend the host node for a given time duration"),
950 .desc = N_("Suspend the host node for a given time duration "
951 "and attempt to resume thereafter."),
954 static const vshCmdOptDef opts_node_suspend[] = {
955 {.name = "target",
956 .type = VSH_OT_STRING,
957 .positional = true,
958 .required = true,
959 .completer = virshNodeSuspendTargetCompleter,
960 .help = N_("mem(Suspend-to-RAM), disk(Suspend-to-Disk), "
961 "hybrid(Hybrid-Suspend)")
963 {.name = "duration",
964 .type = VSH_OT_INT,
965 .positional = true,
966 .required = true,
967 .help = N_("Suspend duration in seconds, at least 60")
969 {.name = NULL}
972 static bool
973 cmdNodeSuspend(vshControl *ctl, const vshCmd *cmd)
975 const char *target = NULL;
976 int suspendTarget;
977 long long duration;
978 virshControl *priv = ctl->privData;
980 if (vshCommandOptString(ctl, cmd, "target", &target) < 0)
981 return false;
983 if (vshCommandOptLongLong(ctl, cmd, "duration", &duration) < 0)
984 return false;
986 if ((suspendTarget = virshNodeSuspendTargetTypeFromString(target)) < 0) {
987 vshError(ctl, "%s", _("Invalid target"));
988 return false;
991 if (duration < 0) {
992 vshError(ctl, "%s", _("Invalid duration"));
993 return false;
996 if (virNodeSuspendForDuration(priv->conn, suspendTarget, duration, 0) < 0) {
997 vshError(ctl, "%s", _("The host was not suspended"));
998 return false;
1000 return true;
1004 * "sysinfo" command
1006 static const vshCmdInfo info_sysinfo = {
1007 .help = N_("print the hypervisor sysinfo"),
1008 .desc = N_("output an XML string for the hypervisor sysinfo, if available"),
1011 static bool
1012 cmdSysinfo(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
1014 g_autofree char *sysinfo = NULL;
1015 virshControl *priv = ctl->privData;
1017 sysinfo = virConnectGetSysinfo(priv->conn, 0);
1018 if (sysinfo == NULL) {
1019 vshError(ctl, "%s", _("failed to get sysinfo"));
1020 return false;
1023 vshPrint(ctl, "%s", sysinfo);
1025 return true;
1029 * "hostname" command
1031 static const vshCmdInfo info_hostname = {
1032 .help = N_("print the hypervisor hostname"),
1033 .desc = "",
1036 static bool
1037 cmdHostname(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
1039 g_autofree char *hostname = NULL;
1040 virshControl *priv = ctl->privData;
1042 hostname = virConnectGetHostname(priv->conn);
1043 if (hostname == NULL) {
1044 vshError(ctl, "%s", _("failed to get hostname"));
1045 return false;
1048 vshPrint(ctl, "%s\n", hostname);
1050 return true;
1054 * "uri" command
1056 static const vshCmdInfo info_uri = {
1057 .help = N_("print the hypervisor canonical URI"),
1058 .desc = "",
1061 static bool
1062 cmdURI(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
1064 g_autofree char *uri = NULL;
1065 virshControl *priv = ctl->privData;
1067 uri = virConnectGetURI(priv->conn);
1068 if (uri == NULL) {
1069 vshError(ctl, "%s", _("failed to get URI"));
1070 return false;
1073 vshPrint(ctl, "%s\n", uri);
1075 return true;
1079 /* Extracts the CPU definition XML strings from a file which may contain either
1080 * - just the CPU definitions,
1081 * - domain XMLs,
1082 * - capabilities XMLs, or
1083 * - domain capabilities XMLs.
1085 * Returns NULL terminated string list.
1087 static char **
1088 vshExtractCPUDefXMLs(vshControl *ctl,
1089 const char *xmlFile)
1091 g_auto(GStrv) cpus = NULL;
1092 g_autofree char *buffer = NULL;
1093 g_autofree char *xmlStr = NULL;
1094 g_autoptr(xmlDoc) xml = NULL;
1095 g_autoptr(xmlXPathContext) ctxt = NULL;
1096 g_autofree xmlNodePtr *nodes = NULL;
1097 char *doc;
1098 size_t i;
1099 int n;
1101 if (virFileReadAll(xmlFile, VSH_MAX_XML_FILE, &buffer) < 0)
1102 return NULL;
1104 /* Strip possible XML declaration */
1105 if (STRPREFIX(buffer, "<?xml") && (doc = strstr(buffer, "?>")))
1106 doc += 2;
1107 else
1108 doc = buffer;
1110 xmlStr = g_strdup_printf("<container>%s</container>", doc);
1112 if (!(xml = virXMLParseStringCtxt(xmlStr, xmlFile, &ctxt)))
1113 return NULL;
1115 n = virXPathNodeSet("/container/cpu|"
1116 "/container/domain/cpu|"
1117 "/container/capabilities/host/cpu|"
1118 "/container/domainCapabilities/cpu/"
1119 "mode[@name='host-model' and @supported='yes']",
1120 ctxt, &nodes);
1121 if (n < 0)
1122 return NULL;
1124 if (n == 0) {
1125 vshError(ctl, _("File '%1$s' does not contain any <cpu> element or valid domain XML, host capabilities XML, or domain capabilities XML"),
1126 xmlFile);
1127 return NULL;
1130 cpus = g_new0(char *, n + 1);
1132 for (i = 0; i < n; i++) {
1133 /* If the user provided domain capabilities XML, we need to replace
1134 * <mode ...> element with <cpu>. */
1135 if (xmlStrEqual(nodes[i]->name, BAD_CAST "mode")) {
1136 xmlNodeSetName(nodes[i], (const xmlChar *)"cpu");
1137 while (nodes[i]->properties) {
1138 if (xmlRemoveProp(nodes[i]->properties) < 0) {
1139 vshError(ctl,
1140 _("Cannot extract CPU definition from domain capabilities XML"));
1141 return NULL;
1146 if (!(cpus[i] = virXMLNodeToString(xml, nodes[i]))) {
1147 vshSaveLibvirtError();
1148 return NULL;
1152 return g_steal_pointer(&cpus);
1157 * "cpu-compare" command
1159 static const vshCmdInfo info_cpu_compare = {
1160 .help = N_("compare host CPU with a CPU described by an XML file"),
1161 .desc = N_("compare CPU with host CPU"),
1164 static const vshCmdOptDef opts_cpu_compare[] = {
1165 VIRSH_COMMON_OPT_FILE(N_("file containing an XML CPU description")),
1166 {.name = "error",
1167 .type = VSH_OT_BOOL,
1168 .help = N_("report error if CPUs are incompatible")
1170 {.name = "validate",
1171 .type = VSH_OT_BOOL,
1172 .help = N_("validate the XML document against schema")
1174 {.name = NULL}
1177 static bool
1178 cmdCPUCompare(vshControl *ctl, const vshCmd *cmd)
1180 const char *from = NULL;
1181 int result;
1182 g_auto(GStrv) cpus = NULL;
1183 unsigned int flags = 0;
1184 virshControl *priv = ctl->privData;
1186 if (vshCommandOptBool(cmd, "error"))
1187 flags |= VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE;
1189 if (vshCommandOptBool(cmd, "validate"))
1190 flags |= VIR_CONNECT_COMPARE_CPU_VALIDATE_XML;
1192 if (vshCommandOptString(ctl, cmd, "file", &from) < 0)
1193 return false;
1195 if (!(cpus = vshExtractCPUDefXMLs(ctl, from)))
1196 return false;
1198 result = virConnectCompareCPU(priv->conn, cpus[0], flags);
1200 switch (result) {
1201 case VIR_CPU_COMPARE_INCOMPATIBLE:
1202 vshPrint(ctl, _("CPU described in %1$s is incompatible with host CPU\n"),
1203 from);
1204 return false;
1205 break;
1207 case VIR_CPU_COMPARE_IDENTICAL:
1208 vshPrint(ctl, _("CPU described in %1$s is identical to host CPU\n"),
1209 from);
1210 break;
1212 case VIR_CPU_COMPARE_SUPERSET:
1213 vshPrint(ctl, _("Host CPU is a superset of CPU described in %1$s\n"),
1214 from);
1215 break;
1217 case VIR_CPU_COMPARE_ERROR:
1218 default:
1219 vshError(ctl, _("Failed to compare host CPU with %1$s"), from);
1220 return false;
1223 return true;
1227 * "cpu-baseline" command
1229 static const vshCmdInfo info_cpu_baseline = {
1230 .help = N_("compute baseline CPU"),
1231 .desc = N_("Compute baseline CPU for a set of given CPUs."),
1234 static const vshCmdOptDef opts_cpu_baseline[] = {
1235 VIRSH_COMMON_OPT_FILE(N_("file containing XML CPU descriptions")),
1236 {.name = "features",
1237 .type = VSH_OT_BOOL,
1238 .help = N_("Show features that are part of the CPU model type")
1240 {.name = "migratable",
1241 .type = VSH_OT_BOOL,
1242 .help = N_("Do not include features that block migration")
1244 {.name = NULL}
1247 static bool
1248 cmdCPUBaseline(vshControl *ctl, const vshCmd *cmd)
1250 const char *from = NULL;
1251 g_autofree char *result = NULL;
1252 g_auto(GStrv) list = NULL;
1253 unsigned int flags = 0;
1254 virshControl *priv = ctl->privData;
1256 if (vshCommandOptBool(cmd, "features"))
1257 flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
1258 if (vshCommandOptBool(cmd, "migratable"))
1259 flags |= VIR_CONNECT_BASELINE_CPU_MIGRATABLE;
1261 if (vshCommandOptString(ctl, cmd, "file", &from) < 0)
1262 return false;
1264 if (!(list = vshExtractCPUDefXMLs(ctl, from)))
1265 return false;
1267 if (!(result = virConnectBaselineCPU(priv->conn, (const char **)list,
1268 g_strv_length(list), flags)))
1269 return false;
1271 vshPrint(ctl, "%s", result);
1272 return true;
1276 * "cpu-models" command
1278 static const vshCmdInfo info_cpu_models = {
1279 .help = N_("CPU models"),
1280 .desc = N_("Get the CPU models for an arch."),
1283 static const vshCmdOptDef opts_cpu_models[] = {
1284 {.name = "arch",
1285 .type = VSH_OT_STRING,
1286 .positional = true,
1287 .required = true,
1288 .completer = virshArchCompleter,
1289 .help = N_("architecture")
1291 {.name = NULL}
1294 static bool
1295 cmdCPUModelNames(vshControl *ctl, const vshCmd *cmd)
1297 char **models;
1298 size_t i;
1299 int nmodels;
1300 const char *arch = NULL;
1301 virshControl *priv = ctl->privData;
1303 if (vshCommandOptString(ctl, cmd, "arch", &arch) < 0)
1304 return false;
1306 nmodels = virConnectGetCPUModelNames(priv->conn, arch, &models, 0);
1307 if (nmodels < 0) {
1308 vshError(ctl, "%s", _("failed to get CPU model names"));
1309 return false;
1312 if (nmodels == 0) {
1313 vshPrintExtra(ctl, "%s\n", _("all CPU models are accepted"));
1314 } else {
1315 for (i = 0; i < nmodels; i++) {
1316 vshPrint(ctl, "%s\n", models[i]);
1317 VIR_FREE(models[i]);
1320 VIR_FREE(models);
1322 return true;
1326 * "version" command
1328 static const vshCmdInfo info_version = {
1329 .help = N_("show version"),
1330 .desc = N_("Display the system version information."),
1333 static const vshCmdOptDef opts_version[] = {
1334 {.name = "daemon",
1335 .type = VSH_OT_BOOL,
1336 .help = N_("report daemon version too")
1338 {.name = NULL}
1341 static bool
1342 cmdVersion(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
1344 unsigned long hvVersion;
1345 const char *hvType;
1346 unsigned long libVersion;
1347 unsigned long includeVersion;
1348 unsigned long apiVersion;
1349 unsigned long daemonVersion;
1350 unsigned int major;
1351 unsigned int minor;
1352 unsigned int rel;
1353 virshControl *priv = ctl->privData;
1355 hvType = virConnectGetType(priv->conn);
1356 if (hvType == NULL) {
1357 vshError(ctl, "%s", _("failed to get hypervisor type"));
1358 return false;
1361 includeVersion = LIBVIR_VERSION_NUMBER;
1362 major = includeVersion / 1000000;
1363 includeVersion %= 1000000;
1364 minor = includeVersion / 1000;
1365 rel = includeVersion % 1000;
1366 vshPrint(ctl, _("Compiled against library: libvirt %1$d.%2$d.%3$d\n"),
1367 major, minor, rel);
1369 if (virGetVersion(&libVersion, hvType, &apiVersion) < 0) {
1370 vshError(ctl, "%s", _("failed to get the library version"));
1371 return false;
1373 major = libVersion / 1000000;
1374 libVersion %= 1000000;
1375 minor = libVersion / 1000;
1376 rel = libVersion % 1000;
1377 vshPrint(ctl, _("Using library: libvirt %1$d.%2$d.%3$d\n"),
1378 major, minor, rel);
1380 major = apiVersion / 1000000;
1381 apiVersion %= 1000000;
1382 minor = apiVersion / 1000;
1383 rel = apiVersion % 1000;
1384 vshPrint(ctl, _("Using API: %1$s %2$d.%3$d.%4$d\n"), hvType,
1385 major, minor, rel);
1387 if (virConnectGetVersion(priv->conn, &hvVersion) < 0) {
1388 if (last_error->code == VIR_ERR_NO_SUPPORT) {
1389 vshResetLibvirtError();
1390 } else {
1391 vshError(ctl, "%s", _("failed to get the hypervisor version"));
1392 return false;
1394 } else {
1395 if (hvVersion == 0) {
1396 vshPrint(ctl,
1397 _("Cannot extract running %1$s hypervisor version\n"), hvType);
1398 } else {
1399 major = hvVersion / 1000000;
1400 hvVersion %= 1000000;
1401 minor = hvVersion / 1000;
1402 rel = hvVersion % 1000;
1404 vshPrint(ctl, _("Running hypervisor: %1$s %2$d.%3$d.%4$d\n"),
1405 hvType, major, minor, rel);
1409 if (vshCommandOptBool(cmd, "daemon")) {
1410 if (virConnectGetLibVersion(priv->conn, &daemonVersion) < 0) {
1411 vshError(ctl, "%s", _("failed to get the daemon version"));
1412 } else {
1413 major = daemonVersion / 1000000;
1414 daemonVersion %= 1000000;
1415 minor = daemonVersion / 1000;
1416 rel = daemonVersion % 1000;
1417 vshPrint(ctl, _("Running against daemon: %1$d.%2$d.%3$d\n"),
1418 major, minor, rel);
1422 return true;
1425 static const vshCmdInfo info_node_memory_tune = {
1426 .help = N_("Get or set node memory parameters"),
1427 .desc = N_("Get or set node memory parameters"),
1430 static const vshCmdOptDef opts_node_memory_tune[] = {
1431 {.name = "shm-pages-to-scan",
1432 .type = VSH_OT_INT,
1433 .unwanted_positional = true,
1434 .help = N_("number of pages to scan before the shared memory service "
1435 "goes to sleep")
1437 {.name = "shm-sleep-millisecs",
1438 .type = VSH_OT_INT,
1439 .unwanted_positional = true,
1440 .help = N_("number of millisecs the shared memory service should "
1441 "sleep before next scan")
1443 {.name = "shm-merge-across-nodes",
1444 .type = VSH_OT_INT,
1445 .unwanted_positional = true,
1446 .help = N_("Specifies if pages from different numa nodes can be merged")
1448 {.name = NULL}
1451 static bool
1452 cmdNodeMemoryTune(vshControl *ctl, const vshCmd *cmd)
1454 virTypedParameterPtr params = NULL;
1455 int nparams = 0;
1456 int maxparams = 0;
1457 unsigned int flags = 0;
1458 unsigned int value;
1459 bool ret = false;
1460 int rc = -1;
1461 size_t i;
1462 virshControl *priv = ctl->privData;
1464 if ((rc = vshCommandOptUInt(ctl, cmd, "shm-pages-to-scan", &value)) < 0) {
1465 goto cleanup;
1466 } else if (rc > 0) {
1467 if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
1468 VIR_NODE_MEMORY_SHARED_PAGES_TO_SCAN,
1469 value) < 0)
1470 goto save_error;
1473 if ((rc = vshCommandOptUInt(ctl, cmd, "shm-sleep-millisecs", &value)) < 0) {
1474 goto cleanup;
1475 } else if (rc > 0) {
1476 if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
1477 VIR_NODE_MEMORY_SHARED_SLEEP_MILLISECS,
1478 value) < 0)
1479 goto save_error;
1482 if ((rc = vshCommandOptUInt(ctl, cmd, "shm-merge-across-nodes", &value)) < 0) {
1483 goto cleanup;
1484 } else if (rc > 0) {
1485 if (virTypedParamsAddUInt(&params, &nparams, &maxparams,
1486 VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES,
1487 value) < 0)
1488 goto save_error;
1491 if (nparams == 0) {
1492 /* Get the number of memory parameters */
1493 if (virNodeGetMemoryParameters(priv->conn, NULL, &nparams, flags) != 0) {
1494 vshError(ctl, "%s",
1495 _("Unable to get number of memory parameters"));
1496 goto cleanup;
1499 if (nparams == 0) {
1500 ret = true;
1501 goto cleanup;
1504 /* Now go get all the memory parameters */
1505 params = g_new0(virTypedParameter, nparams);
1506 if (virNodeGetMemoryParameters(priv->conn, params, &nparams, flags) != 0) {
1507 vshError(ctl, "%s", _("Unable to get memory parameters"));
1508 goto cleanup;
1511 /* XXX: Need to sort the returned params once new parameter
1512 * fields not of shared memory are added.
1514 vshPrint(ctl, _("Shared memory:\n"));
1515 for (i = 0; i < nparams; i++) {
1516 g_autofree char *str = vshGetTypedParamValue(ctl, &params[i]);
1517 vshPrint(ctl, "\t%-15s %s\n", params[i].field, str);
1519 } else {
1520 if (virNodeSetMemoryParameters(priv->conn, params, nparams, flags) != 0)
1521 goto error;
1524 ret = true;
1526 cleanup:
1527 virTypedParamsFree(params, nparams);
1528 return ret;
1530 save_error:
1531 vshSaveLibvirtError();
1532 error:
1533 vshError(ctl, "%s", _("Unable to change memory parameters"));
1534 goto cleanup;
1539 * "hypervisor-cpu-compare" command
1541 static const vshCmdInfo info_hypervisor_cpu_compare = {
1542 .help = N_("compare a CPU with the CPU created by a hypervisor on the host"),
1543 .desc = N_("compare CPU with hypervisor CPU"),
1546 static const vshCmdOptDef opts_hypervisor_cpu_compare[] = {
1547 VIRSH_COMMON_OPT_FILE(N_("file containing an XML CPU description")),
1548 {.name = "virttype",
1549 .type = VSH_OT_STRING,
1550 .unwanted_positional = true,
1551 .completer = virshDomainVirtTypeCompleter,
1552 .help = N_("virtualization type (/domain/@type)"),
1554 {.name = "emulator",
1555 .type = VSH_OT_STRING,
1556 .unwanted_positional = true,
1557 .help = N_("path to emulator binary (/domain/devices/emulator)"),
1559 {.name = "arch",
1560 .type = VSH_OT_STRING,
1561 .unwanted_positional = true,
1562 .completer = virshArchCompleter,
1563 .help = N_("CPU architecture (/domain/os/type/@arch)"),
1565 {.name = "machine",
1566 .type = VSH_OT_STRING,
1567 .unwanted_positional = true,
1568 .help = N_("machine type (/domain/os/type/@machine)"),
1570 {.name = "error",
1571 .type = VSH_OT_BOOL,
1572 .help = N_("report error if CPUs are incompatible")
1574 {.name = "validate",
1575 .type = VSH_OT_BOOL,
1576 .help = N_("validate the XML document against schema")
1578 {.name = NULL}
1581 static bool
1582 cmdHypervisorCPUCompare(vshControl *ctl,
1583 const vshCmd *cmd)
1585 const char *from = NULL;
1586 const char *virttype = NULL;
1587 const char *emulator = NULL;
1588 const char *arch = NULL;
1589 const char *machine = NULL;
1590 int result;
1591 g_auto(GStrv) cpus = NULL;
1592 unsigned int flags = 0;
1593 virshControl *priv = ctl->privData;
1595 if (vshCommandOptBool(cmd, "error"))
1596 flags |= VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE;
1598 if (vshCommandOptBool(cmd, "validate"))
1599 flags |= VIR_CONNECT_COMPARE_CPU_VALIDATE_XML;
1601 if (vshCommandOptString(ctl, cmd, "file", &from) < 0 ||
1602 vshCommandOptString(ctl, cmd, "virttype", &virttype) < 0 ||
1603 vshCommandOptString(ctl, cmd, "emulator", &emulator) < 0 ||
1604 vshCommandOptString(ctl, cmd, "arch", &arch) < 0 ||
1605 vshCommandOptString(ctl, cmd, "machine", &machine) < 0)
1606 return false;
1608 if (!(cpus = vshExtractCPUDefXMLs(ctl, from)))
1609 return false;
1611 result = virConnectCompareHypervisorCPU(priv->conn, emulator, arch,
1612 machine, virttype, cpus[0], flags);
1614 switch (result) {
1615 case VIR_CPU_COMPARE_INCOMPATIBLE:
1616 vshPrint(ctl,
1617 _("CPU described in %1$s is incompatible with the CPU provided by hypervisor on the host\n"),
1618 from);
1619 return false;
1620 break;
1622 case VIR_CPU_COMPARE_IDENTICAL:
1623 vshPrint(ctl,
1624 _("CPU described in %1$s is identical to the CPU provided by hypervisor on the host\n"),
1625 from);
1626 break;
1628 case VIR_CPU_COMPARE_SUPERSET:
1629 vshPrint(ctl,
1630 _("The CPU provided by hypervisor on the host is a superset of CPU described in %1$s\n"),
1631 from);
1632 break;
1634 case VIR_CPU_COMPARE_ERROR:
1635 default:
1636 vshError(ctl, _("Failed to compare hypervisor CPU with %1$s"), from);
1637 return false;
1640 return true;
1645 * "hypervisor-cpu-baseline" command
1647 static const vshCmdInfo info_hypervisor_cpu_baseline = {
1648 .help = N_("compute baseline CPU usable by a specific hypervisor"),
1649 .desc = N_("Compute baseline CPU for a set of given CPUs. The result "
1650 "will be tailored to the specified hypervisor."),
1653 static const vshCmdOptDef opts_hypervisor_cpu_baseline[] = {
1654 {.name = "file",
1655 .type = VSH_OT_STRING,
1656 .unwanted_positional = true,
1657 .completer = virshCompletePathLocalExisting,
1658 .help = N_("file containing XML CPU descriptions"),
1660 {.name = "virttype",
1661 .type = VSH_OT_STRING,
1662 .unwanted_positional = true,
1663 .completer = virshDomainVirtTypeCompleter,
1664 .help = N_("virtualization type (/domain/@type)"),
1666 {.name = "emulator",
1667 .type = VSH_OT_STRING,
1668 .unwanted_positional = true,
1669 .help = N_("path to emulator binary (/domain/devices/emulator)"),
1671 {.name = "arch",
1672 .type = VSH_OT_STRING,
1673 .unwanted_positional = true,
1674 .completer = virshArchCompleter,
1675 .help = N_("CPU architecture (/domain/os/type/@arch)"),
1677 {.name = "machine",
1678 .type = VSH_OT_STRING,
1679 .unwanted_positional = true,
1680 .help = N_("machine type (/domain/os/type/@machine)"),
1682 {.name = "features",
1683 .type = VSH_OT_BOOL,
1684 .help = N_("Show features that are part of the CPU model type")
1686 {.name = "migratable",
1687 .type = VSH_OT_BOOL,
1688 .help = N_("Do not include features that block migration")
1690 {.name = "model",
1691 .type = VSH_OT_STRING,
1692 .unwanted_positional = true,
1693 .completer = virshCPUModelCompleter,
1694 .help = N_("Shortcut for calling the command with a single CPU model "
1695 "and no additional features")
1697 {.name = NULL}
1700 static bool
1701 cmdHypervisorCPUBaseline(vshControl *ctl,
1702 const vshCmd *cmd)
1704 const char *from = NULL;
1705 const char *virttype = NULL;
1706 const char *emulator = NULL;
1707 const char *arch = NULL;
1708 const char *machine = NULL;
1709 const char *model = NULL;
1710 bool ret = false;
1711 g_autofree char *result = NULL;
1712 g_auto(GStrv) list = NULL;
1713 unsigned int flags = 0;
1714 virshControl *priv = ctl->privData;
1716 if (vshCommandOptBool(cmd, "features"))
1717 flags |= VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES;
1718 if (vshCommandOptBool(cmd, "migratable"))
1719 flags |= VIR_CONNECT_BASELINE_CPU_MIGRATABLE;
1721 if (vshCommandOptString(ctl, cmd, "file", &from) < 0 ||
1722 vshCommandOptString(ctl, cmd, "virttype", &virttype) < 0 ||
1723 vshCommandOptString(ctl, cmd, "emulator", &emulator) < 0 ||
1724 vshCommandOptString(ctl, cmd, "arch", &arch) < 0 ||
1725 vshCommandOptString(ctl, cmd, "machine", &machine) < 0 ||
1726 vshCommandOptString(ctl, cmd, "model", &model) < 0)
1727 return false;
1729 VSH_ALTERNATIVE_OPTIONS_EXPR("file", from, "model", model);
1731 if (from) {
1732 if (!(list = vshExtractCPUDefXMLs(ctl, from)))
1733 return false;
1734 } else {
1735 list = g_new0(char *, 2);
1736 list[0] = g_strdup_printf("<cpu><model>%s</model></cpu>", model);
1739 result = virConnectBaselineHypervisorCPU(priv->conn, emulator, arch,
1740 machine, virttype,
1741 (const char **)list,
1742 g_strv_length(list),
1743 flags);
1745 if (result) {
1746 vshPrint(ctl, "%s", result);
1747 ret = true;
1750 return ret;
1754 const vshCmdDef hostAndHypervisorCmds[] = {
1755 {.name = "allocpages",
1756 .handler = cmdAllocpages,
1757 .opts = opts_allocpages,
1758 .info = &info_allocpages,
1759 .flags = 0
1761 {.name = "capabilities",
1762 .handler = cmdCapabilities,
1763 .opts = opts_capabilities,
1764 .info = &info_capabilities,
1765 .flags = 0
1767 {.name = "cpu-baseline",
1768 .handler = cmdCPUBaseline,
1769 .opts = opts_cpu_baseline,
1770 .info = &info_cpu_baseline,
1771 .flags = 0
1773 {.name = "cpu-compare",
1774 .handler = cmdCPUCompare,
1775 .opts = opts_cpu_compare,
1776 .info = &info_cpu_compare,
1777 .flags = 0
1779 {.name = "cpu-models",
1780 .handler = cmdCPUModelNames,
1781 .opts = opts_cpu_models,
1782 .info = &info_cpu_models,
1783 .flags = 0
1785 {.name = "domcapabilities",
1786 .handler = cmdDomCapabilities,
1787 .opts = opts_domcapabilities,
1788 .info = &info_domcapabilities,
1789 .flags = 0
1791 {.name = "freecell",
1792 .handler = cmdFreecell,
1793 .opts = opts_freecell,
1794 .info = &info_freecell,
1795 .flags = 0
1797 {.name = "freepages",
1798 .handler = cmdFreepages,
1799 .opts = opts_freepages,
1800 .info = &info_freepages,
1801 .flags = 0
1803 {.name = "hostname",
1804 .handler = cmdHostname,
1805 .opts = NULL,
1806 .info = &info_hostname,
1807 .flags = 0
1809 {.name = "hypervisor-cpu-baseline",
1810 .handler = cmdHypervisorCPUBaseline,
1811 .opts = opts_hypervisor_cpu_baseline,
1812 .info = &info_hypervisor_cpu_baseline,
1813 .flags = 0
1815 {.name = "hypervisor-cpu-compare",
1816 .handler = cmdHypervisorCPUCompare,
1817 .opts = opts_hypervisor_cpu_compare,
1818 .info = &info_hypervisor_cpu_compare,
1819 .flags = 0
1821 {.name = "maxvcpus",
1822 .handler = cmdMaxvcpus,
1823 .opts = opts_maxvcpus,
1824 .info = &info_maxvcpus,
1825 .flags = 0
1827 {.name = "node-memory-tune",
1828 .handler = cmdNodeMemoryTune,
1829 .opts = opts_node_memory_tune,
1830 .info = &info_node_memory_tune,
1831 .flags = 0
1833 {.name = "nodecpumap",
1834 .handler = cmdNodeCpuMap,
1835 .opts = opts_node_cpumap,
1836 .info = &info_node_cpumap,
1837 .flags = 0
1839 {.name = "nodecpustats",
1840 .handler = cmdNodeCpuStats,
1841 .opts = opts_node_cpustats,
1842 .info = &info_nodecpustats,
1843 .flags = 0
1845 {.name = "nodeinfo",
1846 .handler = cmdNodeinfo,
1847 .opts = NULL,
1848 .info = &info_nodeinfo,
1849 .flags = 0
1851 {.name = "nodememstats",
1852 .handler = cmdNodeMemStats,
1853 .opts = opts_node_memstats,
1854 .info = &info_nodememstats,
1855 .flags = 0
1857 {.name = "nodesevinfo",
1858 .handler = cmdNodeSEVInfo,
1859 .opts = NULL,
1860 .info = &info_nodesevinfo,
1861 .flags = 0
1863 {.name = "nodesuspend",
1864 .handler = cmdNodeSuspend,
1865 .opts = opts_node_suspend,
1866 .info = &info_nodesuspend,
1867 .flags = 0
1869 {.name = "sysinfo",
1870 .handler = cmdSysinfo,
1871 .opts = NULL,
1872 .info = &info_sysinfo,
1873 .flags = 0
1875 {.name = "uri",
1876 .handler = cmdURI,
1877 .opts = NULL,
1878 .info = &info_uri,
1879 .flags = 0
1881 {.name = "version",
1882 .handler = cmdVersion,
1883 .opts = opts_version,
1884 .info = &info_version,
1885 .flags = 0
1887 {.name = NULL}