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/>.
22 #include "virsh-host.h"
25 #include <libxml/parser.h>
26 #include <libxml/xpath.h>
29 #include "virbitmap.h"
32 #include "virstring.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
[] = {
47 .type
= VSH_OT_STRING
,
48 .completer
= virshCompleteEmpty
,
49 .help
= N_("xpath expression to filter the XML document")
53 .help
= N_("wrap xpath results in an common root element"),
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)
69 if ((caps
= virConnectGetCapabilities(priv
->conn
)) == NULL
) {
70 vshError(ctl
, "%s", _("failed to get capabilities"));
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
[] = {
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)"),
98 .type
= VSH_OT_STRING
,
99 .unwanted_positional
= true,
100 .completer
= virshArchCompleter
,
101 .help
= N_("domain architecture (/domain/os/type/@arch)"),
104 .type
= VSH_OT_STRING
,
105 .unwanted_positional
= true,
106 .help
= N_("machine type (/domain/os/type/@machine)"),
109 .type
= VSH_OT_STRING
,
110 .completer
= virshCompleteEmpty
,
111 .help
= N_("xpath expression to filter the XML document")
115 .help
= N_("wrap xpath results in an common root element"),
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)
140 caps
= virConnectGetDomainCapabilities(priv
->conn
, emulatorbin
,
141 arch
, machine
, virttype
, flags
);
143 vshError(ctl
, "%s", _("failed to get emulator capabilities"));
147 return virshDumpXML(ctl
, caps
, "domcapabilities", xpath
, wrap
);
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
[] = {
161 .unwanted_positional
= true,
162 .completer
= virshCellnoCompleter
,
163 .help
= N_("NUMA cell number")
167 .help
= N_("show free memory for all NUMA cells")
173 cmdFreecell(vshControl
*ctl
, const vshCmd
*cmd
)
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");
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)
195 if (virNodeGetCellsFreeMemory(priv
->conn
, &memory
, cell
, 1) != 1)
198 vshPrint(ctl
, "%d: %llu KiB\n", cell
, (memory
/1024));
202 if ((memory
= virNodeGetFreeMemory(priv
->conn
)) == 0)
205 vshPrint(ctl
, "%s: %llu KiB\n", _("Total"), (memory
/1024));
209 if (!(cap_xml
= virConnectGetCapabilities(priv
->conn
))) {
210 vshError(ctl
, "%s", _("unable to get node capabilities"));
214 if (!virXMLParseStringCtxt(cap_xml
, _("(capabilities)"), &ctxt
)) {
215 vshError(ctl
, "%s", _("unable to get node capabilities"));
219 nodes_cnt
= virXPathNodeSet("/capabilities/host/topology/cells/cell",
222 if (nodes_cnt
== -1) {
223 vshError(ctl
, "%s", _("could not get information about NUMA topology"));
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
++) {
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"));
238 if (virNodeGetCellsFreeMemory(priv
->conn
, &(nodes_free
[i
]),
240 vshError(ctl
, _("failed to get free memory for NUMA node number: %1$lu"),
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);
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
[] = {
270 .unwanted_positional
= true,
271 .completer
= virshCellnoCompleter
,
272 .help
= N_("NUMA cell number")
276 .unwanted_positional
= true,
277 .completer
= virshAllocpagesPagesizeCompleter
,
278 .help
= N_("page size (in kibibytes)")
282 .help
= N_("show free pages for all NUMA cells")
288 vshPageSizeSorter(const void *a
,
290 void *opaque G_GNUC_UNUSED
)
292 unsigned int pa
= *(unsigned int *)a
;
293 unsigned int pb
= *(unsigned int *)b
;
299 cmdFreepages(vshControl
*ctl
, const vshCmd
*cmd
)
303 g_autofree
unsigned int *pagesize
= NULL
;
304 unsigned long long bytes
= 0;
305 unsigned int kibibytes
= 0;
307 g_autofree
unsigned long long *counts
= NULL
;
309 xmlNodePtr
*nodes
= NULL
;
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;
321 VSH_EXCLUSIVE_OPTIONS_VAR(all
, cellno
);
323 if (vshCommandOptScaledInt(ctl
, cmd
, "pagesize", &bytes
,
324 1024, UINT_MAX
* 1024ULL) < 0) {
327 kibibytes
= VIR_DIV_UP(bytes
, 1024);
330 if (!(cap_xml
= virConnectGetCapabilities(priv
->conn
))) {
331 vshError(ctl
, "%s", _("unable to get node capabilities"));
335 if (!(doc
= virXMLParseStringCtxt(cap_xml
, _("capabilities"), &ctxt
))) {
336 vshError(ctl
, "%s", _("unable to parse node capabilities"));
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",
348 if (nodes_cnt
<= 0) {
349 vshError(ctl
, "%s", _("could not get information about supported page sizes"));
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
);
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
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
));
385 pagesize
= g_new0(unsigned int, 1);
386 pagesize
[0] = kibibytes
;
390 counts
= g_new0(unsigned long long, npages
);
392 nodes_cnt
= virXPathNodeSet("/capabilities/host/topology/cells/cell",
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
);
402 rv
= virNodeGetFreePages(priv
->conn
, npages
, pagesize
,
408 pagesize_missing
= true;
409 vshError(ctl
, _("Did not get all free page data for node %1$d"), cell
);
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');
420 vshError(ctl
, "%s", _("missing cellno argument"));
424 if (vshCommandOptInt(ctl
, cmd
, "cellno", &cell
) < 0)
429 _("cell number must be non-negative integer or -1"));
434 vshError(ctl
, "%s", _("missing pagesize argument"));
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
,
451 "Could not get count of free %uKiB pages, no data returned",
456 vshPrint(ctl
, "%uKiB: %lld\n", *pagesize
, counts
[0]);
459 ret
= !pagesize_missing
;
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
[] = {
478 .completer
= virshAllocpagesPagesizeCompleter
,
479 .help
= N_("page size (in kibibytes)")
481 {.name
= "pagecount",
485 .help
= N_("page count")
489 .unwanted_positional
= true,
490 .completer
= virshCellnoCompleter
,
491 .help
= N_("NUMA cell number")
495 .help
= N_("instead of setting new pool size add pages to it")
499 .help
= N_("set on all NUMA cells")
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");
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)
526 if (vshCommandOptScaledInt(ctl
, cmd
, "pagesize", &tmp
, 1024, UINT_MAX
* 1024ULL) < 0)
528 pageSizes
[0] = VIR_DIV_UP(tmp
, 1024);
530 if (vshCommandOptULongLong(ctl
, cmd
, "pagecount", &pageCounts
[0]) < 0)
533 flags
|= add
? VIR_NODE_ALLOC_PAGES_ADD
: VIR_NODE_ALLOC_PAGES_SET
;
536 unsigned long nodes_cnt
;
539 if (!(cap_xml
= virConnectGetCapabilities(priv
->conn
))) {
540 vshError(ctl
, "%s", _("unable to get node capabilities"));
544 xml
= virXMLParseStringCtxt(cap_xml
, _("(capabilities)"), &ctxt
);
546 vshError(ctl
, "%s", _("unable to get node capabilities"));
550 nodes_cnt
= virXPathNodeSet("/capabilities/host/topology/cells/cell",
553 if (nodes_cnt
== -1) {
554 vshError(ctl
, "%s", _("could not get information about NUMA topology"));
558 for (i
= 0; i
< nodes_cnt
; i
++) {
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"));
566 if (virNodeAllocPages(priv
->conn
, 1, pageSizes
,
567 pageCounts
, id
, 1, flags
) < 0)
571 if (virNodeAllocPages(priv
->conn
, 1, pageSizes
, pageCounts
,
572 startCell
, cellCount
, flags
) < 0)
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
[] = {
590 .type
= VSH_OT_STRING
,
591 .unwanted_positional
= true,
592 .completer
= virshDomainVirtTypeCompleter
,
593 .help
= N_("domain type")
599 cmdMaxvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
601 const char *type
= NULL
;
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)
611 if ((caps
= virConnectGetDomainCapabilities(priv
->conn
, NULL
, NULL
, NULL
,
613 if (!(xml
= virXMLParseStringCtxt(caps
, _("(domainCapabilities)"), &ctxt
)))
616 ignore_value(virXPathInt("string(./vcpu[1]/@max)", ctxt
, &vcpus
));
618 vshResetLibvirtError();
621 if (vcpus
< 0 && (vcpus
= virConnectGetMaxVcpus(priv
->conn
, type
)) < 0)
624 vshPrint(ctl
, "%d\n", vcpus
);
632 static const vshCmdInfo info_nodeinfo
= {
633 .help
= N_("node information"),
634 .desc
= N_("Returns basic information about the node."),
638 cmdNodeinfo(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
641 virshControl
*priv
= ctl
->privData
;
643 if (virNodeGetInfo(priv
->conn
, &info
) < 0) {
644 vshError(ctl
, "%s", _("failed to get node information"));
647 vshPrint(ctl
, "%-20s %s\n", _("CPU model:"), info
.model
);
648 vshPrint(ctl
, "%-20s %d\n", _("CPU(s):"), info
.cpus
);
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
);
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
[] = {
672 .help
= N_("return human readable output")
678 cmdNodeCpuMap(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
681 g_autofree
unsigned char *cpumap
= NULL
;
683 bool pretty
= vshCommandOptBool(cmd
, "pretty");
684 virshControl
*priv
= ctl
->privData
;
686 cpunum
= virNodeGetCPUMap(priv
->conn
, &cpumap
, &online
, 0);
688 vshError(ctl
, "%s", _("Unable to get cpu map"));
692 vshPrint(ctl
, "%-15s %d\n", _("CPUs present:"), cpunum
);
693 vshPrint(ctl
, "%-15s %d\n", _("CPUs online:"), online
);
695 vshPrint(ctl
, "%-15s ", _("CPU map:"));
697 g_autofree
char *str
= virBitmapDataFormat(cpumap
, VIR_CPU_MAPLEN(cpunum
));
701 vshPrint(ctl
, "%s", str
);
703 for (cpu
= 0; cpu
< cpunum
; cpu
++)
704 vshPrint(ctl
, "%c", VIR_CPU_USED(cpumap
, cpu
) ? 'y' : '-');
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
[] = {
722 .unwanted_positional
= true,
723 .completer
= virshNodeCpuCompleter
,
724 .help
= N_("prints specified cpu statistics only.")
728 .help
= N_("prints by percentage during 1 second.")
743 VIR_ENUM_DECL(virshCPUStats
);
744 VIR_ENUM_IMPL(virshCPUStats
,
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
[] = {
763 cmdNodeCpuStats(vshControl
*ctl
, const vshCmd
*cmd
)
766 bool flag_percent
= vshCommandOptBool(cmd
, "percent");
767 int cpuNum
= VIR_NODE_CPU_STATS_ALL_CPUS
;
768 g_autofree virNodeCPUStatsPtr params
= NULL
;
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)
777 if (virNodeGetCPUStats(priv
->conn
, cpuNum
, NULL
, &nparams
, 0) != 0) {
779 _("Unable to get number of cpu stats"));
783 /* nothing to output */
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"));
796 for (j
= 0; j
< nparams
; j
++) {
797 int field
= virshCPUStatsTypeFromString(params
[j
].field
);
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
)
817 for (i
= 0; i
< VIRSH_CPU_USAGE
; i
++) {
819 vshPrint(ctl
, "%-15s %20llu\n", _(virshCPUOutput
[i
]),
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
]);
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
])
839 vshPrint(ctl
, "%-15s %5.1lf%%\n", _("usage:"), usage
);
840 for (i
= 0; i
< VIRSH_CPU_USAGE
; i
++) {
842 vshPrint(ctl
, "%-15s %5.1lf%%\n", _(virshCPUOutput
[i
]),
843 cpu_stats
[i
] / total_time
* 100);
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
[] = {
861 .unwanted_positional
= true,
862 .help
= N_("prints specified cell statistics only.")
868 cmdNodeMemStats(vshControl
*ctl
, const vshCmd
*cmd
)
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)
879 /* get the number of memory parameters */
880 if (virNodeGetMemoryStats(priv
->conn
, cellNum
, NULL
, &nparams
, 0) != 0) {
882 _("Unable to get number of memory stats"));
887 /* nothing to output */
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"));
898 for (i
= 0; i
< nparams
; i
++)
899 vshPrint(ctl
, "%-7s: %20llu KiB\n", params
[i
].field
, params
[i
].value
);
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."),
913 cmdNodeSEVInfo(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
915 virshControl
*priv
= ctl
->privData
;
918 virTypedParameterPtr params
= NULL
;
921 if (virNodeGetSEVInfo(priv
->conn
, ¶ms
, &nparams
, 0) != 0) {
922 vshError(ctl
, "%s", _("Unable to get host SEV information"));
926 for (i
= 0; i
< nparams
; i
++) {
927 g_autofree
char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
928 vshPrint(ctl
, "%-18s: %s\n", params
[i
].field
, str
);
934 virTypedParamsFree(params
, nparams
);
939 * "nodesuspend" command
942 VIR_ENUM_IMPL(virshNodeSuspendTarget
,
943 VIR_NODE_SUSPEND_TARGET_LAST
,
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
[] = {
956 .type
= VSH_OT_STRING
,
959 .completer
= virshNodeSuspendTargetCompleter
,
960 .help
= N_("mem(Suspend-to-RAM), disk(Suspend-to-Disk), "
961 "hybrid(Hybrid-Suspend)")
967 .help
= N_("Suspend duration in seconds, at least 60")
973 cmdNodeSuspend(vshControl
*ctl
, const vshCmd
*cmd
)
975 const char *target
= NULL
;
978 virshControl
*priv
= ctl
->privData
;
980 if (vshCommandOptString(ctl
, cmd
, "target", &target
) < 0)
983 if (vshCommandOptLongLong(ctl
, cmd
, "duration", &duration
) < 0)
986 if ((suspendTarget
= virshNodeSuspendTargetTypeFromString(target
)) < 0) {
987 vshError(ctl
, "%s", _("Invalid target"));
992 vshError(ctl
, "%s", _("Invalid duration"));
996 if (virNodeSuspendForDuration(priv
->conn
, suspendTarget
, duration
, 0) < 0) {
997 vshError(ctl
, "%s", _("The host was not suspended"));
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"),
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"));
1023 vshPrint(ctl
, "%s", sysinfo
);
1029 * "hostname" command
1031 static const vshCmdInfo info_hostname
= {
1032 .help
= N_("print the hypervisor hostname"),
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"));
1048 vshPrint(ctl
, "%s\n", hostname
);
1056 static const vshCmdInfo info_uri
= {
1057 .help
= N_("print the hypervisor canonical URI"),
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
);
1069 vshError(ctl
, "%s", _("failed to get URI"));
1073 vshPrint(ctl
, "%s\n", uri
);
1079 /* Extracts the CPU definition XML strings from a file which may contain either
1080 * - just the CPU definitions,
1082 * - capabilities XMLs, or
1083 * - domain capabilities XMLs.
1085 * Returns NULL terminated string list.
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
;
1101 if (virFileReadAll(xmlFile
, VSH_MAX_XML_FILE
, &buffer
) < 0)
1104 /* Strip possible XML declaration */
1105 if (STRPREFIX(buffer
, "<?xml") && (doc
= strstr(buffer
, "?>")))
1110 xmlStr
= g_strdup_printf("<container>%s</container>", doc
);
1112 if (!(xml
= virXMLParseStringCtxt(xmlStr
, xmlFile
, &ctxt
)))
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']",
1125 vshError(ctl
, _("File '%1$s' does not contain any <cpu> element or valid domain XML, host capabilities XML, or domain capabilities XML"),
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) {
1140 _("Cannot extract CPU definition from domain capabilities XML"));
1146 if (!(cpus
[i
] = virXMLNodeToString(xml
, nodes
[i
]))) {
1147 vshSaveLibvirtError();
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")),
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")
1178 cmdCPUCompare(vshControl
*ctl
, const vshCmd
*cmd
)
1180 const char *from
= NULL
;
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)
1195 if (!(cpus
= vshExtractCPUDefXMLs(ctl
, from
)))
1198 result
= virConnectCompareCPU(priv
->conn
, cpus
[0], flags
);
1201 case VIR_CPU_COMPARE_INCOMPATIBLE
:
1202 vshPrint(ctl
, _("CPU described in %1$s is incompatible with host CPU\n"),
1207 case VIR_CPU_COMPARE_IDENTICAL
:
1208 vshPrint(ctl
, _("CPU described in %1$s is identical to host CPU\n"),
1212 case VIR_CPU_COMPARE_SUPERSET
:
1213 vshPrint(ctl
, _("Host CPU is a superset of CPU described in %1$s\n"),
1217 case VIR_CPU_COMPARE_ERROR
:
1219 vshError(ctl
, _("Failed to compare host CPU with %1$s"), from
);
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")
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)
1264 if (!(list
= vshExtractCPUDefXMLs(ctl
, from
)))
1267 if (!(result
= virConnectBaselineCPU(priv
->conn
, (const char **)list
,
1268 g_strv_length(list
), flags
)))
1271 vshPrint(ctl
, "%s", result
);
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
[] = {
1285 .type
= VSH_OT_STRING
,
1288 .completer
= virshArchCompleter
,
1289 .help
= N_("architecture")
1295 cmdCPUModelNames(vshControl
*ctl
, const vshCmd
*cmd
)
1300 const char *arch
= NULL
;
1301 virshControl
*priv
= ctl
->privData
;
1303 if (vshCommandOptString(ctl
, cmd
, "arch", &arch
) < 0)
1306 nmodels
= virConnectGetCPUModelNames(priv
->conn
, arch
, &models
, 0);
1308 vshError(ctl
, "%s", _("failed to get CPU model names"));
1313 vshPrintExtra(ctl
, "%s\n", _("all CPU models are accepted"));
1315 for (i
= 0; i
< nmodels
; i
++) {
1316 vshPrint(ctl
, "%s\n", models
[i
]);
1317 VIR_FREE(models
[i
]);
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
[] = {
1335 .type
= VSH_OT_BOOL
,
1336 .help
= N_("report daemon version too")
1342 cmdVersion(vshControl
*ctl
, const vshCmd
*cmd G_GNUC_UNUSED
)
1344 unsigned long hvVersion
;
1346 unsigned long libVersion
;
1347 unsigned long includeVersion
;
1348 unsigned long apiVersion
;
1349 unsigned long daemonVersion
;
1353 virshControl
*priv
= ctl
->privData
;
1355 hvType
= virConnectGetType(priv
->conn
);
1356 if (hvType
== NULL
) {
1357 vshError(ctl
, "%s", _("failed to get hypervisor type"));
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"),
1369 if (virGetVersion(&libVersion
, hvType
, &apiVersion
) < 0) {
1370 vshError(ctl
, "%s", _("failed to get the library version"));
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"),
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
,
1387 if (virConnectGetVersion(priv
->conn
, &hvVersion
) < 0) {
1388 if (last_error
->code
== VIR_ERR_NO_SUPPORT
) {
1389 vshResetLibvirtError();
1391 vshError(ctl
, "%s", _("failed to get the hypervisor version"));
1395 if (hvVersion
== 0) {
1397 _("Cannot extract running %1$s hypervisor version\n"), hvType
);
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"));
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"),
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",
1433 .unwanted_positional
= true,
1434 .help
= N_("number of pages to scan before the shared memory service "
1437 {.name
= "shm-sleep-millisecs",
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",
1445 .unwanted_positional
= true,
1446 .help
= N_("Specifies if pages from different numa nodes can be merged")
1452 cmdNodeMemoryTune(vshControl
*ctl
, const vshCmd
*cmd
)
1454 virTypedParameterPtr params
= NULL
;
1457 unsigned int flags
= 0;
1462 virshControl
*priv
= ctl
->privData
;
1464 if ((rc
= vshCommandOptUInt(ctl
, cmd
, "shm-pages-to-scan", &value
)) < 0) {
1466 } else if (rc
> 0) {
1467 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
1468 VIR_NODE_MEMORY_SHARED_PAGES_TO_SCAN
,
1473 if ((rc
= vshCommandOptUInt(ctl
, cmd
, "shm-sleep-millisecs", &value
)) < 0) {
1475 } else if (rc
> 0) {
1476 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
1477 VIR_NODE_MEMORY_SHARED_SLEEP_MILLISECS
,
1482 if ((rc
= vshCommandOptUInt(ctl
, cmd
, "shm-merge-across-nodes", &value
)) < 0) {
1484 } else if (rc
> 0) {
1485 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
1486 VIR_NODE_MEMORY_SHARED_MERGE_ACROSS_NODES
,
1492 /* Get the number of memory parameters */
1493 if (virNodeGetMemoryParameters(priv
->conn
, NULL
, &nparams
, flags
) != 0) {
1495 _("Unable to get number of memory parameters"));
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"));
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
, ¶ms
[i
]);
1517 vshPrint(ctl
, "\t%-15s %s\n", params
[i
].field
, str
);
1520 if (virNodeSetMemoryParameters(priv
->conn
, params
, nparams
, flags
) != 0)
1527 virTypedParamsFree(params
, nparams
);
1531 vshSaveLibvirtError();
1533 vshError(ctl
, "%s", _("Unable to change memory parameters"));
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)"),
1560 .type
= VSH_OT_STRING
,
1561 .unwanted_positional
= true,
1562 .completer
= virshArchCompleter
,
1563 .help
= N_("CPU architecture (/domain/os/type/@arch)"),
1566 .type
= VSH_OT_STRING
,
1567 .unwanted_positional
= true,
1568 .help
= N_("machine type (/domain/os/type/@machine)"),
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")
1582 cmdHypervisorCPUCompare(vshControl
*ctl
,
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
;
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)
1608 if (!(cpus
= vshExtractCPUDefXMLs(ctl
, from
)))
1611 result
= virConnectCompareHypervisorCPU(priv
->conn
, emulator
, arch
,
1612 machine
, virttype
, cpus
[0], flags
);
1615 case VIR_CPU_COMPARE_INCOMPATIBLE
:
1617 _("CPU described in %1$s is incompatible with the CPU provided by hypervisor on the host\n"),
1622 case VIR_CPU_COMPARE_IDENTICAL
:
1624 _("CPU described in %1$s is identical to the CPU provided by hypervisor on the host\n"),
1628 case VIR_CPU_COMPARE_SUPERSET
:
1630 _("The CPU provided by hypervisor on the host is a superset of CPU described in %1$s\n"),
1634 case VIR_CPU_COMPARE_ERROR
:
1636 vshError(ctl
, _("Failed to compare hypervisor CPU with %1$s"), from
);
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
[] = {
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)"),
1672 .type
= VSH_OT_STRING
,
1673 .unwanted_positional
= true,
1674 .completer
= virshArchCompleter
,
1675 .help
= N_("CPU architecture (/domain/os/type/@arch)"),
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")
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")
1701 cmdHypervisorCPUBaseline(vshControl
*ctl
,
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
;
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)
1729 VSH_ALTERNATIVE_OPTIONS_EXPR("file", from
, "model", model
);
1732 if (!(list
= vshExtractCPUDefXMLs(ctl
, from
)))
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
,
1741 (const char **)list
,
1742 g_strv_length(list
),
1746 vshPrint(ctl
, "%s", result
);
1754 const vshCmdDef hostAndHypervisorCmds
[] = {
1755 {.name
= "allocpages",
1756 .handler
= cmdAllocpages
,
1757 .opts
= opts_allocpages
,
1758 .info
= &info_allocpages
,
1761 {.name
= "capabilities",
1762 .handler
= cmdCapabilities
,
1763 .opts
= opts_capabilities
,
1764 .info
= &info_capabilities
,
1767 {.name
= "cpu-baseline",
1768 .handler
= cmdCPUBaseline
,
1769 .opts
= opts_cpu_baseline
,
1770 .info
= &info_cpu_baseline
,
1773 {.name
= "cpu-compare",
1774 .handler
= cmdCPUCompare
,
1775 .opts
= opts_cpu_compare
,
1776 .info
= &info_cpu_compare
,
1779 {.name
= "cpu-models",
1780 .handler
= cmdCPUModelNames
,
1781 .opts
= opts_cpu_models
,
1782 .info
= &info_cpu_models
,
1785 {.name
= "domcapabilities",
1786 .handler
= cmdDomCapabilities
,
1787 .opts
= opts_domcapabilities
,
1788 .info
= &info_domcapabilities
,
1791 {.name
= "freecell",
1792 .handler
= cmdFreecell
,
1793 .opts
= opts_freecell
,
1794 .info
= &info_freecell
,
1797 {.name
= "freepages",
1798 .handler
= cmdFreepages
,
1799 .opts
= opts_freepages
,
1800 .info
= &info_freepages
,
1803 {.name
= "hostname",
1804 .handler
= cmdHostname
,
1806 .info
= &info_hostname
,
1809 {.name
= "hypervisor-cpu-baseline",
1810 .handler
= cmdHypervisorCPUBaseline
,
1811 .opts
= opts_hypervisor_cpu_baseline
,
1812 .info
= &info_hypervisor_cpu_baseline
,
1815 {.name
= "hypervisor-cpu-compare",
1816 .handler
= cmdHypervisorCPUCompare
,
1817 .opts
= opts_hypervisor_cpu_compare
,
1818 .info
= &info_hypervisor_cpu_compare
,
1821 {.name
= "maxvcpus",
1822 .handler
= cmdMaxvcpus
,
1823 .opts
= opts_maxvcpus
,
1824 .info
= &info_maxvcpus
,
1827 {.name
= "node-memory-tune",
1828 .handler
= cmdNodeMemoryTune
,
1829 .opts
= opts_node_memory_tune
,
1830 .info
= &info_node_memory_tune
,
1833 {.name
= "nodecpumap",
1834 .handler
= cmdNodeCpuMap
,
1835 .opts
= opts_node_cpumap
,
1836 .info
= &info_node_cpumap
,
1839 {.name
= "nodecpustats",
1840 .handler
= cmdNodeCpuStats
,
1841 .opts
= opts_node_cpustats
,
1842 .info
= &info_nodecpustats
,
1845 {.name
= "nodeinfo",
1846 .handler
= cmdNodeinfo
,
1848 .info
= &info_nodeinfo
,
1851 {.name
= "nodememstats",
1852 .handler
= cmdNodeMemStats
,
1853 .opts
= opts_node_memstats
,
1854 .info
= &info_nodememstats
,
1857 {.name
= "nodesevinfo",
1858 .handler
= cmdNodeSEVInfo
,
1860 .info
= &info_nodesevinfo
,
1863 {.name
= "nodesuspend",
1864 .handler
= cmdNodeSuspend
,
1865 .opts
= opts_node_suspend
,
1866 .info
= &info_nodesuspend
,
1870 .handler
= cmdSysinfo
,
1872 .info
= &info_sysinfo
,
1882 .handler
= cmdVersion
,
1883 .opts
= opts_version
,
1884 .info
= &info_version
,