2 * virsh-domain.c: Commands to manage domain
4 * Copyright (C) 2005, 2007-2016 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-domain.h"
23 #include "virsh-util.h"
30 #include <libxml/parser.h>
31 #include <libxml/tree.h>
32 #include <libxml/xpath.h>
33 #include <libxml/xmlsave.h>
36 #include "virbitmap.h"
37 #include "virbuffer.h"
39 #include "conf/domain_conf.h"
41 #include "vircommand.h"
44 #include "virkeycode.h"
45 #include "virmacaddr.h"
46 #include "virnetdevbandwidth.h"
47 #include "virprocess.h"
48 #include "virstring.h"
49 #include "virsh-console.h"
50 #include "virsh-domain-monitor.h"
53 #include "virtypedparam.h"
55 #include "virsh-nodedev.h"
57 #include "vsh-table.h"
60 /* Gnulib doesn't guarantee SA_SIGINFO support. */
65 #define VIRSH_COMMON_OPT_DOMAIN_PERSISTENT \
66 {.name = "persistent", \
67 .type = VSH_OT_BOOL, \
68 .help = N_("make live change persistent") \
71 #define VIRSH_COMMON_OPT_DOMAIN_CONFIG \
72 VIRSH_COMMON_OPT_CONFIG(N_("affect next boot"))
74 #define VIRSH_COMMON_OPT_DOMAIN_LIVE \
75 VIRSH_COMMON_OPT_LIVE(N_("affect running domain"))
77 #define VIRSH_COMMON_OPT_DOMAIN_CURRENT \
78 VIRSH_COMMON_OPT_CURRENT(N_("affect current domain"))
82 virshDomainDefine(virConnectPtr conn
, const char *xml
, unsigned int flags
)
86 dom
= virDomainDefineXMLFlags(conn
, xml
, flags
);
87 /* If validate is the only flag, just drop it and
91 if ((virGetLastErrorCode() == VIR_ERR_NO_SUPPORT
) &&
92 (flags
== VIR_DOMAIN_DEFINE_VALIDATE
))
93 dom
= virDomainDefineXML(conn
, xml
);
96 dom
= virDomainDefineXML(conn
, xml
);
101 VIR_ENUM_DECL(virshDomainVcpuState
);
102 VIR_ENUM_IMPL(virshDomainVcpuState
,
109 virshDomainVcpuStateToString(int state
)
111 const char *str
= virshDomainVcpuStateTypeToString(state
);
112 return str
? _(str
) : _("no state");
116 * Determine number of CPU nodes present by trying
117 * virNodeGetCPUMap and falling back to virNodeGetInfo
121 virshNodeGetCPUCount(virConnectPtr conn
)
124 virNodeInfo nodeinfo
;
126 if ((ret
= virNodeGetCPUMap(conn
, NULL
, NULL
, 0)) < 0) {
127 /* fall back to nodeinfo */
128 vshResetLibvirtError();
129 if (virNodeGetInfo(conn
, &nodeinfo
) == 0)
130 ret
= VIR_NODEINFO_MAXCPUS(nodeinfo
);
136 * "attach-device" command
138 static const vshCmdInfo info_attach_device
[] = {
140 .data
= N_("attach device from an XML file")
143 .data
= N_("Attach device from an XML <file>.")
148 static const vshCmdOptDef opts_attach_device
[] = {
149 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
150 VIRSH_COMMON_OPT_FILE(N_("XML file")),
151 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
152 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
153 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
154 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
159 cmdAttachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
162 const char *from
= NULL
;
166 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
167 bool current
= vshCommandOptBool(cmd
, "current");
168 bool config
= vshCommandOptBool(cmd
, "config");
169 bool live
= vshCommandOptBool(cmd
, "live");
170 bool persistent
= vshCommandOptBool(cmd
, "persistent");
172 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
174 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
175 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
177 if (config
|| persistent
)
178 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
180 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
182 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
185 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
189 virDomainIsActive(dom
) == 1)
190 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
192 if (virFileReadAll(from
, VSH_MAX_XML_FILE
, &buffer
) < 0) {
197 if (flags
|| current
)
198 rv
= virDomainAttachDeviceFlags(dom
, buffer
, flags
);
200 rv
= virDomainAttachDevice(dom
, buffer
);
205 vshError(ctl
, _("Failed to attach device from %s"), from
);
209 vshPrintExtra(ctl
, "%s", _("Device attached successfully\n"));
213 virshDomainFree(dom
);
218 * "attach-disk" command
220 static const vshCmdInfo info_attach_disk
[] = {
222 .data
= N_("attach disk device")
225 .data
= N_("Attach new disk device.")
230 static const vshCmdOptDef opts_attach_disk
[] = {
231 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
234 .flags
= VSH_OFLAG_REQ
| VSH_OFLAG_EMPTY_OK
,
235 .help
= N_("source of disk device")
239 .flags
= VSH_OFLAG_REQ
,
240 .help
= N_("target of disk device")
242 {.name
= "targetbus",
243 .type
= VSH_OT_STRING
,
244 .help
= N_("target bus of disk device")
247 .type
= VSH_OT_STRING
,
248 .help
= N_("driver of disk device")
250 {.name
= "subdriver",
251 .type
= VSH_OT_STRING
,
252 .help
= N_("subdriver of disk device")
255 .type
= VSH_OT_STRING
,
256 .help
= N_("IOThread to be used by supported device")
259 .type
= VSH_OT_STRING
,
260 .help
= N_("cache mode of disk device")
263 .type
= VSH_OT_STRING
,
264 .help
= N_("io policy of disk device")
267 .type
= VSH_OT_STRING
,
268 .help
= N_("target device type")
270 {.name
= "shareable",
271 .type
= VSH_OT_ALIAS
,
272 .help
= "mode=shareable"
275 .type
= VSH_OT_STRING
,
276 .help
= N_("mode of device reading and writing")
278 {.name
= "sourcetype",
279 .type
= VSH_OT_STRING
,
280 .help
= N_("type of source (block|file)")
283 .type
= VSH_OT_STRING
,
284 .help
= N_("serial of disk device")
287 .type
= VSH_OT_STRING
,
288 .help
= N_("wwn of disk device")
291 .type
= VSH_OT_STRING
,
292 .help
= N_("custom alias name of disk device")
296 .help
= N_("needs rawio capability")
299 .type
= VSH_OT_STRING
,
300 .help
= N_("address of disk device")
302 {.name
= "multifunction",
304 .help
= N_("use multifunction pci under specified address")
306 {.name
= "print-xml",
308 .help
= N_("print XML document rather than attach the disk")
310 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
311 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
312 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
313 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
318 DISK_ADDR_TYPE_INVALID
,
331 unsigned int function
;
335 unsigned int controller
;
337 unsigned long long unit
;
341 unsigned int controller
;
358 unsigned int controller
;
360 unsigned long long unit
;
366 struct PCIAddress pci
;
367 struct SCSIAddress scsi
;
368 struct IDEAddress ide
;
369 struct CCWAddress ccw
;
370 struct USBAddress usb
;
371 struct SATAAddress sata
;
375 static int str2PCIAddress(const char *str
, struct PCIAddress
*pciAddr
)
377 char *domain
, *bus
, *slot
, *function
;
384 domain
= (char *)str
;
386 if (virStrToLong_uip(domain
, &bus
, 16, &pciAddr
->domain
) != 0)
390 if (virStrToLong_uip(bus
, &slot
, 16, &pciAddr
->bus
) != 0)
394 if (virStrToLong_uip(slot
, &function
, 16, &pciAddr
->slot
) != 0)
398 if (virStrToLong_uip(function
, NULL
, 16, &pciAddr
->function
) != 0)
404 static int str2SCSIAddress(const char *str
, struct SCSIAddress
*scsiAddr
)
406 char *controller
, *bus
, *unit
;
413 controller
= (char *)str
;
415 if (virStrToLong_uip(controller
, &bus
, 10, &scsiAddr
->controller
) != 0)
419 if (virStrToLong_uip(bus
, &unit
, 10, &scsiAddr
->bus
) != 0)
423 if (virStrToLong_ullp(unit
, NULL
, 10, &scsiAddr
->unit
) != 0)
429 static int str2IDEAddress(const char *str
, struct IDEAddress
*ideAddr
)
431 char *controller
, *bus
, *unit
;
438 controller
= (char *)str
;
440 if (virStrToLong_uip(controller
, &bus
, 10, &ideAddr
->controller
) != 0)
444 if (virStrToLong_uip(bus
, &unit
, 10, &ideAddr
->bus
) != 0)
448 if (virStrToLong_uip(unit
, NULL
, 10, &ideAddr
->unit
) != 0)
454 static int str2CCWAddress(const char *str
, struct CCWAddress
*ccwAddr
)
456 char *cssid
, *ssid
, *devno
;
465 if (virStrToLong_uip(cssid
, &ssid
, 16, &ccwAddr
->cssid
) != 0)
469 if (virStrToLong_uip(ssid
, &devno
, 16, &ccwAddr
->ssid
) != 0)
473 if (virStrToLong_uip(devno
, NULL
, 16, &ccwAddr
->devno
) != 0)
479 static int str2USBAddress(const char *str
, struct USBAddress
*usbAddr
)
490 if (virStrToLong_uip(bus
, &port
, 10, &usbAddr
->bus
) != 0)
494 if (virStrToLong_uip(port
, NULL
, 10, &usbAddr
->port
) != 0)
500 static int str2SATAAddress(const char *str
, struct SATAAddress
*sataAddr
)
502 char *controller
, *bus
, *unit
;
509 controller
= (char *)str
;
511 if (virStrToLong_uip(controller
, &bus
, 10, &sataAddr
->controller
) != 0)
515 if (virStrToLong_uip(bus
, &unit
, 10, &sataAddr
->bus
) != 0)
519 if (virStrToLong_ullp(unit
, NULL
, 10, &sataAddr
->unit
) != 0)
525 /* pci address pci:0000.00.0x0a.0 (domain:bus:slot:function)
526 * ide disk address: ide:00.00.0 (controller:bus:unit)
527 * scsi disk address: scsi:00.00.0 (controller:bus:unit)
528 * ccw disk address: ccw:0xfe.0.0000 (cssid:ssid:devno)
529 * usb disk address: usb:00.00 (bus:port)
530 * sata disk address: sata:00.00.0 (controller:bus:unit)
533 static int str2DiskAddress(const char *str
, struct DiskAddress
*diskAddr
)
543 addr
= strchr(type
, ':');
547 if (STREQLEN(type
, "pci", addr
- type
)) {
548 diskAddr
->type
= DISK_ADDR_TYPE_PCI
;
549 return str2PCIAddress(addr
+ 1, &diskAddr
->addr
.pci
);
550 } else if (STREQLEN(type
, "scsi", addr
- type
)) {
551 diskAddr
->type
= DISK_ADDR_TYPE_SCSI
;
552 return str2SCSIAddress(addr
+ 1, &diskAddr
->addr
.scsi
);
553 } else if (STREQLEN(type
, "ide", addr
- type
)) {
554 diskAddr
->type
= DISK_ADDR_TYPE_IDE
;
555 return str2IDEAddress(addr
+ 1, &diskAddr
->addr
.ide
);
556 } else if (STREQLEN(type
, "ccw", addr
- type
)) {
557 diskAddr
->type
= DISK_ADDR_TYPE_CCW
;
558 return str2CCWAddress(addr
+ 1, &diskAddr
->addr
.ccw
);
559 } else if (STREQLEN(type
, "usb", addr
- type
)) {
560 diskAddr
->type
= DISK_ADDR_TYPE_USB
;
561 return str2USBAddress(addr
+ 1, &diskAddr
->addr
.usb
);
562 } else if (STREQLEN(type
, "sata", addr
- type
)) {
563 diskAddr
->type
= DISK_ADDR_TYPE_SATA
;
564 return str2SATAAddress(addr
+ 1, &diskAddr
->addr
.sata
);
571 cmdAttachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
573 virDomainPtr dom
= NULL
;
574 const char *source
= NULL
, *target
= NULL
, *driver
= NULL
,
575 *subdriver
= NULL
, *type
= NULL
, *mode
= NULL
,
576 *iothread
= NULL
, *cache
= NULL
, *io
= NULL
,
577 *serial
= NULL
, *straddr
= NULL
, *wwn
= NULL
,
578 *targetbus
= NULL
, *alias
= NULL
;
579 struct DiskAddress diskAddr
;
580 bool isFile
= false, functionReturn
= false;
582 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
583 const char *stype
= NULL
;
584 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
587 bool current
= vshCommandOptBool(cmd
, "current");
588 bool config
= vshCommandOptBool(cmd
, "config");
589 bool live
= vshCommandOptBool(cmd
, "live");
590 bool persistent
= vshCommandOptBool(cmd
, "persistent");
592 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
594 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
595 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
597 if (config
|| persistent
)
598 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
600 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
602 if (vshCommandOptStringReq(ctl
, cmd
, "source", &source
) < 0 ||
603 vshCommandOptStringReq(ctl
, cmd
, "target", &target
) < 0 ||
604 vshCommandOptStringReq(ctl
, cmd
, "driver", &driver
) < 0 ||
605 vshCommandOptStringReq(ctl
, cmd
, "subdriver", &subdriver
) < 0 ||
606 vshCommandOptStringReq(ctl
, cmd
, "type", &type
) < 0 ||
607 vshCommandOptStringReq(ctl
, cmd
, "mode", &mode
) < 0 ||
608 vshCommandOptStringReq(ctl
, cmd
, "iothread", &iothread
) < 0 ||
609 vshCommandOptStringReq(ctl
, cmd
, "cache", &cache
) < 0 ||
610 vshCommandOptStringReq(ctl
, cmd
, "io", &io
) < 0 ||
611 vshCommandOptStringReq(ctl
, cmd
, "serial", &serial
) < 0 ||
612 vshCommandOptStringReq(ctl
, cmd
, "wwn", &wwn
) < 0 ||
613 vshCommandOptStringReq(ctl
, cmd
, "address", &straddr
) < 0 ||
614 vshCommandOptStringReq(ctl
, cmd
, "targetbus", &targetbus
) < 0 ||
615 vshCommandOptStringReq(ctl
, cmd
, "alias", &alias
) < 0 ||
616 vshCommandOptStringReq(ctl
, cmd
, "sourcetype", &stype
) < 0)
620 if (driver
&& (STREQ(driver
, "file") || STREQ(driver
, "tap"))) {
623 if (source
&& !stat(source
, &st
))
624 isFile
= S_ISREG(st
.st_mode
) ? true : false;
626 } else if (STREQ(stype
, "file")) {
628 } else if (STRNEQ(stype
, "block")) {
629 vshError(ctl
, _("Unknown source type: '%s'"), stype
);
634 if (STRNEQ(mode
, "readonly") && STRNEQ(mode
, "shareable")) {
635 vshError(ctl
, _("No support for %s in command 'attach-disk'"),
641 if (wwn
&& !virValidateWWN(wwn
))
644 /* Make XML of disk */
645 virBufferAsprintf(&buf
, "<disk type='%s'",
646 isFile
? "file" : "block");
648 virBufferAsprintf(&buf
, " device='%s'", type
);
649 if (vshCommandOptBool(cmd
, "rawio"))
650 virBufferAddLit(&buf
, " rawio='yes'");
651 virBufferAddLit(&buf
, ">\n");
652 virBufferAdjustIndent(&buf
, 2);
654 if (driver
|| subdriver
|| iothread
|| cache
|| io
) {
655 virBufferAddLit(&buf
, "<driver");
658 virBufferAsprintf(&buf
, " name='%s'", driver
);
660 virBufferAsprintf(&buf
, " type='%s'", subdriver
);
662 virBufferAsprintf(&buf
, " iothread='%s'", iothread
);
664 virBufferAsprintf(&buf
, " cache='%s'", cache
);
666 virBufferAsprintf(&buf
, " io='%s'", io
);
668 virBufferAddLit(&buf
, "/>\n");
672 virBufferAsprintf(&buf
, "<source %s='%s'/>\n",
673 isFile
? "file" : "dev", source
);
674 virBufferAsprintf(&buf
, "<target dev='%s'", target
);
676 virBufferAsprintf(&buf
, " bus='%s'", targetbus
);
677 virBufferAddLit(&buf
, "/>\n");
680 virBufferAsprintf(&buf
, "<%s/>\n", mode
);
683 virBufferAsprintf(&buf
, "<serial>%s</serial>\n", serial
);
686 virBufferAsprintf(&buf
, "<alias name='%s'/>\n", alias
);
689 virBufferAsprintf(&buf
, "<wwn>%s</wwn>\n", wwn
);
692 if (str2DiskAddress(straddr
, &diskAddr
) != 0) {
693 vshError(ctl
, _("Invalid address."));
697 if (STRPREFIX((const char *)target
, "vd")) {
698 if (diskAddr
.type
== DISK_ADDR_TYPE_PCI
) {
699 virBufferAsprintf(&buf
,
700 "<address type='pci' domain='0x%04x'"
701 " bus ='0x%02x' slot='0x%02x' function='0x%0x'",
702 diskAddr
.addr
.pci
.domain
, diskAddr
.addr
.pci
.bus
,
703 diskAddr
.addr
.pci
.slot
, diskAddr
.addr
.pci
.function
);
704 if (vshCommandOptBool(cmd
, "multifunction"))
705 virBufferAddLit(&buf
, " multifunction='on'");
706 virBufferAddLit(&buf
, "/>\n");
707 } else if (diskAddr
.type
== DISK_ADDR_TYPE_CCW
) {
708 virBufferAsprintf(&buf
,
709 "<address type='ccw' cssid='0x%02x'"
710 " ssid='0x%01x' devno='0x%04x' />\n",
711 diskAddr
.addr
.ccw
.cssid
, diskAddr
.addr
.ccw
.ssid
,
712 diskAddr
.addr
.ccw
.devno
);
715 _("expecting a pci:0000.00.00.00 or ccw:00.0.0000 address."));
718 } else if (STRPREFIX((const char *)target
, "sd")) {
719 if (diskAddr
.type
== DISK_ADDR_TYPE_SCSI
) {
720 virBufferAsprintf(&buf
,
721 "<address type='drive' controller='%u'"
722 " bus='%u' unit='%llu' />\n",
723 diskAddr
.addr
.scsi
.controller
, diskAddr
.addr
.scsi
.bus
,
724 diskAddr
.addr
.scsi
.unit
);
725 } else if (diskAddr
.type
== DISK_ADDR_TYPE_USB
) {
726 virBufferAsprintf(&buf
,
727 "<address type='usb' bus='%u' port='%u' />\n",
728 diskAddr
.addr
.usb
.bus
, diskAddr
.addr
.usb
.port
);
729 } else if (diskAddr
.type
== DISK_ADDR_TYPE_SATA
) {
730 virBufferAsprintf(&buf
,
731 "<address type='drive' controller='%u'"
732 " bus='%u' unit='%llu' />\n",
733 diskAddr
.addr
.sata
.controller
, diskAddr
.addr
.sata
.bus
,
734 diskAddr
.addr
.sata
.unit
);
737 _("expecting a scsi:00.00.00 or usb:00.00 or sata:00.00.00 address."));
740 } else if (STRPREFIX((const char *)target
, "hd")) {
741 if (diskAddr
.type
== DISK_ADDR_TYPE_IDE
) {
742 virBufferAsprintf(&buf
,
743 "<address type='drive' controller='%u'"
744 " bus='%u' unit='%u' />\n",
745 diskAddr
.addr
.ide
.controller
, diskAddr
.addr
.ide
.bus
,
746 diskAddr
.addr
.ide
.unit
);
748 vshError(ctl
, "%s", _("expecting an ide:00.00.00 address."));
754 virBufferAdjustIndent(&buf
, -2);
755 virBufferAddLit(&buf
, "</disk>\n");
757 if (virBufferError(&buf
)) {
758 vshError(ctl
, "%s", _("Failed to allocate XML buffer"));
762 xml
= virBufferContentAndReset(&buf
);
764 if (vshCommandOptBool(cmd
, "print-xml")) {
765 vshPrint(ctl
, "%s", xml
);
766 functionReturn
= true;
770 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
774 virDomainIsActive(dom
) == 1)
775 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
777 if (flags
|| current
)
778 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
780 ret
= virDomainAttachDevice(dom
, xml
);
783 vshError(ctl
, "%s", _("Failed to attach disk"));
785 vshPrintExtra(ctl
, "%s", _("Disk attached successfully\n"));
786 functionReturn
= true;
791 virshDomainFree(dom
);
792 virBufferFreeAndReset(&buf
);
793 return functionReturn
;
797 * "attach-interface" command
799 static const vshCmdInfo info_attach_interface
[] = {
801 .data
= N_("attach network interface")
804 .data
= N_("Attach new network interface.")
809 static const vshCmdOptDef opts_attach_interface
[] = {
810 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
813 .flags
= VSH_OFLAG_REQ
,
814 .help
= N_("network interface type")
818 .flags
= VSH_OFLAG_REQ
,
819 .help
= N_("source of network interface")
822 .type
= VSH_OT_STRING
,
823 .help
= N_("target network name")
826 .type
= VSH_OT_STRING
,
827 .help
= N_("MAC address")
830 .type
= VSH_OT_STRING
,
831 .help
= N_("script used to bridge network interface")
834 .type
= VSH_OT_STRING
,
835 .help
= N_("model type")
838 .type
= VSH_OT_STRING
,
839 .help
= N_("custom alias name of interface device")
842 .type
= VSH_OT_STRING
,
843 .help
= N_("control domain's incoming traffics")
846 .type
= VSH_OT_STRING
,
847 .help
= N_("control domain's outgoing traffics")
849 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
850 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
851 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
852 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
853 {.name
= "print-xml",
855 .help
= N_("print XML document rather than attach the interface")
859 .help
= N_("libvirt will automatically detach/attach the device from/to host")
864 /* parse inbound and outbound which are in the format of
865 * 'average,peak,burst,floor', in which peak and burst are optional,
866 * thus 'average,,burst' and 'average,peak' are also legal. */
868 #define VIRSH_PARSE_RATE_FIELD(index, name) \
870 if (index < ntok && \
871 *tok[index] != '\0' && \
872 virStrToLong_ullp(tok[index], NULL, 10, &rate->name) < 0) { \
873 vshError(ctl, _("field '%s' is malformed"), #name); \
879 virshParseRateStr(vshControl
*ctl
,
881 virNetDevBandwidthRatePtr rate
)
887 if (!(tok
= virStringSplitCount(rateStr
, ",", 0, &ntok
)))
891 vshError(ctl
, _("Rate string '%s' has too many fields"), rateStr
);
895 VIRSH_PARSE_RATE_FIELD(0, average
);
896 VIRSH_PARSE_RATE_FIELD(1, peak
);
897 VIRSH_PARSE_RATE_FIELD(2, burst
);
898 VIRSH_PARSE_RATE_FIELD(3, floor
);
902 virStringListFree(tok
);
906 #undef VIRSH_PARSE_RATE_FIELD
909 cmdAttachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
911 virDomainPtr dom
= NULL
;
912 const char *mac
= NULL
, *target
= NULL
, *script
= NULL
,
913 *type
= NULL
, *source
= NULL
, *model
= NULL
,
914 *inboundStr
= NULL
, *outboundStr
= NULL
, *alias
= NULL
;
915 virNetDevBandwidthRate inbound
, outbound
;
916 virDomainNetType typ
;
918 bool functionReturn
= false;
919 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
921 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
922 bool current
= vshCommandOptBool(cmd
, "current");
923 bool config
= vshCommandOptBool(cmd
, "config");
924 bool live
= vshCommandOptBool(cmd
, "live");
925 bool persistent
= vshCommandOptBool(cmd
, "persistent");
926 bool managed
= vshCommandOptBool(cmd
, "managed");
928 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
930 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
931 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
933 if (config
|| persistent
)
934 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
936 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
938 if (vshCommandOptStringReq(ctl
, cmd
, "type", &type
) < 0 ||
939 vshCommandOptStringReq(ctl
, cmd
, "source", &source
) < 0 ||
940 vshCommandOptStringReq(ctl
, cmd
, "target", &target
) < 0 ||
941 vshCommandOptStringReq(ctl
, cmd
, "mac", &mac
) < 0 ||
942 vshCommandOptStringReq(ctl
, cmd
, "script", &script
) < 0 ||
943 vshCommandOptStringReq(ctl
, cmd
, "model", &model
) < 0 ||
944 vshCommandOptStringReq(ctl
, cmd
, "alias", &alias
) < 0 ||
945 vshCommandOptStringReq(ctl
, cmd
, "inbound", &inboundStr
) < 0 ||
946 vshCommandOptStringReq(ctl
, cmd
, "outbound", &outboundStr
) < 0)
949 /* check interface type */
950 if ((int)(typ
= virDomainNetTypeFromString(type
)) < 0) {
951 vshError(ctl
, _("No support for %s in command 'attach-interface'"),
957 memset(&inbound
, 0, sizeof(inbound
));
958 if (virshParseRateStr(ctl
, inboundStr
, &inbound
) < 0)
960 if (!inbound
.average
&& !inbound
.floor
) {
961 vshError(ctl
, _("either inbound average or floor is mandatory"));
966 memset(&outbound
, 0, sizeof(outbound
));
967 if (virshParseRateStr(ctl
, outboundStr
, &outbound
) < 0)
969 if (outbound
.average
== 0) {
970 vshError(ctl
, _("outbound average is mandatory"));
973 if (outbound
.floor
) {
974 vshError(ctl
, _("outbound floor is unsupported yet"));
979 /* Make XML of interface */
980 virBufferAsprintf(&buf
, "<interface type='%s'", type
);
983 virBufferAddLit(&buf
, " managed='yes'>\n");
985 virBufferAddLit(&buf
, ">\n");
986 virBufferAdjustIndent(&buf
, 2);
989 case VIR_DOMAIN_NET_TYPE_NETWORK
:
990 case VIR_DOMAIN_NET_TYPE_BRIDGE
:
991 virBufferAsprintf(&buf
, "<source %s='%s'/>\n",
992 virDomainNetTypeToString(typ
), source
);
994 case VIR_DOMAIN_NET_TYPE_DIRECT
:
995 virBufferAsprintf(&buf
, "<source dev='%s'/>\n", source
);
997 case VIR_DOMAIN_NET_TYPE_HOSTDEV
:
999 struct PCIAddress pciAddr
= {0, 0, 0, 0};
1001 if (str2PCIAddress(source
, &pciAddr
) < 0) {
1002 vshError(ctl
, _("cannot parse pci address '%s' for network "
1003 "interface"), source
);
1007 virBufferAddLit(&buf
, "<source>\n");
1008 virBufferAdjustIndent(&buf
, 2);
1009 virBufferAsprintf(&buf
, "<address type='pci' domain='0x%04x'"
1010 " bus='0x%02x' slot='0x%02x' function='0x%d'/>\n",
1011 pciAddr
.domain
, pciAddr
.bus
,
1012 pciAddr
.slot
, pciAddr
.function
);
1013 virBufferAdjustIndent(&buf
, -2);
1014 virBufferAddLit(&buf
, "</source>\n");
1018 case VIR_DOMAIN_NET_TYPE_USER
:
1019 case VIR_DOMAIN_NET_TYPE_ETHERNET
:
1020 case VIR_DOMAIN_NET_TYPE_VHOSTUSER
:
1021 case VIR_DOMAIN_NET_TYPE_SERVER
:
1022 case VIR_DOMAIN_NET_TYPE_CLIENT
:
1023 case VIR_DOMAIN_NET_TYPE_MCAST
:
1024 case VIR_DOMAIN_NET_TYPE_UDP
:
1025 case VIR_DOMAIN_NET_TYPE_INTERNAL
:
1026 case VIR_DOMAIN_NET_TYPE_LAST
:
1027 vshError(ctl
, _("No support for %s in command 'attach-interface'"),
1034 virBufferAsprintf(&buf
, "<target dev='%s'/>\n", target
);
1036 virBufferAsprintf(&buf
, "<mac address='%s'/>\n", mac
);
1038 virBufferAsprintf(&buf
, "<script path='%s'/>\n", script
);
1040 virBufferAsprintf(&buf
, "<model type='%s'/>\n", model
);
1043 virBufferAsprintf(&buf
, "<alias name='%s'/>\n", alias
);
1045 if (inboundStr
|| outboundStr
) {
1046 virBufferAddLit(&buf
, "<bandwidth>\n");
1047 virBufferAdjustIndent(&buf
, 2);
1048 if (inboundStr
&& (inbound
.average
|| inbound
.floor
)) {
1049 virBufferAddLit(&buf
, "<inbound");
1050 if (inbound
.average
> 0)
1051 virBufferAsprintf(&buf
, " average='%llu'", inbound
.average
);
1052 if (inbound
.peak
> 0)
1053 virBufferAsprintf(&buf
, " peak='%llu'", inbound
.peak
);
1054 if (inbound
.burst
> 0)
1055 virBufferAsprintf(&buf
, " burst='%llu'", inbound
.burst
);
1056 if (inbound
.floor
> 0)
1057 virBufferAsprintf(&buf
, " floor='%llu'", inbound
.floor
);
1058 virBufferAddLit(&buf
, "/>\n");
1060 if (outboundStr
&& outbound
.average
> 0) {
1061 virBufferAsprintf(&buf
, "<outbound average='%llu'", outbound
.average
);
1062 if (outbound
.peak
> 0)
1063 virBufferAsprintf(&buf
, " peak='%llu'", outbound
.peak
);
1064 if (outbound
.burst
> 0)
1065 virBufferAsprintf(&buf
, " burst='%llu'", outbound
.burst
);
1066 virBufferAddLit(&buf
, "/>\n");
1068 virBufferAdjustIndent(&buf
, -2);
1069 virBufferAddLit(&buf
, "</bandwidth>\n");
1072 virBufferAdjustIndent(&buf
, -2);
1073 virBufferAddLit(&buf
, "</interface>\n");
1075 if (virBufferError(&buf
)) {
1076 vshError(ctl
, "%s", _("Failed to allocate XML buffer"));
1080 xml
= virBufferContentAndReset(&buf
);
1082 if (vshCommandOptBool(cmd
, "print-xml")) {
1083 vshPrint(ctl
, "%s", xml
);
1084 functionReturn
= true;
1088 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
1092 virDomainIsActive(dom
) == 1)
1093 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
1095 if (flags
|| current
)
1096 ret
= virDomainAttachDeviceFlags(dom
, xml
, flags
);
1098 ret
= virDomainAttachDevice(dom
, xml
);
1101 vshError(ctl
, "%s", _("Failed to attach interface"));
1103 vshPrintExtra(ctl
, "%s", _("Interface attached successfully\n"));
1104 functionReturn
= true;
1109 virshDomainFree(dom
);
1110 virBufferFreeAndReset(&buf
);
1111 return functionReturn
;
1115 * "autostart" command
1117 static const vshCmdInfo info_autostart
[] = {
1119 .data
= N_("autostart a domain")
1122 .data
= N_("Configure a domain to be automatically started at boot.")
1127 static const vshCmdOptDef opts_autostart
[] = {
1128 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_PERSISTENT
),
1130 .type
= VSH_OT_BOOL
,
1131 .help
= N_("disable autostarting")
1137 cmdAutostart(vshControl
*ctl
, const vshCmd
*cmd
)
1143 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
1146 autostart
= !vshCommandOptBool(cmd
, "disable");
1148 if (virDomainSetAutostart(dom
, autostart
) < 0) {
1150 vshError(ctl
, _("Failed to mark domain %s as autostarted"), name
);
1152 vshError(ctl
, _("Failed to unmark domain %s as autostarted"), name
);
1153 virshDomainFree(dom
);
1158 vshPrintExtra(ctl
, _("Domain %s marked as autostarted\n"), name
);
1160 vshPrintExtra(ctl
, _("Domain %s unmarked as autostarted\n"), name
);
1162 virshDomainFree(dom
);
1167 * "blkdeviotune" command
1169 static const vshCmdInfo info_blkdeviotune
[] = {
1171 .data
= N_("Set or query a block device I/O tuning parameters.")
1174 .data
= N_("Set or query disk I/O parameters such as block throttling.")
1179 static const vshCmdOptDef opts_blkdeviotune
[] = {
1180 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
1182 .type
= VSH_OT_DATA
,
1183 .flags
= VSH_OFLAG_REQ
,
1184 .completer
= virshDomainDiskTargetCompleter
,
1185 .help
= N_("block device")
1187 {.name
= "total_bytes_sec",
1188 .type
= VSH_OT_ALIAS
,
1189 .help
= "total-bytes-sec"
1191 {.name
= "total-bytes-sec",
1193 .help
= N_("total throughput limit, as scaled integer (default bytes)")
1195 {.name
= "read_bytes_sec",
1196 .type
= VSH_OT_ALIAS
,
1197 .help
= "read-bytes-sec"
1199 {.name
= "read-bytes-sec",
1201 .help
= N_("read throughput limit, as scaled integer (default bytes)")
1203 {.name
= "write_bytes_sec",
1204 .type
= VSH_OT_ALIAS
,
1205 .help
= "write-bytes-sec"
1207 {.name
= "write-bytes-sec",
1209 .help
= N_("write throughput limit, as scaled integer (default bytes)")
1211 {.name
= "total_iops_sec",
1212 .type
= VSH_OT_ALIAS
,
1213 .help
= "total-iops-sec"
1215 {.name
= "total-iops-sec",
1217 .help
= N_("total I/O operations limit per second")
1219 {.name
= "read_iops_sec",
1220 .type
= VSH_OT_ALIAS
,
1221 .help
= "read-iops-sec"
1223 {.name
= "read-iops-sec",
1225 .help
= N_("read I/O operations limit per second")
1227 {.name
= "write_iops_sec",
1228 .type
= VSH_OT_ALIAS
,
1229 .help
= "write-iops-sec"
1231 {.name
= "write-iops-sec",
1233 .help
= N_("write I/O operations limit per second")
1235 {.name
= "total_bytes_sec_max",
1236 .type
= VSH_OT_ALIAS
,
1237 .help
= "total-bytes-sec-max"
1239 {.name
= "total-bytes-sec-max",
1241 .help
= N_("total max, as scaled integer (default bytes)")
1243 {.name
= "read_bytes_sec_max",
1244 .type
= VSH_OT_ALIAS
,
1245 .help
= "read-bytes-sec-max"
1247 {.name
= "read-bytes-sec-max",
1249 .help
= N_("read max, as scaled integer (default bytes)")
1251 {.name
= "write_bytes_sec_max",
1252 .type
= VSH_OT_ALIAS
,
1253 .help
= "write-bytes-sec-max"
1255 {.name
= "write-bytes-sec-max",
1257 .help
= N_("write max, as scaled integer (default bytes)")
1259 {.name
= "total_iops_sec_max",
1260 .type
= VSH_OT_ALIAS
,
1261 .help
= "total-iops-sec-max"
1263 {.name
= "total-iops-sec-max",
1265 .help
= N_("total I/O operations max")
1267 {.name
= "read_iops_sec_max",
1268 .type
= VSH_OT_ALIAS
,
1269 .help
= "read-iops-sec-max"
1271 {.name
= "read-iops-sec-max",
1273 .help
= N_("read I/O operations max")
1275 {.name
= "write_iops_sec_max",
1276 .type
= VSH_OT_ALIAS
,
1277 .help
= "write-iops-sec-max"
1279 {.name
= "write-iops-sec-max",
1281 .help
= N_("write I/O operations max")
1283 {.name
= "size_iops_sec",
1284 .type
= VSH_OT_ALIAS
,
1285 .help
= "size-iops-sec"
1287 {.name
= "size-iops-sec",
1289 .help
= N_("I/O size in bytes")
1291 {.name
= "group_name",
1292 .type
= VSH_OT_ALIAS
,
1293 .help
= "group-name"
1295 {.name
= "group-name",
1296 .type
= VSH_OT_STRING
,
1297 .help
= N_("group name to share I/O quota between multiple drives")
1299 {.name
= "total_bytes_sec_max_length",
1300 .type
= VSH_OT_ALIAS
,
1301 .help
= "total-bytes-sec-max-length"
1303 {.name
= "total-bytes-sec-max-length",
1305 .help
= N_("duration in seconds to allow total max bytes")
1307 {.name
= "read_bytes_sec_max_length",
1308 .type
= VSH_OT_ALIAS
,
1309 .help
= "read-bytes-sec-max-length"
1311 {.name
= "read-bytes-sec-max-length",
1313 .help
= N_("duration in seconds to allow read max bytes")
1315 {.name
= "write_bytes_sec_max_length",
1316 .type
= VSH_OT_ALIAS
,
1317 .help
= "write-bytes-sec-max-length"
1319 {.name
= "write-bytes-sec-max-length",
1321 .help
= N_("duration in seconds to allow write max bytes")
1323 {.name
= "total_iops_sec_max_length",
1324 .type
= VSH_OT_ALIAS
,
1325 .help
= "total-iops-sec-max-length"
1327 {.name
= "total-iops-sec-max-length",
1329 .help
= N_("duration in seconds to allow total I/O operations max")
1331 {.name
= "read_iops_sec_max_length",
1332 .type
= VSH_OT_ALIAS
,
1333 .help
= "read-iops-sec-max-length"
1335 {.name
= "read-iops-sec-max-length",
1337 .help
= N_("duration in seconds to allow read I/O operations max")
1339 {.name
= "write_iops_sec_max_length",
1340 .type
= VSH_OT_ALIAS
,
1341 .help
= "write-iops-sec-max-length"
1343 {.name
= "write-iops-sec-max-length",
1345 .help
= N_("duration in seconds to allow write I/O operations max")
1347 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
1348 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
1349 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
1354 cmdBlkdeviotune(vshControl
*ctl
, const vshCmd
*cmd
)
1356 virDomainPtr dom
= NULL
;
1357 const char *name
, *disk
;
1358 const char *group_name
= NULL
;
1359 unsigned long long value
;
1362 virTypedParameterPtr params
= NULL
;
1363 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
1366 bool current
= vshCommandOptBool(cmd
, "current");
1367 bool config
= vshCommandOptBool(cmd
, "config");
1368 bool live
= vshCommandOptBool(cmd
, "live");
1371 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
1372 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
1375 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
1377 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
1379 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
1382 if (vshCommandOptStringReq(ctl
, cmd
, "device", &disk
) < 0)
1385 #define VSH_ADD_IOTUNE_SCALED(PARAM, CONST) \
1386 if ((rv = vshCommandOptScaledInt(ctl, cmd, #PARAM, &value, \
1387 1, ULLONG_MAX)) < 0) { \
1389 } else if (rv > 0) { \
1390 if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \
1391 VIR_DOMAIN_BLOCK_IOTUNE_##CONST, \
1396 VSH_ADD_IOTUNE_SCALED(total
-bytes
-sec
, TOTAL_BYTES_SEC
);
1397 VSH_ADD_IOTUNE_SCALED(read
-bytes
-sec
, READ_BYTES_SEC
);
1398 VSH_ADD_IOTUNE_SCALED(write
-bytes
-sec
, WRITE_BYTES_SEC
);
1399 VSH_ADD_IOTUNE_SCALED(total
-bytes
-sec
-max
, TOTAL_BYTES_SEC_MAX
);
1400 VSH_ADD_IOTUNE_SCALED(read
-bytes
-sec
-max
, READ_BYTES_SEC_MAX
);
1401 VSH_ADD_IOTUNE_SCALED(write
-bytes
-sec
-max
, WRITE_BYTES_SEC_MAX
);
1402 #undef VSH_ADD_IOTUNE_SCALED
1404 #define VSH_ADD_IOTUNE(PARAM, CONST) \
1405 if ((rv = vshCommandOptULongLong(ctl, cmd, #PARAM, &value)) < 0) { \
1407 } else if (rv > 0) { \
1408 if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \
1409 VIR_DOMAIN_BLOCK_IOTUNE_##CONST, \
1414 VSH_ADD_IOTUNE(total
-iops
-sec
, TOTAL_IOPS_SEC
);
1415 VSH_ADD_IOTUNE(read
-iops
-sec
, READ_IOPS_SEC
);
1416 VSH_ADD_IOTUNE(write
-iops
-sec
, WRITE_IOPS_SEC
);
1417 VSH_ADD_IOTUNE(total
-iops
-sec
-max
, TOTAL_IOPS_SEC_MAX
);
1418 VSH_ADD_IOTUNE(read
-iops
-sec
-max
, READ_IOPS_SEC_MAX
);
1419 VSH_ADD_IOTUNE(write
-iops
-sec
-max
, WRITE_IOPS_SEC_MAX
);
1420 VSH_ADD_IOTUNE(size
-iops
-sec
, SIZE_IOPS_SEC
);
1422 VSH_ADD_IOTUNE(total
-bytes
-sec
-max
-length
, TOTAL_BYTES_SEC_MAX_LENGTH
);
1423 VSH_ADD_IOTUNE(read
-bytes
-sec
-max
-length
, READ_BYTES_SEC_MAX_LENGTH
);
1424 VSH_ADD_IOTUNE(write
-bytes
-sec
-max
-length
, WRITE_BYTES_SEC_MAX_LENGTH
);
1425 VSH_ADD_IOTUNE(total
-iops
-sec
-max
-length
, TOTAL_IOPS_SEC_MAX_LENGTH
);
1426 VSH_ADD_IOTUNE(read
-iops
-sec
-max
-length
, READ_IOPS_SEC_MAX_LENGTH
);
1427 VSH_ADD_IOTUNE(write
-iops
-sec
-max
-length
, WRITE_IOPS_SEC_MAX_LENGTH
);
1428 #undef VSH_ADD_IOTUNE
1430 if (vshCommandOptStringReq(ctl
, cmd
, "group-name", &group_name
) < 0) {
1431 vshError(ctl
, "%s", _("Unable to parse group-name parameter"));
1436 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1437 VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME
,
1444 if (virDomainGetBlockIoTune(dom
, NULL
, NULL
, &nparams
, flags
) != 0) {
1446 _("Unable to get number of block I/O throttle parameters"));
1455 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
1457 if (virDomainGetBlockIoTune(dom
, disk
, params
, &nparams
, flags
) != 0) {
1459 _("Unable to get block I/O throttle parameters"));
1463 for (i
= 0; i
< nparams
; i
++) {
1464 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
1465 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
1469 if (virDomainSetBlockIoTune(dom
, disk
, params
, nparams
, flags
) < 0)
1476 virTypedParamsFree(params
, nparams
);
1477 virshDomainFree(dom
);
1481 vshSaveLibvirtError();
1483 vshError(ctl
, "%s", _("Unable to change block I/O throttle"));
1487 vshError(ctl
, "%s", _("Unable to parse integer parameter"));
1492 * "blkiotune" command
1494 static const vshCmdInfo info_blkiotune
[] = {
1496 .data
= N_("Get or set blkio parameters")
1499 .data
= N_("Get or set the current blkio parameters for a guest"
1501 " To get the blkio parameters use following command: \n\n"
1502 " virsh # blkiotune <domain>")
1507 static const vshCmdOptDef opts_blkiotune
[] = {
1508 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
1511 .help
= N_("IO Weight")
1513 {.name
= "device-weights",
1514 .type
= VSH_OT_STRING
,
1515 .help
= N_("per-device IO Weights, in the form of /path/to/device,weight,...")
1517 {.name
= "device-read-iops-sec",
1518 .type
= VSH_OT_STRING
,
1519 .help
= N_("per-device read I/O limit per second, in the form of /path/to/device,read_iops_sec,...")
1521 {.name
= "device-write-iops-sec",
1522 .type
= VSH_OT_STRING
,
1523 .help
= N_("per-device write I/O limit per second, in the form of /path/to/device,write_iops_sec,...")
1525 {.name
= "device-read-bytes-sec",
1526 .type
= VSH_OT_STRING
,
1527 .help
= N_("per-device bytes read per second, in the form of /path/to/device,read_bytes_sec,...")
1529 {.name
= "device-write-bytes-sec",
1530 .type
= VSH_OT_STRING
,
1531 .help
= N_("per-device bytes wrote per second, in the form of /path/to/device,write_bytes_sec,...")
1533 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
1534 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
1535 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
1540 cmdBlkiotune(vshControl
* ctl
, const vshCmd
* cmd
)
1543 const char *device_weight
= NULL
;
1544 const char *device_riops
= NULL
;
1545 const char *device_wiops
= NULL
;
1546 const char *device_rbps
= NULL
;
1547 const char *device_wbps
= NULL
;
1553 virTypedParameterPtr params
= NULL
;
1555 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
1556 bool current
= vshCommandOptBool(cmd
, "current");
1557 bool config
= vshCommandOptBool(cmd
, "config");
1558 bool live
= vshCommandOptBool(cmd
, "live");
1560 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
1561 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
1564 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
1566 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
1568 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
1571 if ((rv
= vshCommandOptInt(ctl
, cmd
, "weight", &weight
)) < 0) {
1573 } else if (rv
> 0) {
1575 vshError(ctl
, _("Invalid value of %d for I/O weight"), weight
);
1578 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
1579 VIR_DOMAIN_BLKIO_WEIGHT
, weight
) < 0)
1583 rv
= vshCommandOptStringQuiet(ctl
, cmd
, "device-weights", &device_weight
);
1585 vshError(ctl
, "%s", _("Unable to parse string parameter"));
1587 } else if (rv
> 0) {
1588 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1589 VIR_DOMAIN_BLKIO_DEVICE_WEIGHT
,
1594 rv
= vshCommandOptStringQuiet(ctl
, cmd
, "device-read-iops-sec", &device_riops
);
1596 vshError(ctl
, "%s", _("Unable to parse string parameter"));
1598 } else if (rv
> 0) {
1599 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1600 VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS
,
1605 rv
= vshCommandOptStringQuiet(ctl
, cmd
, "device-write-iops-sec", &device_wiops
);
1607 vshError(ctl
, "%s", _("Unable to parse string parameter"));
1609 } else if (rv
> 0) {
1610 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1611 VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS
,
1616 rv
= vshCommandOptStringQuiet(ctl
, cmd
, "device-read-bytes-sec", &device_rbps
);
1618 vshError(ctl
, "%s", _("Unable to parse string parameter"));
1620 } else if (rv
> 0) {
1621 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1622 VIR_DOMAIN_BLKIO_DEVICE_READ_BPS
,
1627 rv
= vshCommandOptStringQuiet(ctl
, cmd
, "device-write-bytes-sec", &device_wbps
);
1629 vshError(ctl
, "%s", _("Unable to parse string parameter"));
1631 } else if (rv
> 0) {
1632 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
1633 VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS
,
1639 /* get the number of blkio parameters */
1640 if (virDomainGetBlkioParameters(dom
, NULL
, &nparams
, flags
) != 0) {
1642 _("Unable to get number of blkio parameters"));
1647 /* nothing to output */
1652 /* now go get all the blkio parameters */
1653 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
1654 if (virDomainGetBlkioParameters(dom
, params
, &nparams
, flags
) != 0) {
1655 vshError(ctl
, "%s", _("Unable to get blkio parameters"));
1659 for (i
= 0; i
< nparams
; i
++) {
1660 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
1661 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
1665 /* set the blkio parameters */
1666 if (virDomainSetBlkioParameters(dom
, params
, nparams
, flags
) < 0)
1673 virTypedParamsFree(params
, nparams
);
1674 virshDomainFree(dom
);
1678 vshSaveLibvirtError();
1680 vshError(ctl
, "%s", _("Unable to change blkio parameters"));
1686 virshPrintJobProgress(const char *label
, unsigned long long remaining
,
1687 unsigned long long total
)
1691 if (remaining
== 0) {
1692 /* migration has completed */
1695 /* use float to avoid overflow */
1696 progress
= (int)(100.0 - remaining
* 100.0 / total
);
1697 if (progress
>= 100) {
1698 /* migration has not completed, do not print [100 %] */
1703 /* see comments in vshError about why we must flush */
1705 fprintf(stderr
, "\r%s: [%3d %%]", label
, progress
);
1709 static volatile sig_atomic_t intCaught
;
1711 static void virshCatchInt(int sig ATTRIBUTE_UNUSED
,
1712 siginfo_t
*siginfo ATTRIBUTE_UNUSED
,
1713 void *context ATTRIBUTE_UNUSED
)
1719 typedef struct _virshBlockJobWaitData virshBlockJobWaitData
;
1720 typedef virshBlockJobWaitData
*virshBlockJobWaitDataPtr
;
1721 struct _virshBlockJobWaitData
{
1725 const char *job_name
;
1728 unsigned int timeout
;
1738 virshBlockJobStatusHandler(virConnectPtr conn ATTRIBUTE_UNUSED
,
1739 virDomainPtr dom ATTRIBUTE_UNUSED
,
1741 int type ATTRIBUTE_UNUSED
,
1745 virshBlockJobWaitDataPtr data
= opaque
;
1747 if (STREQ_NULLABLE(disk
, data
->dev
))
1748 data
->status
= status
;
1753 * virshBlockJobWaitInit:
1754 * @ctl: vsh control structure
1755 * @dom: domain object
1756 * @dev: block device name to wait for
1757 * @job_name: block job name to display in user-facing messages
1758 * @verbose: enable progress reporting
1759 * @timeout: number of milliseconds to wait before aborting the job
1760 * @async_abort: abort the job asynchronously
1762 * Prepares virsh for waiting for completion of a block job. This function
1763 * registers event handlers for block job events and prepares the data structures
1764 * for them. A call to virshBlockJobWait then waits for completion of the given
1765 * block job. This function should be tolerant to different versions of daemon
1766 * and the reporting capabilities of those.
1768 * Returns the data structure that holds data needed for block job waiting or
1769 * NULL in case of error.
1771 static virshBlockJobWaitDataPtr
1772 virshBlockJobWaitInit(vshControl
*ctl
,
1775 const char *job_name
,
1777 unsigned int timeout
,
1780 virshBlockJobWaitDataPtr ret
;
1781 virshControlPtr priv
= ctl
->privData
;
1783 if (VIR_ALLOC(ret
) < 0)
1789 ret
->job_name
= job_name
;
1791 ret
->async_abort
= async_abort
;
1792 ret
->timeout
= timeout
;
1793 ret
->verbose
= verbose
;
1797 virConnectDomainEventGenericCallback cb
=
1798 VIR_DOMAIN_EVENT_CALLBACK(virshBlockJobStatusHandler
);
1800 if ((ret
->cb_id
= virConnectDomainEventRegisterAny(priv
->conn
, dom
,
1801 VIR_DOMAIN_EVENT_ID_BLOCK_JOB
,
1802 cb
, ret
, NULL
)) < 0)
1803 vshResetLibvirtError();
1805 if ((ret
->cb_id2
= virConnectDomainEventRegisterAny(priv
->conn
, dom
,
1806 VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2
,
1807 cb
, ret
, NULL
)) < 0)
1808 vshResetLibvirtError();
1815 virshBlockJobWaitFree(virshBlockJobWaitDataPtr data
)
1817 virshControlPtr priv
= NULL
;
1822 priv
= data
->ctl
->privData
;
1823 if (data
->cb_id
>= 0)
1824 virConnectDomainEventDeregisterAny(priv
->conn
, data
->cb_id
);
1825 if (data
->cb_id2
>= 0)
1826 virConnectDomainEventDeregisterAny(priv
->conn
, data
->cb_id2
);
1833 * virshBlockJobWait:
1834 * @data: private data initialized by virshBlockJobWaitInit
1836 * Waits for the block job to complete. This function prefers to wait for a
1837 * matching VIR_DOMAIN_EVENT_ID_BLOCK_JOB or VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2
1838 * event from libvirt; however, it has a fallback mode should either of these
1839 * events not be available.
1841 * This function returns values from the virConnectDomainEventBlockJobStatus
1842 * enum or -1 in case of an internal error.
1844 * If the fallback mode is activated the returned event is
1845 * VIR_DOMAIN_BLOCK_JOB_COMPLETED if the block job vanishes or
1846 * VIR_DOMAIN_BLOCK_JOB_READY if the block job reaches 100%.
1849 virshBlockJobWait(virshBlockJobWaitDataPtr data
)
1851 /* For two phase jobs like active commit or block copy, the marker reaches
1852 * 100% and an event fires. In case where virsh would not be able to match
1853 * the event to the given block job we will wait for the number of retries
1854 * before claiming that we entered synchronised phase */
1855 unsigned int retries
= 5;
1857 struct sigaction sig_action
;
1858 struct sigaction old_sig_action
;
1859 sigset_t sigmask
, oldsigmask
;
1861 unsigned long long start
= 0;
1862 unsigned long long curr
= 0;
1864 unsigned int abort_flags
= 0;
1866 virDomainBlockJobInfo info
, last
;
1872 if (data
->async_abort
)
1873 abort_flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC
;
1875 sigemptyset(&sigmask
);
1876 sigaddset(&sigmask
, SIGINT
);
1879 sig_action
.sa_sigaction
= virshCatchInt
;
1880 sig_action
.sa_flags
= SA_SIGINFO
;
1881 sigemptyset(&sig_action
.sa_mask
);
1882 sigaction(SIGINT
, &sig_action
, &old_sig_action
);
1884 if (data
->timeout
&& virTimeMillisNow(&start
) < 0) {
1885 vshSaveLibvirtError();
1889 last
.cur
= last
.end
= 0;
1892 pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
);
1893 result
= virDomainGetBlockJobInfo(data
->dom
, data
->dev
, &info
, 0);
1894 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
1897 vshError(data
->ctl
, _("failed to query job for disk %s"), data
->dev
);
1901 /* If either callback could be registered and we've got an event, we can
1902 * can end the waiting loop */
1903 if ((data
->cb_id
>= 0 || data
->cb_id2
>= 0) && data
->status
!= -1) {
1908 /* Fallback behaviour is only needed if one or both callbacks could not
1910 if (data
->cb_id
< 0 || data
->cb_id2
< 0) {
1911 /* If the block job vanishes, synthesize a COMPLETED event */
1913 ret
= VIR_DOMAIN_BLOCK_JOB_COMPLETED
;
1917 /* If the block job hits 100%, wait a little while for a possible
1918 * event from libvirt unless both callbacks could not be registered
1919 * in order to synthesize our own READY event */
1920 if (info
.end
== info
.cur
&&
1921 ((data
->cb_id
< 0 && data
->cb_id2
< 0) || --retries
== 0)) {
1922 ret
= VIR_DOMAIN_BLOCK_JOB_READY
;
1927 if (data
->verbose
&& (info
.cur
!= last
.cur
|| info
.end
!= last
.end
))
1928 virshPrintJobProgress(data
->job_name
, info
.end
- info
.cur
,
1932 if (data
->timeout
&& virTimeMillisNow(&curr
) < 0) {
1933 vshSaveLibvirtError();
1937 if (intCaught
|| (data
->timeout
&& (curr
- start
> data
->timeout
))) {
1938 if (virDomainBlockJobAbort(data
->dom
, data
->dev
, abort_flags
) < 0) {
1939 vshError(data
->ctl
, _("failed to abort job for disk '%s'"),
1944 ret
= VIR_DOMAIN_BLOCK_JOB_CANCELED
;
1951 /* print 100% completed */
1952 if (data
->verbose
&&
1953 (ret
== VIR_DOMAIN_BLOCK_JOB_COMPLETED
||
1954 ret
== VIR_DOMAIN_BLOCK_JOB_READY
))
1955 virshPrintJobProgress(data
->job_name
, 0, 1);
1958 sigaction(SIGINT
, &old_sig_action
, NULL
);
1964 * "blockcommit" command
1966 static const vshCmdInfo info_blockcommit
[] = {
1968 .data
= N_("Start a block commit operation.")
1971 .data
= N_("Commit changes from a snapshot down to its backing image.")
1976 static const vshCmdOptDef opts_blockcommit
[] = {
1977 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
1979 .type
= VSH_OT_DATA
,
1980 .flags
= VSH_OFLAG_REQ
,
1981 .completer
= virshDomainDiskTargetCompleter
,
1982 .help
= N_("fully-qualified path of disk")
1984 {.name
= "bandwidth",
1986 .help
= N_("bandwidth limit in MiB/s")
1989 .type
= VSH_OT_STRING
,
1990 .help
= N_("path of base file to commit into (default bottom of chain)")
1993 .type
= VSH_OT_BOOL
,
1994 .help
= N_("use backing file of top as base")
1997 .type
= VSH_OT_STRING
,
1998 .help
= N_("path of top file to commit from (default top of chain)")
2001 .type
= VSH_OT_BOOL
,
2002 .help
= N_("trigger two-stage active commit of top file")
2005 .type
= VSH_OT_BOOL
,
2006 .help
= N_("delete files that were successfully committed")
2009 .type
= VSH_OT_BOOL
,
2010 .help
= N_("wait for job to complete "
2011 "(with --active, wait for job to sync)")
2014 .type
= VSH_OT_BOOL
,
2015 .help
= N_("with --wait, display the progress")
2019 .help
= N_("implies --wait, abort if copy exceeds timeout (in seconds)")
2022 .type
= VSH_OT_BOOL
,
2023 .help
= N_("implies --active --wait, pivot when commit is synced")
2025 {.name
= "keep-overlay",
2026 .type
= VSH_OT_BOOL
,
2027 .help
= N_("implies --active --wait, quit when commit is synced")
2030 .type
= VSH_OT_BOOL
,
2031 .help
= N_("with --wait, don't wait for cancel to finish")
2033 {.name
= "keep-relative",
2034 .type
= VSH_OT_BOOL
,
2035 .help
= N_("keep the backing chain relatively referenced")
2038 .type
= VSH_OT_BOOL
,
2039 .help
= N_("the bandwidth limit is in bytes/s rather than MiB/s")
2045 cmdBlockcommit(vshControl
*ctl
, const vshCmd
*cmd
)
2047 virDomainPtr dom
= NULL
;
2049 bool verbose
= vshCommandOptBool(cmd
, "verbose");
2050 bool pivot
= vshCommandOptBool(cmd
, "pivot");
2051 bool finish
= vshCommandOptBool(cmd
, "keep-overlay");
2052 bool active
= vshCommandOptBool(cmd
, "active") || pivot
|| finish
;
2053 bool blocking
= vshCommandOptBool(cmd
, "wait") || pivot
|| finish
;
2054 bool async
= vshCommandOptBool(cmd
, "async");
2055 bool bytes
= vshCommandOptBool(cmd
, "bytes");
2057 const char *path
= NULL
;
2058 const char *base
= NULL
;
2059 const char *top
= NULL
;
2060 int abort_flags
= 0;
2061 unsigned int flags
= 0;
2062 unsigned long bandwidth
= 0;
2063 virshBlockJobWaitDataPtr bjWait
= NULL
;
2065 VSH_EXCLUSIVE_OPTIONS("pivot", "keep-overlay");
2067 if (vshCommandOptStringReq(ctl
, cmd
, "path", &path
) < 0)
2070 if (vshCommandOptStringReq(ctl
, cmd
, "base", &base
) < 0)
2073 if (vshCommandOptStringReq(ctl
, cmd
, "top", &top
) < 0)
2076 if (vshBlockJobOptionBandwidth(ctl
, cmd
, bytes
, &bandwidth
) < 0)
2080 flags
|= VIR_DOMAIN_BLOCK_COMMIT_BANDWIDTH_BYTES
;
2082 if (vshCommandOptBool(cmd
, "shallow"))
2083 flags
|= VIR_DOMAIN_BLOCK_COMMIT_SHALLOW
;
2085 if (vshCommandOptBool(cmd
, "delete"))
2086 flags
|= VIR_DOMAIN_BLOCK_COMMIT_DELETE
;
2089 flags
|= VIR_DOMAIN_BLOCK_COMMIT_ACTIVE
;
2091 if (vshCommandOptBool(cmd
, "keep-relative"))
2092 flags
|= VIR_DOMAIN_BLOCK_COMMIT_RELATIVE
;
2094 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0)
2102 vshError(ctl
, "%s", _("--verbose requires at least one of --timeout, "
2103 "--wait, --pivot, or --keep-overlay"));
2108 vshError(ctl
, "%s", _("--async requires at least one of --timeout, "
2109 "--wait, --pivot, or --keep-overlay"));
2115 abort_flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC
;
2117 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
2121 !(bjWait
= virshBlockJobWaitInit(ctl
, dom
, path
, _("Block commit"),
2122 verbose
, timeout
, async
)))
2125 if (virDomainBlockCommit(dom
, path
, base
, top
, bandwidth
, flags
) < 0)
2130 vshPrintExtra(ctl
, "%s", _("Active Block Commit started"));
2132 vshPrintExtra(ctl
, "%s", _("Block Commit started"));
2138 /* Execution continues here only if --wait or friends were specified */
2139 switch (virshBlockJobWait(bjWait
)) {
2143 case VIR_DOMAIN_BLOCK_JOB_CANCELED
:
2144 vshPrintExtra(ctl
, "\n%s", _("Commit aborted"));
2148 case VIR_DOMAIN_BLOCK_JOB_FAILED
:
2149 vshError(ctl
, "\n%s", _("Commit failed"));
2153 case VIR_DOMAIN_BLOCK_JOB_READY
:
2154 case VIR_DOMAIN_BLOCK_JOB_COMPLETED
:
2160 abort_flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT
;
2161 if (virDomainBlockJobAbort(dom
, path
, abort_flags
) < 0) {
2162 vshError(ctl
, _("failed to pivot job for disk %s"), path
);
2166 vshPrintExtra(ctl
, "\n%s", _("Successfully pivoted"));
2167 } else if (finish
) {
2168 if (virDomainBlockJobAbort(dom
, path
, abort_flags
) < 0) {
2169 vshError(ctl
, _("failed to finish job for disk %s"), path
);
2173 vshPrintExtra(ctl
, "\n%s", _("Commit complete, overlay "
2176 vshPrintExtra(ctl
, "\n%s", _("Now in synchronized phase"));
2179 vshPrintExtra(ctl
, "\n%s", _("Commit complete"));
2184 virshDomainFree(dom
);
2185 virshBlockJobWaitFree(bjWait
);
2190 * "blockcopy" command
2192 static const vshCmdInfo info_blockcopy
[] = {
2194 .data
= N_("Start a block copy operation.")
2197 .data
= N_("Copy a disk backing image chain to dest.")
2202 static const vshCmdOptDef opts_blockcopy
[] = {
2203 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
2205 .type
= VSH_OT_DATA
,
2206 .flags
= VSH_OFLAG_REQ
,
2207 .completer
= virshDomainDiskTargetCompleter
,
2208 .help
= N_("fully-qualified path of source disk")
2211 .type
= VSH_OT_STRING
,
2212 .help
= N_("path of the copy to create")
2214 {.name
= "bandwidth",
2216 .help
= N_("bandwidth limit in MiB/s")
2219 .type
= VSH_OT_BOOL
,
2220 .help
= N_("make the copy share a backing chain")
2222 {.name
= "reuse-external",
2223 .type
= VSH_OT_BOOL
,
2224 .help
= N_("reuse existing destination")
2227 .type
= VSH_OT_ALIAS
,
2228 .help
= "format=raw"
2230 {.name
= "blockdev",
2231 .type
= VSH_OT_BOOL
,
2232 .help
= N_("copy destination is block device instead of regular file")
2235 .type
= VSH_OT_BOOL
,
2236 .help
= N_("wait for job to reach mirroring phase")
2239 .type
= VSH_OT_BOOL
,
2240 .help
= N_("with --wait, display the progress")
2244 .help
= N_("implies --wait, abort if copy exceeds timeout (in seconds)")
2247 .type
= VSH_OT_BOOL
,
2248 .help
= N_("implies --wait, pivot when mirroring starts")
2251 .type
= VSH_OT_BOOL
,
2252 .help
= N_("implies --wait, quit when mirroring starts")
2255 .type
= VSH_OT_BOOL
,
2256 .help
= N_("with --wait, don't wait for cancel to finish")
2259 .type
= VSH_OT_STRING
,
2260 .help
= N_("filename containing XML description of the copy destination")
2263 .type
= VSH_OT_STRING
,
2264 .help
= N_("format of the destination file")
2266 {.name
= "granularity",
2268 .help
= N_("power-of-two granularity to use during the copy")
2270 {.name
= "buf-size",
2272 .help
= N_("maximum amount of in-flight data during the copy")
2275 .type
= VSH_OT_BOOL
,
2276 .help
= N_("the bandwidth limit is in bytes/s rather than MiB/s")
2278 {.name
= "transient-job",
2279 .type
= VSH_OT_BOOL
,
2280 .help
= N_("the copy job is not persisted if VM is turned off")
2286 cmdBlockcopy(vshControl
*ctl
, const vshCmd
*cmd
)
2288 virDomainPtr dom
= NULL
;
2289 const char *dest
= NULL
;
2290 const char *format
= NULL
;
2291 unsigned long bandwidth
= 0;
2292 unsigned int granularity
= 0;
2293 unsigned long long buf_size
= 0;
2294 unsigned int flags
= 0;
2296 bool verbose
= vshCommandOptBool(cmd
, "verbose");
2297 bool pivot
= vshCommandOptBool(cmd
, "pivot");
2298 bool finish
= vshCommandOptBool(cmd
, "finish");
2299 bool blockdev
= vshCommandOptBool(cmd
, "blockdev");
2300 bool blocking
= vshCommandOptBool(cmd
, "wait") || finish
|| pivot
;
2301 bool async
= vshCommandOptBool(cmd
, "async");
2302 bool bytes
= vshCommandOptBool(cmd
, "bytes");
2303 bool transientjob
= vshCommandOptBool(cmd
, "transient-job");
2305 const char *path
= NULL
;
2306 int abort_flags
= 0;
2307 const char *xml
= NULL
;
2308 char *xmlstr
= NULL
;
2309 virTypedParameterPtr params
= NULL
;
2310 virshBlockJobWaitDataPtr bjWait
= NULL
;
2313 if (vshCommandOptStringReq(ctl
, cmd
, "path", &path
) < 0)
2315 if (vshCommandOptStringReq(ctl
, cmd
, "dest", &dest
) < 0)
2317 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &xml
) < 0)
2319 if (vshCommandOptStringReq(ctl
, cmd
, "format", &format
) < 0)
2321 if (vshBlockJobOptionBandwidth(ctl
, cmd
, bytes
, &bandwidth
) < 0)
2323 if (vshCommandOptUInt(ctl
, cmd
, "granularity", &granularity
) < 0)
2325 if (vshCommandOptULongLong(ctl
, cmd
, "buf-size", &buf_size
) < 0)
2327 /* Exploit that some VIR_DOMAIN_BLOCK_REBASE_* and
2328 * VIR_DOMAIN_BLOCK_COPY_* flags have the same values. */
2329 if (vshCommandOptBool(cmd
, "shallow"))
2330 flags
|= VIR_DOMAIN_BLOCK_REBASE_SHALLOW
;
2331 if (vshCommandOptBool(cmd
, "reuse-external"))
2332 flags
|= VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT
;
2334 flags
|= VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB
;
2335 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0)
2342 abort_flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC
;
2344 VSH_EXCLUSIVE_OPTIONS_VAR(dest
, xml
);
2345 VSH_EXCLUSIVE_OPTIONS_VAR(format
, xml
);
2346 VSH_EXCLUSIVE_OPTIONS_VAR(blockdev
, xml
);
2347 VSH_EXCLUSIVE_OPTIONS_VAR(pivot
, finish
);
2349 if (!dest
&& !xml
) {
2350 vshError(ctl
, "%s", _("need either --dest or --xml"));
2356 vshError(ctl
, "%s", _("--verbose requires at least one of --timeout, "
2357 "--wait, --pivot, or --finish"));
2362 vshError(ctl
, "%s", _("--async requires at least one of --timeout, "
2363 "--wait, --pivot, or --finish"));
2368 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
2372 !(bjWait
= virshBlockJobWaitInit(ctl
, dom
, path
, _("Block Copy"),
2373 verbose
, timeout
, async
)))
2377 if (virFileReadAll(xml
, VSH_MAX_XML_FILE
, &xmlstr
) < 0) {
2378 vshReportError(ctl
);
2383 if (granularity
|| buf_size
|| (format
&& STRNEQ(format
, "raw")) || xml
||
2386 if (bandwidth
|| granularity
|| buf_size
) {
2387 params
= vshCalloc(ctl
, 3, sizeof(*params
));
2390 /* bandwidth is ulong MiB/s, but the typed parameter is
2391 * ullong bytes/s; make sure we don't overflow */
2392 unsigned long long limit
= MIN(ULONG_MAX
, ULLONG_MAX
>> 20);
2393 if (bandwidth
> limit
) {
2394 vshError(ctl
, _("bandwidth must be less than %llu"), limit
);
2398 bandwidth
<<= 20ULL;
2400 if (virTypedParameterAssign(¶ms
[nparams
++],
2401 VIR_DOMAIN_BLOCK_COPY_BANDWIDTH
,
2402 VIR_TYPED_PARAM_ULLONG
,
2407 virTypedParameterAssign(¶ms
[nparams
++],
2408 VIR_DOMAIN_BLOCK_COPY_GRANULARITY
,
2409 VIR_TYPED_PARAM_UINT
,
2413 virTypedParameterAssign(¶ms
[nparams
++],
2414 VIR_DOMAIN_BLOCK_COPY_BUF_SIZE
,
2415 VIR_TYPED_PARAM_ULLONG
,
2421 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
2422 virBufferAsprintf(&buf
, "<disk type='%s'>\n",
2423 blockdev
? "block" : "file");
2424 virBufferAdjustIndent(&buf
, 2);
2425 virBufferAsprintf(&buf
, "<source %s", blockdev
? "dev" : "file");
2426 virBufferEscapeString(&buf
, "='%s'/>\n", dest
);
2427 virBufferEscapeString(&buf
, "<driver type='%s'/>\n", format
);
2428 virBufferAdjustIndent(&buf
, -2);
2429 virBufferAddLit(&buf
, "</disk>\n");
2430 if (virBufferCheckError(&buf
) < 0)
2432 xmlstr
= virBufferContentAndReset(&buf
);
2435 if (virDomainBlockCopy(dom
, path
, xmlstr
, params
, nparams
, flags
) < 0)
2439 flags
|= VIR_DOMAIN_BLOCK_REBASE_COPY
;
2441 flags
|= VIR_DOMAIN_BLOCK_REBASE_COPY_DEV
;
2442 if (STREQ_NULLABLE(format
, "raw"))
2443 flags
|= VIR_DOMAIN_BLOCK_REBASE_COPY_RAW
;
2445 flags
|= VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES
;
2447 if (virDomainBlockRebase(dom
, path
, dest
, bandwidth
, flags
) < 0)
2452 vshPrintExtra(ctl
, "%s", _("Block Copy started"));
2457 /* Execution continues here only if --wait or friends were specified */
2458 switch (virshBlockJobWait(bjWait
)) {
2462 case VIR_DOMAIN_BLOCK_JOB_CANCELED
:
2463 vshPrintExtra(ctl
, "\n%s", _("Copy aborted"));
2467 case VIR_DOMAIN_BLOCK_JOB_FAILED
:
2468 vshError(ctl
, "\n%s", _("Copy failed"));
2472 case VIR_DOMAIN_BLOCK_JOB_READY
:
2473 case VIR_DOMAIN_BLOCK_JOB_COMPLETED
:
2478 abort_flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT
;
2479 if (virDomainBlockJobAbort(dom
, path
, abort_flags
) < 0) {
2480 vshError(ctl
, _("failed to pivot job for disk %s"), path
);
2484 vshPrintExtra(ctl
, "\n%s", _("Successfully pivoted"));
2485 } else if (finish
) {
2486 if (virDomainBlockJobAbort(dom
, path
, abort_flags
) < 0) {
2487 vshError(ctl
, _("failed to finish job for disk %s"), path
);
2491 vshPrintExtra(ctl
, "\n%s", _("Successfully copied"));
2493 vshPrintExtra(ctl
, "\n%s", _("Now in mirroring phase"));
2500 virTypedParamsFree(params
, nparams
);
2501 virshDomainFree(dom
);
2502 virshBlockJobWaitFree(bjWait
);
2507 * "blockjob" command
2509 static const vshCmdInfo info_blockjob
[] = {
2511 .data
= N_("Manage active block operations")
2514 .data
= N_("Query, adjust speed, or cancel active block operations.")
2519 static const vshCmdOptDef opts_blockjob
[] = {
2520 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
2522 .type
= VSH_OT_DATA
,
2523 .flags
= VSH_OFLAG_REQ
,
2524 .completer
= virshDomainDiskTargetCompleter
,
2525 .help
= N_("fully-qualified path of disk")
2528 .type
= VSH_OT_BOOL
,
2529 .help
= N_("abort the active job on the specified disk")
2532 .type
= VSH_OT_BOOL
,
2533 .help
= N_("implies --abort; request but don't wait for job end")
2536 .type
= VSH_OT_BOOL
,
2537 .help
= N_("implies --abort; conclude and pivot a copy or commit job")
2540 .type
= VSH_OT_BOOL
,
2541 .help
= N_("get active job information for the specified disk")
2544 .type
= VSH_OT_BOOL
,
2545 .help
= N_("get/set bandwidth in bytes rather than MiB/s")
2548 .type
= VSH_OT_BOOL
,
2549 .help
= N_("implies --info; output details rather than human summary")
2551 {.name
= "bandwidth",
2553 .help
= N_("set the bandwidth limit in MiB/s")
2558 VIR_ENUM_DECL(virshDomainBlockJob
);
2559 VIR_ENUM_IMPL(virshDomainBlockJob
,
2560 VIR_DOMAIN_BLOCK_JOB_TYPE_LAST
,
2565 N_("Active Block Commit"),
2570 virshDomainBlockJobToString(int type
)
2572 const char *str
= virshDomainBlockJobTypeToString(type
);
2573 return str
? _(str
) : _("Unknown job");
2578 virshBlockJobInfo(vshControl
*ctl
,
2584 virDomainBlockJobInfo info
;
2585 virshControlPtr priv
= ctl
->privData
;
2586 unsigned long long speed
;
2587 unsigned int flags
= 0;
2591 /* If bytes were requested, or if raw mode is not forcing a MiB/s
2592 * query and cache can't prove failure, then query bytes/sec. */
2593 if (bytes
|| !(raw
|| priv
->blockJobNoBytes
)) {
2594 flags
|= VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES
;
2595 rc
= virDomainGetBlockJobInfo(dom
, path
, &info
, flags
);
2597 /* Check for particular errors, let all the rest be fatal. */
2598 switch (last_error
->code
) {
2599 case VIR_ERR_INVALID_ARG
:
2600 priv
->blockJobNoBytes
= true;
2601 ATTRIBUTE_FALLTHROUGH
;
2602 case VIR_ERR_OVERFLOW
:
2603 if (!bytes
&& !raw
) {
2604 /* try again with MiB/s, unless forcing bytes */
2605 vshResetLibvirtError();
2608 ATTRIBUTE_FALLTHROUGH
;
2613 speed
= info
.bandwidth
;
2615 /* If we don't already have a query result, query for MiB/s */
2617 flags
&= ~VIR_DOMAIN_BLOCK_JOB_INFO_BANDWIDTH_BYTES
;
2618 if ((rc
= virDomainGetBlockJobInfo(dom
, path
, &info
, flags
)) < 0)
2620 speed
= info
.bandwidth
;
2621 /* Scale to bytes/s unless in raw mode */
2624 if (speed
>> 20 != info
.bandwidth
) {
2625 vshError(ctl
, _("overflow in converting %ld MiB/s to bytes\n"),
2634 vshPrintExtra(ctl
, _("No current block job for %s"), path
);
2640 vshPrint(ctl
, _(" type=%s\n bandwidth=%lu\n cur=%llu\n end=%llu\n"),
2641 virshDomainBlockJobTypeToString(info
.type
),
2642 info
.bandwidth
, info
.cur
, info
.end
);
2644 virshPrintJobProgress(virshDomainBlockJobToString(info
.type
),
2645 info
.end
- info
.cur
, info
.end
);
2648 double val
= vshPrettyCapacity(speed
, &unit
);
2649 vshPrint(ctl
, _(" Bandwidth limit: %llu bytes/s (%-.3lf %s/s)"),
2652 vshPrint(ctl
, "\n");
2663 virshBlockJobSetSpeed(vshControl
*ctl
,
2669 unsigned long bandwidth
;
2670 unsigned int flags
= 0;
2673 flags
|= VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES
;
2675 if (vshBlockJobOptionBandwidth(ctl
, cmd
, bytes
, &bandwidth
) < 0)
2678 if (virDomainBlockJobSetSpeed(dom
, path
, bandwidth
, flags
) < 0)
2686 virshBlockJobAbort(virDomainPtr dom
,
2691 unsigned int flags
= 0;
2694 flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC
;
2696 flags
|= VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT
;
2698 if (virDomainBlockJobAbort(dom
, path
, flags
) < 0)
2706 cmdBlockjob(vshControl
*ctl
, const vshCmd
*cmd
)
2709 bool raw
= vshCommandOptBool(cmd
, "raw");
2710 bool bytes
= vshCommandOptBool(cmd
, "bytes");
2711 bool abortMode
= vshCommandOptBool(cmd
, "abort");
2712 bool pivot
= vshCommandOptBool(cmd
, "pivot");
2713 bool async
= vshCommandOptBool(cmd
, "async");
2714 bool info
= vshCommandOptBool(cmd
, "info");
2715 bool bandwidth
= vshCommandOptBool(cmd
, "bandwidth");
2716 virDomainPtr dom
= NULL
;
2719 VSH_EXCLUSIVE_OPTIONS("raw", "abort");
2720 VSH_EXCLUSIVE_OPTIONS_VAR(raw
, pivot
);
2721 VSH_EXCLUSIVE_OPTIONS_VAR(raw
, async
);
2722 VSH_EXCLUSIVE_OPTIONS_VAR(raw
, bandwidth
);
2724 VSH_EXCLUSIVE_OPTIONS("info", "abort");
2725 VSH_EXCLUSIVE_OPTIONS_VAR(info
, pivot
);
2726 VSH_EXCLUSIVE_OPTIONS_VAR(info
, async
);
2727 VSH_EXCLUSIVE_OPTIONS_VAR(info
, bandwidth
);
2729 VSH_EXCLUSIVE_OPTIONS("bytes", "abort");
2730 VSH_EXCLUSIVE_OPTIONS_VAR(bytes
, pivot
);
2731 VSH_EXCLUSIVE_OPTIONS_VAR(bytes
, async
);
2733 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
2736 /* XXX Allow path to be optional to list info on all devices at once */
2737 if (vshCommandOptStringReq(ctl
, cmd
, "path", &path
) < 0)
2741 ret
= virshBlockJobSetSpeed(ctl
, cmd
, dom
, path
, bytes
);
2742 else if (abortMode
|| pivot
|| async
)
2743 ret
= virshBlockJobAbort(dom
, path
, pivot
, async
);
2745 ret
= virshBlockJobInfo(ctl
, dom
, path
, raw
, bytes
);
2748 virshDomainFree(dom
);
2753 * "blockpull" command
2755 static const vshCmdInfo info_blockpull
[] = {
2757 .data
= N_("Populate a disk from its backing image.")
2760 .data
= N_("Populate a disk from its backing image.")
2765 static const vshCmdOptDef opts_blockpull
[] = {
2766 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
2768 .type
= VSH_OT_DATA
,
2769 .flags
= VSH_OFLAG_REQ
,
2770 .completer
= virshDomainDiskTargetCompleter
,
2771 .help
= N_("fully-qualified path of disk")
2773 {.name
= "bandwidth",
2775 .help
= N_("bandwidth limit in MiB/s")
2778 .type
= VSH_OT_STRING
,
2779 .help
= N_("path of backing file in chain for a partial pull")
2782 .type
= VSH_OT_BOOL
,
2783 .help
= N_("wait for job to finish")
2786 .type
= VSH_OT_BOOL
,
2787 .help
= N_("with --wait, display the progress")
2791 .help
= N_("with --wait, abort if pull exceeds timeout (in seconds)")
2794 .type
= VSH_OT_BOOL
,
2795 .help
= N_("with --wait, don't wait for cancel to finish")
2797 {.name
= "keep-relative",
2798 .type
= VSH_OT_BOOL
,
2799 .help
= N_("keep the backing chain relatively referenced")
2802 .type
= VSH_OT_BOOL
,
2803 .help
= N_("the bandwidth limit is in bytes/s rather than MiB/s")
2809 cmdBlockpull(vshControl
*ctl
, const vshCmd
*cmd
)
2811 virDomainPtr dom
= NULL
;
2813 bool blocking
= vshCommandOptBool(cmd
, "wait");
2814 bool verbose
= vshCommandOptBool(cmd
, "verbose");
2815 bool async
= vshCommandOptBool(cmd
, "async");
2816 bool bytes
= vshCommandOptBool(cmd
, "bytes");
2818 const char *path
= NULL
;
2819 const char *base
= NULL
;
2820 unsigned long bandwidth
= 0;
2821 unsigned int flags
= 0;
2822 virshBlockJobWaitDataPtr bjWait
= NULL
;
2824 VSH_REQUIRE_OPTION("verbose", "wait");
2825 VSH_REQUIRE_OPTION("async", "wait");
2827 if (vshCommandOptStringReq(ctl
, cmd
, "path", &path
) < 0)
2830 if (vshCommandOptStringReq(ctl
, cmd
, "base", &base
) < 0)
2833 if (vshBlockJobOptionBandwidth(ctl
, cmd
, bytes
, &bandwidth
) < 0)
2836 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0)
2839 if (vshCommandOptBool(cmd
, "keep-relative"))
2840 flags
|= VIR_DOMAIN_BLOCK_REBASE_RELATIVE
;
2842 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
2846 !(bjWait
= virshBlockJobWaitInit(ctl
, dom
, path
, _("Block Pull"),
2847 verbose
, timeout
, async
)))
2850 if (base
|| flags
) {
2852 flags
|= VIR_DOMAIN_BLOCK_REBASE_BANDWIDTH_BYTES
;
2854 if (virDomainBlockRebase(dom
, path
, base
, bandwidth
, flags
) < 0)
2858 flags
|= VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES
;
2860 if (virDomainBlockPull(dom
, path
, bandwidth
, flags
) < 0)
2865 vshPrintExtra(ctl
, "%s", _("Block Pull started"));
2870 /* Execution continues here only if --wait or friends were specified */
2871 switch (virshBlockJobWait(bjWait
)) {
2875 case VIR_DOMAIN_BLOCK_JOB_CANCELED
:
2876 vshPrintExtra(ctl
, "\n%s", _("Pull aborted"));
2880 case VIR_DOMAIN_BLOCK_JOB_FAILED
:
2881 vshError(ctl
, "\n%s", _("Pull failed"));
2885 case VIR_DOMAIN_BLOCK_JOB_READY
:
2886 case VIR_DOMAIN_BLOCK_JOB_COMPLETED
:
2887 vshPrintExtra(ctl
, "\n%s", _("Pull complete"));
2894 virshDomainFree(dom
);
2895 virshBlockJobWaitFree(bjWait
);
2900 * "blockresize" command
2902 static const vshCmdInfo info_blockresize
[] = {
2904 .data
= N_("Resize block device of domain.")
2907 .data
= N_("Resize block device of domain.")
2912 static const vshCmdOptDef opts_blockresize
[] = {
2913 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
2915 .type
= VSH_OT_DATA
,
2916 .flags
= VSH_OFLAG_REQ
,
2917 .completer
= virshDomainDiskTargetCompleter
,
2918 .help
= N_("Fully-qualified path of block device")
2922 .flags
= VSH_OFLAG_REQ
,
2923 .help
= N_("New size of the block device, as scaled integer (default KiB)")
2929 cmdBlockresize(vshControl
*ctl
, const vshCmd
*cmd
)
2932 const char *path
= NULL
;
2933 unsigned long long size
= 0;
2934 unsigned int flags
= 0;
2937 if (vshCommandOptStringReq(ctl
, cmd
, "path", (const char **) &path
) < 0)
2940 if (vshCommandOptScaledInt(ctl
, cmd
, "size", &size
, 1024, ULLONG_MAX
) < 0)
2943 /* Prefer the older interface of KiB. */
2944 if (size
% 1024 == 0)
2947 flags
|= VIR_DOMAIN_BLOCK_RESIZE_BYTES
;
2949 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
2952 if (virDomainBlockResize(dom
, path
, size
, flags
) < 0) {
2953 vshError(ctl
, _("Failed to resize block device '%s'"), path
);
2955 vshPrintExtra(ctl
, _("Block device '%s' is resized"), path
);
2959 virshDomainFree(dom
);
2967 static const vshCmdInfo info_console
[] = {
2969 .data
= N_("connect to the guest console")
2972 .data
= N_("Connect the virtual serial console for the guest")
2977 static const vshCmdOptDef opts_console
[] = {
2978 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
2979 {.name
= "devname", /* sc_prohibit_devname */
2980 .type
= VSH_OT_STRING
,
2981 .help
= N_("character device name")
2984 .type
= VSH_OT_BOOL
,
2985 .help
= N_("force console connection (disconnect already connected sessions)")
2988 .type
= VSH_OT_BOOL
,
2989 .help
= N_("only connect if safe console handling is supported")
2995 cmdRunConsole(vshControl
*ctl
, virDomainPtr dom
,
3001 virshControlPtr priv
= ctl
->privData
;
3003 if ((state
= virshDomainState(ctl
, dom
, NULL
)) < 0) {
3004 vshError(ctl
, "%s", _("Unable to get domain status"));
3008 if (state
== VIR_DOMAIN_SHUTOFF
) {
3009 vshError(ctl
, "%s", _("The domain is not running"));
3013 if (!isatty(STDIN_FILENO
)) {
3014 vshError(ctl
, "%s", _("Cannot run interactive console without a controlling TTY"));
3018 vshPrintExtra(ctl
, _("Connected to domain %s\n"), virDomainGetName(dom
));
3019 vshPrintExtra(ctl
, _("Escape character is %s\n"), priv
->escapeChar
);
3021 if (virshRunConsole(ctl
, dom
, name
, flags
) == 0)
3030 cmdConsole(vshControl
*ctl
, const vshCmd
*cmd
)
3034 bool force
= vshCommandOptBool(cmd
, "force");
3035 bool safe
= vshCommandOptBool(cmd
, "safe");
3036 unsigned int flags
= 0;
3037 const char *name
= NULL
;
3039 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
3042 if (vshCommandOptStringReq(ctl
, cmd
, "devname", &name
) < 0) /* sc_prohibit_devname */
3046 flags
|= VIR_DOMAIN_CONSOLE_FORCE
;
3048 flags
|= VIR_DOMAIN_CONSOLE_SAFE
;
3050 ret
= cmdRunConsole(ctl
, dom
, name
, flags
);
3053 virshDomainFree(dom
);
3058 /* "domif-setlink" command
3060 static const vshCmdInfo info_domif_setlink
[] = {
3062 .data
= N_("set link state of a virtual interface")
3065 .data
= N_("Set link state of a domain's virtual interface. This command "
3066 "wraps usage of update-device command.")
3071 static const vshCmdOptDef opts_domif_setlink
[] = {
3072 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
3073 {.name
= "interface",
3074 .type
= VSH_OT_DATA
,
3075 .flags
= VSH_OFLAG_REQ
,
3076 .completer
= virshDomainInterfaceCompleter
,
3077 .help
= N_("interface device (MAC Address)")
3080 .type
= VSH_OT_DATA
,
3081 .flags
= VSH_OFLAG_REQ
,
3082 .completer
= virshDomainInterfaceStateCompleter
,
3083 .help
= N_("new state of the device")
3085 {.name
= "persistent",
3086 .type
= VSH_OT_ALIAS
,
3089 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
3094 cmdDomIfSetLink(vshControl
*ctl
, const vshCmd
*cmd
)
3101 const char *element
;
3105 unsigned int flags
= 0;
3106 unsigned int xmlflags
= 0;
3108 xmlDocPtr xml
= NULL
;
3109 xmlXPathContextPtr ctxt
= NULL
;
3110 xmlXPathObjectPtr obj
= NULL
;
3111 xmlNodePtr cur
= NULL
;
3112 char *xml_buf
= NULL
;
3114 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
3117 if (vshCommandOptStringReq(ctl
, cmd
, "interface", &iface
) < 0 ||
3118 vshCommandOptStringReq(ctl
, cmd
, "state", &state
) < 0)
3121 config
= vshCommandOptBool(cmd
, "config");
3123 if (STRNEQ(state
, "up") && STRNEQ(state
, "down")) {
3124 vshError(ctl
, _("invalid link state '%s'"), state
);
3129 flags
= VIR_DOMAIN_AFFECT_CONFIG
;
3130 xmlflags
|= VIR_DOMAIN_XML_INACTIVE
;
3132 flags
= VIR_DOMAIN_AFFECT_LIVE
;
3135 if (virDomainIsActive(dom
) == 0)
3136 flags
= VIR_DOMAIN_AFFECT_CONFIG
;
3138 if (virshDomainGetXMLFromDom(ctl
, dom
, xmlflags
, &xml
, &ctxt
) < 0)
3141 obj
= xmlXPathEval(BAD_CAST
"/domain/devices/interface", ctxt
);
3142 if (obj
== NULL
|| obj
->type
!= XPATH_NODESET
||
3143 obj
->nodesetval
== NULL
|| obj
->nodesetval
->nodeNr
== 0) {
3144 vshError(ctl
, _("Failed to extract interface information or no interfaces found"));
3148 if (virMacAddrParse(iface
, &macaddr
) == 0) {
3156 /* find interface with matching mac addr */
3157 for (i
= 0; i
< obj
->nodesetval
->nodeNr
; i
++) {
3158 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
3161 if (cur
->type
== XML_ELEMENT_NODE
&&
3162 virXMLNodeNameEqual(cur
, element
)) {
3163 value
= virXMLPropString(cur
, attr
);
3165 if (STRCASEEQ(value
, iface
)) {
3175 vshError(ctl
, _("interface (%s: %s) not found"), element
, iface
);
3179 /* find and modify/add link state node */
3180 /* try to find <link> element */
3181 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
3184 if (cur
->type
== XML_ELEMENT_NODE
&&
3185 virXMLNodeNameEqual(cur
, "link")) {
3186 /* found, just modify the property */
3187 xmlSetProp(cur
, BAD_CAST
"state", BAD_CAST state
);
3195 /* element <link> not found, add one */
3196 cur
= xmlNewChild(obj
->nodesetval
->nodeTab
[i
],
3203 if (xmlNewProp(cur
, BAD_CAST
"state", BAD_CAST state
) == NULL
)
3207 if (!(xml_buf
= virXMLNodeToString(xml
, obj
->nodesetval
->nodeTab
[i
]))) {
3208 vshSaveLibvirtError();
3209 vshError(ctl
, _("Failed to create XML"));
3213 if (virDomainUpdateDeviceFlags(dom
, xml_buf
, flags
) < 0) {
3214 vshError(ctl
, _("Failed to update interface link state"));
3217 vshPrintExtra(ctl
, "%s", _("Device updated successfully\n"));
3222 xmlXPathFreeObject(obj
);
3223 xmlXPathFreeContext(ctxt
);
3226 virshDomainFree(dom
);
3231 /* "domiftune" command
3233 static const vshCmdInfo info_domiftune
[] = {
3235 .data
= N_("get/set parameters of a virtual interface")
3238 .data
= N_("Get/set parameters of a domain's virtual interface.")
3243 static const vshCmdOptDef opts_domiftune
[] = {
3244 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
3245 {.name
= "interface",
3246 .type
= VSH_OT_DATA
,
3247 .flags
= VSH_OFLAG_REQ
,
3248 .completer
= virshDomainInterfaceCompleter
,
3249 .help
= N_("interface device (MAC Address)")
3252 .type
= VSH_OT_STRING
,
3253 .help
= N_("control domain's incoming traffics")
3255 {.name
= "outbound",
3256 .type
= VSH_OT_STRING
,
3257 .help
= N_("control domain's outgoing traffics")
3259 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
3260 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
3261 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
3266 cmdDomIftune(vshControl
*ctl
, const vshCmd
*cmd
)
3269 const char *name
= NULL
, *device
= NULL
,
3270 *inboundStr
= NULL
, *outboundStr
= NULL
;
3271 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
3274 virTypedParameterPtr params
= NULL
;
3276 bool current
= vshCommandOptBool(cmd
, "current");
3277 bool config
= vshCommandOptBool(cmd
, "config");
3278 bool live
= vshCommandOptBool(cmd
, "live");
3279 virNetDevBandwidthRate inbound
, outbound
;
3282 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
3283 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
3286 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
3288 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
3290 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
3293 if (vshCommandOptStringReq(ctl
, cmd
, "interface", &device
) < 0)
3296 if (vshCommandOptStringReq(ctl
, cmd
, "inbound", &inboundStr
) < 0 ||
3297 vshCommandOptStringReq(ctl
, cmd
, "outbound", &outboundStr
) < 0)
3300 memset(&inbound
, 0, sizeof(inbound
));
3301 memset(&outbound
, 0, sizeof(outbound
));
3304 if (virshParseRateStr(ctl
, inboundStr
, &inbound
) < 0)
3306 /* we parse the rate as unsigned long long, but the API
3307 * only accepts UINT */
3308 if (inbound
.average
> UINT_MAX
|| inbound
.peak
> UINT_MAX
||
3309 inbound
.burst
> UINT_MAX
) {
3310 vshError(ctl
, _("inbound rate larger than maximum %u"),
3315 if ((!inbound
.average
&& (inbound
.burst
|| inbound
.peak
)) &&
3317 vshError(ctl
, _("either inbound average or floor is mandatory"));
3321 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3322 VIR_DOMAIN_BANDWIDTH_IN_AVERAGE
,
3323 inbound
.average
) < 0)
3327 virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3328 VIR_DOMAIN_BANDWIDTH_IN_PEAK
,
3332 if (inbound
.burst
&&
3333 virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3334 VIR_DOMAIN_BANDWIDTH_IN_BURST
,
3338 if (inbound
.floor
&&
3339 virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3340 VIR_DOMAIN_BANDWIDTH_IN_FLOOR
,
3346 if (virshParseRateStr(ctl
, outboundStr
, &outbound
) < 0)
3348 if (outbound
.average
> UINT_MAX
|| outbound
.peak
> UINT_MAX
||
3349 outbound
.burst
> UINT_MAX
) {
3350 vshError(ctl
, _("outbound rate larger than maximum %u"),
3354 if (outbound
.average
== 0 && (outbound
.burst
|| outbound
.peak
)) {
3355 vshError(ctl
, _("outbound average is mandatory"));
3359 if (outbound
.floor
) {
3360 vshError(ctl
, _("outbound floor is unsupported yet"));
3364 if (virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3365 VIR_DOMAIN_BANDWIDTH_OUT_AVERAGE
,
3366 outbound
.average
) < 0)
3369 if (outbound
.peak
&&
3370 virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3371 VIR_DOMAIN_BANDWIDTH_OUT_PEAK
,
3375 if (outbound
.burst
&&
3376 virTypedParamsAddUInt(¶ms
, &nparams
, &maxparams
,
3377 VIR_DOMAIN_BANDWIDTH_OUT_BURST
,
3378 outbound
.burst
) < 0)
3383 /* get the number of interface parameters */
3384 if (virDomainGetInterfaceParameters(dom
, device
, NULL
, &nparams
, flags
) != 0) {
3386 _("Unable to get number of interface parameters"));
3391 /* nothing to output */
3396 /* get all interface parameters */
3397 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
3398 if (virDomainGetInterfaceParameters(dom
, device
, params
, &nparams
, flags
) != 0) {
3399 vshError(ctl
, "%s", _("Unable to get interface parameters"));
3403 for (i
= 0; i
< nparams
; i
++) {
3404 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
3405 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
3409 if (virDomainSetInterfaceParameters(dom
, device
, params
,
3410 nparams
, flags
) != 0)
3417 virTypedParamsFree(params
, nparams
);
3418 virshDomainFree(dom
);
3422 vshSaveLibvirtError();
3424 vshError(ctl
, "%s", _("Unable to set interface parameters"));
3431 static const vshCmdInfo info_suspend
[] = {
3433 .data
= N_("suspend a domain")
3436 .data
= N_("Suspend a running domain.")
3441 static const vshCmdOptDef opts_suspend
[] = {
3442 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_RUNNING
),
3447 cmdSuspend(vshControl
*ctl
, const vshCmd
*cmd
)
3453 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
3456 if (virDomainSuspend(dom
) == 0) {
3457 vshPrintExtra(ctl
, _("Domain %s suspended\n"), name
);
3459 vshError(ctl
, _("Failed to suspend domain %s"), name
);
3463 virshDomainFree(dom
);
3468 * "dompmsuspend" command
3470 static const vshCmdInfo info_dom_pm_suspend
[] = {
3472 .data
= N_("suspend a domain gracefully using power management "
3476 .data
= N_("Suspends a running domain using guest OS's power management. "
3477 "(Note: This requires a guest agent configured and running in "
3483 static const vshCmdOptDef opts_dom_pm_suspend
[] = {
3484 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_RUNNING
),
3486 .type
= VSH_OT_DATA
,
3487 .flags
= VSH_OFLAG_REQ
,
3488 .help
= N_("mem(Suspend-to-RAM), "
3489 "disk(Suspend-to-Disk), "
3490 "hybrid(Hybrid-Suspend)")
3492 {.name
= "duration",
3494 .flags
= VSH_OFLAG_REQ_OPT
,
3495 .help
= N_("duration in seconds")
3501 cmdDomPMSuspend(vshControl
*ctl
, const vshCmd
*cmd
)
3506 const char *target
= NULL
;
3507 unsigned int suspendTarget
;
3508 unsigned long long duration
= 0;
3510 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
3513 if (vshCommandOptULongLong(ctl
, cmd
, "duration", &duration
) < 0)
3516 if (vshCommandOptStringReq(ctl
, cmd
, "target", &target
) < 0)
3519 if (STREQ(target
, "mem")) {
3520 suspendTarget
= VIR_NODE_SUSPEND_TARGET_MEM
;
3521 } else if (STREQ(target
, "disk")) {
3522 suspendTarget
= VIR_NODE_SUSPEND_TARGET_DISK
;
3523 } else if (STREQ(target
, "hybrid")) {
3524 suspendTarget
= VIR_NODE_SUSPEND_TARGET_HYBRID
;
3526 vshError(ctl
, "%s", _("Invalid target"));
3530 if (virDomainPMSuspendForDuration(dom
, suspendTarget
, duration
, 0) < 0) {
3531 vshError(ctl
, _("Domain %s could not be suspended"),
3532 virDomainGetName(dom
));
3536 vshPrintExtra(ctl
, _("Domain %s successfully suspended"),
3537 virDomainGetName(dom
));
3542 virshDomainFree(dom
);
3547 * "dompmwakeup" command
3550 static const vshCmdInfo info_dom_pm_wakeup
[] = {
3552 .data
= N_("wakeup a domain from pmsuspended state")
3555 .data
= N_("Wakeup a domain that was previously suspended "
3556 "by power management.")
3561 static const vshCmdOptDef opts_dom_pm_wakeup
[] = {
3562 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_OTHER
),
3567 cmdDomPMWakeup(vshControl
*ctl
, const vshCmd
*cmd
)
3572 unsigned int flags
= 0;
3574 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
3577 if (virDomainPMWakeup(dom
, flags
) < 0) {
3578 vshError(ctl
, _("Domain %s could not be woken up"),
3579 virDomainGetName(dom
));
3583 vshPrintExtra(ctl
, _("Domain %s successfully woken up"),
3584 virDomainGetName(dom
));
3589 virshDomainFree(dom
);
3594 * "undefine" command
3596 static const vshCmdInfo info_undefine
[] = {
3598 .data
= N_("undefine a domain")
3601 .data
= N_("Undefine an inactive domain, or convert persistent to transient.")
3606 static const vshCmdOptDef opts_undefine
[] = {
3607 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_PERSISTENT
),
3608 {.name
= "managed-save",
3609 .type
= VSH_OT_BOOL
,
3610 .help
= N_("remove domain managed state file")
3613 .type
= VSH_OT_STRING
,
3614 .help
= N_("remove associated storage volumes (comma separated list of "
3615 "targets or source paths) (see domblklist)")
3617 {.name
= "remove-all-storage",
3618 .type
= VSH_OT_BOOL
,
3619 .help
= N_("remove all associated storage volumes (use with caution)")
3621 {.name
= "delete-snapshots",
3622 .type
= VSH_OT_ALIAS
,
3623 .help
= "delete-storage-volume-snapshots"
3625 {.name
= "delete-storage-volume-snapshots",
3626 .type
= VSH_OT_BOOL
,
3627 .help
= N_("delete snapshots associated with volume(s), requires "
3628 "--remove-all-storage (must be supported by storage driver)")
3630 {.name
= "wipe-storage",
3631 .type
= VSH_OT_BOOL
,
3632 .help
= N_("wipe data on the removed volumes")
3634 {.name
= "snapshots-metadata",
3635 .type
= VSH_OT_BOOL
,
3636 .help
= N_("remove all domain snapshot metadata (vm must be inactive)")
3638 {.name
= "checkpoints-metadata",
3639 .type
= VSH_OT_BOOL
,
3640 .help
= N_("remove all domain checkpoint metadata (vm must be inactive)")
3643 .type
= VSH_OT_BOOL
,
3644 .help
= N_("remove nvram file, if inactive")
3646 {.name
= "keep-nvram",
3647 .type
= VSH_OT_BOOL
,
3648 .help
= N_("keep nvram file, if inactive")
3654 virStorageVolPtr vol
;
3657 } virshUndefineVolume
;
3660 cmdUndefine(vshControl
*ctl
, const vshCmd
*cmd
)
3664 const char *name
= NULL
;
3665 /* Flags to attempt. */
3666 unsigned int flags
= 0;
3667 unsigned int vol_flags
= 0;
3668 /* User-requested actions. */
3669 bool managed_save
= vshCommandOptBool(cmd
, "managed-save");
3670 bool snapshots_metadata
= vshCommandOptBool(cmd
, "snapshots-metadata");
3671 bool checkpoints_metadata
= vshCommandOptBool(cmd
, "checkpoints-metadata");
3672 bool wipe_storage
= vshCommandOptBool(cmd
, "wipe-storage");
3673 bool remove_all_storage
= vshCommandOptBool(cmd
, "remove-all-storage");
3674 bool delete_snapshots
= vshCommandOptBool(cmd
, "delete-snapshots");
3675 bool nvram
= vshCommandOptBool(cmd
, "nvram");
3676 bool keep_nvram
= vshCommandOptBool(cmd
, "keep-nvram");
3677 /* Positive if these items exist. */
3678 int has_managed_save
= 0;
3679 int has_snapshots_metadata
= 0;
3680 int has_snapshots
= 0;
3681 /* True if undefine will not strand data, even on older servers. */
3682 bool managed_save_safe
= false;
3683 bool snapshots_safe
= false;
3686 /* list of volumes to remove along with this domain */
3687 const char *vol_string
= NULL
; /* string containing volumes to delete */
3688 char **vol_list
= NULL
; /* tokenized vol_string */
3690 virshUndefineVolume
*vols
= NULL
; /* info about the volumes to delete*/
3692 xmlDocPtr doc
= NULL
;
3693 xmlXPathContextPtr ctxt
= NULL
;
3694 xmlNodePtr
*vol_nodes
= NULL
; /* XML nodes of volumes of the guest */
3696 char *source
= NULL
;
3697 char *target
= NULL
;
3701 virshControlPtr priv
= ctl
->privData
;
3703 VSH_REQUIRE_OPTION("delete-snapshots", "remove-all-storage");
3704 VSH_EXCLUSIVE_OPTIONS("nvram", "keep-nvram");
3706 ignore_value(vshCommandOptStringQuiet(ctl
, cmd
, "storage", &vol_string
));
3708 if (!(vol_string
|| remove_all_storage
) && wipe_storage
) {
3710 _("'--wipe-storage' requires '--storage <string>' or "
3711 "'--remove-all-storage'"));
3715 if (delete_snapshots
)
3716 vol_flags
|= VIR_STORAGE_VOL_DELETE_WITH_SNAPSHOTS
;
3719 flags
|= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE
;
3720 managed_save_safe
= true;
3722 if (snapshots_metadata
) {
3723 flags
|= VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA
;
3724 snapshots_safe
= true;
3726 if (checkpoints_metadata
)
3727 flags
|= VIR_DOMAIN_UNDEFINE_CHECKPOINTS_METADATA
;
3729 flags
|= VIR_DOMAIN_UNDEFINE_NVRAM
;
3731 flags
|= VIR_DOMAIN_UNDEFINE_KEEP_NVRAM
;
3733 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
3736 /* Do some flag manipulation. The goal here is to disable bits
3737 * from flags to reduce the likelihood of a server rejecting
3738 * unknown flag bits, as well as to track conditions which are
3739 * safe by default for the given hypervisor and server version. */
3740 if ((running
= virDomainIsActive(dom
)) < 0)
3744 /* Undefine with snapshots only fails for inactive domains,
3745 * and managed save only exists on inactive domains; if
3746 * running, then we don't want to remove anything. */
3747 has_managed_save
= virDomainHasManagedSaveImage(dom
, 0);
3748 if (has_managed_save
< 0) {
3749 if (last_error
->code
!= VIR_ERR_NO_SUPPORT
)
3751 vshResetLibvirtError();
3752 has_managed_save
= 0;
3755 has_snapshots
= virDomainSnapshotNum(dom
, 0);
3756 if (has_snapshots
< 0) {
3757 if (last_error
->code
!= VIR_ERR_NO_SUPPORT
)
3759 vshResetLibvirtError();
3762 if (has_snapshots
) {
3763 has_snapshots_metadata
3764 = virDomainSnapshotNum(dom
, VIR_DOMAIN_SNAPSHOT_LIST_METADATA
);
3765 if (has_snapshots_metadata
< 0) {
3766 /* The server did not know the new flag, assume that all
3767 snapshots have metadata. */
3768 vshResetLibvirtError();
3769 has_snapshots_metadata
= has_snapshots
;
3771 /* The server knew the new flag, all aspects of
3772 * undefineFlags are safe. */
3773 managed_save_safe
= snapshots_safe
= true;
3777 if (!has_managed_save
) {
3778 flags
&= ~VIR_DOMAIN_UNDEFINE_MANAGED_SAVE
;
3779 managed_save_safe
= true;
3781 if (has_snapshots
== 0)
3782 snapshots_safe
= true;
3783 if (has_snapshots_metadata
== 0) {
3784 flags
&= ~VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA
;
3785 snapshots_safe
= true;
3788 /* Stash domain description for later use */
3789 if (vol_string
|| remove_all_storage
) {
3792 _("Storage volume deletion is supported only on "
3793 "stopped domains"));
3797 if (vol_string
&& remove_all_storage
) {
3799 _("Specified both --storage and --remove-all-storage"));
3803 if (virshDomainGetXMLFromDom(ctl
, dom
, 0, &doc
, &ctxt
) < 0)
3806 /* tokenize the string from user and save its parts into an array */
3808 (nvol_list
= vshStringToArray(vol_string
, &vol_list
)) < 0)
3811 if ((nvol_nodes
= virXPathNodeSet("./devices/disk", ctxt
,
3815 for (i
= 0; i
< nvol_nodes
; i
++) {
3816 ctxt
->node
= vol_nodes
[i
];
3817 virshUndefineVolume vol
;
3822 /* get volume source and target paths */
3823 if (!(target
= virXPathString("string(./target/@dev)", ctxt
)))
3826 if (!(source
= virXPathString("string("
3831 "./source/@volume)", ctxt
)))
3834 pool
= virXPathString("string(./source/@pool)", ctxt
);
3836 /* lookup if volume was selected by user */
3839 for (j
= 0; j
< nvol_list
; j
++) {
3840 if (STREQ_NULLABLE(vol_list
[j
], target
) ||
3841 STREQ_NULLABLE(vol_list
[j
], source
)) {
3842 VIR_FREE(vol_list
[j
]);
3852 virStoragePoolPtr storagepool
= NULL
;
3856 _("Missing storage volume name for disk '%s'"),
3861 if (!(storagepool
= virStoragePoolLookupByName(priv
->conn
,
3864 _("Storage pool '%s' for volume '%s' not found."),
3866 vshResetLibvirtError();
3870 vol
.vol
= virStorageVolLookupByName(storagepool
, source
);
3871 virStoragePoolFree(storagepool
);
3874 vol
.vol
= virStorageVolLookupByPath(priv
->conn
, source
);
3879 _("Storage volume '%s'(%s) is not managed by libvirt. "
3880 "Remove it manually.\n"), target
, source
);
3881 vshResetLibvirtError();
3885 vol
.source
= source
;
3886 vol
.target
= target
;
3889 if (VIR_APPEND_ELEMENT(vols
, nvols
, vol
) < 0)
3893 /* print volumes specified by user that were not found in domain definition */
3896 for (i
= 0; i
< nvol_list
; i
++) {
3899 _("Volume '%s' was not found in domain's "
3900 "definition.\n"), vol_list
[i
]);
3910 /* Generally we want to try the new API first. However, while
3911 * virDomainUndefineFlags was introduced at the same time as
3912 * VIR_DOMAIN_UNDEFINE_MANAGED_SAVE in 0.9.4, the
3913 * VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA flag was not present
3914 * until 0.9.5; skip to piecewise emulation if we couldn't prove
3915 * above that the new API is safe.
3916 * Moreover, only the newer UndefineFlags() API understands
3917 * the VIR_DOMAIN_UNDEFINE_NVRAM flag. So if user has
3918 * specified --nvram we must use the Flags() API. */
3919 if ((managed_save_safe
&& snapshots_safe
) || nvram
) {
3920 rc
= virDomainUndefineFlags(dom
, flags
);
3921 if (rc
== 0 || nvram
||
3922 (last_error
->code
!= VIR_ERR_NO_SUPPORT
&&
3923 last_error
->code
!= VIR_ERR_INVALID_ARG
))
3925 vshResetLibvirtError();
3928 /* The new API is unsupported or unsafe; fall back to doing things
3930 if (has_managed_save
) {
3931 if (!managed_save
) {
3933 _("Refusing to undefine while domain managed save "
3937 if (virDomainManagedSaveRemove(dom
, 0) < 0) {
3938 vshReportError(ctl
);
3943 /* No way to emulate deletion of just snapshot metadata
3944 * without support for the newer flags. Oh well. */
3945 if (has_snapshots_metadata
) {
3947 snapshots_metadata
?
3948 _("Unable to remove metadata of %d snapshots") :
3949 _("Refusing to undefine while %d snapshots exist"),
3950 has_snapshots_metadata
);
3954 rc
= virDomainUndefine(dom
);
3958 vshPrintExtra(ctl
, _("Domain %s has been undefined\n"), name
);
3961 vshError(ctl
, _("Failed to undefine domain %s"), name
);
3965 /* try to undefine storage volumes associated with this domain, if it's requested */
3967 for (i
= 0; i
< nvols
; i
++) {
3969 vshPrintExtra(ctl
, _("Wiping volume '%s'(%s) ... "),
3970 vols
[i
].target
, vols
[i
].source
);
3972 if (virStorageVolWipe(vols
[i
].vol
, 0) < 0) {
3973 vshError(ctl
, _("Failed! Volume not removed."));
3977 vshPrintExtra(ctl
, _("Done.\n"));
3981 /* delete the volume */
3982 if (virStorageVolDelete(vols
[i
].vol
, vol_flags
) < 0) {
3983 vshError(ctl
, _("Failed to remove storage volume '%s'(%s)"),
3984 vols
[i
].target
, vols
[i
].source
);
3987 vshPrintExtra(ctl
, _("Volume '%s'(%s) removed.\n"),
3988 vols
[i
].target
, vols
[i
].source
);
3997 for (i
= 0; i
< nvols
; i
++) {
3998 VIR_FREE(vols
[i
].source
);
3999 VIR_FREE(vols
[i
].target
);
4001 virStorageVolFree(vols
[i
].vol
);
4005 for (i
= 0; i
< nvol_list
; i
++)
4006 VIR_FREE(vol_list
[i
]);
4009 VIR_FREE(vol_nodes
);
4011 xmlXPathFreeContext(ctxt
);
4012 virshDomainFree(dom
);
4016 vshReportError(ctl
);
4023 static const vshCmdInfo info_start
[] = {
4025 .data
= N_("start a (previously defined) inactive domain")
4028 .data
= N_("Start a domain, either from the last managedsave\n"
4029 " state, or via a fresh boot if no managedsave state\n"
4035 static const vshCmdOptDef opts_start
[] = {
4036 VIRSH_COMMON_OPT_DOMAIN(N_("name of the inactive domain"),
4037 VIR_CONNECT_LIST_DOMAINS_SHUTOFF
),
4040 .type
= VSH_OT_BOOL
,
4041 .help
= N_("attach to console after creation")
4045 .type
= VSH_OT_BOOL
,
4046 .help
= N_("leave the guest paused after creation")
4048 {.name
= "autodestroy",
4049 .type
= VSH_OT_BOOL
,
4050 .help
= N_("automatically destroy the guest when virsh disconnects")
4052 {.name
= "bypass-cache",
4053 .type
= VSH_OT_BOOL
,
4054 .help
= N_("avoid file system cache when loading")
4056 {.name
= "force-boot",
4057 .type
= VSH_OT_BOOL
,
4058 .help
= N_("force fresh boot by discarding any managed save")
4060 {.name
= "pass-fds",
4061 .type
= VSH_OT_STRING
,
4062 .help
= N_("pass file descriptors N,M,... to the guest")
4068 cmdStartGetFDs(vshControl
*ctl
,
4074 char **fdlist
= NULL
;
4082 if (vshCommandOptStringQuiet(ctl
, cmd
, "pass-fds", &fdopt
) <= 0)
4085 if (!(fdlist
= virStringSplit(fdopt
, ",", -1))) {
4086 vshError(ctl
, _("Unable to split FD list '%s'"), fdopt
);
4090 for (i
= 0; fdlist
[i
] != NULL
; i
++) {
4092 if (virStrToLong_i(fdlist
[i
], NULL
, 10, &fd
) < 0) {
4093 vshError(ctl
, _("Unable to parse FD number '%s'"), fdlist
[i
]);
4096 if (VIR_EXPAND_N(fds
, nfds
, 1) < 0) {
4097 vshError(ctl
, "%s", _("Unable to allocate FD list"));
4103 virStringListFree(fdlist
);
4110 virStringListFree(fdlist
);
4116 cmdStart(vshControl
*ctl
, const vshCmd
*cmd
)
4121 bool console
= vshCommandOptBool(cmd
, "console");
4123 unsigned int flags
= VIR_DOMAIN_NONE
;
4128 if (!(dom
= virshCommandOptDomainBy(ctl
, cmd
, NULL
,
4129 VIRSH_BYNAME
| VIRSH_BYUUID
)))
4132 if (virDomainGetID(dom
) != (unsigned int)-1) {
4133 vshError(ctl
, "%s", _("Domain is already active"));
4137 if (cmdStartGetFDs(ctl
, cmd
, &nfds
, &fds
) < 0)
4140 if (vshCommandOptBool(cmd
, "paused"))
4141 flags
|= VIR_DOMAIN_START_PAUSED
;
4142 if (vshCommandOptBool(cmd
, "autodestroy"))
4143 flags
|= VIR_DOMAIN_START_AUTODESTROY
;
4144 if (vshCommandOptBool(cmd
, "bypass-cache"))
4145 flags
|= VIR_DOMAIN_START_BYPASS_CACHE
;
4146 if (vshCommandOptBool(cmd
, "force-boot"))
4147 flags
|= VIR_DOMAIN_START_FORCE_BOOT
;
4149 /* We can emulate force boot, even for older servers that reject it. */
4150 if (flags
& VIR_DOMAIN_START_FORCE_BOOT
) {
4152 virDomainCreateWithFiles(dom
, nfds
, fds
, flags
) :
4153 virDomainCreateWithFlags(dom
, flags
)) == 0)
4155 if (last_error
->code
!= VIR_ERR_NO_SUPPORT
&&
4156 last_error
->code
!= VIR_ERR_INVALID_ARG
) {
4157 vshReportError(ctl
);
4160 vshResetLibvirtError();
4161 rc
= virDomainHasManagedSaveImage(dom
, 0);
4163 /* No managed save image to remove */
4164 vshResetLibvirtError();
4165 } else if (rc
> 0) {
4166 if (virDomainManagedSaveRemove(dom
, 0) < 0) {
4167 vshReportError(ctl
);
4171 flags
&= ~VIR_DOMAIN_START_FORCE_BOOT
;
4174 /* Prefer older API unless we have to pass a flag. */
4175 if ((nfds
? virDomainCreateWithFiles(dom
, nfds
, fds
, flags
) :
4176 (flags
? virDomainCreateWithFlags(dom
, flags
)
4177 : virDomainCreate(dom
))) < 0) {
4178 vshError(ctl
, _("Failed to start domain %s"), virDomainGetName(dom
));
4183 vshPrintExtra(ctl
, _("Domain %s started\n"),
4184 virDomainGetName(dom
));
4186 if (console
&& !cmdRunConsole(ctl
, dom
, NULL
, 0))
4193 virshDomainFree(dom
);
4201 static const vshCmdInfo info_save
[] = {
4203 .data
= N_("save a domain state to a file")
4206 .data
= N_("Save the RAM state of a running domain.")
4211 static const vshCmdOptDef opts_save
[] = {
4212 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
4213 VIRSH_COMMON_OPT_FILE(N_("where to save the data")),
4214 {.name
= "bypass-cache",
4215 .type
= VSH_OT_BOOL
,
4216 .help
= N_("avoid file system cache when saving")
4219 .type
= VSH_OT_STRING
,
4220 .help
= N_("filename containing updated XML for the target")
4223 .type
= VSH_OT_BOOL
,
4224 .help
= N_("set domain to be running on restore")
4227 .type
= VSH_OT_BOOL
,
4228 .help
= N_("set domain to be paused on restore")
4231 .type
= VSH_OT_BOOL
,
4232 .help
= N_("display the progress of save")
4238 doSave(void *opaque
)
4240 virshCtrlData
*data
= opaque
;
4241 vshControl
*ctl
= data
->ctl
;
4242 const vshCmd
*cmd
= data
->cmd
;
4244 virDomainPtr dom
= NULL
;
4245 const char *name
= NULL
;
4246 const char *to
= NULL
;
4247 unsigned int flags
= 0;
4248 const char *xmlfile
= NULL
;
4250 sigset_t sigmask
, oldsigmask
;
4252 sigemptyset(&sigmask
);
4253 sigaddset(&sigmask
, SIGINT
);
4254 if (pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
) < 0)
4257 if (vshCommandOptStringReq(ctl
, cmd
, "file", &to
) < 0)
4260 if (vshCommandOptBool(cmd
, "bypass-cache"))
4261 flags
|= VIR_DOMAIN_SAVE_BYPASS_CACHE
;
4262 if (vshCommandOptBool(cmd
, "running"))
4263 flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4264 if (vshCommandOptBool(cmd
, "paused"))
4265 flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4267 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &xmlfile
) < 0)
4270 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
4274 virFileReadAll(xmlfile
, VSH_MAX_XML_FILE
, &xml
) < 0) {
4275 vshReportError(ctl
);
4280 ? virDomainSaveFlags(dom
, to
, xml
, flags
)
4281 : virDomainSave(dom
, to
)) < 0) {
4282 vshError(ctl
, _("Failed to save domain %s to %s"), name
, to
);
4289 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
4291 virshDomainFree(dom
);
4293 ignore_value(safewrite(data
->writefd
, &ret
, sizeof(ret
)));
4296 typedef void (*jobWatchTimeoutFunc
)(vshControl
*ctl
, virDomainPtr dom
,
4300 virshWatchJob(vshControl
*ctl
,
4305 jobWatchTimeoutFunc timeout_func
,
4309 struct sigaction sig_action
;
4310 struct sigaction old_sig_action
;
4311 struct pollfd pollfd
[2] = {{.fd
= pipe_fd
, .events
= POLLIN
, .revents
= 0},
4312 {.fd
= STDIN_FILENO
, .events
= POLLIN
, .revents
= 0}};
4313 struct timeval start
, curr
;
4314 virDomainJobInfo jobinfo
;
4317 bool functionReturn
= false;
4318 sigset_t sigmask
, oldsigmask
;
4319 bool jobStarted
= false;
4322 sigemptyset(&sigmask
);
4323 sigaddset(&sigmask
, SIGINT
);
4326 sig_action
.sa_sigaction
= virshCatchInt
;
4327 sig_action
.sa_flags
= SA_SIGINFO
;
4328 sigemptyset(&sig_action
.sa_mask
);
4329 sigaction(SIGINT
, &sig_action
, &old_sig_action
);
4331 /* don't poll on STDIN if we are not using a terminal */
4332 if (!vshTTYAvailable(ctl
))
4335 GETTIMEOFDAY(&start
);
4337 ret
= poll((struct pollfd
*)&pollfd
, npollfd
, 500);
4339 if (pollfd
[1].revents
& POLLIN
&&
4340 saferead(STDIN_FILENO
, &retchar
, sizeof(retchar
)) > 0) {
4341 if (vshTTYIsInterruptCharacter(ctl
, retchar
))
4342 virDomainAbortJob(dom
);
4346 if (pollfd
[0].revents
& POLLIN
&&
4347 saferead(pipe_fd
, &retchar
, sizeof(retchar
)) > 0 &&
4351 virshPrintJobProgress(label
, 0, 1);
4359 if (errno
== EINTR
) {
4361 virDomainAbortJob(dom
);
4369 GETTIMEOFDAY(&curr
);
4370 if (timeout_ms
&& (((int)(curr
.tv_sec
- start
.tv_sec
) * 1000 +
4371 (int)(curr
.tv_usec
- start
.tv_usec
) / 1000) >
4373 /* suspend the domain when migration timeouts. */
4374 vshDebug(ctl
, VSH_ERR_DEBUG
, "%s timeout", label
);
4376 (timeout_func
)(ctl
, dom
, opaque
);
4380 if (verbose
|| !jobStarted
) {
4381 pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
);
4382 ret
= virDomainGetJobInfo(dom
, &jobinfo
);
4383 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
4385 if (verbose
&& jobinfo
.dataTotal
> 0)
4386 virshPrintJobProgress(label
, jobinfo
.dataRemaining
,
4390 (jobinfo
.type
== VIR_DOMAIN_JOB_BOUNDED
||
4391 jobinfo
.type
== VIR_DOMAIN_JOB_UNBOUNDED
)) {
4392 vshTTYDisableInterrupt(ctl
);
4396 vshResetLibvirtError();
4401 functionReturn
= true;
4404 sigaction(SIGINT
, &old_sig_action
, NULL
);
4406 return functionReturn
;
4410 cmdSave(vshControl
*ctl
, const vshCmd
*cmd
)
4413 virDomainPtr dom
= NULL
;
4414 int p
[2] = {-1. -1};
4415 virThread workerThread
;
4416 bool verbose
= false;
4418 const char *to
= NULL
;
4419 const char *name
= NULL
;
4421 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
4424 if (vshCommandOptStringReq(ctl
, cmd
, "file", &to
) < 0)
4427 if (vshCommandOptBool(cmd
, "verbose"))
4435 data
.writefd
= p
[1];
4437 if (virThreadCreate(&workerThread
,
4443 ret
= virshWatchJob(ctl
, dom
, verbose
, p
[0], 0, NULL
, NULL
, _("Save"));
4445 virThreadJoin(&workerThread
);
4448 vshPrintExtra(ctl
, _("\nDomain %s saved to %s\n"), name
, to
);
4451 virshDomainFree(dom
);
4456 * "save-image-dumpxml" command
4458 static const vshCmdInfo info_save_image_dumpxml
[] = {
4460 .data
= N_("saved state domain information in XML")
4463 .data
= N_("Dump XML of domain information for a saved state file to stdout.")
4468 static const vshCmdOptDef opts_save_image_dumpxml
[] = {
4469 VIRSH_COMMON_OPT_FILE(N_("saved state file to read")),
4470 {.name
= "security-info",
4471 .type
= VSH_OT_BOOL
,
4472 .help
= N_("include security sensitive information in XML dump")
4478 cmdSaveImageDumpxml(vshControl
*ctl
, const vshCmd
*cmd
)
4480 const char *file
= NULL
;
4482 unsigned int flags
= 0;
4484 virshControlPtr priv
= ctl
->privData
;
4486 if (vshCommandOptBool(cmd
, "security-info"))
4487 flags
|= VIR_DOMAIN_XML_SECURE
;
4489 if (vshCommandOptStringReq(ctl
, cmd
, "file", &file
) < 0)
4492 xml
= virDomainSaveImageGetXMLDesc(priv
->conn
, file
, flags
);
4496 vshPrint(ctl
, "%s", xml
);
4505 * "save-image-define" command
4507 static const vshCmdInfo info_save_image_define
[] = {
4509 .data
= N_("redefine the XML for a domain's saved state file")
4512 .data
= N_("Replace the domain XML associated with a saved state file")
4517 static const vshCmdOptDef opts_save_image_define
[] = {
4518 VIRSH_COMMON_OPT_FILE(N_("saved state file to modify")),
4520 .type
= VSH_OT_DATA
,
4521 .flags
= VSH_OFLAG_REQ
,
4522 .help
= N_("filename containing updated XML for the target")
4525 .type
= VSH_OT_BOOL
,
4526 .help
= N_("set domain to be running on restore")
4529 .type
= VSH_OT_BOOL
,
4530 .help
= N_("set domain to be paused on restore")
4536 cmdSaveImageDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4538 const char *file
= NULL
;
4540 const char *xmlfile
= NULL
;
4542 unsigned int flags
= 0;
4543 virshControlPtr priv
= ctl
->privData
;
4545 if (vshCommandOptBool(cmd
, "running"))
4546 flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4547 if (vshCommandOptBool(cmd
, "paused"))
4548 flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4550 if (vshCommandOptStringReq(ctl
, cmd
, "file", &file
) < 0)
4553 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &xmlfile
) < 0)
4556 if (virFileReadAll(xmlfile
, VSH_MAX_XML_FILE
, &xml
) < 0)
4559 if (virDomainSaveImageDefineXML(priv
->conn
, file
, xml
, flags
) < 0) {
4560 vshError(ctl
, _("Failed to update %s"), file
);
4564 vshPrintExtra(ctl
, _("State file %s updated.\n"), file
);
4573 * "save-image-edit" command
4575 static const vshCmdInfo info_save_image_edit
[] = {
4577 .data
= N_("edit XML for a domain's saved state file")
4580 .data
= N_("Edit the domain XML associated with a saved state file")
4585 static const vshCmdOptDef opts_save_image_edit
[] = {
4586 VIRSH_COMMON_OPT_FILE(N_("saved state file to edit")),
4588 .type
= VSH_OT_BOOL
,
4589 .help
= N_("set domain to be running on restore")
4592 .type
= VSH_OT_BOOL
,
4593 .help
= N_("set domain to be paused on restore")
4599 cmdSaveImageEdit(vshControl
*ctl
, const vshCmd
*cmd
)
4601 const char *file
= NULL
;
4603 unsigned int getxml_flags
= VIR_DOMAIN_XML_SECURE
;
4604 unsigned int define_flags
= 0;
4605 virshControlPtr priv
= ctl
->privData
;
4607 if (vshCommandOptBool(cmd
, "running"))
4608 define_flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4609 if (vshCommandOptBool(cmd
, "paused"))
4610 define_flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4612 /* Normally, we let the API reject mutually exclusive flags.
4613 * However, in the edit cycle, we let the user retry if the define
4614 * step fails, but the define step will always fail on invalid
4615 * flags, so we reject it up front to avoid looping. */
4616 VSH_EXCLUSIVE_OPTIONS("running", "paused");
4618 if (vshCommandOptStringReq(ctl
, cmd
, "file", &file
) < 0)
4621 #define EDIT_GET_XML \
4622 virDomainSaveImageGetXMLDesc(priv->conn, file, getxml_flags)
4623 #define EDIT_NOT_CHANGED \
4625 vshPrintExtra(ctl, _("Saved image %s XML configuration " \
4626 "not changed.\n"), file); \
4628 goto edit_cleanup; \
4630 #define EDIT_DEFINE \
4631 (virDomainSaveImageDefineXML(priv->conn, file, doc_edited, define_flags) == 0)
4632 #include "virsh-edit.c"
4634 vshPrintExtra(ctl
, _("State file %s edited.\n"), file
);
4642 * "managedsave" command
4644 static const vshCmdInfo info_managedsave
[] = {
4646 .data
= N_("managed save of a domain state")
4649 .data
= N_("Save and destroy a running domain, so it can be restarted from\n"
4650 " the same state at a later time. When the virsh 'start'\n"
4651 " command is next run for the domain, it will automatically\n"
4652 " be started from this saved state.")
4657 static const vshCmdOptDef opts_managedsave
[] = {
4658 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
4659 {.name
= "bypass-cache",
4660 .type
= VSH_OT_BOOL
,
4661 .help
= N_("avoid file system cache when saving")
4664 .type
= VSH_OT_BOOL
,
4665 .help
= N_("set domain to be running on next start")
4668 .type
= VSH_OT_BOOL
,
4669 .help
= N_("set domain to be paused on next start")
4672 .type
= VSH_OT_BOOL
,
4673 .help
= N_("display the progress of save")
4679 doManagedsave(void *opaque
)
4682 virshCtrlData
*data
= opaque
;
4683 vshControl
*ctl
= data
->ctl
;
4684 const vshCmd
*cmd
= data
->cmd
;
4685 virDomainPtr dom
= NULL
;
4687 unsigned int flags
= 0;
4688 sigset_t sigmask
, oldsigmask
;
4690 sigemptyset(&sigmask
);
4691 sigaddset(&sigmask
, SIGINT
);
4692 if (pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
) < 0)
4695 if (vshCommandOptBool(cmd
, "bypass-cache"))
4696 flags
|= VIR_DOMAIN_SAVE_BYPASS_CACHE
;
4697 if (vshCommandOptBool(cmd
, "running"))
4698 flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4699 if (vshCommandOptBool(cmd
, "paused"))
4700 flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4702 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
4705 if (virDomainManagedSave(dom
, flags
) < 0) {
4706 vshError(ctl
, _("Failed to save domain %s state"), name
);
4712 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
4714 virshDomainFree(dom
);
4715 ignore_value(safewrite(data
->writefd
, &ret
, sizeof(ret
)));
4719 cmdManagedSave(vshControl
*ctl
, const vshCmd
*cmd
)
4722 int p
[2] = { -1, -1};
4724 bool verbose
= false;
4725 const char *name
= NULL
;
4727 virThread workerThread
;
4729 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
4732 if (vshCommandOptBool(cmd
, "verbose"))
4740 data
.writefd
= p
[1];
4742 if (virThreadCreate(&workerThread
,
4748 ret
= virshWatchJob(ctl
, dom
, verbose
, p
[0], 0,
4749 NULL
, NULL
, _("Managedsave"));
4751 virThreadJoin(&workerThread
);
4754 vshPrintExtra(ctl
, _("\nDomain %s state saved by libvirt\n"), name
);
4757 virshDomainFree(dom
);
4758 VIR_FORCE_CLOSE(p
[0]);
4759 VIR_FORCE_CLOSE(p
[1]);
4764 * "managedsave-remove" command
4766 static const vshCmdInfo info_managedsaveremove
[] = {
4768 .data
= N_("Remove managed save of a domain")
4771 .data
= N_("Remove an existing managed save state file from a domain")
4776 static const vshCmdOptDef opts_managedsaveremove
[] = {
4777 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
4782 cmdManagedSaveRemove(vshControl
*ctl
, const vshCmd
*cmd
)
4789 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
4792 hassave
= virDomainHasManagedSaveImage(dom
, 0);
4794 vshError(ctl
, "%s", _("Failed to check for domain managed save image"));
4799 if (virDomainManagedSaveRemove(dom
, 0) < 0) {
4800 vshError(ctl
, _("Failed to remove managed save image for domain %s"),
4805 vshPrintExtra(ctl
, _("Removed managedsave image for domain %s"), name
);
4808 vshPrintExtra(ctl
, _("Domain %s has no manage save image; removal skipped"),
4814 virshDomainFree(dom
);
4819 * "managedsave-edit" command
4821 static const vshCmdInfo info_managed_save_edit
[] = {
4823 .data
= N_("edit XML for a domain's managed save state file")
4826 .data
= N_("Edit the domain XML associated with the managed save state file")
4831 static const vshCmdOptDef opts_managed_save_edit
[] = {
4832 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
4834 .type
= VSH_OT_BOOL
,
4835 .help
= N_("set domain to be running on start")
4838 .type
= VSH_OT_BOOL
,
4839 .help
= N_("set domain to be paused on start")
4845 cmdManagedSaveEdit(vshControl
*ctl
, const vshCmd
*cmd
)
4848 virDomainPtr dom
= NULL
;
4849 unsigned int getxml_flags
= VIR_DOMAIN_XML_SECURE
;
4850 unsigned int define_flags
= 0;
4852 if (vshCommandOptBool(cmd
, "running"))
4853 define_flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4854 if (vshCommandOptBool(cmd
, "paused"))
4855 define_flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4857 VSH_EXCLUSIVE_OPTIONS("running", "paused");
4859 dom
= virshCommandOptDomain(ctl
, cmd
, NULL
);
4863 #define EDIT_GET_XML virDomainManagedSaveGetXMLDesc(dom, getxml_flags)
4864 #define EDIT_NOT_CHANGED \
4866 vshPrintExtra(ctl, _("Managed save image of domain %s XML configuration " \
4867 "not changed.\n"), virDomainGetName(dom)); \
4869 goto edit_cleanup; \
4871 #define EDIT_DEFINE \
4872 (virDomainManagedSaveDefineXML(dom, doc_edited, define_flags) == 0)
4873 #include "virsh-edit.c"
4875 vshPrintExtra(ctl
, _("Managed save image of Domain %s XML configuration edited.\n"),
4876 virDomainGetName(dom
));
4880 virshDomainFree(dom
);
4885 * "managedsave-dumpxml" command
4887 static const vshCmdInfo info_managed_save_dumpxml
[] = {
4889 .data
= N_("Domain information of managed save state file in XML")
4892 .data
= N_("Dump XML of domain information for a managed save state file to stdout.")
4897 static const vshCmdOptDef opts_managed_save_dumpxml
[] = {
4898 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
4899 {.name
= "security-info",
4900 .type
= VSH_OT_BOOL
,
4901 .help
= N_("include security sensitive information in XML dump")
4907 cmdManagedSaveDumpxml(vshControl
*ctl
, const vshCmd
*cmd
)
4910 virDomainPtr dom
= NULL
;
4911 unsigned int flags
= 0;
4914 if (vshCommandOptBool(cmd
, "security-info"))
4915 flags
|= VIR_DOMAIN_XML_SECURE
;
4917 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
4920 if (!(xml
= virDomainManagedSaveGetXMLDesc(dom
, flags
)))
4923 vshPrint(ctl
, "%s", xml
);
4927 virshDomainFree(dom
);
4933 * "managedsave-define" command
4935 static const vshCmdInfo info_managed_save_define
[] = {
4937 .data
= N_("redefine the XML for a domain's managed save state file")
4940 .data
= N_("Replace the domain XML associated with a managed save state file")
4945 static const vshCmdOptDef opts_managed_save_define
[] = {
4946 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
4948 .type
= VSH_OT_DATA
,
4949 .flags
= VSH_OFLAG_REQ
,
4950 .help
= N_("filename containing updated XML for the target")
4953 .type
= VSH_OT_BOOL
,
4954 .help
= N_("set domain to be running on start")
4957 .type
= VSH_OT_BOOL
,
4958 .help
= N_("set domain to be paused on start")
4964 cmdManagedSaveDefine(vshControl
*ctl
, const vshCmd
*cmd
)
4967 virDomainPtr dom
= NULL
;
4968 const char *xmlfile
= NULL
;
4970 unsigned int flags
= 0;
4972 if (vshCommandOptBool(cmd
, "running"))
4973 flags
|= VIR_DOMAIN_SAVE_RUNNING
;
4974 if (vshCommandOptBool(cmd
, "paused"))
4975 flags
|= VIR_DOMAIN_SAVE_PAUSED
;
4977 VSH_EXCLUSIVE_OPTIONS("running", "paused");
4979 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &xmlfile
) < 0)
4982 if (virFileReadAll(xmlfile
, VSH_MAX_XML_FILE
, &xml
) < 0)
4985 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
4988 if (virDomainManagedSaveDefineXML(dom
, xml
, flags
) < 0) {
4989 vshError(ctl
, _("Failed to update %s XML configuration"),
4990 virDomainGetName(dom
));
4994 vshPrintExtra(ctl
, _("Managed save state file of domain %s updated.\n"),
4995 virDomainGetName(dom
));
4999 virshDomainFree(dom
);
5005 * "schedinfo" command
5007 static const vshCmdInfo info_schedinfo
[] = {
5009 .data
= N_("show/set scheduler parameters")
5012 .data
= N_("Show/Set scheduler parameters.")
5017 static const vshCmdOptDef opts_schedinfo
[] = {
5018 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
5021 .flags
= VSH_OFLAG_REQ_OPT
,
5022 .help
= N_("weight for XEN_CREDIT")
5026 .flags
= VSH_OFLAG_REQ_OPT
,
5027 .help
= N_("cap for XEN_CREDIT")
5029 VIRSH_COMMON_OPT_CURRENT(N_("get/set current scheduler info")),
5030 VIRSH_COMMON_OPT_CONFIG(N_("get/set value to be used on next boot")),
5031 VIRSH_COMMON_OPT_LIVE(N_("get/set value from running domain")),
5033 .type
= VSH_OT_ARGV
,
5034 .flags
= VSH_OFLAG_NONE
,
5035 .help
= N_("parameter=value")
5041 cmdSchedInfoUpdateOne(vshControl
*ctl
,
5042 virTypedParameterPtr src_params
, int nsrc_params
,
5043 virTypedParameterPtr
*params
,
5044 int *nparams
, int *maxparams
,
5045 const char *field
, const char *value
)
5047 virTypedParameterPtr param
;
5051 for (i
= 0; i
< nsrc_params
; i
++) {
5052 param
= &(src_params
[i
]);
5054 if (STRNEQ(field
, param
->field
))
5057 if (virTypedParamsAddFromString(params
, nparams
, maxparams
,
5060 vshSaveLibvirtError();
5068 vshError(ctl
, _("invalid scheduler option: %s"), field
);
5075 cmdSchedInfoUpdate(vshControl
*ctl
, const vshCmd
*cmd
,
5076 virTypedParameterPtr src_params
, int nsrc_params
,
5077 virTypedParameterPtr
*update_params
)
5079 char *set_field
= NULL
;
5080 char *set_val
= NULL
;
5081 const char *val
= NULL
;
5082 const vshCmdOpt
*opt
= NULL
;
5083 virTypedParameterPtr params
= NULL
;
5089 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
))) {
5090 set_field
= vshStrdup(ctl
, opt
->data
);
5091 if (!(set_val
= strchr(set_field
, '='))) {
5092 vshError(ctl
, "%s", _("Invalid syntax for --set, "
5093 "expecting name=value"));
5100 if (cmdSchedInfoUpdateOne(ctl
, src_params
, nsrc_params
,
5101 ¶ms
, &nparams
, &maxparams
,
5102 set_field
, set_val
) < 0)
5105 VIR_FREE(set_field
);
5108 rv
= vshCommandOptStringReq(ctl
, cmd
, "cap", &val
);
5111 cmdSchedInfoUpdateOne(ctl
, src_params
, nsrc_params
,
5112 ¶ms
, &nparams
, &maxparams
,
5116 rv
= vshCommandOptStringReq(ctl
, cmd
, "weight", &val
);
5119 cmdSchedInfoUpdateOne(ctl
, src_params
, nsrc_params
,
5120 ¶ms
, &nparams
, &maxparams
,
5121 "weight", val
) < 0))
5125 *update_params
= params
;
5129 VIR_FREE(set_field
);
5130 virTypedParamsFree(params
, nparams
);
5135 cmdSchedinfo(vshControl
*ctl
, const vshCmd
*cmd
)
5137 char *schedulertype
;
5139 virTypedParameterPtr params
= NULL
;
5140 virTypedParameterPtr updates
= NULL
;
5145 bool ret_val
= false;
5146 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
5147 bool current
= vshCommandOptBool(cmd
, "current");
5148 bool config
= vshCommandOptBool(cmd
, "config");
5149 bool live
= vshCommandOptBool(cmd
, "live");
5151 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
5152 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
5155 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
5157 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
5159 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
5162 /* Print SchedulerType */
5163 schedulertype
= virDomainGetSchedulerType(dom
, &nparams
);
5164 if (schedulertype
!= NULL
) {
5165 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"), schedulertype
);
5166 VIR_FREE(schedulertype
);
5168 vshPrint(ctl
, "%-15s: %s\n", _("Scheduler"), _("Unknown"));
5173 params
= vshMalloc(ctl
, sizeof(*params
) * nparams
);
5175 memset(params
, 0, sizeof(*params
) * nparams
);
5176 if (flags
|| current
) {
5177 /* We cannot query both live and config at once, so settle
5178 on current in that case. If we are setting, then the
5179 two values should match when we re-query; otherwise, we
5180 report the error later. */
5181 ret
= virDomainGetSchedulerParametersFlags(dom
, params
, &nparams
,
5182 ((live
&& config
) ? 0
5185 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
5190 /* See if any params are being set */
5191 if ((nupdates
= cmdSchedInfoUpdate(ctl
, cmd
, params
, nparams
,
5195 /* Update parameters & refresh data */
5197 if (flags
|| current
)
5198 ret
= virDomainSetSchedulerParametersFlags(dom
, updates
,
5201 ret
= virDomainSetSchedulerParameters(dom
, updates
, nupdates
);
5206 if (flags
|| current
)
5207 ret
= virDomainGetSchedulerParametersFlags(dom
, params
,
5209 ((live
&& config
) ? 0
5212 ret
= virDomainGetSchedulerParameters(dom
, params
, &nparams
);
5216 /* When not doing --set, --live and --config do not mix. */
5217 if (live
&& config
) {
5219 _("cannot query both live and config at once"));
5225 for (i
= 0; i
< nparams
; i
++) {
5226 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
5227 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
5233 virTypedParamsFree(params
, nparams
);
5234 virTypedParamsFree(updates
, nupdates
);
5235 virshDomainFree(dom
);
5242 static const vshCmdInfo info_restore
[] = {
5244 .data
= N_("restore a domain from a saved state in a file")
5247 .data
= N_("Restore a domain.")
5252 static const vshCmdOptDef opts_restore
[] = {
5253 VIRSH_COMMON_OPT_FILE(N_("the state to restore")),
5254 {.name
= "bypass-cache",
5255 .type
= VSH_OT_BOOL
,
5256 .help
= N_("avoid file system cache when restoring")
5259 .type
= VSH_OT_STRING
,
5260 .help
= N_("filename containing updated XML for the target")
5263 .type
= VSH_OT_BOOL
,
5264 .help
= N_("restore domain into running state")
5267 .type
= VSH_OT_BOOL
,
5268 .help
= N_("restore domain into paused state")
5274 cmdRestore(vshControl
*ctl
, const vshCmd
*cmd
)
5276 const char *from
= NULL
;
5278 unsigned int flags
= 0;
5279 const char *xmlfile
= NULL
;
5281 virshControlPtr priv
= ctl
->privData
;
5283 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
5286 if (vshCommandOptBool(cmd
, "bypass-cache"))
5287 flags
|= VIR_DOMAIN_SAVE_BYPASS_CACHE
;
5288 if (vshCommandOptBool(cmd
, "running"))
5289 flags
|= VIR_DOMAIN_SAVE_RUNNING
;
5290 if (vshCommandOptBool(cmd
, "paused"))
5291 flags
|= VIR_DOMAIN_SAVE_PAUSED
;
5293 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &xmlfile
) < 0)
5297 virFileReadAll(xmlfile
, VSH_MAX_XML_FILE
, &xml
) < 0)
5301 ? virDomainRestoreFlags(priv
->conn
, from
, xml
, flags
)
5302 : virDomainRestore(priv
->conn
, from
)) < 0) {
5303 vshError(ctl
, _("Failed to restore domain from %s"), from
);
5307 vshPrintExtra(ctl
, _("Domain restored from %s\n"), from
);
5318 static const vshCmdInfo info_dump
[] = {
5320 .data
= N_("dump the core of a domain to a file for analysis")
5323 .data
= N_("Core dump a domain.")
5328 static const vshCmdOptDef opts_dump
[] = {
5329 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
5330 VIRSH_COMMON_OPT_FILE(N_("where to dump the core")),
5331 VIRSH_COMMON_OPT_LIVE(N_("perform a live core dump if supported")),
5333 .type
= VSH_OT_BOOL
,
5334 .help
= N_("crash the domain after core dump")
5336 {.name
= "bypass-cache",
5337 .type
= VSH_OT_BOOL
,
5338 .help
= N_("avoid file system cache when dumping")
5341 .type
= VSH_OT_BOOL
,
5342 .help
= N_("reset the domain after core dump")
5345 .type
= VSH_OT_BOOL
,
5346 .help
= N_("display the progress of dump")
5348 {.name
= "memory-only",
5349 .type
= VSH_OT_BOOL
,
5350 .help
= N_("dump domain's memory only")
5353 .type
= VSH_OT_STRING
,
5354 .help
= N_("specify the format of memory-only dump")
5360 doDump(void *opaque
)
5363 virshCtrlData
*data
= opaque
;
5364 vshControl
*ctl
= data
->ctl
;
5365 const vshCmd
*cmd
= data
->cmd
;
5366 virDomainPtr dom
= NULL
;
5367 sigset_t sigmask
, oldsigmask
;
5368 const char *name
= NULL
;
5369 const char *to
= NULL
;
5370 unsigned int flags
= 0;
5371 const char *format
= NULL
;
5372 unsigned int dumpformat
= VIR_DOMAIN_CORE_DUMP_FORMAT_RAW
;
5374 sigemptyset(&sigmask
);
5375 sigaddset(&sigmask
, SIGINT
);
5376 if (pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
) < 0)
5379 if (vshCommandOptStringReq(ctl
, cmd
, "file", &to
) < 0)
5382 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5385 if (vshCommandOptBool(cmd
, "live"))
5386 flags
|= VIR_DUMP_LIVE
;
5387 if (vshCommandOptBool(cmd
, "crash"))
5388 flags
|= VIR_DUMP_CRASH
;
5389 if (vshCommandOptBool(cmd
, "bypass-cache"))
5390 flags
|= VIR_DUMP_BYPASS_CACHE
;
5391 if (vshCommandOptBool(cmd
, "reset"))
5392 flags
|= VIR_DUMP_RESET
;
5393 if (vshCommandOptBool(cmd
, "memory-only"))
5394 flags
|= VIR_DUMP_MEMORY_ONLY
;
5396 if (vshCommandOptBool(cmd
, "format")) {
5397 if (!(flags
& VIR_DUMP_MEMORY_ONLY
)) {
5398 vshError(ctl
, "%s", _("--format only works with --memory-only"));
5402 if (vshCommandOptStringQuiet(ctl
, cmd
, "format", &format
) > 0) {
5403 if (STREQ(format
, "kdump-zlib")) {
5404 dumpformat
= VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_ZLIB
;
5405 } else if (STREQ(format
, "kdump-lzo")) {
5406 dumpformat
= VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_LZO
;
5407 } else if (STREQ(format
, "kdump-snappy")) {
5408 dumpformat
= VIR_DOMAIN_CORE_DUMP_FORMAT_KDUMP_SNAPPY
;
5409 } else if (STREQ(format
, "elf")) {
5410 dumpformat
= VIR_DOMAIN_CORE_DUMP_FORMAT_RAW
;
5412 vshError(ctl
, _("format '%s' is not supported, expecting "
5413 "'kdump-zlib', 'kdump-lzo', 'kdump-snappy' "
5414 "or 'elf'"), format
);
5420 if (dumpformat
!= VIR_DOMAIN_CORE_DUMP_FORMAT_RAW
) {
5421 if (virDomainCoreDumpWithFormat(dom
, to
, dumpformat
, flags
) < 0) {
5422 vshError(ctl
, _("Failed to core dump domain %s to %s"), name
, to
);
5426 if (virDomainCoreDump(dom
, to
, flags
) < 0) {
5427 vshError(ctl
, _("Failed to core dump domain %s to %s"), name
, to
);
5434 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
5437 virshDomainFree(dom
);
5438 ignore_value(safewrite(data
->writefd
, &ret
, sizeof(ret
)));
5442 cmdDump(vshControl
*ctl
, const vshCmd
*cmd
)
5445 int p
[2] = { -1, -1};
5447 bool verbose
= false;
5448 const char *name
= NULL
;
5449 const char *to
= NULL
;
5451 virThread workerThread
;
5453 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5456 if (vshCommandOptStringReq(ctl
, cmd
, "file", &to
) < 0)
5459 if (vshCommandOptBool(cmd
, "verbose"))
5467 data
.writefd
= p
[1];
5469 if (virThreadCreate(&workerThread
,
5475 ret
= virshWatchJob(ctl
, dom
, verbose
, p
[0], 0, NULL
, NULL
, _("Dump"));
5477 virThreadJoin(&workerThread
);
5480 vshPrintExtra(ctl
, _("\nDomain %s dumped to %s\n"), name
, to
);
5483 virshDomainFree(dom
);
5484 VIR_FORCE_CLOSE(p
[0]);
5485 VIR_FORCE_CLOSE(p
[1]);
5489 static const vshCmdInfo info_screenshot
[] = {
5491 .data
= N_("take a screenshot of a current domain console and store it "
5495 .data
= N_("screenshot of a current domain console")
5500 static const vshCmdOptDef opts_screenshot
[] = {
5501 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
5503 .type
= VSH_OT_STRING
,
5504 .help
= N_("where to store the screenshot")
5508 .help
= N_("ID of a screen to take screenshot of")
5514 * Generate string: '<domain name>-<timestamp>[<extension>]'
5517 virshGenFileName(vshControl
*ctl
, virDomainPtr dom
, const char *mime
)
5521 struct tm time_info
;
5522 const char *ext
= NULL
;
5526 vshError(ctl
, "%s", _("Invalid domain supplied"));
5530 if (STREQ(mime
, "image/x-portable-pixmap"))
5532 else if (STREQ(mime
, "image/png"))
5534 /* add mime type here */
5537 localtime_r(&cur_time
, &time_info
);
5538 strftime(timestr
, sizeof(timestr
), "%Y-%m-%d-%H:%M:%S", &time_info
);
5540 if (virAsprintf(&ret
, "%s-%s%s", virDomainGetName(dom
),
5541 timestr
, NULLSTR_EMPTY(ext
)) < 0) {
5542 vshError(ctl
, "%s", _("Out of memory"));
5550 cmdScreenshot(vshControl
*ctl
, const vshCmd
*cmd
)
5553 const char *name
= NULL
;
5556 virStreamPtr st
= NULL
;
5557 unsigned int screen
= 0;
5558 unsigned int flags
= 0; /* currently unused */
5560 bool created
= false;
5561 bool generated
= false;
5563 virshControlPtr priv
= ctl
->privData
;
5565 if (vshCommandOptStringReq(ctl
, cmd
, "file", (const char **) &file
) < 0)
5568 if (vshCommandOptUInt(ctl
, cmd
, "screen", &screen
) < 0)
5571 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5574 if (!(st
= virStreamNew(priv
->conn
, 0)))
5577 mime
= virDomainScreenshot(dom
, st
, screen
, flags
);
5579 vshError(ctl
, _("could not take a screenshot of %s"), name
);
5584 if (!(file
= virshGenFileName(ctl
, dom
, mime
)))
5589 if ((fd
= open(file
, O_WRONLY
|O_CREAT
|O_EXCL
, 0666)) < 0) {
5590 if (errno
!= EEXIST
||
5591 (fd
= open(file
, O_WRONLY
|O_TRUNC
, 0666)) < 0) {
5592 vshError(ctl
, _("cannot create file %s"), file
);
5599 if (virStreamRecvAll(st
, virshStreamSink
, &fd
) < 0) {
5600 vshError(ctl
, _("could not receive data from domain %s"), name
);
5604 if (VIR_CLOSE(fd
) < 0) {
5605 vshError(ctl
, _("cannot close file %s"), file
);
5609 if (virStreamFinish(st
) < 0) {
5610 vshError(ctl
, _("cannot close stream on domain %s"), name
);
5614 vshPrintExtra(ctl
, _("Screenshot saved to %s, with type of %s"), file
, mime
);
5618 if (!ret
&& created
)
5622 virshDomainFree(dom
);
5625 VIR_FORCE_CLOSE(fd
);
5631 * "set-lifecycle-action" command
5633 static const vshCmdInfo info_setLifecycleAction
[] = {
5635 .data
= N_("change lifecycle actions")
5638 .data
= N_("Change lifecycle actions for the guest domain.")
5643 static const vshCmdOptDef opts_setLifecycleAction
[] = {
5644 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
5646 .type
= VSH_OT_DATA
,
5647 .flags
= VSH_OFLAG_REQ
,
5648 .help
= N_("lifecycle type to modify")
5651 .type
= VSH_OT_DATA
,
5652 .flags
= VSH_OFLAG_REQ
,
5653 .help
= N_("lifecycle action to set")
5655 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
5656 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
5657 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
5661 VIR_ENUM_IMPL(virDomainLifecycle
,
5662 VIR_DOMAIN_LIFECYCLE_LAST
,
5667 VIR_ENUM_IMPL(virDomainLifecycleAction
,
5668 VIR_DOMAIN_LIFECYCLE_ACTION_LAST
,
5674 "coredump-restart");
5677 cmdSetLifecycleAction(vshControl
*ctl
, const vshCmd
*cmd
)
5681 bool config
= vshCommandOptBool(cmd
, "config");
5682 bool live
= vshCommandOptBool(cmd
, "live");
5683 bool current
= vshCommandOptBool(cmd
, "current");
5684 const char *typeStr
;
5685 const char *actionStr
;
5687 unsigned int action
;
5688 unsigned int flags
= 0;
5691 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
5692 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
5695 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
5697 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
5699 if (vshCommandOptStringReq(ctl
, cmd
, "type", &typeStr
) < 0 ||
5700 vshCommandOptStringReq(ctl
, cmd
, "action", &actionStr
) < 0) {
5704 if ((tmpVal
= virDomainLifecycleTypeFromString(typeStr
)) < 0) {
5705 vshError(ctl
, _("Invalid lifecycle type '%s'."), typeStr
);
5710 if ((tmpVal
= virDomainLifecycleActionTypeFromString(actionStr
)) < 0) {
5711 vshError(ctl
, _("Invalid lifecycle action '%s'."), actionStr
);
5716 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
5719 if (virDomainSetLifecycleAction(dom
, type
, action
, flags
) < 0) {
5720 vshError(ctl
, "%s", _("Unable to change lifecycle action."));
5724 virshDomainFree(dom
);
5729 * "set-user-password" command
5731 static const vshCmdInfo info_set_user_password
[] = {
5733 .data
= N_("set the user password inside the domain")
5736 .data
= N_("changes the password of the specified user inside the domain")
5741 static const vshCmdOptDef opts_set_user_password
[] = {
5742 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
5744 .type
= VSH_OT_DATA
,
5745 .flags
= VSH_OFLAG_REQ
,
5746 .help
= N_("the username")
5748 {.name
= "password",
5749 .type
= VSH_OT_DATA
,
5750 .flags
= VSH_OFLAG_REQ
,
5751 .help
= N_("the new password")
5753 {.name
= "encrypted",
5754 .type
= VSH_OT_BOOL
,
5755 .help
= N_("the password is already encrypted")
5761 cmdSetUserPassword(vshControl
*ctl
, const vshCmd
*cmd
)
5765 const char *password
= NULL
;
5766 const char *user
= NULL
;
5767 unsigned int flags
= 0;
5770 if (vshCommandOptBool(cmd
, "encrypted"))
5771 flags
= VIR_DOMAIN_PASSWORD_ENCRYPTED
;
5773 if (vshCommandOptStringReq(ctl
, cmd
, "user", &user
) < 0)
5776 if (vshCommandOptStringReq(ctl
, cmd
, "password", &password
) < 0)
5779 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5782 if (virDomainSetUserPassword(dom
, user
, password
, flags
) < 0)
5785 vshPrintExtra(ctl
, _("Password set successfully for %s in %s"), user
, name
);
5789 virshDomainFree(dom
);
5795 static const vshCmdInfo info_resume
[] = {
5797 .data
= N_("resume a domain")
5800 .data
= N_("Resume a previously suspended domain.")
5805 static const vshCmdOptDef opts_resume
[] = {
5806 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_PAUSED
),
5811 cmdResume(vshControl
*ctl
, const vshCmd
*cmd
)
5817 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5820 if (virDomainResume(dom
) == 0) {
5821 vshPrintExtra(ctl
, _("Domain %s resumed\n"), name
);
5823 vshError(ctl
, _("Failed to resume domain %s"), name
);
5827 virshDomainFree(dom
);
5832 * "shutdown" command
5834 static const vshCmdInfo info_shutdown
[] = {
5836 .data
= N_("gracefully shutdown a domain")
5839 .data
= N_("Run shutdown in the target domain.")
5844 static const vshCmdOptDef opts_shutdown
[] = {
5845 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
5847 .type
= VSH_OT_STRING
,
5848 .completer
= virshDomainShutdownModeCompleter
,
5849 .help
= N_("shutdown mode: acpi|agent|initctl|signal|paravirt")
5855 cmdShutdown(vshControl
*ctl
, const vshCmd
*cmd
)
5857 virDomainPtr dom
= NULL
;
5860 const char *mode
= NULL
;
5863 char **modes
= NULL
, **tmp
;
5865 if (vshCommandOptStringReq(ctl
, cmd
, "mode", &mode
) < 0)
5868 if (mode
&& !(modes
= virStringSplit(mode
, ",", 0))) {
5869 vshError(ctl
, "%s", _("Cannot parse mode string"));
5874 while (tmp
&& *tmp
) {
5876 if (STREQ(mode
, "acpi")) {
5877 flags
|= VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN
;
5878 } else if (STREQ(mode
, "agent")) {
5879 flags
|= VIR_DOMAIN_SHUTDOWN_GUEST_AGENT
;
5880 } else if (STREQ(mode
, "initctl")) {
5881 flags
|= VIR_DOMAIN_SHUTDOWN_INITCTL
;
5882 } else if (STREQ(mode
, "signal")) {
5883 flags
|= VIR_DOMAIN_SHUTDOWN_SIGNAL
;
5884 } else if (STREQ(mode
, "paravirt")) {
5885 flags
|= VIR_DOMAIN_SHUTDOWN_PARAVIRT
;
5887 vshError(ctl
, _("Unknown mode %s value, expecting "
5888 "'acpi', 'agent', 'initctl', 'signal', "
5889 "or 'paravirt'"), mode
);
5895 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5899 rv
= virDomainShutdownFlags(dom
, flags
);
5901 rv
= virDomainShutdown(dom
);
5903 vshPrintExtra(ctl
, _("Domain %s is being shutdown\n"), name
);
5905 vshError(ctl
, _("Failed to shutdown domain %s"), name
);
5911 virshDomainFree(dom
);
5912 virStringListFree(modes
);
5919 static const vshCmdInfo info_reboot
[] = {
5921 .data
= N_("reboot a domain")
5924 .data
= N_("Run a reboot command in the target domain.")
5929 static const vshCmdOptDef opts_reboot
[] = {
5930 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
5932 .type
= VSH_OT_STRING
,
5933 .completer
= virshDomainShutdownModeCompleter
,
5934 .help
= N_("shutdown mode: acpi|agent|initctl|signal|paravirt")
5940 cmdReboot(vshControl
*ctl
, const vshCmd
*cmd
)
5942 virDomainPtr dom
= NULL
;
5945 const char *mode
= NULL
;
5947 char **modes
= NULL
, **tmp
;
5949 if (vshCommandOptStringReq(ctl
, cmd
, "mode", &mode
) < 0)
5952 if (mode
&& !(modes
= virStringSplit(mode
, ",", 0))) {
5953 vshError(ctl
, "%s", _("Cannot parse mode string"));
5958 while (tmp
&& *tmp
) {
5960 if (STREQ(mode
, "acpi")) {
5961 flags
|= VIR_DOMAIN_REBOOT_ACPI_POWER_BTN
;
5962 } else if (STREQ(mode
, "agent")) {
5963 flags
|= VIR_DOMAIN_REBOOT_GUEST_AGENT
;
5964 } else if (STREQ(mode
, "initctl")) {
5965 flags
|= VIR_DOMAIN_REBOOT_INITCTL
;
5966 } else if (STREQ(mode
, "signal")) {
5967 flags
|= VIR_DOMAIN_REBOOT_SIGNAL
;
5968 } else if (STREQ(mode
, "paravirt")) {
5969 flags
|= VIR_DOMAIN_REBOOT_PARAVIRT
;
5971 vshError(ctl
, _("Unknown mode %s value, expecting "
5972 "'acpi', 'agent', 'initctl', 'signal' "
5973 "or 'paravirt'"), mode
);
5979 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
5982 if (virDomainReboot(dom
, flags
) == 0) {
5983 vshPrintExtra(ctl
, _("Domain %s is being rebooted\n"), name
);
5985 vshError(ctl
, _("Failed to reboot domain %s"), name
);
5991 virshDomainFree(dom
);
5992 virStringListFree(modes
);
5999 static const vshCmdInfo info_reset
[] = {
6001 .data
= N_("reset a domain")
6004 .data
= N_("Reset the target domain as if by power button")
6009 static const vshCmdOptDef opts_reset
[] = {
6010 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
6015 cmdReset(vshControl
*ctl
, const vshCmd
*cmd
)
6021 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
6024 if (virDomainReset(dom
, 0) == 0) {
6025 vshPrintExtra(ctl
, _("Domain %s was reset\n"), name
);
6027 vshError(ctl
, _("Failed to reset domain %s"), name
);
6031 virshDomainFree(dom
);
6036 * "domjobinfo" command
6038 static const vshCmdInfo info_domjobinfo
[] = {
6040 .data
= N_("domain job information")
6043 .data
= N_("Returns information about jobs running on a domain.")
6048 static const vshCmdOptDef opts_domjobinfo
[] = {
6049 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
6050 {.name
= "completed",
6051 .type
= VSH_OT_BOOL
,
6052 .help
= N_("return statistics of a recently completed job")
6057 VIR_ENUM_DECL(virshDomainJob
);
6058 VIR_ENUM_IMPL(virshDomainJob
,
6059 VIR_DOMAIN_JOB_LAST
,
6068 virshDomainJobToString(int type
)
6070 const char *str
= virshDomainJobTypeToString(type
);
6071 return str
? _(str
) : _("unknown");
6074 VIR_ENUM_DECL(virshDomainJobOperation
);
6075 VIR_ENUM_IMPL(virshDomainJobOperation
,
6076 VIR_DOMAIN_JOB_OPERATION_LAST
,
6081 N_("Incoming migration"),
6082 N_("Outgoing migration"),
6084 N_("Snapshot revert"),
6090 virshDomainJobOperationToString(int op
)
6092 const char *str
= virshDomainJobOperationTypeToString(op
);
6093 return str
? _(str
) : _("unknown");
6097 cmdDomjobinfo(vshControl
*ctl
, const vshCmd
*cmd
)
6099 virDomainJobInfo info
;
6104 virTypedParameterPtr params
= NULL
;
6106 unsigned long long value
;
6107 unsigned int flags
= 0;
6112 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
6115 if (vshCommandOptBool(cmd
, "completed"))
6116 flags
|= VIR_DOMAIN_JOB_STATS_COMPLETED
;
6118 memset(&info
, 0, sizeof(info
));
6120 rc
= virDomainGetJobStats(dom
, &info
.type
, ¶ms
, &nparams
, flags
);
6122 if (virTypedParamsGetULLong(params
, nparams
,
6123 VIR_DOMAIN_JOB_TIME_ELAPSED
,
6124 &info
.timeElapsed
) < 0 ||
6125 virTypedParamsGetULLong(params
, nparams
,
6126 VIR_DOMAIN_JOB_TIME_REMAINING
,
6127 &info
.timeRemaining
) < 0 ||
6128 virTypedParamsGetULLong(params
, nparams
,
6129 VIR_DOMAIN_JOB_DATA_TOTAL
,
6130 &info
.dataTotal
) < 0 ||
6131 virTypedParamsGetULLong(params
, nparams
,
6132 VIR_DOMAIN_JOB_DATA_PROCESSED
,
6133 &info
.dataProcessed
) < 0 ||
6134 virTypedParamsGetULLong(params
, nparams
,
6135 VIR_DOMAIN_JOB_DATA_REMAINING
,
6136 &info
.dataRemaining
) < 0 ||
6137 virTypedParamsGetULLong(params
, nparams
,
6138 VIR_DOMAIN_JOB_MEMORY_TOTAL
,
6139 &info
.memTotal
) < 0 ||
6140 virTypedParamsGetULLong(params
, nparams
,
6141 VIR_DOMAIN_JOB_MEMORY_PROCESSED
,
6142 &info
.memProcessed
) < 0 ||
6143 virTypedParamsGetULLong(params
, nparams
,
6144 VIR_DOMAIN_JOB_MEMORY_REMAINING
,
6145 &info
.memRemaining
) < 0 ||
6146 virTypedParamsGetULLong(params
, nparams
,
6147 VIR_DOMAIN_JOB_DISK_TOTAL
,
6148 &info
.fileTotal
) < 0 ||
6149 virTypedParamsGetULLong(params
, nparams
,
6150 VIR_DOMAIN_JOB_DISK_PROCESSED
,
6151 &info
.fileProcessed
) < 0 ||
6152 virTypedParamsGetULLong(params
, nparams
,
6153 VIR_DOMAIN_JOB_DISK_REMAINING
,
6154 &info
.fileRemaining
) < 0)
6156 } else if (last_error
->code
== VIR_ERR_NO_SUPPORT
) {
6158 vshError(ctl
, "%s", _("Optional flags are not supported by the "
6162 vshDebug(ctl
, VSH_ERR_DEBUG
, "detailed statistics not supported\n");
6163 vshResetLibvirtError();
6164 rc
= virDomainGetJobInfo(dom
, &info
);
6169 vshPrint(ctl
, "%-17s %-12s\n", _("Job type:"),
6170 virshDomainJobToString(info
.type
));
6171 if (info
.type
!= VIR_DOMAIN_JOB_BOUNDED
&&
6172 info
.type
!= VIR_DOMAIN_JOB_UNBOUNDED
&&
6173 (!(flags
& VIR_DOMAIN_JOB_STATS_COMPLETED
) ||
6174 info
.type
!= VIR_DOMAIN_JOB_COMPLETED
)) {
6179 op
= VIR_DOMAIN_JOB_OPERATION_UNKNOWN
;
6180 if ((rc
= virTypedParamsGetInt(params
, nparams
,
6181 VIR_DOMAIN_JOB_OPERATION
, &op
)) < 0)
6184 vshPrint(ctl
, "%-17s %-12s\n", _("Operation:"),
6185 virshDomainJobOperationToString(op
));
6187 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time elapsed:"), info
.timeElapsed
);
6188 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6189 VIR_DOMAIN_JOB_TIME_ELAPSED_NET
,
6193 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time elapsed w/o network:"),
6197 if (info
.type
== VIR_DOMAIN_JOB_BOUNDED
)
6198 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Time remaining:"),
6199 info
.timeRemaining
);
6201 if (info
.dataTotal
|| info
.dataRemaining
|| info
.dataProcessed
) {
6202 val
= vshPrettyCapacity(info
.dataProcessed
, &unit
);
6203 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data processed:"), val
, unit
);
6204 val
= vshPrettyCapacity(info
.dataRemaining
, &unit
);
6205 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data remaining:"), val
, unit
);
6206 val
= vshPrettyCapacity(info
.dataTotal
, &unit
);
6207 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Data total:"), val
, unit
);
6210 if (info
.memTotal
|| info
.memRemaining
|| info
.memProcessed
) {
6211 val
= vshPrettyCapacity(info
.memProcessed
, &unit
);
6212 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory processed:"), val
, unit
);
6213 val
= vshPrettyCapacity(info
.memRemaining
, &unit
);
6214 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory remaining:"), val
, unit
);
6215 val
= vshPrettyCapacity(info
.memTotal
, &unit
);
6216 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Memory total:"), val
, unit
);
6218 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6219 VIR_DOMAIN_JOB_MEMORY_BPS
,
6222 } else if (rc
&& value
) {
6223 val
= vshPrettyCapacity(value
, &unit
);
6224 vshPrint(ctl
, "%-17s %-.3lf %s/s\n",
6225 _("Memory bandwidth:"), val
, unit
);
6228 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6229 VIR_DOMAIN_JOB_MEMORY_DIRTY_RATE
,
6233 vshPrint(ctl
, "%-17s %-12llu pages/s\n", _("Dirty rate:"), value
);
6236 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6237 VIR_DOMAIN_JOB_MEMORY_PAGE_SIZE
,
6241 vshPrint(ctl
, "%-17s %-12llu bytes\n", _("Page size:"), value
);
6244 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6245 VIR_DOMAIN_JOB_MEMORY_ITERATION
,
6249 vshPrint(ctl
, "%-17s %-12llu\n", _("Iteration:"), value
);
6252 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6253 VIR_DOMAIN_JOB_MEMORY_POSTCOPY_REQS
,
6257 vshPrint(ctl
, "%-17s %-12llu\n", _("Postcopy requests:"), value
);
6261 if (info
.fileTotal
|| info
.fileRemaining
|| info
.fileProcessed
) {
6262 val
= vshPrettyCapacity(info
.fileProcessed
, &unit
);
6263 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File processed:"), val
, unit
);
6264 val
= vshPrettyCapacity(info
.fileRemaining
, &unit
);
6265 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File remaining:"), val
, unit
);
6266 val
= vshPrettyCapacity(info
.fileTotal
, &unit
);
6267 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("File total:"), val
, unit
);
6269 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6270 VIR_DOMAIN_JOB_DISK_BPS
,
6273 } else if (rc
&& value
) {
6274 val
= vshPrettyCapacity(value
, &unit
);
6275 vshPrint(ctl
, "%-17s %-.3lf %s/s\n",
6276 _("File bandwidth:"), val
, unit
);
6280 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6281 VIR_DOMAIN_JOB_MEMORY_CONSTANT
,
6285 vshPrint(ctl
, "%-17s %-12llu\n", _("Constant pages:"), value
);
6287 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6288 VIR_DOMAIN_JOB_MEMORY_NORMAL
,
6292 vshPrint(ctl
, "%-17s %-12llu\n", _("Normal pages:"), value
);
6294 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6295 VIR_DOMAIN_JOB_MEMORY_NORMAL_BYTES
,
6299 val
= vshPrettyCapacity(value
, &unit
);
6300 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Normal data:"), val
, unit
);
6303 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6304 VIR_DOMAIN_JOB_DOWNTIME
,
6308 if (info
.type
== VIR_DOMAIN_JOB_COMPLETED
) {
6309 vshPrint(ctl
, "%-17s %-12llu ms\n",
6310 _("Total downtime:"), value
);
6312 vshPrint(ctl
, "%-17s %-12llu ms\n",
6313 _("Expected downtime:"), value
);
6317 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6318 VIR_DOMAIN_JOB_DOWNTIME_NET
,
6322 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Downtime w/o network:"), value
);
6324 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6325 VIR_DOMAIN_JOB_SETUP_TIME
,
6329 vshPrint(ctl
, "%-17s %-12llu ms\n", _("Setup time:"), value
);
6331 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6332 VIR_DOMAIN_JOB_COMPRESSION_CACHE
,
6336 val
= vshPrettyCapacity(value
, &unit
);
6337 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Compression cache:"), val
, unit
);
6339 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6340 VIR_DOMAIN_JOB_COMPRESSION_BYTES
,
6344 val
= vshPrettyCapacity(value
, &unit
);
6345 vshPrint(ctl
, "%-17s %-.3lf %s\n", _("Compressed data:"), val
, unit
);
6347 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6348 VIR_DOMAIN_JOB_COMPRESSION_PAGES
,
6352 vshPrint(ctl
, "%-17s %-13llu\n", _("Compressed pages:"), value
);
6354 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6355 VIR_DOMAIN_JOB_COMPRESSION_CACHE_MISSES
,
6359 vshPrint(ctl
, "%-17s %-13llu\n", _("Compression cache misses:"), value
);
6361 if ((rc
= virTypedParamsGetULLong(params
, nparams
,
6362 VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW
,
6366 vshPrint(ctl
, "%-17s %-13llu\n", _("Compression overflows:"), value
);
6369 if ((rc
= virTypedParamsGetInt(params
, nparams
,
6370 VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE
,
6374 vshPrint(ctl
, "%-17s %-13d\n", _("Auto converge throttle:"), ivalue
);
6380 virshDomainFree(dom
);
6381 virTypedParamsFree(params
, nparams
);
6385 vshSaveLibvirtError();
6390 * "domjobabort" command
6392 static const vshCmdInfo info_domjobabort
[] = {
6394 .data
= N_("abort active domain job")
6397 .data
= N_("Aborts the currently running domain job")
6402 static const vshCmdOptDef opts_domjobabort
[] = {
6403 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
6408 cmdDomjobabort(vshControl
*ctl
, const vshCmd
*cmd
)
6413 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
6416 if (virDomainAbortJob(dom
) < 0)
6419 virshDomainFree(dom
);
6424 * "vcpucount" command
6426 static const vshCmdInfo info_vcpucount
[] = {
6428 .data
= N_("domain vcpu counts")
6431 .data
= N_("Returns the number of virtual CPUs used by the domain.")
6436 static const vshCmdOptDef opts_vcpucount
[] = {
6437 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
6439 .type
= VSH_OT_BOOL
,
6440 .help
= N_("get maximum count of vcpus")
6443 .type
= VSH_OT_BOOL
,
6444 .help
= N_("get number of currently active vcpus")
6446 VIRSH_COMMON_OPT_LIVE(N_("get value from running domain")),
6447 VIRSH_COMMON_OPT_CONFIG(N_("get value to be used on next boot")),
6448 VIRSH_COMMON_OPT_CURRENT(N_("get value according to current domain state")),
6450 .type
= VSH_OT_BOOL
,
6451 .help
= N_("retrieve vcpu count from the guest instead of the hypervisor")
6457 * Collect the number of vCPUs for a guest possibly with fallback means.
6459 * Returns the count of vCPUs for a domain and certain flags. Returns -2 in case
6460 * of error. If @checkState is true, in case live stats can't be collected when
6461 * the domain is inactive or persistent stats can't be collected if domain is
6462 * transient -1 is returned and no error is reported.
6466 virshCPUCountCollect(vshControl
*ctl
,
6474 xmlDocPtr xml
= NULL
;
6475 xmlXPathContextPtr ctxt
= NULL
;
6478 ((flags
& VIR_DOMAIN_AFFECT_LIVE
&& virDomainIsActive(dom
) < 1) ||
6479 (flags
& VIR_DOMAIN_AFFECT_CONFIG
&& virDomainIsPersistent(dom
) < 1)))
6482 /* In all cases, try the new API first; if it fails because we are talking
6483 * to an older daemon, generally we try a fallback API before giving up.
6484 * --current requires the new API, since we don't know whether the domain is
6485 * running or inactive. */
6486 if ((count
= virDomainGetVcpusFlags(dom
, flags
)) >= 0)
6490 if (!(last_error
->code
== VIR_ERR_NO_SUPPORT
||
6491 last_error
->code
== VIR_ERR_INVALID_ARG
))
6494 if (flags
& VIR_DOMAIN_VCPU_GUEST
) {
6495 vshError(ctl
, "%s", _("Failed to retrieve vCPU count from the guest"));
6499 if (!(flags
& (VIR_DOMAIN_AFFECT_LIVE
| VIR_DOMAIN_AFFECT_CONFIG
)) &&
6500 virDomainIsActive(dom
) == 1)
6501 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
6503 vshResetLibvirtError();
6505 if (flags
& VIR_DOMAIN_AFFECT_LIVE
) {
6506 if (flags
& VIR_DOMAIN_VCPU_MAXIMUM
) {
6507 count
= virDomainGetMaxVcpus(dom
);
6509 if (virDomainGetInfo(dom
, &info
) < 0)
6512 count
= info
.nrVirtCpu
;
6515 if (virshDomainGetXMLFromDom(ctl
, dom
, VIR_DOMAIN_XML_INACTIVE
,
6519 if (flags
& VIR_DOMAIN_VCPU_MAXIMUM
) {
6520 if (virXPathInt("string(/domain/vcpu)", ctxt
, &count
) < 0) {
6521 vshError(ctl
, "%s", _("Failed to retrieve maximum vcpu count"));
6525 if (virXPathInt("string(/domain/vcpu/@current)", ctxt
, &count
) < 0) {
6526 vshError(ctl
, "%s", _("Failed to retrieve current vcpu count"));
6534 xmlXPathFreeContext(ctxt
);
6541 cmdVcpucount(vshControl
*ctl
, const vshCmd
*cmd
)
6545 bool maximum
= vshCommandOptBool(cmd
, "maximum");
6546 bool active
= vshCommandOptBool(cmd
, "active");
6547 bool config
= vshCommandOptBool(cmd
, "config");
6548 bool live
= vshCommandOptBool(cmd
, "live");
6549 bool current
= vshCommandOptBool(cmd
, "current");
6550 bool guest
= vshCommandOptBool(cmd
, "guest");
6551 bool all
= maximum
+ active
+ current
+ config
+ live
+ guest
== 0;
6552 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
6554 /* Backwards compatibility: prior to 0.9.4,
6555 * VIR_DOMAIN_AFFECT_CURRENT was unsupported, and --current meant
6556 * the opposite of --maximum. Translate the old '--current
6557 * --live' into the new '--active --live', while treating the new
6558 * '--maximum --current' correctly rather than rejecting it as
6559 * '--maximum --active'. */
6560 if (!maximum
&& !active
&& current
)
6563 VSH_EXCLUSIVE_OPTIONS_VAR(live
, config
)
6564 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
6565 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
6566 VSH_EXCLUSIVE_OPTIONS_VAR(active
, maximum
);
6567 VSH_EXCLUSIVE_OPTIONS_VAR(guest
, config
);
6570 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
6572 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
6574 flags
|= VIR_DOMAIN_VCPU_MAXIMUM
;
6576 flags
|= VIR_DOMAIN_VCPU_GUEST
;
6578 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
6582 int conf_max
= virshCPUCountCollect(ctl
, dom
,
6583 VIR_DOMAIN_AFFECT_CONFIG
|
6584 VIR_DOMAIN_VCPU_MAXIMUM
, true);
6585 int conf_cur
= virshCPUCountCollect(ctl
, dom
,
6586 VIR_DOMAIN_AFFECT_CONFIG
, true);
6587 int live_max
= virshCPUCountCollect(ctl
, dom
,
6588 VIR_DOMAIN_AFFECT_LIVE
|
6589 VIR_DOMAIN_VCPU_MAXIMUM
, true);
6590 int live_cur
= virshCPUCountCollect(ctl
, dom
,
6591 VIR_DOMAIN_AFFECT_LIVE
, true);
6593 if (conf_max
== -2 || conf_cur
== -2 || live_max
== -2 || live_cur
== -2)
6596 #define PRINT_COUNT(VAR, WHICH, STATE) if (VAR > 0) \
6597 vshPrint(ctl, "%-12s %-12s %3d\n", WHICH, STATE, VAR)
6598 PRINT_COUNT(conf_max
, _("maximum"), _("config"));
6599 PRINT_COUNT(live_max
, _("maximum"), _("live"));
6600 PRINT_COUNT(conf_cur
, _("current"), _("config"));
6601 PRINT_COUNT(live_cur
, _("current"), _("live"));
6605 int count
= virshCPUCountCollect(ctl
, dom
, flags
, false);
6610 vshPrint(ctl
, "%d\n", count
);
6616 virshDomainFree(dom
);
6621 * "vcpuinfo" command
6623 static const vshCmdInfo info_vcpuinfo
[] = {
6625 .data
= N_("detailed domain vcpu information")
6628 .data
= N_("Returns basic information about the domain virtual CPUs.")
6633 static const vshCmdOptDef opts_vcpuinfo
[] = {
6634 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
6636 .type
= VSH_OT_BOOL
,
6637 .help
= N_("return human readable output")
6644 virshVcpuinfoPrintAffinity(vshControl
*ctl
,
6645 const unsigned char *cpumap
,
6653 vshPrint(ctl
, "%-15s ", _("CPU Affinity:"));
6655 if (!(str
= virBitmapDataFormat(cpumap
, VIR_CPU_MAPLEN(maxcpu
))))
6657 vshPrint(ctl
, _("%s (out of %d)"), str
, maxcpu
);
6659 for (i
= 0; i
< maxcpu
; i
++)
6660 vshPrint(ctl
, "%c", VIR_CPU_USED(cpumap
, i
) ? 'y' : '-');
6662 vshPrint(ctl
, "\n");
6673 virshDomainGetVcpuBitmap(vshControl
*ctl
,
6677 unsigned int flags
= 0;
6678 virBitmapPtr ret
= NULL
;
6679 xmlDocPtr xml
= NULL
;
6680 xmlXPathContextPtr ctxt
= NULL
;
6681 xmlNodePtr
*nodes
= NULL
;
6685 unsigned int curvcpus
= 0;
6686 unsigned int maxvcpus
= 0;
6687 unsigned int vcpuid
;
6688 char *online
= NULL
;
6691 flags
|= VIR_DOMAIN_XML_INACTIVE
;
6693 if (virshDomainGetXMLFromDom(ctl
, dom
, flags
, &xml
, &ctxt
) < 0)
6696 if (virXPathUInt("string(/domain/vcpu)", ctxt
, &maxvcpus
) < 0) {
6697 vshError(ctl
, "%s", _("Failed to retrieve maximum vcpu count"));
6701 ignore_value(virXPathUInt("string(/domain/vcpu/@current)", ctxt
, &curvcpus
));
6704 curvcpus
= maxvcpus
;
6706 if (!(ret
= virBitmapNew(maxvcpus
)))
6709 if ((nnodes
= virXPathNodeSet("/domain/vcpus/vcpu", ctxt
, &nodes
)) <= 0) {
6710 /* if the specific vcpu state is missing provide a fallback */
6711 for (i
= 0; i
< curvcpus
; i
++)
6712 ignore_value(virBitmapSetBit(ret
, i
));
6719 for (i
= 0; i
< nnodes
; i
++) {
6720 ctxt
->node
= nodes
[i
];
6722 if (virXPathUInt("string(@id)", ctxt
, &vcpuid
) < 0 ||
6723 !(online
= virXPathString("string(@enabled)", ctxt
)))
6726 if (STREQ(online
, "yes"))
6727 ignore_value(virBitmapSetBit(ret
, vcpuid
));
6734 if (virBitmapCountBits(ret
) != curvcpus
) {
6735 vshError(ctl
, "%s", _("Failed to retrieve vcpu state bitmap"));
6743 xmlXPathFreeContext(ctxt
);
6750 virshVcpuinfoInactive(vshControl
*ctl
,
6755 unsigned char *cpumaps
= NULL
;
6758 virBitmapPtr vcpus
= NULL
;
6759 ssize_t nextvcpu
= -1;
6763 if (!(vcpus
= virshDomainGetVcpuBitmap(ctl
, dom
, true)))
6766 cpumaplen
= VIR_CPU_MAPLEN(maxcpu
);
6767 cpumaps
= vshMalloc(ctl
, virBitmapSize(vcpus
) * cpumaplen
);
6769 if ((ncpus
= virDomainGetVcpuPinInfo(dom
, virBitmapSize(vcpus
),
6771 VIR_DOMAIN_AFFECT_CONFIG
)) < 0)
6774 while ((nextvcpu
= virBitmapNextSetBit(vcpus
, nextvcpu
)) >= 0) {
6776 vshPrint(ctl
, "\n");
6779 vshPrint(ctl
, "%-15s %zd\n", _("VCPU:"), nextvcpu
);
6780 vshPrint(ctl
, "%-15s %s\n", _("CPU:"), _("N/A"));
6781 vshPrint(ctl
, "%-15s %s\n", _("State:"), _("N/A"));
6782 vshPrint(ctl
, "%-15s %s\n", _("CPU time"), _("N/A"));
6784 if (virshVcpuinfoPrintAffinity(ctl
,
6785 VIR_GET_CPUMAP(cpumaps
, cpumaplen
, nextvcpu
),
6786 maxcpu
, pretty
) < 0)
6793 virBitmapFree(vcpus
);
6800 cmdVcpuinfo(vshControl
*ctl
, const vshCmd
*cmd
)
6804 virVcpuInfoPtr cpuinfo
= NULL
;
6805 unsigned char *cpumaps
= NULL
;
6809 bool pretty
= vshCommandOptBool(cmd
, "pretty");
6811 virshControlPtr priv
= ctl
->privData
;
6813 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
6816 if ((maxcpu
= virshNodeGetCPUCount(priv
->conn
)) < 0)
6819 if (virDomainGetInfo(dom
, &info
) != 0)
6822 cpuinfo
= vshMalloc(ctl
, sizeof(virVcpuInfo
)*info
.nrVirtCpu
);
6823 cpumaplen
= VIR_CPU_MAPLEN(maxcpu
);
6824 cpumaps
= vshMalloc(ctl
, info
.nrVirtCpu
* cpumaplen
);
6826 if ((ncpus
= virDomainGetVcpus(dom
,
6827 cpuinfo
, info
.nrVirtCpu
,
6828 cpumaps
, cpumaplen
)) < 0) {
6829 if (info
.state
!= VIR_DOMAIN_SHUTOFF
)
6832 vshResetLibvirtError();
6834 /* for offline VMs we can return pinning information */
6835 ret
= virshVcpuinfoInactive(ctl
, dom
, maxcpu
, pretty
);
6839 for (n
= 0; n
< ncpus
; n
++) {
6840 vshPrint(ctl
, "%-15s %d\n", _("VCPU:"), cpuinfo
[n
].number
);
6841 vshPrint(ctl
, "%-15s %d\n", _("CPU:"), cpuinfo
[n
].cpu
);
6842 vshPrint(ctl
, "%-15s %s\n", _("State:"),
6843 virshDomainVcpuStateToString(cpuinfo
[n
].state
));
6844 if (cpuinfo
[n
].cpuTime
!= 0) {
6845 double cpuUsed
= cpuinfo
[n
].cpuTime
;
6847 cpuUsed
/= 1000000000.0;
6849 vshPrint(ctl
, "%-15s %.1lfs\n", _("CPU time:"), cpuUsed
);
6852 if (virshVcpuinfoPrintAffinity(ctl
, VIR_GET_CPUMAP(cpumaps
, cpumaplen
, n
),
6853 maxcpu
, pretty
) < 0)
6856 if (n
< (ncpus
- 1))
6857 vshPrint(ctl
, "\n");
6865 virshDomainFree(dom
);
6872 static const vshCmdInfo info_vcpupin
[] = {
6874 .data
= N_("control or query domain vcpu affinity")
6877 .data
= N_("Pin domain VCPUs to host physical CPUs.")
6882 static const vshCmdOptDef opts_vcpupin
[] = {
6883 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
6886 .help
= N_("vcpu number")
6889 .type
= VSH_OT_STRING
,
6890 .flags
= VSH_OFLAG_EMPTY_OK
,
6891 .help
= N_("host cpu number(s) to set, or omit option to query")
6893 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
6894 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
6895 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
6900 * Helper function to print vcpupin info.
6903 virshPrintPinInfo(vshControl
*ctl
,
6904 unsigned char *cpumap
,
6909 if (!(str
= virBitmapDataFormat(cpumap
, cpumaplen
)))
6912 vshPrint(ctl
, "%s", str
);
6919 virshVcpuPinQuery(vshControl
*ctl
,
6926 unsigned char *cpumap
= NULL
;
6927 unsigned int countFlags
= flags
| VIR_DOMAIN_VCPU_MAXIMUM
;
6932 vshTablePtr table
= NULL
;
6934 if ((ncpus
= virshCPUCountCollect(ctl
, dom
, countFlags
, true)) < 0) {
6936 if (flags
& VIR_DOMAIN_AFFECT_LIVE
)
6937 vshError(ctl
, "%s", _("cannot get vcpupin for offline domain"));
6939 vshError(ctl
, "%s", _("cannot get vcpupin for transient domain"));
6944 if (got_vcpu
&& vcpu
>= ncpus
) {
6945 if (flags
& VIR_DOMAIN_AFFECT_LIVE
||
6946 (!(flags
& VIR_DOMAIN_AFFECT_CONFIG
) &&
6947 virDomainIsActive(dom
) == 1))
6949 _("vcpu %d is out of range of live cpu count %d"),
6953 _("vcpu %d is out of range of persistent cpu count %d"),
6958 cpumaplen
= VIR_CPU_MAPLEN(maxcpu
);
6959 cpumap
= vshMalloc(ctl
, ncpus
* cpumaplen
);
6960 if ((ncpus
= virDomainGetVcpuPinInfo(dom
, ncpus
, cpumap
,
6961 cpumaplen
, flags
)) >= 0) {
6962 table
= vshTableNew(_("VCPU"), _("CPU Affinity"), NULL
);
6966 for (i
= 0; i
< ncpus
; i
++) {
6967 VIR_AUTOFREE(char *) pinInfo
= NULL
;
6968 VIR_AUTOFREE(char *) vcpuStr
= NULL
;
6969 if (got_vcpu
&& i
!= vcpu
)
6972 if (!(pinInfo
= virBitmapDataFormat(VIR_GET_CPUMAP(cpumap
, cpumaplen
, i
),
6976 if (virAsprintf(&vcpuStr
, "%zu", i
) < 0)
6979 if (vshTableRowAppend(table
, vcpuStr
, pinInfo
, NULL
) < 0)
6983 vshTablePrintToStdout(table
, ctl
);
6988 vshTableFree(table
);
6994 static unsigned char *
6995 virshParseCPUList(vshControl
*ctl
, int *cpumaplen
,
6996 const char *cpulist
, int maxcpu
)
6998 unsigned char *cpumap
= NULL
;
6999 virBitmapPtr map
= NULL
;
7001 if (cpulist
[0] == 'r') {
7002 if (!(map
= virBitmapNew(maxcpu
)))
7004 virBitmapSetAll(map
);
7006 if (virBitmapParse(cpulist
, &map
, 1024) < 0 ||
7007 virBitmapIsAllClear(map
)) {
7008 vshError(ctl
, _("Invalid cpulist '%s'"), cpulist
);
7011 int lastcpu
= virBitmapLastSetBit(map
);
7012 if (lastcpu
>= maxcpu
) {
7013 vshError(ctl
, _("CPU %d in cpulist '%s' exceed the maxcpu %d"),
7014 lastcpu
, cpulist
, maxcpu
);
7019 if (virBitmapToData(map
, &cpumap
, cpumaplen
) < 0)
7028 cmdVcpuPin(vshControl
*ctl
, const vshCmd
*cmd
)
7031 unsigned int vcpu
= 0;
7032 const char *cpulist
= NULL
;
7034 unsigned char *cpumap
= NULL
;
7037 bool config
= vshCommandOptBool(cmd
, "config");
7038 bool live
= vshCommandOptBool(cmd
, "live");
7039 bool current
= vshCommandOptBool(cmd
, "current");
7041 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7042 virshControlPtr priv
= ctl
->privData
;
7044 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7045 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7048 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7050 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7052 if (vshCommandOptStringReq(ctl
, cmd
, "cpulist", &cpulist
) < 0)
7056 VSH_EXCLUSIVE_OPTIONS_VAR(live
, config
);
7058 if ((got_vcpu
= vshCommandOptUInt(ctl
, cmd
, "vcpu", &vcpu
)) < 0)
7061 /* In pin mode, "vcpu" is necessary */
7062 if (cpulist
&& got_vcpu
== 0) {
7063 vshError(ctl
, "%s", _("vcpupin: Missing vCPU number in pin mode."));
7067 if ((maxcpu
= virshNodeGetCPUCount(priv
->conn
)) < 0)
7070 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7073 /* Query mode: show CPU affinity information then exit.*/
7075 ret
= virshVcpuPinQuery(ctl
, dom
, vcpu
, got_vcpu
, maxcpu
, flags
);
7079 /* Pin mode: pinning specified vcpu to specified physical cpus*/
7080 if (!(cpumap
= virshParseCPUList(ctl
, &cpumaplen
, cpulist
, maxcpu
)))
7083 /* use old API without any explicit flags */
7084 if (flags
== VIR_DOMAIN_AFFECT_CURRENT
&& !current
) {
7085 if (virDomainPinVcpu(dom
, vcpu
, cpumap
, cpumaplen
) != 0)
7088 if (virDomainPinVcpuFlags(dom
, vcpu
, cpumap
, cpumaplen
, flags
) != 0)
7095 virshDomainFree(dom
);
7100 * "emulatorpin" command
7102 static const vshCmdInfo info_emulatorpin
[] = {
7104 .data
= N_("control or query domain emulator affinity")
7107 .data
= N_("Pin domain emulator threads to host physical CPUs.")
7112 static const vshCmdOptDef opts_emulatorpin
[] = {
7113 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7115 .type
= VSH_OT_STRING
,
7116 .flags
= VSH_OFLAG_EMPTY_OK
,
7117 .help
= N_("host cpu number(s) to set, or omit option to query")
7119 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7120 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7121 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7126 cmdEmulatorPin(vshControl
*ctl
, const vshCmd
*cmd
)
7129 const char *cpulist
= NULL
;
7131 unsigned char *cpumap
= NULL
;
7134 bool config
= vshCommandOptBool(cmd
, "config");
7135 bool live
= vshCommandOptBool(cmd
, "live");
7136 bool current
= vshCommandOptBool(cmd
, "current");
7137 bool query
= false; /* Query mode if no cpulist */
7138 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7139 virshControlPtr priv
= ctl
->privData
;
7141 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7142 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7145 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7147 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7148 /* none of the options were specified */
7149 if (!current
&& !live
&& !config
)
7152 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7155 if (vshCommandOptStringReq(ctl
, cmd
, "cpulist", &cpulist
) < 0) {
7156 virshDomainFree(dom
);
7161 if ((maxcpu
= virshNodeGetCPUCount(priv
->conn
)) < 0) {
7162 virshDomainFree(dom
);
7166 /* Query mode: show CPU affinity information then exit.*/
7168 /* When query mode and neither "live", "config" nor "current"
7169 * is specified, set VIR_DOMAIN_AFFECT_CURRENT as flags */
7171 flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7173 cpumaplen
= VIR_CPU_MAPLEN(maxcpu
);
7174 cpumap
= vshMalloc(ctl
, cpumaplen
);
7175 if (virDomainGetEmulatorPinInfo(dom
, cpumap
,
7176 cpumaplen
, flags
) >= 0) {
7177 vshPrintExtra(ctl
, "%s %s\n", _("emulator:"), _("CPU Affinity"));
7178 vshPrintExtra(ctl
, "----------------------------------\n");
7179 vshPrintExtra(ctl
, " *: ");
7180 ret
= virshPrintPinInfo(ctl
, cpumap
, cpumaplen
);
7181 vshPrint(ctl
, "\n");
7186 /* Pin mode: pinning emulator threads to specified physical cpus*/
7187 if (!(cpumap
= virshParseCPUList(ctl
, &cpumaplen
, cpulist
, maxcpu
)))
7191 flags
= VIR_DOMAIN_AFFECT_LIVE
;
7193 if (virDomainPinEmulator(dom
, cpumap
, cpumaplen
, flags
) != 0)
7199 virshDomainFree(dom
);
7204 * "setvcpus" command
7206 static const vshCmdInfo info_setvcpus
[] = {
7208 .data
= N_("change number of virtual CPUs")
7211 .data
= N_("Change the number of virtual CPUs in the guest domain.")
7216 static const vshCmdOptDef opts_setvcpus
[] = {
7217 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7220 .flags
= VSH_OFLAG_REQ
,
7221 .help
= N_("number of virtual CPUs")
7224 .type
= VSH_OT_BOOL
,
7225 .help
= N_("set maximum limit on next boot")
7227 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7228 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7229 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7231 .type
= VSH_OT_BOOL
,
7232 .help
= N_("modify cpu state in the guest")
7234 {.name
= "hotpluggable",
7235 .type
= VSH_OT_BOOL
,
7236 .help
= N_("make added vcpus hot(un)pluggable")
7242 cmdSetvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
7245 unsigned int count
= 0;
7247 bool maximum
= vshCommandOptBool(cmd
, "maximum");
7248 bool config
= vshCommandOptBool(cmd
, "config");
7249 bool live
= vshCommandOptBool(cmd
, "live");
7250 bool current
= vshCommandOptBool(cmd
, "current");
7251 bool guest
= vshCommandOptBool(cmd
, "guest");
7252 bool hotpluggable
= vshCommandOptBool(cmd
, "hotpluggable");
7253 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7255 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7256 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7257 VSH_EXCLUSIVE_OPTIONS_VAR(guest
, config
);
7259 VSH_REQUIRE_OPTION_VAR(maximum
, config
);
7262 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7264 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7266 flags
|= VIR_DOMAIN_VCPU_GUEST
;
7268 flags
|= VIR_DOMAIN_VCPU_MAXIMUM
;
7270 flags
|= VIR_DOMAIN_VCPU_HOTPLUGGABLE
;
7272 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7275 if (vshCommandOptUInt(ctl
, cmd
, "count", &count
) < 0)
7279 vshError(ctl
, _("Can't set 0 processors for a VM"));
7283 /* none of the options were specified */
7284 if (!current
&& flags
== 0) {
7285 if (virDomainSetVcpus(dom
, count
) != 0)
7288 if (virDomainSetVcpusFlags(dom
, count
, flags
) < 0)
7295 virshDomainFree(dom
);
7301 * "guestvcpus" command
7303 static const vshCmdInfo info_guestvcpus
[] = {
7305 .data
= N_("query or modify state of vcpu in the guest (via agent)")
7308 .data
= N_("Use the guest agent to query or set cpu state from guest's "
7314 static const vshCmdOptDef opts_guestvcpus
[] = {
7315 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
7317 .type
= VSH_OT_STRING
,
7318 .help
= N_("list of cpus to enable or disable")
7321 .type
= VSH_OT_BOOL
,
7322 .help
= N_("enable cpus specified by cpulist")
7325 .type
= VSH_OT_BOOL
,
7326 .help
= N_("disable cpus specified by cpulist")
7332 cmdGuestvcpus(vshControl
*ctl
, const vshCmd
*cmd
)
7335 bool enable
= vshCommandOptBool(cmd
, "enable");
7336 bool disable
= vshCommandOptBool(cmd
, "disable");
7337 virTypedParameterPtr params
= NULL
;
7338 unsigned int nparams
= 0;
7339 const char *cpulist
= NULL
;
7344 VSH_EXCLUSIVE_OPTIONS_VAR(enable
, disable
);
7345 VSH_REQUIRE_OPTION("enable", "cpulist");
7346 VSH_REQUIRE_OPTION("disable", "cpulist");
7348 if (vshCommandOptStringReq(ctl
, cmd
, "cpulist", &cpulist
))
7351 if (cpulist
&& !(enable
|| disable
)) {
7352 vshError(ctl
, _("One of options --enable or --disable is required by "
7353 "option --cpulist"));
7357 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7364 if (virDomainSetGuestVcpus(dom
, cpulist
, state
, 0) < 0)
7367 if (virDomainGetGuestVcpus(dom
, ¶ms
, &nparams
, 0) < 0)
7370 for (i
= 0; i
< nparams
; i
++) {
7371 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
7372 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
7380 virTypedParamsFree(params
, nparams
);
7381 virshDomainFree(dom
);
7389 static const vshCmdInfo info_setvcpu
[] = {
7391 .data
= N_("attach/detach vcpu or groups of threads")
7394 .data
= N_("Add or remove vcpus")
7399 static const vshCmdOptDef opts_setvcpu
[] = {
7400 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7401 {.name
= "vcpulist",
7402 .type
= VSH_OT_DATA
,
7403 .flags
= VSH_OFLAG_REQ
,
7404 .help
= N_("ids of vcpus to manipulate")
7407 .type
= VSH_OT_BOOL
,
7408 .help
= N_("enable cpus specified by cpumap")
7411 .type
= VSH_OT_BOOL
,
7412 .help
= N_("disable cpus specified by cpumap")
7414 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7415 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7416 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7421 cmdSetvcpu(vshControl
*ctl
, const vshCmd
*cmd
)
7424 bool enable
= vshCommandOptBool(cmd
, "enable");
7425 bool disable
= vshCommandOptBool(cmd
, "disable");
7426 bool config
= vshCommandOptBool(cmd
, "config");
7427 bool live
= vshCommandOptBool(cmd
, "live");
7428 const char *vcpulist
= NULL
;
7431 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7433 VSH_EXCLUSIVE_OPTIONS_VAR(enable
, disable
);
7435 VSH_EXCLUSIVE_OPTIONS("current", "live");
7436 VSH_EXCLUSIVE_OPTIONS("current", "config");
7439 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7441 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7443 if (!(enable
|| disable
)) {
7444 vshError(ctl
, "%s", _("one of --enable, --disable is required"));
7448 if (vshCommandOptStringReq(ctl
, cmd
, "vcpulist", &vcpulist
))
7451 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7457 if (virDomainSetVcpu(dom
, vcpulist
, state
, flags
) < 0)
7463 virshDomainFree(dom
);
7469 * "domblkthreshold" command
7471 static const vshCmdInfo info_domblkthreshold
[] = {
7473 .data
= N_("set the threshold for block-threshold event for a given block "
7474 "device or it's backing chain element")
7477 .data
= N_("set threshold for block-threshold event for a block device")
7482 static const vshCmdOptDef opts_domblkthreshold
[] = {
7483 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
7485 .type
= VSH_OT_DATA
,
7486 .flags
= VSH_OFLAG_REQ
,
7487 .completer
= virshDomainDiskTargetCompleter
,
7488 .help
= N_("device to set threshold for")
7490 {.name
= "threshold",
7492 .flags
= VSH_OFLAG_REQ
,
7493 .help
= N_("threshold as a scaled number (by default bytes)")
7499 cmdDomblkthreshold(vshControl
*ctl
, const vshCmd
*cmd
)
7501 unsigned long long threshold
;
7502 const char *dev
= NULL
;
7506 if (vshCommandOptStringReq(ctl
, cmd
, "dev", &dev
))
7509 if (vshCommandOptScaledInt(ctl
, cmd
, "threshold",
7510 &threshold
, 1, ULLONG_MAX
) < 0)
7513 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7516 if (virDomainSetBlockThreshold(dom
, dev
, threshold
, 0) < 0)
7522 virshDomainFree(dom
);
7528 * "iothreadinfo" command
7530 static const vshCmdInfo info_iothreadinfo
[] = {
7532 .data
= N_("view domain IOThreads")
7535 .data
= N_("Returns basic information about the domain IOThreads.")
7539 static const vshCmdOptDef opts_iothreadinfo
[] = {
7540 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7541 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7542 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7543 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7548 cmdIOThreadInfo(vshControl
*ctl
, const vshCmd
*cmd
)
7551 bool config
= vshCommandOptBool(cmd
, "config");
7552 bool live
= vshCommandOptBool(cmd
, "live");
7553 bool current
= vshCommandOptBool(cmd
, "current");
7554 size_t niothreads
= 0;
7555 virDomainIOThreadInfoPtr
*info
= NULL
;
7557 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7558 vshTablePtr table
= NULL
;
7562 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7563 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7566 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7568 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7570 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7573 if ((rc
= virDomainGetIOThreadInfo(dom
, &info
, flags
)) < 0) {
7574 vshError(ctl
, _("Unable to get domain IOThreads information"));
7579 if (niothreads
== 0) {
7581 vshPrintExtra(ctl
, _("No IOThreads found for the domain"));
7585 table
= vshTableNew(_("IOThread ID"), _("CPU Affinity"), NULL
);
7589 for (i
= 0; i
< niothreads
; i
++) {
7590 VIR_AUTOFREE(char *) pinInfo
= NULL
;
7591 VIR_AUTOFREE(char *) iothreadIdStr
= NULL
;
7593 if (virAsprintf(&iothreadIdStr
, "%u", info
[i
]->iothread_id
) < 0)
7596 ignore_value(pinInfo
= virBitmapDataFormat(info
[i
]->cpumap
, info
[i
]->cpumaplen
));
7598 if (vshTableRowAppend(table
, iothreadIdStr
, pinInfo
? pinInfo
: "", NULL
) < 0)
7602 vshTablePrintToStdout(table
, ctl
);
7607 for (i
= 0; i
< niothreads
; i
++)
7608 virDomainIOThreadInfoFree(info
[i
]);
7610 vshTableFree(table
);
7611 virshDomainFree(dom
);
7616 * "iothreadpin" command
7618 static const vshCmdInfo info_iothreadpin
[] = {
7620 .data
= N_("control domain IOThread affinity")
7623 .data
= N_("Pin domain IOThreads to host physical CPUs.")
7628 static const vshCmdOptDef opts_iothreadpin
[] = {
7629 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7630 {.name
= "iothread",
7632 .flags
= VSH_OFLAG_REQ
,
7633 .help
= N_("IOThread ID number")
7636 .type
= VSH_OT_DATA
,
7637 .flags
= VSH_OFLAG_REQ
,
7638 .help
= N_("host cpu number(s) to set")
7640 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7641 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7642 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7647 cmdIOThreadPin(vshControl
*ctl
, const vshCmd
*cmd
)
7650 const char *cpulist
= NULL
;
7651 bool config
= vshCommandOptBool(cmd
, "config");
7652 bool live
= vshCommandOptBool(cmd
, "live");
7653 bool current
= vshCommandOptBool(cmd
, "current");
7654 unsigned int iothread_id
= 0;
7657 unsigned char *cpumap
= NULL
;
7659 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7660 virshControlPtr priv
= ctl
->privData
;
7662 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7663 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7666 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7668 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7670 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7673 if (vshCommandOptUInt(ctl
, cmd
, "iothread", &iothread_id
) < 0)
7676 if (vshCommandOptStringReq(ctl
, cmd
, "cpulist", &cpulist
) < 0)
7679 if ((maxcpu
= virshNodeGetCPUCount(priv
->conn
)) < 0)
7682 if (!(cpumap
= virshParseCPUList(ctl
, &cpumaplen
, cpulist
, maxcpu
)))
7685 if (virDomainPinIOThread(dom
, iothread_id
,
7686 cpumap
, cpumaplen
, flags
) != 0)
7693 virshDomainFree(dom
);
7698 * "iothreadadd" command
7700 static const vshCmdInfo info_iothreadadd
[] = {
7702 .data
= N_("add an IOThread to the guest domain")
7705 .data
= N_("Add an IOThread to the guest domain.")
7710 static const vshCmdOptDef opts_iothreadadd
[] = {
7711 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7714 .flags
= VSH_OFLAG_REQ
,
7715 .help
= N_("iothread for the new IOThread")
7717 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7718 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7719 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7724 cmdIOThreadAdd(vshControl
*ctl
, const vshCmd
*cmd
)
7727 int iothread_id
= 0;
7729 bool config
= vshCommandOptBool(cmd
, "config");
7730 bool live
= vshCommandOptBool(cmd
, "live");
7731 bool current
= vshCommandOptBool(cmd
, "current");
7732 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7734 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7735 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7738 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7740 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7742 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7745 if (vshCommandOptInt(ctl
, cmd
, "id", &iothread_id
) < 0)
7747 if (iothread_id
<= 0) {
7748 vshError(ctl
, _("Invalid IOThread id value: '%d'"), iothread_id
);
7752 if (virDomainAddIOThread(dom
, iothread_id
, flags
) < 0)
7758 virshDomainFree(dom
);
7764 * "iothreadset" command
7766 static const vshCmdInfo info_iothreadset
[] = {
7768 .data
= N_("modifies an existing IOThread of the guest domain")
7771 .data
= N_("Modifies an existing IOThread of the guest domain.")
7776 static const vshCmdOptDef opts_iothreadset
[] = {
7777 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7780 .flags
= VSH_OFLAG_REQ
,
7781 .help
= N_("iothread id of existing IOThread")
7783 {.name
= "poll-max-ns",
7785 .help
= N_("set the maximum IOThread polling time in ns")
7787 {.name
= "poll-grow",
7789 .help
= N_("set the value to increase the IOThread polling time")
7791 {.name
= "poll-shrink",
7793 .help
= N_("set the value for reduction of the IOThread polling time ")
7795 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7796 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7801 cmdIOThreadSet(vshControl
*ctl
, const vshCmd
*cmd
)
7806 bool live
= vshCommandOptBool(cmd
, "live");
7807 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7808 virTypedParameterPtr params
= NULL
;
7811 unsigned long long poll_max
;
7812 unsigned int poll_val
;
7816 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7818 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7821 if (vshCommandOptInt(ctl
, cmd
, "id", &id
) < 0)
7824 vshError(ctl
, _("Invalid IOThread id value: '%d'"), id
);
7829 if ((rc
= vshCommandOptULongLong(ctl
, cmd
, "poll-max-ns", &poll_max
)) < 0)
7831 if (rc
> 0 && virTypedParamsAddULLong(¶ms
, &nparams
, &maxparams
,
7832 VIR_DOMAIN_IOTHREAD_POLL_MAX_NS
,
7836 #define VSH_IOTHREAD_SET_UINT_PARAMS(opt, param) \
7838 if ((rc = vshCommandOptUInt(ctl, cmd, opt, &poll_val)) < 0) \
7841 virTypedParamsAddUInt(¶ms, &nparams, &maxparams, \
7842 param, poll_val) < 0) \
7845 VSH_IOTHREAD_SET_UINT_PARAMS("poll-grow", VIR_DOMAIN_IOTHREAD_POLL_GROW
)
7846 VSH_IOTHREAD_SET_UINT_PARAMS("poll-shrink", VIR_DOMAIN_IOTHREAD_POLL_SHRINK
)
7848 #undef VSH_IOTHREAD_SET_UINT_PARAMS
7850 if (virDomainSetIOThreadParams(dom
, id
, params
, nparams
, flags
) < 0)
7856 virTypedParamsFree(params
, nparams
);
7857 virshDomainFree(dom
);
7861 vshSaveLibvirtError();
7867 * "iothreaddel" command
7869 static const vshCmdInfo info_iothreaddel
[] = {
7871 .data
= N_("delete an IOThread from the guest domain")
7874 .data
= N_("Delete an IOThread from the guest domain.")
7879 static const vshCmdOptDef opts_iothreaddel
[] = {
7880 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
7883 .flags
= VSH_OFLAG_REQ
,
7884 .help
= N_("iothread_id for the IOThread to delete")
7886 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
7887 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
7888 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
7893 cmdIOThreadDel(vshControl
*ctl
, const vshCmd
*cmd
)
7896 int iothread_id
= 0;
7898 bool config
= vshCommandOptBool(cmd
, "config");
7899 bool live
= vshCommandOptBool(cmd
, "live");
7900 bool current
= vshCommandOptBool(cmd
, "current");
7901 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
7903 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
7904 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
7907 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
7909 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
7911 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7914 if (vshCommandOptInt(ctl
, cmd
, "id", &iothread_id
) < 0)
7916 if (iothread_id
<= 0) {
7917 vshError(ctl
, _("Invalid IOThread id value: '%d'"), iothread_id
);
7921 if (virDomainDelIOThread(dom
, iothread_id
, flags
) < 0)
7927 virshDomainFree(dom
);
7932 * "cpu-stats" command
7934 static const vshCmdInfo info_cpu_stats
[] = {
7936 .data
= N_("show domain cpu statistics")
7939 .data
= N_("Display per-CPU and total statistics about the domain's CPUs")
7944 static const vshCmdOptDef opts_cpu_stats
[] = {
7945 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
7947 .type
= VSH_OT_BOOL
,
7948 .help
= N_("Show total statistics only")
7952 .help
= N_("Show statistics from this CPU")
7956 .help
= N_("Number of shown CPUs at most")
7962 vshCPUStatsPrintField(vshControl
*ctl
,
7963 virTypedParameterPtr param
)
7965 vshPrint(ctl
, "\t%-12s ", param
->field
);
7966 if ((STREQ(param
->field
, VIR_DOMAIN_CPU_STATS_CPUTIME
) ||
7967 STREQ(param
->field
, VIR_DOMAIN_CPU_STATS_VCPUTIME
) ||
7968 STREQ(param
->field
, VIR_DOMAIN_CPU_STATS_USERTIME
) ||
7969 STREQ(param
->field
, VIR_DOMAIN_CPU_STATS_SYSTEMTIME
)) &&
7970 param
->type
== VIR_TYPED_PARAM_ULLONG
) {
7971 vshPrint(ctl
, "%9lld.%09lld seconds\n",
7972 param
->value
.ul
/ 1000000000,
7973 param
->value
.ul
% 1000000000);
7975 char *s
= vshGetTypedParamValue(ctl
, param
);
7976 vshPrint(ctl
, "%s\n", s
);
7982 cmdCPUStats(vshControl
*ctl
, const vshCmd
*cmd
)
7985 virTypedParameterPtr params
= NULL
;
7986 int max_id
, cpu
= 0, show_count
= -1, nparams
= 0, stats_per_cpu
;
7988 bool show_total
= false, show_per_cpu
= false;
7992 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
7995 show_total
= vshCommandOptBool(cmd
, "total");
7997 if ((rv
= vshCommandOptInt(ctl
, cmd
, "start", &cpu
)) < 0) {
7999 } else if (rv
> 0) {
8001 vshError(ctl
, "%s", _("Invalid value for start CPU"));
8004 show_per_cpu
= true;
8007 if ((rv
= vshCommandOptInt(ctl
, cmd
, "count", &show_count
)) < 0) {
8009 } else if (rv
> 0) {
8010 if (show_count
< 0) {
8011 vshError(ctl
, "%s", _("Invalid value for number of CPUs to show"));
8014 show_per_cpu
= true;
8017 /* default show per_cpu and total */
8018 if (!show_total
&& !show_per_cpu
) {
8020 show_per_cpu
= true;
8023 if (!show_per_cpu
) /* show total stats only */
8026 /* get number of cpus on the node */
8027 if ((max_id
= virDomainGetCPUStats(dom
, NULL
, 0, 0, 0, 0)) < 0)
8030 if (cpu
>= max_id
) {
8031 vshError(ctl
, "Start CPU %d is out of range (min: 0, max: %d)",
8036 if (show_count
< 0 || show_count
> max_id
) {
8037 if (show_count
> max_id
)
8038 vshPrint(ctl
, _("Only %d CPUs available to show\n"), max_id
);
8039 show_count
= max_id
- cpu
;
8042 /* get percpu information */
8043 if ((nparams
= virDomainGetCPUStats(dom
, NULL
, 0, 0, 1, 0)) < 0)
8047 vshPrint(ctl
, "%s", _("No per-CPU stats available"));
8053 if (VIR_ALLOC_N(params
, nparams
* MIN(show_count
, 128)) < 0)
8056 while (show_count
) {
8057 int ncpus
= MIN(show_count
, 128);
8059 if (virDomainGetCPUStats(dom
, params
, nparams
, cpu
, ncpus
, 0) < 0)
8062 for (i
= 0; i
< ncpus
; i
++) {
8063 if (params
[i
* nparams
].type
== 0) /* this cpu is not in the map */
8065 vshPrint(ctl
, "CPU%zu:\n", cpu
+ i
);
8067 for (j
= 0; j
< nparams
; j
++)
8068 vshCPUStatsPrintField(ctl
, params
+ (i
* nparams
+ j
));
8071 show_count
-= ncpus
;
8072 virTypedParamsClear(params
, nparams
* ncpus
);
8082 /* get supported num of parameter for total statistics */
8083 if ((nparams
= virDomainGetCPUStats(dom
, NULL
, 0, -1, 1, 0)) < 0)
8087 vshPrint(ctl
, "%s", _("No total stats available"));
8091 if (VIR_ALLOC_N(params
, nparams
) < 0)
8094 /* passing start_cpu == -1 gives us domain's total status */
8095 if ((stats_per_cpu
= virDomainGetCPUStats(dom
, params
, nparams
,
8099 vshPrint(ctl
, _("Total:\n"));
8100 for (i
= 0; i
< stats_per_cpu
; i
++)
8101 vshCPUStatsPrintField(ctl
, params
+ i
);
8106 virTypedParamsFree(params
, nparams
);
8107 virshDomainFree(dom
);
8111 vshError(ctl
, _("Failed to retrieve CPU statistics for domain '%s'"),
8112 virDomainGetName(dom
));
8119 static const vshCmdInfo info_create
[] = {
8121 .data
= N_("create a domain from an XML file")
8124 .data
= N_("Create a domain.")
8129 static const vshCmdOptDef opts_create
[] = {
8130 VIRSH_COMMON_OPT_FILE(N_("file containing an XML domain description")),
8133 .type
= VSH_OT_BOOL
,
8134 .help
= N_("attach to console after creation")
8138 .type
= VSH_OT_BOOL
,
8139 .help
= N_("leave the guest paused after creation")
8141 {.name
= "autodestroy",
8142 .type
= VSH_OT_BOOL
,
8143 .help
= N_("automatically destroy the guest when virsh disconnects")
8145 {.name
= "pass-fds",
8146 .type
= VSH_OT_STRING
,
8147 .help
= N_("pass file descriptors N,M,... to the guest")
8149 {.name
= "validate",
8150 .type
= VSH_OT_BOOL
,
8151 .help
= N_("validate the XML against the schema")
8157 cmdCreate(vshControl
*ctl
, const vshCmd
*cmd
)
8160 const char *from
= NULL
;
8164 bool console
= vshCommandOptBool(cmd
, "console");
8166 unsigned int flags
= 0;
8169 virshControlPtr priv
= ctl
->privData
;
8171 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
8174 if (virFileReadAll(from
, VSH_MAX_XML_FILE
, &buffer
) < 0)
8177 if (cmdStartGetFDs(ctl
, cmd
, &nfds
, &fds
) < 0)
8180 if (vshCommandOptBool(cmd
, "paused"))
8181 flags
|= VIR_DOMAIN_START_PAUSED
;
8182 if (vshCommandOptBool(cmd
, "autodestroy"))
8183 flags
|= VIR_DOMAIN_START_AUTODESTROY
;
8184 if (vshCommandOptBool(cmd
, "validate"))
8185 flags
|= VIR_DOMAIN_START_VALIDATE
;
8188 dom
= virDomainCreateXMLWithFiles(priv
->conn
, buffer
, nfds
, fds
, flags
);
8190 dom
= virDomainCreateXML(priv
->conn
, buffer
, flags
);
8193 vshError(ctl
, _("Failed to create domain from %s"), from
);
8197 vshPrintExtra(ctl
, _("Domain %s created from %s\n"),
8198 virDomainGetName(dom
), from
);
8201 cmdRunConsole(ctl
, dom
, NULL
, 0);
8203 virshDomainFree(dom
);
8215 static const vshCmdInfo info_define
[] = {
8217 .data
= N_("define (but don't start) a domain from an XML file")
8220 .data
= N_("Define a domain.")
8225 static const vshCmdOptDef opts_define
[] = {
8226 VIRSH_COMMON_OPT_FILE(N_("file containing an XML domain description")),
8227 {.name
= "validate",
8228 .type
= VSH_OT_BOOL
,
8229 .help
= N_("validate the XML against the schema")
8235 cmdDefine(vshControl
*ctl
, const vshCmd
*cmd
)
8238 const char *from
= NULL
;
8241 unsigned int flags
= 0;
8242 virshControlPtr priv
= ctl
->privData
;
8244 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
8247 if (vshCommandOptBool(cmd
, "validate"))
8248 flags
|= VIR_DOMAIN_DEFINE_VALIDATE
;
8250 if (virFileReadAll(from
, VSH_MAX_XML_FILE
, &buffer
) < 0)
8254 dom
= virDomainDefineXMLFlags(priv
->conn
, buffer
, flags
);
8256 dom
= virDomainDefineXML(priv
->conn
, buffer
);
8260 vshPrintExtra(ctl
, _("Domain %s defined from %s\n"),
8261 virDomainGetName(dom
), from
);
8262 virshDomainFree(dom
);
8264 vshError(ctl
, _("Failed to define domain from %s"), from
);
8273 static const vshCmdInfo info_destroy
[] = {
8275 .data
= N_("destroy (stop) a domain")
8278 .data
= N_("Forcefully stop a given domain, but leave its resources intact.")
8283 static const vshCmdOptDef opts_destroy
[] = {
8284 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
8285 {.name
= "graceful",
8286 .type
= VSH_OT_BOOL
,
8287 .help
= N_("terminate gracefully")
8293 cmdDestroy(vshControl
*ctl
, const vshCmd
*cmd
)
8298 unsigned int flags
= 0;
8301 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, &name
)))
8304 if (vshCommandOptBool(cmd
, "graceful"))
8305 flags
|= VIR_DOMAIN_DESTROY_GRACEFUL
;
8308 result
= virDomainDestroyFlags(dom
, VIR_DOMAIN_DESTROY_GRACEFUL
);
8310 result
= virDomainDestroy(dom
);
8313 vshPrintExtra(ctl
, _("Domain %s destroyed\n"), name
);
8315 vshError(ctl
, _("Failed to destroy domain %s"), name
);
8319 virshDomainFree(dom
);
8324 * "desc" command for managing domain description and title
8326 static const vshCmdInfo info_desc
[] = {
8328 .data
= N_("show or set domain's description or title")
8331 .data
= N_("Allows setting or modifying the description or title of "
8337 static const vshCmdOptDef opts_desc
[] = {
8338 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
8339 VIRSH_COMMON_OPT_LIVE(N_("modify/get running state")),
8340 VIRSH_COMMON_OPT_CONFIG(N_("modify/get persistent configuration")),
8341 VIRSH_COMMON_OPT_CURRENT(N_("modify/get current state configuration")),
8343 .type
= VSH_OT_BOOL
,
8344 .help
= N_("modify/get the title instead of description")
8347 .type
= VSH_OT_BOOL
,
8348 .help
= N_("open an editor to modify the description")
8350 {.name
= "new-desc",
8351 .type
= VSH_OT_ARGV
,
8352 .help
= N_("message")
8358 cmdDesc(vshControl
*ctl
, const vshCmd
*cmd
)
8361 bool config
= vshCommandOptBool(cmd
, "config");
8362 bool live
= vshCommandOptBool(cmd
, "live");
8363 bool current
= vshCommandOptBool(cmd
, "current");
8365 bool title
= vshCommandOptBool(cmd
, "title");
8366 bool edit
= vshCommandOptBool(cmd
, "edit");
8371 char *desc_edited
= NULL
;
8374 const vshCmdOpt
*opt
= NULL
;
8375 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
8377 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
8379 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
8380 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
8383 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
8385 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
8387 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8390 if ((state
= virshDomainState(ctl
, dom
, NULL
)) < 0)
8394 type
= VIR_DOMAIN_METADATA_TITLE
;
8396 type
= VIR_DOMAIN_METADATA_DESCRIPTION
;
8398 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
)))
8399 virBufferAsprintf(&buf
, "%s ", opt
->data
);
8401 virBufferTrim(&buf
, " ", -1);
8403 if (virBufferError(&buf
)) {
8404 vshError(ctl
, "%s", _("Failed to collect new description/title"));
8407 desc
= virBufferContentAndReset(&buf
);
8411 desc
= virshGetDomainDescription(ctl
, dom
, title
,
8412 config
?VIR_DOMAIN_XML_INACTIVE
:0);
8418 /* Create and open the temporary file. */
8419 if (!(tmp
= vshEditWriteToTempFile(ctl
, desc
)))
8422 /* Start the editor. */
8423 if (vshEditFile(ctl
, tmp
) == -1)
8426 /* Read back the edited file. */
8427 if (!(desc_edited
= vshEditReadBackFile(ctl
, tmp
)))
8430 /* strip a possible newline at the end of file; some
8431 * editors enforce a newline, this makes editing the title
8432 * more convenient */
8434 (tmpstr
= strrchr(desc_edited
, '\n')) &&
8435 *(tmpstr
+1) == '\0')
8438 /* Compare original XML with edited. Has it changed at all? */
8439 if (STREQ(desc
, desc_edited
)) {
8440 vshPrintExtra(ctl
, "%s",
8441 title
? _("Domain title not changed\n") :
8442 _("Domain description not changed\n"));
8448 VIR_STEAL_PTR(desc
, desc_edited
);
8451 if (virDomainSetMetadata(dom
, type
, desc
, NULL
, NULL
, flags
) < 0) {
8453 title
? _("Failed to set new domain title") :
8454 _("Failed to set new domain description"));
8457 vshPrintExtra(ctl
, "%s",
8458 title
? _("Domain title updated successfully") :
8459 _("Domain description updated successfully"));
8461 desc
= virshGetDomainDescription(ctl
, dom
, title
,
8462 config
?VIR_DOMAIN_XML_INACTIVE
:0);
8466 if (strlen(desc
) > 0)
8467 vshPrint(ctl
, "%s", desc
);
8470 title
? _("No title for domain: %s") :
8471 _("No description for domain: %s"),
8472 virDomainGetName(dom
));
8477 VIR_FREE(desc_edited
);
8483 virshDomainFree(dom
);
8488 static const vshCmdInfo info_metadata
[] = {
8490 .data
= N_("show or set domain's custom XML metadata")
8493 .data
= N_("Shows or modifies the XML metadata of a domain.")
8498 static const vshCmdOptDef opts_metadata
[] = {
8499 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
8501 .type
= VSH_OT_DATA
,
8502 .flags
= VSH_OFLAG_REQ
,
8503 .help
= N_("URI of the namespace")
8505 VIRSH_COMMON_OPT_LIVE(N_("modify/get running state")),
8506 VIRSH_COMMON_OPT_CONFIG(N_("modify/get persistent configuration")),
8507 VIRSH_COMMON_OPT_CURRENT(N_("modify/get current state configuration")),
8509 .type
= VSH_OT_BOOL
,
8510 .help
= N_("use an editor to change the metadata")
8513 .type
= VSH_OT_STRING
,
8514 .help
= N_("key to be used as a namespace identifier"),
8517 .type
= VSH_OT_STRING
,
8518 .help
= N_("new metadata to set"),
8521 .type
= VSH_OT_BOOL
,
8522 .help
= N_("remove the metadata corresponding to an uri")
8528 /* helper to add new metadata using the --edit option */
8530 virshDomainGetEditMetadata(vshControl
*ctl
,
8537 if (!(ret
= virDomainGetMetadata(dom
, VIR_DOMAIN_METADATA_ELEMENT
,
8539 vshResetLibvirtError();
8540 ret
= vshStrdup(ctl
, "\n");
8548 cmdMetadata(vshControl
*ctl
, const vshCmd
*cmd
)
8551 bool config
= vshCommandOptBool(cmd
, "config");
8552 bool live
= vshCommandOptBool(cmd
, "live");
8553 bool current
= vshCommandOptBool(cmd
, "current");
8554 bool edit
= vshCommandOptBool(cmd
, "edit");
8555 bool rem
= vshCommandOptBool(cmd
, "remove");
8556 const char *set
= NULL
;
8557 const char *uri
= NULL
;
8558 const char *key
= NULL
;
8559 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
8562 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
8563 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
8564 VSH_EXCLUSIVE_OPTIONS("edit", "set");
8565 VSH_EXCLUSIVE_OPTIONS("remove", "set");
8566 VSH_EXCLUSIVE_OPTIONS("remove", "edit");
8569 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
8571 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
8573 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8576 if (vshCommandOptStringReq(ctl
, cmd
, "uri", &uri
) < 0 ||
8577 vshCommandOptStringReq(ctl
, cmd
, "key", &key
) < 0 ||
8578 vshCommandOptStringReq(ctl
, cmd
, "set", &set
) < 0)
8581 if ((set
|| edit
) && !key
) {
8583 _("namespace key is required when modifying metadata"));
8588 if (virDomainSetMetadata(dom
, VIR_DOMAIN_METADATA_ELEMENT
,
8589 set
, key
, uri
, flags
))
8593 vshPrintExtra(ctl
, "%s\n", _("Metadata removed"));
8595 vshPrintExtra(ctl
, "%s\n", _("Metadata modified"));
8597 #define EDIT_GET_XML \
8598 virshDomainGetEditMetadata(ctl, dom, uri, flags)
8599 #define EDIT_NOT_CHANGED \
8601 vshPrintExtra(ctl, "%s", _("Metadata not changed")); \
8603 goto edit_cleanup; \
8606 #define EDIT_DEFINE \
8607 (virDomainSetMetadata(dom, VIR_DOMAIN_METADATA_ELEMENT, doc_edited, \
8608 key, uri, flags) == 0)
8609 #include "virsh-edit.c"
8611 vshPrintExtra(ctl
, "%s\n", _("Metadata modified"));
8615 if (!(data
= virDomainGetMetadata(dom
, VIR_DOMAIN_METADATA_ELEMENT
,
8619 vshPrint(ctl
, "%s\n", data
);
8626 virshDomainFree(dom
);
8632 * "inject-nmi" command
8634 static const vshCmdInfo info_inject_nmi
[] = {
8636 .data
= N_("Inject NMI to the guest")
8639 .data
= N_("Inject NMI to the guest domain.")
8644 static const vshCmdOptDef opts_inject_nmi
[] = {
8645 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
8650 cmdInjectNMI(vshControl
*ctl
, const vshCmd
*cmd
)
8655 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8658 if (virDomainInjectNMI(dom
, 0) < 0)
8661 virshDomainFree(dom
);
8666 * "send-key" command
8668 static const vshCmdInfo info_send_key
[] = {
8670 .data
= N_("Send keycodes to the guest")
8673 .data
= N_("Send keycodes (integers or symbolic names) to the guest")
8678 static const vshCmdOptDef opts_send_key
[] = {
8679 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
8681 .type
= VSH_OT_STRING
,
8682 .flags
= VSH_OFLAG_REQ_OPT
,
8683 .help
= N_("the codeset of keycodes, default:linux")
8685 {.name
= "holdtime",
8687 .flags
= VSH_OFLAG_REQ_OPT
,
8688 .help
= N_("the time (in milliseconds) how long the keys will be held")
8691 .type
= VSH_OT_ARGV
,
8692 .flags
= VSH_OFLAG_REQ
,
8693 .help
= N_("the key code")
8699 virshKeyCodeGetInt(const char *key_name
)
8703 if (virStrToLong_uip(key_name
, NULL
, 0, &val
) < 0 || val
> 0xffff)
8709 cmdSendKey(vshControl
*ctl
, const vshCmd
*cmd
)
8713 const char *codeset_option
;
8715 unsigned int holdtime
= 0;
8717 const vshCmdOpt
*opt
= NULL
;
8719 unsigned int keycodes
[VIR_DOMAIN_SEND_KEY_MAX_KEYS
];
8721 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8724 if (vshCommandOptStringQuiet(ctl
, cmd
, "codeset", &codeset_option
) <= 0)
8725 codeset_option
= "linux";
8727 if (vshCommandOptUInt(ctl
, cmd
, "holdtime", &holdtime
) < 0)
8730 /* The qnum codeset was originally called rfb, so we need to keep
8731 * accepting the old name for backwards compatibility reasons */
8732 if (STREQ(codeset_option
, "rfb"))
8733 codeset_option
= "qnum";
8735 codeset
= virKeycodeSetTypeFromString(codeset_option
);
8737 vshError(ctl
, _("unknown codeset: '%s'"), codeset_option
);
8741 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
))) {
8742 if (count
== VIR_DOMAIN_SEND_KEY_MAX_KEYS
) {
8743 vshError(ctl
, _("too many keycodes"));
8747 if ((keycode
= virshKeyCodeGetInt(opt
->data
)) < 0) {
8748 if ((keycode
= virKeycodeValueFromString(codeset
, opt
->data
)) < 0) {
8749 vshError(ctl
, _("invalid keycode: '%s'"), opt
->data
);
8754 keycodes
[count
] = keycode
;
8758 if (!(virDomainSendKey(dom
, codeset
, holdtime
, keycodes
, count
, 0) < 0))
8762 virshDomainFree(dom
);
8767 * "send-process-signal" command
8769 static const vshCmdInfo info_send_process_signal
[] = {
8771 .data
= N_("Send signals to processes")
8774 .data
= N_("Send signals to processes in the guest")
8779 static const vshCmdOptDef opts_send_process_signal
[] = {
8780 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
8782 .type
= VSH_OT_DATA
,
8783 .flags
= VSH_OFLAG_REQ
,
8784 .help
= N_("the process ID")
8787 .type
= VSH_OT_DATA
,
8788 .flags
= VSH_OFLAG_REQ
,
8789 .help
= N_("the signal number or name")
8794 VIR_ENUM_DECL(virDomainProcessSignal
);
8795 VIR_ENUM_IMPL(virDomainProcessSignal
,
8796 VIR_DOMAIN_PROCESS_SIGNAL_LAST
,
8797 "nop", "hup", "int", "quit", "ill", /* 0-4 */
8798 "trap", "abrt", "bus", "fpe", "kill", /* 5-9 */
8799 "usr1", "segv", "usr2", "pipe", "alrm", /* 10-14 */
8800 "term", "stkflt", "chld", "cont", "stop", /* 15-19 */
8801 "tstp", "ttin", "ttou", "urg", "xcpu", /* 20-24 */
8802 "xfsz", "vtalrm", "prof", "winch", "poll", /* 25-29 */
8803 "pwr", "sys", "rt0", "rt1", "rt2", /* 30-34 */
8804 "rt3", "rt4", "rt5", "rt6", "rt7", /* 35-39 */
8805 "rt8", "rt9", "rt10", "rt11", "rt12", /* 40-44 */
8806 "rt13", "rt14", "rt15", "rt16", "rt17", /* 45-49 */
8807 "rt18", "rt19", "rt20", "rt21", "rt22", /* 50-54 */
8808 "rt23", "rt24", "rt25", "rt26", "rt27", /* 55-59 */
8809 "rt28", "rt29", "rt30", "rt31", "rt32"); /* 60-64 */
8811 static int getSignalNumber(vshControl
*ctl
, const char *signame
)
8815 char *lower
= vshStrdup(ctl
, signame
);
8818 for (i
= 0; signame
[i
]; i
++)
8819 lower
[i
] = c_tolower(signame
[i
]);
8821 if (virStrToLong_i(lower
, NULL
, 10, &signum
) >= 0)
8824 if (STRPREFIX(lower
, "sig_"))
8826 else if (STRPREFIX(lower
, "sig"))
8829 if ((signum
= virDomainProcessSignalTypeFromString(lower
)) >= 0)
8839 cmdSendProcessSignal(vshControl
*ctl
, const vshCmd
*cmd
)
8843 const char *signame
;
8844 long long pid_value
;
8847 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8850 if (vshCommandOptLongLong(ctl
, cmd
, "pid", &pid_value
) < 0)
8853 if (vshCommandOptStringReq(ctl
, cmd
, "signame", &signame
) < 0)
8856 if ((signum
= getSignalNumber(ctl
, signame
)) < 0) {
8857 vshError(ctl
, _("malformed signal name: %s"), signame
);
8861 if (virDomainSendProcessSignal(dom
, pid_value
, signum
, 0) < 0)
8867 virshDomainFree(dom
);
8874 static const vshCmdInfo info_setmem
[] = {
8876 .data
= N_("change memory allocation")
8879 .data
= N_("Change the current memory allocation in the guest domain.")
8884 static const vshCmdOptDef opts_setmem
[] = {
8885 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
8886 {.name
= "kilobytes",
8887 .type
= VSH_OT_ALIAS
,
8892 .flags
= VSH_OFLAG_REQ
,
8893 .help
= N_("new memory size, as scaled integer (default KiB)")
8895 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
8896 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
8897 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
8902 cmdSetmem(vshControl
*ctl
, const vshCmd
*cmd
)
8905 unsigned long long bytes
= 0;
8906 unsigned long long max
;
8907 unsigned long kibibytes
= 0;
8909 bool config
= vshCommandOptBool(cmd
, "config");
8910 bool live
= vshCommandOptBool(cmd
, "live");
8911 bool current
= vshCommandOptBool(cmd
, "current");
8912 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
8914 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
8915 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
8918 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
8920 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
8921 /* none of the options were specified */
8922 if (!current
&& !live
&& !config
)
8925 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
8928 /* The API expects 'unsigned long' KiB, so depending on whether we
8929 * are 32-bit or 64-bit determines the maximum we can use. */
8930 if (sizeof(kibibytes
) < sizeof(max
))
8931 max
= 1024ull * ULONG_MAX
;
8934 if (vshCommandOptScaledInt(ctl
, cmd
, "size", &bytes
, 1024, max
) < 0) {
8935 virshDomainFree(dom
);
8938 kibibytes
= VIR_DIV_UP(bytes
, 1024);
8941 if (virDomainSetMemory(dom
, kibibytes
) != 0)
8944 if (virDomainSetMemoryFlags(dom
, kibibytes
, flags
) < 0)
8948 virshDomainFree(dom
);
8953 * "setmaxmem" command
8955 static const vshCmdInfo info_setmaxmem
[] = {
8957 .data
= N_("change maximum memory limit")
8960 .data
= N_("Change the maximum memory allocation limit in the guest domain.")
8965 static const vshCmdOptDef opts_setmaxmem
[] = {
8966 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
8967 {.name
= "kilobytes",
8968 .type
= VSH_OT_ALIAS
,
8973 .flags
= VSH_OFLAG_REQ
,
8974 .help
= N_("new maximum memory size, as scaled integer (default KiB)")
8976 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
8977 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
8978 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
8983 cmdSetmaxmem(vshControl
*ctl
, const vshCmd
*cmd
)
8986 unsigned long long bytes
= 0;
8987 unsigned long long max
;
8988 unsigned long kibibytes
= 0;
8990 bool config
= vshCommandOptBool(cmd
, "config");
8991 bool live
= vshCommandOptBool(cmd
, "live");
8992 bool current
= vshCommandOptBool(cmd
, "current");
8993 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
| VIR_DOMAIN_MEM_MAXIMUM
;
8995 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
8996 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
8999 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
9001 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
9002 /* none of the options were specified */
9003 if (!current
&& !live
&& !config
)
9006 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9009 /* The API expects 'unsigned long' KiB, so depending on whether we
9010 * are 32-bit or 64-bit determines the maximum we can use. */
9011 if (sizeof(kibibytes
) < sizeof(max
))
9012 max
= 1024ull * ULONG_MAX
;
9015 if (vshCommandOptScaledInt(ctl
, cmd
, "size", &bytes
, 1024, max
) < 0) {
9016 virshDomainFree(dom
);
9019 kibibytes
= VIR_DIV_UP(bytes
, 1024);
9022 if (virDomainSetMaxMemory(dom
, kibibytes
) != 0) {
9023 vshError(ctl
, "%s", _("Unable to change MaxMemorySize"));
9027 if (virDomainSetMemoryFlags(dom
, kibibytes
, flags
) < 0) {
9028 vshError(ctl
, "%s", _("Unable to change MaxMemorySize"));
9033 virshDomainFree(dom
);
9040 static const vshCmdInfo info_memtune
[] = {
9042 .data
= N_("Get or set memory parameters")
9045 .data
= N_("Get or set the current memory parameters for a guest"
9047 " To get the memory parameters use following command: \n\n"
9048 " virsh # memtune <domain>")
9053 static const vshCmdOptDef opts_memtune
[] = {
9054 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
9055 {.name
= "hard-limit",
9057 .help
= N_("Max memory, as scaled integer (default KiB)")
9059 {.name
= "soft-limit",
9061 .help
= N_("Memory during contention, as scaled integer (default KiB)")
9063 {.name
= "swap-hard-limit",
9065 .help
= N_("Max memory plus swap, as scaled integer (default KiB)")
9067 {.name
= "min-guarantee",
9069 .help
= N_("Min guaranteed memory, as scaled integer (default KiB)")
9071 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
9072 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
9073 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
9078 * virshMemtuneGetSize
9080 * @cmd: pointer to vshCmd
9081 * @name: name of a parameter for which we would like to get a value
9082 * @value: pointer to variable where the value will be stored
9084 * This function will parse virsh command line in order to load a value of
9085 * specified parameter. If the value is -1 we will handle it as unlimited and
9086 * use VIR_DOMAIN_MEMORY_PARAM_UNLIMITED instead.
9089 * >0 if option found and valid
9090 * 0 if option not found and not required
9091 * <0 in all other cases
9094 virshMemtuneGetSize(vshControl
*ctl
, const vshCmd
*cmd
,
9095 const char *name
, long long *value
)
9098 unsigned long long tmp
;
9102 ret
= vshCommandOptStringQuiet(ctl
, cmd
, name
, &str
);
9105 if (virStrToLong_ll(str
, &end
, 10, value
) < 0)
9108 *value
= VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
;
9112 if (virScaleInteger(&tmp
, end
, 1024, LLONG_MAX
) < 0)
9114 *value
= VIR_DIV_UP(tmp
, 1024);
9119 cmdMemtune(vshControl
*ctl
, const vshCmd
*cmd
)
9127 virTypedParameterPtr params
= NULL
;
9129 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
9130 bool current
= vshCommandOptBool(cmd
, "current");
9131 bool config
= vshCommandOptBool(cmd
, "config");
9132 bool live
= vshCommandOptBool(cmd
, "live");
9134 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
9135 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
9138 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
9140 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
9142 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9145 #define PARSE_MEMTUNE_PARAM(NAME, FIELD) \
9146 if ((rc = virshMemtuneGetSize(ctl, cmd, NAME, &tmpVal)) < 0) { \
9147 vshError(ctl, _("Unable to parse integer parameter %s"), NAME); \
9151 if (virTypedParamsAddULLong(¶ms, &nparams, &maxparams, \
9152 FIELD, tmpVal) < 0) \
9157 PARSE_MEMTUNE_PARAM("hard-limit", VIR_DOMAIN_MEMORY_HARD_LIMIT
);
9158 PARSE_MEMTUNE_PARAM("soft-limit", VIR_DOMAIN_MEMORY_SOFT_LIMIT
);
9159 PARSE_MEMTUNE_PARAM("swap-hard-limit", VIR_DOMAIN_MEMORY_SWAP_HARD_LIMIT
);
9160 PARSE_MEMTUNE_PARAM("min-guarantee", VIR_DOMAIN_MEMORY_MIN_GUARANTEE
);
9162 #undef PARSE_MEMTUNE_PARAM
9165 /* get the number of memory parameters */
9166 if (virDomainGetMemoryParameters(dom
, NULL
, &nparams
, flags
) != 0) {
9168 _("Unable to get number of memory parameters"));
9173 /* nothing to output */
9178 /* now go get all the memory parameters */
9179 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
9180 if (virDomainGetMemoryParameters(dom
, params
, &nparams
, flags
) != 0) {
9181 vshError(ctl
, "%s", _("Unable to get memory parameters"));
9185 for (i
= 0; i
< nparams
; i
++) {
9186 if (params
[i
].type
== VIR_TYPED_PARAM_ULLONG
&&
9187 params
[i
].value
.ul
== VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
) {
9188 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, _("unlimited"));
9190 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
9191 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
9196 if (virDomainSetMemoryParameters(dom
, params
, nparams
, flags
) != 0)
9203 virTypedParamsFree(params
, nparams
);
9204 virshDomainFree(dom
);
9208 vshSaveLibvirtError();
9210 vshError(ctl
, "%s", _("Unable to change memory parameters"));
9217 static const vshCmdInfo info_perf
[] = {
9219 .data
= N_("Get or set perf event")
9222 .data
= N_("Get or set the current perf events for a guest"
9224 " To get the perf events list use following command: \n\n"
9225 " virsh # perf <domain>")
9230 static const vshCmdOptDef opts_perf
[] = {
9231 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
9233 .type
= VSH_OT_STRING
,
9234 .help
= N_("perf events which will be enabled")
9237 .type
= VSH_OT_STRING
,
9238 .help
= N_("perf events which will be disabled")
9240 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
9241 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
9242 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
9247 virshParseEventStr(const char *event
,
9249 virTypedParameterPtr
*params
,
9257 if (!(tok
= virStringSplitCount(event
, ",", 0, &ntok
)))
9260 for (i
= 0; i
< ntok
; i
++) {
9261 if ((*tok
[i
] != '\0') &&
9262 virTypedParamsAddBoolean(params
, nparams
,
9263 maxparams
, tok
[i
], state
) < 0)
9269 virStringListFree(tok
);
9274 virshPrintPerfStatus(vshControl
*ctl
, virTypedParameterPtr params
, int nparams
)
9278 for (i
= 0; i
< nparams
; i
++) {
9279 if (params
[i
].type
== VIR_TYPED_PARAM_BOOLEAN
&&
9280 params
[i
].value
.b
) {
9281 vshPrintExtra(ctl
, "%-15s: %s\n", params
[i
].field
, _("enabled"));
9283 vshPrintExtra(ctl
, "%-15s: %s\n", params
[i
].field
, _("disabled"));
9289 cmdPerf(vshControl
*ctl
, const vshCmd
*cmd
)
9294 virTypedParameterPtr params
= NULL
;
9296 const char *enable
= NULL
, *disable
= NULL
;
9297 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
9298 bool current
= vshCommandOptBool(cmd
, "current");
9299 bool config
= vshCommandOptBool(cmd
, "config");
9300 bool live
= vshCommandOptBool(cmd
, "live");
9302 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
9303 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
9306 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
9308 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
9310 if (vshCommandOptStringReq(ctl
, cmd
, "enable", &enable
) < 0 ||
9311 vshCommandOptStringReq(ctl
, cmd
, "disable", &disable
) < 0)
9314 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9317 if (enable
&& virshParseEventStr(enable
, true, ¶ms
,
9318 &nparams
, &maxparams
) < 0)
9321 if (disable
&& virshParseEventStr(disable
, false, ¶ms
,
9322 &nparams
, &maxparams
) < 0)
9326 if (virDomainGetPerfEvents(dom
, ¶ms
, &nparams
, flags
) != 0) {
9327 vshError(ctl
, "%s", _("Unable to get perf events"));
9330 virshPrintPerfStatus(ctl
, params
, nparams
);
9332 if (virDomainSetPerfEvents(dom
, params
, nparams
, flags
) != 0) {
9333 vshError(ctl
, "%s", _("Unable to enable/disable perf events"));
9336 virshPrintPerfStatus(ctl
, params
, nparams
);
9342 virTypedParamsFree(params
, nparams
);
9343 virshDomainFree(dom
);
9349 * "numatune" command
9351 static const vshCmdInfo info_numatune
[] = {
9353 .data
= N_("Get or set numa parameters")
9356 .data
= N_("Get or set the current numa parameters for a guest"
9358 " To get the numa parameters use following command: \n\n"
9359 " virsh # numatune <domain>")
9364 static const vshCmdOptDef opts_numatune
[] = {
9365 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
9367 .type
= VSH_OT_STRING
,
9368 .help
= N_("NUMA mode, one of strict, preferred and interleave \n"
9369 "or a number from the virDomainNumatuneMemMode enum")
9372 .type
= VSH_OT_STRING
,
9373 .help
= N_("NUMA node selections to set")
9375 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
9376 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
9377 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
9382 cmdNumatune(vshControl
* ctl
, const vshCmd
* cmd
)
9388 virTypedParameterPtr params
= NULL
;
9389 const char *nodeset
= NULL
;
9391 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
9392 bool current
= vshCommandOptBool(cmd
, "current");
9393 bool config
= vshCommandOptBool(cmd
, "config");
9394 bool live
= vshCommandOptBool(cmd
, "live");
9395 const char *mode
= NULL
;
9397 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
9398 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
9401 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
9403 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
9405 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9408 if (vshCommandOptStringReq(ctl
, cmd
, "nodeset", &nodeset
) < 0)
9412 virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
9413 VIR_DOMAIN_NUMA_NODESET
, nodeset
) < 0)
9416 if (vshCommandOptStringReq(ctl
, cmd
, "mode", &mode
) < 0)
9421 /* Accept string or integer, in case server understands newer
9422 * integer than what strings we were compiled with
9424 if ((m
= virDomainNumatuneMemModeTypeFromString(mode
)) < 0 &&
9425 virStrToLong_i(mode
, NULL
, 0, &m
) < 0) {
9426 vshError(ctl
, _("Invalid mode: %s"), mode
);
9430 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
9431 VIR_DOMAIN_NUMA_MODE
, m
) < 0)
9436 /* get the number of numa parameters */
9437 if (virDomainGetNumaParameters(dom
, NULL
, &nparams
, flags
) != 0) {
9439 _("Unable to get number of memory parameters"));
9444 /* nothing to output */
9449 /* now go get all the numa parameters */
9450 params
= vshCalloc(ctl
, nparams
, sizeof(*params
));
9451 if (virDomainGetNumaParameters(dom
, params
, &nparams
, flags
) != 0) {
9452 vshError(ctl
, "%s", _("Unable to get numa parameters"));
9456 for (i
= 0; i
< nparams
; i
++) {
9457 if (params
[i
].type
== VIR_TYPED_PARAM_INT
&&
9458 STREQ(params
[i
].field
, VIR_DOMAIN_NUMA_MODE
)) {
9459 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
,
9460 virDomainNumatuneMemModeTypeToString(params
[i
].value
.i
));
9462 char *str
= vshGetTypedParamValue(ctl
, ¶ms
[i
]);
9463 vshPrint(ctl
, "%-15s: %s\n", params
[i
].field
, str
);
9468 if (virDomainSetNumaParameters(dom
, params
, nparams
, flags
) != 0)
9475 virTypedParamsFree(params
, nparams
);
9476 virshDomainFree(dom
);
9480 vshSaveLibvirtError();
9482 vshError(ctl
, "%s", _("Unable to change numa parameters"));
9487 * "qemu-monitor-command" command
9489 static const vshCmdInfo info_qemu_monitor_command
[] = {
9491 .data
= N_("QEMU Monitor Command")
9494 .data
= N_("QEMU Monitor Command")
9499 static const vshCmdOptDef opts_qemu_monitor_command
[] = {
9500 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
9502 .type
= VSH_OT_BOOL
,
9503 .help
= N_("command is in human monitor protocol")
9506 .type
= VSH_OT_BOOL
,
9507 .help
= N_("pretty-print any qemu monitor protocol output")
9510 .type
= VSH_OT_ARGV
,
9511 .flags
= VSH_OFLAG_REQ
,
9512 .help
= N_("command")
9518 cmdQemuMonitorCommand(vshControl
*ctl
, const vshCmd
*cmd
)
9520 virDomainPtr dom
= NULL
;
9522 char *monitor_cmd
= NULL
;
9523 char *result
= NULL
;
9524 unsigned int flags
= 0;
9525 const vshCmdOpt
*opt
= NULL
;
9526 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
9527 virJSONValuePtr pretty
= NULL
;
9529 VSH_EXCLUSIVE_OPTIONS("hmp", "pretty");
9531 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9534 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
)))
9535 virBufferAsprintf(&buf
, "%s ", opt
->data
);
9537 virBufferTrim(&buf
, " ", -1);
9539 if (virBufferError(&buf
)) {
9540 vshError(ctl
, "%s", _("Failed to collect command"));
9543 monitor_cmd
= virBufferContentAndReset(&buf
);
9545 if (vshCommandOptBool(cmd
, "hmp"))
9546 flags
|= VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP
;
9548 if (virDomainQemuMonitorCommand(dom
, monitor_cmd
, &result
, flags
) < 0)
9551 if (vshCommandOptBool(cmd
, "pretty")) {
9553 pretty
= virJSONValueFromString(result
);
9554 if (pretty
&& (tmp
= virJSONValueToString(pretty
, true))) {
9557 virTrimSpaces(result
, NULL
);
9559 vshResetLibvirtError();
9562 vshPrint(ctl
, "%s\n", result
);
9568 VIR_FREE(monitor_cmd
);
9569 virJSONValueFree(pretty
);
9570 virshDomainFree(dom
);
9576 * "qemu-monitor-event" command
9579 struct virshQemuEventData
{
9586 typedef struct virshQemuEventData virshQemuEventData
;
9589 virshEventQemuPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
9593 unsigned int micros
,
9594 const char *details
,
9597 virshQemuEventData
*data
= opaque
;
9598 virJSONValuePtr pretty
= NULL
;
9601 if (!data
->loop
&& data
->count
)
9603 if (data
->pretty
&& details
) {
9604 pretty
= virJSONValueFromString(details
);
9605 if (pretty
&& (str
= virJSONValueToString(pretty
, true)))
9609 if (data
->timestamp
) {
9610 char timestamp
[VIR_TIME_STRING_BUFLEN
];
9612 if (virTimeStringNowRaw(timestamp
) < 0)
9613 timestamp
[0] = '\0';
9615 vshPrint(data
->ctl
, "%s: event %s for domain %s: %s\n",
9616 timestamp
, event
, virDomainGetName(dom
), NULLSTR(details
));
9618 vshPrint(data
->ctl
, "event %s at %lld.%06u for domain %s: %s\n",
9619 event
, seconds
, micros
, virDomainGetName(dom
), NULLSTR(details
));
9624 vshEventDone(data
->ctl
);
9629 static const vshCmdInfo info_qemu_monitor_event
[] = {
9631 .data
= N_("QEMU Monitor Events")
9634 .data
= N_("Listen for QEMU Monitor Events")
9639 static const vshCmdOptDef opts_qemu_monitor_event
[] = {
9640 VIRSH_COMMON_OPT_DOMAIN_OT_STRING(N_("filter by domain name, id or uuid"),
9643 .type
= VSH_OT_STRING
,
9644 .help
= N_("filter by event name")
9647 .type
= VSH_OT_BOOL
,
9648 .help
= N_("pretty-print any JSON output")
9651 .type
= VSH_OT_BOOL
,
9652 .help
= N_("loop until timeout or interrupt, rather than one-shot")
9656 .help
= N_("timeout seconds")
9659 .type
= VSH_OT_BOOL
,
9660 .help
= N_("treat event as a regex rather than literal filter")
9663 .type
= VSH_OT_BOOL
,
9664 .help
= N_("treat event case-insensitively")
9666 {.name
= "timestamp",
9667 .type
= VSH_OT_BOOL
,
9668 .help
= N_("show timestamp for each printed event")
9674 cmdQemuMonitorEvent(vshControl
*ctl
, const vshCmd
*cmd
)
9676 virDomainPtr dom
= NULL
;
9678 unsigned int flags
= 0;
9681 const char *event
= NULL
;
9682 virshQemuEventData data
;
9683 virshControlPtr priv
= ctl
->privData
;
9685 if (vshCommandOptBool(cmd
, "regex"))
9686 flags
|= VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_REGEX
;
9687 if (vshCommandOptBool(cmd
, "no-case"))
9688 flags
|= VIR_CONNECT_DOMAIN_QEMU_MONITOR_EVENT_REGISTER_NOCASE
;
9691 data
.loop
= vshCommandOptBool(cmd
, "loop");
9692 data
.pretty
= vshCommandOptBool(cmd
, "pretty");
9693 data
.timestamp
= vshCommandOptBool(cmd
, "timestamp");
9695 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0)
9697 if (vshCommandOptStringReq(ctl
, cmd
, "event", &event
) < 0)
9700 if (vshCommandOptBool(cmd
, "domain"))
9701 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
9704 if (vshEventStart(ctl
, timeout
) < 0)
9707 if ((eventId
= virConnectDomainQemuMonitorEventRegister(priv
->conn
, dom
,
9709 virshEventQemuPrint
,
9713 switch (vshEventWait(ctl
)) {
9714 case VSH_EVENT_INTERRUPT
:
9715 vshPrint(ctl
, _("event loop interrupted\n"));
9717 case VSH_EVENT_TIMEOUT
:
9718 vshPrint(ctl
, _("event loop timed out\n"));
9720 case VSH_EVENT_DONE
:
9725 vshPrint(ctl
, _("events received: %d\n"), data
.count
);
9730 vshEventCleanup(ctl
);
9732 virConnectDomainQemuMonitorEventDeregister(priv
->conn
, eventId
) < 0)
9734 virshDomainFree(dom
);
9740 * "qemu-attach" command
9742 static const vshCmdInfo info_qemu_attach
[] = {
9744 .data
= N_("QEMU Attach")
9747 .data
= N_("QEMU Attach")
9752 static const vshCmdOptDef opts_qemu_attach
[] = {
9754 .type
= VSH_OT_DATA
,
9755 .flags
= VSH_OFLAG_REQ
,
9762 cmdQemuAttach(vshControl
*ctl
, const vshCmd
*cmd
)
9764 virDomainPtr dom
= NULL
;
9766 unsigned int flags
= 0;
9767 unsigned int pid_value
; /* API uses unsigned int, not pid_t */
9768 virshControlPtr priv
= ctl
->privData
;
9770 if (vshCommandOptUInt(ctl
, cmd
, "pid", &pid_value
) <= 0)
9773 if (!(dom
= virDomainQemuAttach(priv
->conn
, pid_value
, flags
))) {
9774 vshError(ctl
, _("Failed to attach to pid %u"), pid_value
);
9778 vshPrintExtra(ctl
, _("Domain %s attached to pid %u\n"),
9779 virDomainGetName(dom
), pid_value
);
9780 virshDomainFree(dom
);
9788 * "qemu-agent-command" command
9790 static const vshCmdInfo info_qemu_agent_command
[] = {
9792 .data
= N_("QEMU Guest Agent Command")
9795 .data
= N_("Run an arbitrary qemu guest agent command; use at your own risk")
9800 static const vshCmdOptDef opts_qemu_agent_command
[] = {
9801 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
9804 .flags
= VSH_OFLAG_REQ_OPT
,
9805 .help
= N_("timeout seconds. must be positive.")
9808 .type
= VSH_OT_BOOL
,
9809 .help
= N_("execute command without waiting for timeout")
9812 .type
= VSH_OT_BOOL
,
9813 .help
= N_("execute command without timeout")
9816 .type
= VSH_OT_BOOL
,
9817 .help
= N_("pretty-print the output")
9820 .type
= VSH_OT_ARGV
,
9821 .flags
= VSH_OFLAG_REQ
,
9822 .help
= N_("command")
9828 cmdQemuAgentCommand(vshControl
*ctl
, const vshCmd
*cmd
)
9830 virDomainPtr dom
= NULL
;
9832 char *guest_agent_cmd
= NULL
;
9833 char *result
= NULL
;
9834 int timeout
= VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT
;
9836 unsigned int flags
= 0;
9837 const vshCmdOpt
*opt
= NULL
;
9838 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
9839 virJSONValuePtr pretty
= NULL
;
9841 dom
= virshCommandOptDomain(ctl
, cmd
, NULL
);
9845 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
)))
9846 virBufferAsprintf(&buf
, "%s ", opt
->data
);
9848 virBufferTrim(&buf
, " ", -1);
9850 if (virBufferError(&buf
)) {
9851 vshError(ctl
, "%s", _("Failed to collect command"));
9854 guest_agent_cmd
= virBufferContentAndReset(&buf
);
9856 judge
= vshCommandOptInt(ctl
, cmd
, "timeout", &timeout
);
9861 if (judge
&& timeout
< 1) {
9862 vshError(ctl
, "%s", _("timeout must be positive"));
9866 if (vshCommandOptBool(cmd
, "async")) {
9867 timeout
= VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT
;
9870 if (vshCommandOptBool(cmd
, "block")) {
9871 timeout
= VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK
;
9876 vshError(ctl
, "%s", _("timeout, async and block options are exclusive"));
9880 result
= virDomainQemuAgentCommand(dom
, guest_agent_cmd
, timeout
, flags
);
9884 if (vshCommandOptBool(cmd
, "pretty")) {
9886 pretty
= virJSONValueFromString(result
);
9887 if (pretty
&& (tmp
= virJSONValueToString(pretty
, true))) {
9891 vshResetLibvirtError();
9895 vshPrint(ctl
, "%s\n", result
);
9901 VIR_FREE(guest_agent_cmd
);
9902 virshDomainFree(dom
);
9908 * "lxc-enter-namespace" namespace
9910 static const vshCmdInfo info_lxc_enter_namespace
[] = {
9912 .data
= N_("LXC Guest Enter Namespace")
9915 .data
= N_("Run an arbitrary command in a lxc guest namespace; use at your own risk")
9920 static const vshCmdOptDef opts_lxc_enter_namespace
[] = {
9921 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
9922 {.name
= "noseclabel",
9923 .type
= VSH_OT_BOOL
,
9924 .help
= N_("Do not change process security label")
9927 .type
= VSH_OT_ARGV
,
9928 .flags
= VSH_OFLAG_REQ
,
9929 .help
= N_("command to run")
9935 cmdLxcEnterNamespace(vshControl
*ctl
, const vshCmd
*cmd
)
9937 virDomainPtr dom
= NULL
;
9939 const vshCmdOpt
*opt
= NULL
;
9940 char **cmdargv
= NULL
;
9941 size_t ncmdargv
= 0;
9946 bool setlabel
= true;
9947 virSecurityModelPtr secmodel
= NULL
;
9948 virSecurityLabelPtr seclabel
= NULL
;
9949 virshControlPtr priv
= ctl
->privData
;
9951 dom
= virshCommandOptDomain(ctl
, cmd
, NULL
);
9955 if (vshCommandOptBool(cmd
, "noseclabel"))
9958 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
))) {
9959 if (VIR_EXPAND_N(cmdargv
, ncmdargv
, 1) < 0) {
9960 vshError(ctl
, _("%s: %d: failed to allocate argv"),
9961 __FILE__
, __LINE__
);
9963 cmdargv
[ncmdargv
-1] = opt
->data
;
9965 if (VIR_EXPAND_N(cmdargv
, ncmdargv
, 1) < 0) {
9966 vshError(ctl
, _("%s: %d: failed to allocate argv"),
9967 __FILE__
, __LINE__
);
9969 cmdargv
[ncmdargv
- 1] = NULL
;
9971 if ((nfdlist
= virDomainLxcOpenNamespace(dom
, &fdlist
, 0)) < 0)
9975 if (VIR_ALLOC(secmodel
) < 0) {
9976 vshError(ctl
, "%s", _("Failed to allocate security model"));
9979 if (VIR_ALLOC(seclabel
) < 0) {
9980 vshError(ctl
, "%s", _("Failed to allocate security label"));
9983 if (virNodeGetSecurityModel(priv
->conn
, secmodel
) < 0)
9985 if (virDomainGetSecurityLabel(dom
, seclabel
) < 0)
9989 /* Fork once because we don't want to affect
9990 * virsh's namespace itself, and because user namespace
9991 * can only be changed in single-threaded process
9993 if ((pid
= virFork()) < 0)
9999 virDomainLxcEnterSecurityLabel(secmodel
,
10003 _exit(EXIT_CANCELED
);
10005 if (virDomainLxcEnterCGroup(dom
, 0) < 0)
10006 _exit(EXIT_CANCELED
);
10008 if (virDomainLxcEnterNamespace(dom
,
10014 _exit(EXIT_CANCELED
);
10016 /* Fork a second time because entering the
10017 * pid namespace only takes effect after fork
10019 if ((pid
= virFork()) < 0)
10020 _exit(EXIT_CANCELED
);
10022 execv(cmdargv
[0], cmdargv
);
10023 _exit(errno
== ENOENT
? EXIT_ENOENT
: EXIT_CANNOT_INVOKE
);
10025 if (virProcessWait(pid
, &status
, true) < 0)
10026 _exit(EXIT_CANNOT_INVOKE
);
10027 virProcessExitWithStatus(status
);
10029 for (i
= 0; i
< nfdlist
; i
++)
10030 VIR_FORCE_CLOSE(fdlist
[i
]);
10032 if (virProcessWait(pid
, NULL
, false) < 0) {
10033 vshReportError(ctl
);
10041 VIR_FREE(seclabel
);
10042 VIR_FREE(secmodel
);
10043 virshDomainFree(dom
);
10049 * "dumpxml" command
10051 static const vshCmdInfo info_dumpxml
[] = {
10053 .data
= N_("domain information in XML")
10056 .data
= N_("Output the domain information as an XML dump to stdout.")
10061 static const vshCmdOptDef opts_dumpxml
[] = {
10062 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
10063 {.name
= "inactive",
10064 .type
= VSH_OT_BOOL
,
10065 .help
= N_("show inactive defined XML")
10067 {.name
= "security-info",
10068 .type
= VSH_OT_BOOL
,
10069 .help
= N_("include security sensitive information in XML dump")
10071 {.name
= "update-cpu",
10072 .type
= VSH_OT_BOOL
,
10073 .help
= N_("update guest CPU according to host CPU")
10075 {.name
= "migratable",
10076 .type
= VSH_OT_BOOL
,
10077 .help
= N_("provide XML suitable for migrations")
10083 cmdDumpXML(vshControl
*ctl
, const vshCmd
*cmd
)
10088 unsigned int flags
= 0;
10089 bool inactive
= vshCommandOptBool(cmd
, "inactive");
10090 bool secure
= vshCommandOptBool(cmd
, "security-info");
10091 bool update
= vshCommandOptBool(cmd
, "update-cpu");
10092 bool migratable
= vshCommandOptBool(cmd
, "migratable");
10095 flags
|= VIR_DOMAIN_XML_INACTIVE
;
10097 flags
|= VIR_DOMAIN_XML_SECURE
;
10099 flags
|= VIR_DOMAIN_XML_UPDATE_CPU
;
10101 flags
|= VIR_DOMAIN_XML_MIGRATABLE
;
10103 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
10106 dump
= virDomainGetXMLDesc(dom
, flags
);
10107 if (dump
!= NULL
) {
10108 vshPrint(ctl
, "%s", dump
);
10114 virshDomainFree(dom
);
10119 * "domxml-from-native" command
10121 static const vshCmdInfo info_domxmlfromnative
[] = {
10123 .data
= N_("Convert native config to domain XML")
10126 .data
= N_("Convert native guest configuration format to domain XML format.")
10131 static const vshCmdOptDef opts_domxmlfromnative
[] = {
10133 .type
= VSH_OT_DATA
,
10134 .flags
= VSH_OFLAG_REQ
,
10135 .help
= N_("source config data format")
10138 .type
= VSH_OT_DATA
,
10139 .flags
= VSH_OFLAG_REQ
,
10140 .help
= N_("config data file to import from")
10146 cmdDomXMLFromNative(vshControl
*ctl
, const vshCmd
*cmd
)
10149 const char *format
= NULL
;
10150 const char *configFile
= NULL
;
10153 unsigned int flags
= 0;
10154 virshControlPtr priv
= ctl
->privData
;
10156 if (vshCommandOptStringReq(ctl
, cmd
, "format", &format
) < 0 ||
10157 vshCommandOptStringReq(ctl
, cmd
, "config", &configFile
) < 0)
10160 if (virFileReadAll(configFile
, VSH_MAX_XML_FILE
, &configData
) < 0)
10163 xmlData
= virConnectDomainXMLFromNative(priv
->conn
, format
, configData
, flags
);
10164 if (xmlData
!= NULL
) {
10165 vshPrint(ctl
, "%s", xmlData
);
10171 VIR_FREE(configData
);
10176 * "domxml-to-native" command
10178 static const vshCmdInfo info_domxmltonative
[] = {
10180 .data
= N_("Convert domain XML to native config")
10183 .data
= N_("Convert domain XML config to a native guest configuration format.")
10188 static const vshCmdOptDef opts_domxmltonative
[] = {
10190 .type
= VSH_OT_DATA
,
10191 .flags
= VSH_OFLAG_REQ
,
10192 .help
= N_("target config data type format")
10194 VIRSH_COMMON_OPT_DOMAIN_OT_STRING_FULL(VSH_OFLAG_REQ_OPT
, 0),
10196 .type
= VSH_OT_STRING
,
10197 .help
= N_("xml data file to export from")
10203 cmdDomXMLToNative(vshControl
*ctl
, const vshCmd
*cmd
)
10206 const char *format
= NULL
;
10207 const char *xmlFile
= NULL
;
10208 char *configData
= NULL
;
10209 char *xmlData
= NULL
;
10210 unsigned int flags
= 0;
10211 virshControlPtr priv
= ctl
->privData
;
10212 virDomainPtr dom
= NULL
;
10214 if (vshCommandOptStringReq(ctl
, cmd
, "format", &format
) < 0 ||
10215 vshCommandOptStringReq(ctl
, cmd
, "xml", &xmlFile
) < 0)
10218 VSH_EXCLUSIVE_OPTIONS("domain", "xml");
10220 if (vshCommandOptBool(cmd
, "domain") &&
10221 (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
))))
10225 xmlData
= virDomainGetXMLDesc(dom
, flags
);
10226 } else if (xmlFile
) {
10227 if (virFileReadAll(xmlFile
, VSH_MAX_XML_FILE
, &xmlData
) < 0)
10230 vshError(ctl
, "%s", _("need either domain or domain XML"));
10235 vshError(ctl
, "%s", _("failed to retrieve XML"));
10239 if (!(configData
= virConnectDomainXMLToNative(priv
->conn
, format
, xmlData
, flags
))) {
10242 vshPrint(ctl
, "%s", configData
);
10247 virshDomainFree(dom
);
10249 VIR_FREE(configData
);
10254 * "domname" command
10256 static const vshCmdInfo info_domname
[] = {
10258 .data
= N_("convert a domain id or UUID to domain name")
10266 static const vshCmdOptDef opts_domname
[] = {
10267 VIRSH_COMMON_OPT_DOMAIN(N_("domain id or uuid"), 0),
10272 cmdDomname(vshControl
*ctl
, const vshCmd
*cmd
)
10276 if (!(dom
= virshCommandOptDomainBy(ctl
, cmd
, NULL
,
10277 VIRSH_BYID
|VIRSH_BYUUID
)))
10280 vshPrint(ctl
, "%s\n", virDomainGetName(dom
));
10281 virshDomainFree(dom
);
10286 * "domrename" command
10288 static const vshCmdInfo info_domrename
[] = {
10290 .data
= N_("rename a domain")
10293 .data
= "Rename an inactive domain."
10298 static const vshCmdOptDef opts_domrename
[] = {
10299 VIRSH_COMMON_OPT_DOMAIN(N_("domain name or uuid"),
10300 VIR_CONNECT_LIST_DOMAINS_INACTIVE
),
10301 {.name
= "new-name",
10302 .type
= VSH_OT_DATA
,
10303 .flags
= VSH_OFLAG_REQ
,
10304 .help
= N_("new domain name")
10310 cmdDomrename(vshControl
*ctl
, const vshCmd
*cmd
)
10313 const char *new_name
= NULL
;
10316 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
10319 if (vshCommandOptStringReq(ctl
, cmd
, "new-name", &new_name
) < 0)
10322 if (virDomainRename(dom
, new_name
, 0) < 0)
10325 vshPrintExtra(ctl
, "Domain successfully renamed\n");
10329 virshDomainFree(dom
);
10336 static const vshCmdInfo info_domid
[] = {
10338 .data
= N_("convert a domain name or UUID to domain id")
10346 static const vshCmdOptDef opts_domid
[] = {
10347 VIRSH_COMMON_OPT_DOMAIN(N_("domain name or uuid"),
10348 VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
10353 cmdDomid(vshControl
*ctl
, const vshCmd
*cmd
)
10358 if (!(dom
= virshCommandOptDomainBy(ctl
, cmd
, NULL
,
10359 VIRSH_BYNAME
|VIRSH_BYUUID
)))
10362 id
= virDomainGetID(dom
);
10363 if (id
== ((unsigned int)-1))
10364 vshPrint(ctl
, "%s\n", "-");
10366 vshPrint(ctl
, "%d\n", id
);
10367 virshDomainFree(dom
);
10372 * "domuuid" command
10374 static const vshCmdInfo info_domuuid
[] = {
10376 .data
= N_("convert a domain name or id to domain UUID")
10384 static const vshCmdOptDef opts_domuuid
[] = {
10385 VIRSH_COMMON_OPT_DOMAIN(N_("domain id or name"), 0),
10390 cmdDomuuid(vshControl
*ctl
, const vshCmd
*cmd
)
10393 char uuid
[VIR_UUID_STRING_BUFLEN
];
10395 if (!(dom
= virshCommandOptDomainBy(ctl
, cmd
, NULL
,
10396 VIRSH_BYNAME
|VIRSH_BYID
)))
10399 if (virDomainGetUUIDString(dom
, uuid
) != -1)
10400 vshPrint(ctl
, "%s\n", uuid
);
10402 vshError(ctl
, "%s", _("failed to get domain UUID"));
10404 virshDomainFree(dom
);
10409 * "migrate" command
10411 static const vshCmdInfo info_migrate
[] = {
10413 .data
= N_("migrate domain to another host")
10416 .data
= N_("Migrate domain to another host. Add --live for live migration.")
10421 static const vshCmdOptDef opts_migrate
[] = {
10422 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
10423 {.name
= "desturi",
10424 .type
= VSH_OT_DATA
,
10425 .flags
= VSH_OFLAG_REQ
,
10426 .help
= N_("connection URI of the destination host as seen from the client(normal migration) or source(p2p migration)")
10428 VIRSH_COMMON_OPT_LIVE(N_("live migration")),
10429 {.name
= "offline",
10430 .type
= VSH_OT_BOOL
,
10431 .help
= N_("offline migration")
10434 .type
= VSH_OT_BOOL
,
10435 .help
= N_("peer-2-peer migration")
10438 .type
= VSH_OT_BOOL
,
10439 .help
= N_("direct migration")
10441 {.name
= "tunneled",
10442 .type
= VSH_OT_ALIAS
,
10443 .help
= "tunnelled"
10445 {.name
= "tunnelled",
10446 .type
= VSH_OT_BOOL
,
10447 .help
= N_("tunnelled migration")
10449 {.name
= "persistent",
10450 .type
= VSH_OT_BOOL
,
10451 .help
= N_("persist VM on destination")
10453 {.name
= "undefinesource",
10454 .type
= VSH_OT_BOOL
,
10455 .help
= N_("undefine VM on source")
10457 {.name
= "suspend",
10458 .type
= VSH_OT_BOOL
,
10459 .help
= N_("do not restart the domain on the destination host")
10461 {.name
= "copy-storage-all",
10462 .type
= VSH_OT_BOOL
,
10463 .help
= N_("migration with non-shared storage with full disk copy")
10465 {.name
= "copy-storage-inc",
10466 .type
= VSH_OT_BOOL
,
10467 .help
= N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)")
10469 {.name
= "change-protection",
10470 .type
= VSH_OT_BOOL
,
10471 .help
= N_("prevent any configuration changes to domain until migration ends")
10474 .type
= VSH_OT_BOOL
,
10475 .help
= N_("force migration even if it may be unsafe")
10477 {.name
= "verbose",
10478 .type
= VSH_OT_BOOL
,
10479 .help
= N_("display the progress of migration")
10481 {.name
= "compressed",
10482 .type
= VSH_OT_BOOL
,
10483 .help
= N_("compress repeated pages during live migration")
10485 {.name
= "auto-converge",
10486 .type
= VSH_OT_BOOL
,
10487 .help
= N_("force convergence during live migration")
10489 {.name
= "rdma-pin-all",
10490 .type
= VSH_OT_BOOL
,
10491 .help
= N_("pin all memory before starting RDMA live migration")
10493 {.name
= "abort-on-error",
10494 .type
= VSH_OT_BOOL
,
10495 .help
= N_("abort on soft errors during migration")
10497 {.name
= "postcopy",
10498 .type
= VSH_OT_BOOL
,
10499 .help
= N_("enable post-copy migration; switch to it using migrate-postcopy command")
10501 {.name
= "postcopy-after-precopy",
10502 .type
= VSH_OT_BOOL
,
10503 .help
= N_("automatically switch to post-copy migration after one pass of pre-copy")
10505 {.name
= "migrateuri",
10506 .type
= VSH_OT_STRING
,
10507 .help
= N_("migration URI, usually can be omitted")
10509 {.name
= "graphicsuri",
10510 .type
= VSH_OT_STRING
,
10511 .help
= N_("graphics URI to be used for seamless graphics migration")
10513 {.name
= "listen-address",
10514 .type
= VSH_OT_STRING
,
10515 .help
= N_("listen address that destination should bind to for incoming migration")
10518 .type
= VSH_OT_STRING
,
10519 .help
= N_("rename to new name during migration (if supported)")
10521 {.name
= "timeout",
10522 .type
= VSH_OT_INT
,
10523 .help
= N_("run action specified by --timeout-* option (suspend by "
10524 "default) if live migration exceeds timeout (in seconds)")
10526 {.name
= "timeout-suspend",
10527 .type
= VSH_OT_BOOL
,
10528 .help
= N_("suspend the guest after timeout")
10530 {.name
= "timeout-postcopy",
10531 .type
= VSH_OT_BOOL
,
10532 .help
= N_("switch to post-copy after timeout")
10535 .type
= VSH_OT_STRING
,
10536 .help
= N_("filename containing updated XML for the target")
10538 {.name
= "migrate-disks",
10539 .type
= VSH_OT_STRING
,
10540 .help
= N_("comma separated list of disks to be migrated")
10542 {.name
= "disks-port",
10543 .type
= VSH_OT_INT
,
10544 .help
= N_("port to use by target server for incoming disks migration")
10546 {.name
= "comp-methods",
10547 .type
= VSH_OT_STRING
,
10548 .help
= N_("comma separated list of compression methods to be used")
10550 {.name
= "comp-mt-level",
10551 .type
= VSH_OT_INT
,
10552 .help
= N_("compress level for multithread compression")
10554 {.name
= "comp-mt-threads",
10555 .type
= VSH_OT_INT
,
10556 .help
= N_("number of compression threads for multithread compression")
10558 {.name
= "comp-mt-dthreads",
10559 .type
= VSH_OT_INT
,
10560 .help
= N_("number of decompression threads for multithread compression")
10562 {.name
= "comp-xbzrle-cache",
10563 .type
= VSH_OT_INT
,
10564 .help
= N_("page cache size for xbzrle compression")
10566 {.name
= "auto-converge-initial",
10567 .type
= VSH_OT_INT
,
10568 .help
= N_("initial CPU throttling rate for auto-convergence")
10570 {.name
= "auto-converge-increment",
10571 .type
= VSH_OT_INT
,
10572 .help
= N_("CPU throttling rate increment for auto-convergence")
10574 {.name
= "persistent-xml",
10575 .type
= VSH_OT_STRING
,
10576 .help
= N_("filename containing updated persistent XML for the target")
10579 .type
= VSH_OT_BOOL
,
10580 .help
= N_("use TLS for migration")
10582 {.name
= "postcopy-bandwidth",
10583 .type
= VSH_OT_INT
,
10584 .help
= N_("post-copy migration bandwidth limit in MiB/s")
10586 {.name
= "parallel",
10587 .type
= VSH_OT_BOOL
,
10588 .help
= N_("enable parallel migration")
10590 {.name
= "parallel-connections",
10591 .type
= VSH_OT_INT
,
10592 .help
= N_("number of connections for parallel migration")
10598 doMigrate(void *opaque
)
10601 virDomainPtr dom
= NULL
;
10602 const char *desturi
= NULL
;
10603 const char *opt
= NULL
;
10605 unsigned int flags
= 0;
10606 virshCtrlData
*data
= opaque
;
10607 vshControl
*ctl
= data
->ctl
;
10608 const vshCmd
*cmd
= data
->cmd
;
10609 sigset_t sigmask
, oldsigmask
;
10610 virTypedParameterPtr params
= NULL
;
10614 unsigned long long ullOpt
= 0;
10616 virConnectPtr dconn
= data
->dconn
;
10618 sigemptyset(&sigmask
);
10619 sigaddset(&sigmask
, SIGINT
);
10620 if (pthread_sigmask(SIG_BLOCK
, &sigmask
, &oldsigmask
) < 0)
10623 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
10626 if (vshCommandOptStringReq(ctl
, cmd
, "desturi", &desturi
) < 0)
10629 if (vshCommandOptStringReq(ctl
, cmd
, "migrateuri", &opt
) < 0)
10632 virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10633 VIR_MIGRATE_PARAM_URI
, opt
) < 0)
10636 if (vshCommandOptStringReq(ctl
, cmd
, "graphicsuri", &opt
) < 0)
10639 virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10640 VIR_MIGRATE_PARAM_GRAPHICS_URI
, opt
) < 0)
10643 if (vshCommandOptStringReq(ctl
, cmd
, "listen-address", &opt
) < 0)
10646 virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10647 VIR_MIGRATE_PARAM_LISTEN_ADDRESS
, opt
) < 0)
10650 if (vshCommandOptInt(ctl
, cmd
, "disks-port", &disksPort
) < 0)
10653 virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10654 VIR_MIGRATE_PARAM_DISKS_PORT
, disksPort
) < 0)
10657 if (vshCommandOptStringReq(ctl
, cmd
, "dname", &opt
) < 0)
10660 virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10661 VIR_MIGRATE_PARAM_DEST_NAME
, opt
) < 0)
10664 if (vshCommandOptStringReq(ctl
, cmd
, "migrate-disks", &opt
) < 0)
10669 val
= virStringSplit(opt
, ",", 0);
10671 if (virTypedParamsAddStringList(¶ms
,
10674 VIR_MIGRATE_PARAM_MIGRATE_DISKS
,
10675 (const char **)val
) < 0) {
10683 if (vshCommandOptStringReq(ctl
, cmd
, "comp-methods", &opt
) < 0)
10686 char **val
= virStringSplit(opt
, ",", 0);
10688 if (virTypedParamsAddStringList(¶ms
,
10691 VIR_MIGRATE_PARAM_COMPRESSION
,
10692 (const char **)val
) < 0) {
10700 if ((rv
= vshCommandOptInt(ctl
, cmd
, "comp-mt-level", &intOpt
)) < 0) {
10702 } else if (rv
> 0) {
10703 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10704 VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL
,
10709 if ((rv
= vshCommandOptInt(ctl
, cmd
, "comp-mt-threads", &intOpt
)) < 0) {
10711 } else if (rv
> 0) {
10712 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10713 VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS
,
10718 if ((rv
= vshCommandOptInt(ctl
, cmd
, "comp-mt-dthreads", &intOpt
)) < 0) {
10720 } else if (rv
> 0) {
10721 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10722 VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS
,
10727 if ((rv
= vshCommandOptULongLong(ctl
, cmd
, "comp-xbzrle-cache", &ullOpt
)) < 0) {
10729 } else if (rv
> 0) {
10730 if (virTypedParamsAddULLong(¶ms
, &nparams
, &maxparams
,
10731 VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE
,
10736 if (vshCommandOptStringReq(ctl
, cmd
, "xml", &opt
) < 0)
10741 if (virFileReadAll(opt
, VSH_MAX_XML_FILE
, &xml
) < 0) {
10742 vshError(ctl
, _("cannot read file '%s'"), opt
);
10746 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10747 VIR_MIGRATE_PARAM_DEST_XML
, xml
) < 0) {
10754 if (vshCommandOptStringReq(ctl
, cmd
, "persistent-xml", &opt
) < 0)
10759 if (virFileReadAll(opt
, VSH_MAX_XML_FILE
, &xml
) < 0) {
10760 vshError(ctl
, _("cannot read file '%s'"), opt
);
10764 if (virTypedParamsAddString(¶ms
, &nparams
, &maxparams
,
10765 VIR_MIGRATE_PARAM_PERSIST_XML
, xml
) < 0) {
10772 if ((rv
= vshCommandOptInt(ctl
, cmd
, "auto-converge-initial", &intOpt
)) < 0) {
10774 } else if (rv
> 0) {
10775 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10776 VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL
,
10781 if ((rv
= vshCommandOptInt(ctl
, cmd
, "auto-converge-increment", &intOpt
)) < 0) {
10783 } else if (rv
> 0) {
10784 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10785 VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT
,
10790 if ((rv
= vshCommandOptULongLong(ctl
, cmd
, "postcopy-bandwidth", &ullOpt
)) < 0) {
10792 } else if (rv
> 0) {
10793 if (virTypedParamsAddULLong(¶ms
, &nparams
, &maxparams
,
10794 VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY
,
10799 if ((rv
= vshCommandOptInt(ctl
, cmd
, "parallel-connections", &intOpt
)) < 0) {
10801 } else if (rv
> 0) {
10802 if (virTypedParamsAddInt(¶ms
, &nparams
, &maxparams
,
10803 VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS
,
10808 if (vshCommandOptBool(cmd
, "live"))
10809 flags
|= VIR_MIGRATE_LIVE
;
10810 if (vshCommandOptBool(cmd
, "p2p"))
10811 flags
|= VIR_MIGRATE_PEER2PEER
;
10812 if (vshCommandOptBool(cmd
, "tunnelled"))
10813 flags
|= VIR_MIGRATE_TUNNELLED
;
10815 if (vshCommandOptBool(cmd
, "persistent"))
10816 flags
|= VIR_MIGRATE_PERSIST_DEST
;
10817 if (vshCommandOptBool(cmd
, "undefinesource"))
10818 flags
|= VIR_MIGRATE_UNDEFINE_SOURCE
;
10820 if (vshCommandOptBool(cmd
, "suspend"))
10821 flags
|= VIR_MIGRATE_PAUSED
;
10823 if (vshCommandOptBool(cmd
, "copy-storage-all"))
10824 flags
|= VIR_MIGRATE_NON_SHARED_DISK
;
10826 if (vshCommandOptBool(cmd
, "copy-storage-inc"))
10827 flags
|= VIR_MIGRATE_NON_SHARED_INC
;
10829 if (vshCommandOptBool(cmd
, "change-protection"))
10830 flags
|= VIR_MIGRATE_CHANGE_PROTECTION
;
10832 if (vshCommandOptBool(cmd
, "unsafe"))
10833 flags
|= VIR_MIGRATE_UNSAFE
;
10835 if (vshCommandOptBool(cmd
, "compressed"))
10836 flags
|= VIR_MIGRATE_COMPRESSED
;
10838 if (vshCommandOptBool(cmd
, "auto-converge"))
10839 flags
|= VIR_MIGRATE_AUTO_CONVERGE
;
10841 if (vshCommandOptBool(cmd
, "rdma-pin-all"))
10842 flags
|= VIR_MIGRATE_RDMA_PIN_ALL
;
10844 if (vshCommandOptBool(cmd
, "offline"))
10845 flags
|= VIR_MIGRATE_OFFLINE
;
10847 if (vshCommandOptBool(cmd
, "abort-on-error"))
10848 flags
|= VIR_MIGRATE_ABORT_ON_ERROR
;
10850 if (vshCommandOptBool(cmd
, "postcopy"))
10851 flags
|= VIR_MIGRATE_POSTCOPY
;
10853 if (vshCommandOptBool(cmd
, "tls"))
10854 flags
|= VIR_MIGRATE_TLS
;
10856 if (vshCommandOptBool(cmd
, "parallel"))
10857 flags
|= VIR_MIGRATE_PARALLEL
;
10859 if (flags
& VIR_MIGRATE_PEER2PEER
|| vshCommandOptBool(cmd
, "direct")) {
10860 if (virDomainMigrateToURI3(dom
, desturi
, params
, nparams
, flags
) == 0)
10863 /* For traditional live migration, connect to the destination host directly. */
10864 virDomainPtr ddom
= NULL
;
10866 if ((ddom
= virDomainMigrate3(dom
, dconn
, params
, nparams
, flags
))) {
10867 virshDomainFree(ddom
);
10873 pthread_sigmask(SIG_SETMASK
, &oldsigmask
, NULL
);
10875 virTypedParamsFree(params
, nparams
);
10876 virshDomainFree(dom
);
10877 ignore_value(safewrite(data
->writefd
, &ret
, sizeof(ret
)));
10881 vshSaveLibvirtError();
10886 VIRSH_MIGRATE_TIMEOUT_DEFAULT
,
10887 VIRSH_MIGRATE_TIMEOUT_SUSPEND
,
10888 VIRSH_MIGRATE_TIMEOUT_POSTCOPY
,
10889 } virshMigrateTimeoutAction
;
10892 virshMigrateTimeout(vshControl
*ctl
,
10896 virshMigrateTimeoutAction action
= *(virshMigrateTimeoutAction
*) opaque
;
10899 case VIRSH_MIGRATE_TIMEOUT_DEFAULT
: /* unreachable */
10900 case VIRSH_MIGRATE_TIMEOUT_SUSPEND
:
10901 vshDebug(ctl
, VSH_ERR_DEBUG
,
10902 "migration timed out; suspending domain\n");
10903 if (virDomainSuspend(dom
) < 0)
10904 vshDebug(ctl
, VSH_ERR_INFO
, "suspending domain failed\n");
10907 case VIRSH_MIGRATE_TIMEOUT_POSTCOPY
:
10908 vshDebug(ctl
, VSH_ERR_DEBUG
,
10909 "migration timed out; switching to post-copy\n");
10910 if (virDomainMigrateStartPostCopy(dom
, 0) < 0)
10911 vshDebug(ctl
, VSH_ERR_INFO
, "switching to post-copy failed\n");
10917 virshMigrateIteration(virConnectPtr conn ATTRIBUTE_UNUSED
,
10922 vshControl
*ctl
= opaque
;
10924 if (iteration
== 2) {
10925 vshDebug(ctl
, VSH_ERR_DEBUG
,
10926 "iteration %d finished; switching to post-copy\n",
10928 if (virDomainMigrateStartPostCopy(dom
, 0) < 0)
10929 vshDebug(ctl
, VSH_ERR_INFO
, "switching to post-copy failed\n");
10934 cmdMigrate(vshControl
*ctl
, const vshCmd
*cmd
)
10936 virDomainPtr dom
= NULL
;
10937 int p
[2] = {-1, -1};
10938 virThread workerThread
;
10939 bool verbose
= false;
10940 bool functionReturn
= false;
10942 virshMigrateTimeoutAction timeoutAction
= VIRSH_MIGRATE_TIMEOUT_DEFAULT
;
10943 bool live_flag
= false;
10944 virshCtrlData data
= { .dconn
= NULL
};
10945 virshControlPtr priv
= ctl
->privData
;
10946 int iterEvent
= -1;
10948 VSH_EXCLUSIVE_OPTIONS("live", "offline");
10949 VSH_EXCLUSIVE_OPTIONS("timeout-suspend", "timeout-postcopy");
10950 VSH_REQUIRE_OPTION("postcopy-after-precopy", "postcopy");
10951 VSH_REQUIRE_OPTION("timeout-postcopy", "postcopy");
10952 VSH_REQUIRE_OPTION("persistent-xml", "persistent");
10954 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
10957 if (vshCommandOptBool(cmd
, "verbose"))
10960 if (vshCommandOptBool(cmd
, "live"))
10962 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0) {
10964 } else if (timeout
> 0 && !live_flag
) {
10965 vshError(ctl
, "%s",
10966 _("migrate: Unexpected timeout for offline migration"));
10970 if (vshCommandOptBool(cmd
, "timeout-suspend"))
10971 timeoutAction
= VIRSH_MIGRATE_TIMEOUT_SUSPEND
;
10972 if (vshCommandOptBool(cmd
, "timeout-postcopy"))
10973 timeoutAction
= VIRSH_MIGRATE_TIMEOUT_POSTCOPY
;
10975 if (timeoutAction
== VIRSH_MIGRATE_TIMEOUT_DEFAULT
)
10976 timeoutAction
= VIRSH_MIGRATE_TIMEOUT_SUSPEND
;
10977 } else if (timeoutAction
) {
10978 vshError(ctl
, "%s",
10979 _("migrate: Unexpected --timeout-* option without --timeout"));
10983 if (vshCommandOptBool(cmd
, "postcopy-after-precopy")) {
10984 iterEvent
= virConnectDomainEventRegisterAny(
10986 VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION
,
10987 VIR_DOMAIN_EVENT_CALLBACK(virshMigrateIteration
),
10998 data
.writefd
= p
[1];
11000 if (vshCommandOptBool(cmd
, "p2p") || vshCommandOptBool(cmd
, "direct")) {
11003 /* For traditional live migration, connect to the destination host. */
11004 virConnectPtr dconn
= NULL
;
11005 const char *desturi
= NULL
;
11007 if (vshCommandOptStringReq(ctl
, cmd
, "desturi", &desturi
) < 0)
11010 dconn
= virshConnect(ctl
, desturi
, false);
11014 data
.dconn
= dconn
;
11017 if (virThreadCreate(&workerThread
,
11022 functionReturn
= virshWatchJob(ctl
, dom
, verbose
, p
[0], timeout
,
11023 virshMigrateTimeout
,
11024 &timeoutAction
, _("Migration"));
11026 virThreadJoin(&workerThread
);
11030 virConnectClose(data
.dconn
);
11031 if (iterEvent
!= -1)
11032 virConnectDomainEventDeregisterAny(priv
->conn
, iterEvent
);
11033 virshDomainFree(dom
);
11034 VIR_FORCE_CLOSE(p
[0]);
11035 VIR_FORCE_CLOSE(p
[1]);
11036 return functionReturn
;
11040 * "migrate-setmaxdowntime" command
11042 static const vshCmdInfo info_migrate_setmaxdowntime
[] = {
11044 .data
= N_("set maximum tolerable downtime")
11047 .data
= N_("Set maximum tolerable downtime of a domain which is being live-migrated to another host.")
11052 static const vshCmdOptDef opts_migrate_setmaxdowntime
[] = {
11053 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11054 {.name
= "downtime",
11055 .type
= VSH_OT_INT
,
11056 .flags
= VSH_OFLAG_REQ
,
11057 .help
= N_("maximum tolerable downtime (in milliseconds) for migration")
11063 cmdMigrateSetMaxDowntime(vshControl
*ctl
, const vshCmd
*cmd
)
11065 virDomainPtr dom
= NULL
;
11066 unsigned long long downtime
= 0;
11069 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11072 if (vshCommandOptULongLong(ctl
, cmd
, "downtime", &downtime
) < 0)
11074 if (downtime
< 1) {
11075 vshError(ctl
, "%s", _("migrate: Invalid downtime"));
11079 if (virDomainMigrateSetMaxDowntime(dom
, downtime
, 0))
11085 virshDomainFree(dom
);
11091 * "migrate-getmaxdowntime" command
11093 static const vshCmdInfo info_migrate_getmaxdowntime
[] = {
11095 .data
= N_("get maximum tolerable downtime")
11098 .data
= N_("Get maximum tolerable downtime of a domain which is being live-migrated to another host.")
11103 static const vshCmdOptDef opts_migrate_getmaxdowntime
[] = {
11104 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11109 cmdMigrateGetMaxDowntime(vshControl
*ctl
, const vshCmd
*cmd
)
11111 virDomainPtr dom
= NULL
;
11112 unsigned long long downtime
;
11115 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11118 if (virDomainMigrateGetMaxDowntime(dom
, &downtime
, 0) < 0)
11121 vshPrint(ctl
, "%llu\n", downtime
);
11125 virshDomainFree(dom
);
11131 * "migrate-compcache" command
11133 static const vshCmdInfo info_migrate_compcache
[] = {
11135 .data
= N_("get/set compression cache size")
11138 .data
= N_("Get/set size of the cache (in bytes) used for compressing "
11139 "repeatedly transferred memory pages during live migration.")
11144 static const vshCmdOptDef opts_migrate_compcache
[] = {
11145 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11147 .type
= VSH_OT_INT
,
11148 .flags
= VSH_OFLAG_REQ_OPT
,
11149 .help
= N_("requested size of the cache (in bytes) used for compression")
11155 cmdMigrateCompCache(vshControl
*ctl
, const vshCmd
*cmd
)
11157 virDomainPtr dom
= NULL
;
11158 unsigned long long size
= 0;
11164 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11167 rc
= vshCommandOptULongLong(ctl
, cmd
, "size", &size
);
11170 } else if (rc
!= 0) {
11171 if (virDomainMigrateSetCompressionCache(dom
, size
, 0) < 0)
11175 if (virDomainMigrateGetCompressionCache(dom
, &size
, 0) < 0)
11178 value
= vshPrettyCapacity(size
, &unit
);
11179 vshPrint(ctl
, _("Compression cache: %.3lf %s"), value
, unit
);
11183 virshDomainFree(dom
);
11188 * "migrate-setspeed" command
11190 static const vshCmdInfo info_migrate_setspeed
[] = {
11192 .data
= N_("Set the maximum migration bandwidth")
11195 .data
= N_("Set the maximum migration bandwidth (in MiB/s) for a domain "
11196 "which is being migrated to another host.")
11201 static const vshCmdOptDef opts_migrate_setspeed
[] = {
11202 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11203 {.name
= "bandwidth",
11204 .type
= VSH_OT_INT
,
11205 .flags
= VSH_OFLAG_REQ
,
11206 .help
= N_("migration bandwidth limit in MiB/s")
11208 {.name
= "postcopy",
11209 .type
= VSH_OT_BOOL
,
11210 .help
= N_("set post-copy migration bandwidth")
11216 cmdMigrateSetMaxSpeed(vshControl
*ctl
, const vshCmd
*cmd
)
11218 virDomainPtr dom
= NULL
;
11219 unsigned long bandwidth
= 0;
11220 unsigned int flags
= 0;
11223 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11226 if (vshCommandOptULWrap(ctl
, cmd
, "bandwidth", &bandwidth
) < 0)
11229 if (vshCommandOptBool(cmd
, "postcopy"))
11230 flags
|= VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY
;
11232 if (virDomainMigrateSetMaxSpeed(dom
, bandwidth
, flags
) < 0)
11238 virshDomainFree(dom
);
11243 * "migrate-getspeed" command
11245 static const vshCmdInfo info_migrate_getspeed
[] = {
11247 .data
= N_("Get the maximum migration bandwidth")
11250 .data
= N_("Get the maximum migration bandwidth (in MiB/s) for a domain.")
11255 static const vshCmdOptDef opts_migrate_getspeed
[] = {
11256 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11257 {.name
= "postcopy",
11258 .type
= VSH_OT_BOOL
,
11259 .help
= N_("get post-copy migration bandwidth")
11265 cmdMigrateGetMaxSpeed(vshControl
*ctl
, const vshCmd
*cmd
)
11267 virDomainPtr dom
= NULL
;
11268 unsigned long bandwidth
;
11269 unsigned int flags
= 0;
11272 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11275 if (vshCommandOptBool(cmd
, "postcopy"))
11276 flags
|= VIR_DOMAIN_MIGRATE_MAX_SPEED_POSTCOPY
;
11278 if (virDomainMigrateGetMaxSpeed(dom
, &bandwidth
, flags
) < 0)
11281 vshPrint(ctl
, "%lu\n", bandwidth
);
11286 virshDomainFree(dom
);
11291 * "migrate-postcopy" command
11293 static const vshCmdInfo info_migrate_postcopy
[] = {
11295 .data
= N_("Switch running migration from pre-copy to post-copy")
11298 .data
= N_("Switch running migration from pre-copy to post-copy. "
11299 "The migration must have been started with --postcopy option.")
11304 static const vshCmdOptDef opts_migrate_postcopy
[] = {
11305 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11310 cmdMigratePostCopy(vshControl
*ctl
, const vshCmd
*cmd
)
11315 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11318 if (virDomainMigrateStartPostCopy(dom
, 0) < 0)
11324 virshDomainFree(dom
);
11329 * "domdisplay" command
11331 static const vshCmdInfo info_domdisplay
[] = {
11333 .data
= N_("domain display connection URI")
11336 .data
= N_("Output the IP address and port number "
11337 "for the graphical display.")
11342 static const vshCmdOptDef opts_domdisplay
[] = {
11343 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11344 {.name
= "include-password",
11345 .type
= VSH_OT_BOOL
,
11346 .help
= N_("includes the password into the connection URI if available")
11349 .type
= VSH_OT_STRING
,
11350 .help
= N_("select particular graphical display "
11351 "(e.g. \"vnc\", \"spice\", \"rdp\")")
11354 .type
= VSH_OT_BOOL
,
11355 .help
= N_("show all possible graphical displays")
11361 cmdDomDisplay(vshControl
*ctl
, const vshCmd
*cmd
)
11363 xmlDocPtr xml
= NULL
;
11364 xmlXPathContextPtr ctxt
= NULL
;
11366 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
11368 char *xpath
= NULL
;
11369 char *listen_addr
= NULL
;
11370 int port
, tls_port
= 0;
11371 char *type_conn
= NULL
;
11372 char *sockpath
= NULL
;
11373 char *passwd
= NULL
;
11374 char *output
= NULL
;
11375 const char *scheme
[] = { "vnc", "spice", "rdp", NULL
};
11376 const char *type
= NULL
;
11380 bool params
= false;
11381 bool all
= vshCommandOptBool(cmd
, "all");
11382 const char *xpath_fmt
= "string(/domain/devices/graphics[@type='%s']/%s)";
11383 virSocketAddr addr
;
11385 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11388 if (!virDomainIsActive(dom
)) {
11389 vshError(ctl
, _("Domain is not running"));
11393 if (vshCommandOptBool(cmd
, "include-password"))
11394 flags
|= VIR_DOMAIN_XML_SECURE
;
11396 if (vshCommandOptStringReq(ctl
, cmd
, "type", &type
) < 0)
11399 if (virshDomainGetXMLFromDom(ctl
, dom
, flags
, &xml
, &ctxt
) < 0)
11402 /* Attempt to grab our display info */
11403 for (iter
= 0; scheme
[iter
] != NULL
; iter
++) {
11404 /* Particular scheme requested */
11405 if (!all
&& type
&& STRNEQ(type
, scheme
[iter
]))
11408 /* Create our XPATH lookup for the current display's port */
11410 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "@port") < 0)
11413 /* Attempt to get the port number for the current graphics scheme */
11414 tmp
= virXPathInt(xpath
, ctxt
, &port
);
11417 /* If there is no port number for this type, then jump to the next
11422 /* Create our XPATH lookup for TLS Port (automatically skipped
11423 * for unsupported schemes */
11424 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "@tlsPort") < 0)
11427 /* Attempt to get the TLS port number */
11428 tmp
= virXPathInt(xpath
, ctxt
, &tls_port
);
11433 /* Create our XPATH lookup for the current display's address */
11434 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "@listen") < 0)
11437 /* Attempt to get the listening addr if set for the current
11438 * graphics scheme */
11439 VIR_FREE(listen_addr
);
11440 listen_addr
= virXPathString(xpath
, ctxt
);
11443 /* Create our XPATH lookup for the current spice type. */
11444 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "listen/@type") < 0)
11447 /* Attempt to get the type of spice connection */
11448 VIR_FREE(type_conn
);
11449 type_conn
= virXPathString(xpath
, ctxt
);
11452 if (STREQ_NULLABLE(type_conn
, "socket")) {
11454 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "listen/@socket") < 0)
11457 sockpath
= virXPathString(xpath
, ctxt
);
11463 if (!port
&& !tls_port
&& !sockpath
)
11466 if (!listen_addr
) {
11467 /* The subelement address - <listen address='xyz'/> -
11468 * *should* have been automatically backfilled into its
11469 * parent <graphics listen='xyz'> (which we just tried to
11470 * retrieve into listen_addr above) but in some cases it
11471 * isn't, so we also do an explicit check for the
11472 * subelement (which, by the way, doesn't exist on libvirt
11473 * < 0.9.4, so we really do need to check both places)
11475 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "listen/@address") < 0)
11478 listen_addr
= virXPathString(xpath
, ctxt
);
11481 /* If listen_addr is 0.0.0.0 or [::] we should try to parse URI and set
11482 * listen_addr based on current URI. */
11483 if (virSocketAddrParse(&addr
, listen_addr
, AF_UNSPEC
) > 0 &&
11484 virSocketAddrIsWildcard(&addr
)) {
11486 virConnectPtr conn
= ((virshControlPtr
)(ctl
->privData
))->conn
;
11487 char *uriStr
= virConnectGetURI(conn
);
11488 virURIPtr uri
= NULL
;
11491 uri
= virURIParse(uriStr
);
11495 /* It's safe to free the listen_addr even if parsing of URI
11496 * fails, if there is no listen_addr we will print "localhost". */
11497 VIR_FREE(listen_addr
);
11500 listen_addr
= vshStrdup(ctl
, uri
->server
);
11506 /* We can query this info for all the graphics types since we'll
11507 * get nothing for the unsupported ones (just rdp for now).
11508 * Also the parameter '--include-password' was already taken
11509 * care of when getting the XML */
11511 /* Create our XPATH lookup for the password */
11512 if (virAsprintf(&xpath
, xpath_fmt
, scheme
[iter
], "@passwd") < 0)
11515 /* Attempt to get the password */
11517 passwd
= virXPathString(xpath
, ctxt
);
11520 /* Build up the full URI, starting with the scheme */
11522 virBufferAsprintf(&buf
, "%s+unix://", scheme
[iter
]);
11524 virBufferAsprintf(&buf
, "%s://", scheme
[iter
]);
11526 /* There is no user, so just append password if there's any */
11527 if (STREQ(scheme
[iter
], "vnc") && passwd
)
11528 virBufferAsprintf(&buf
, ":%s@", passwd
);
11530 /* Then host name or IP */
11531 if (!listen_addr
&& !sockpath
)
11532 virBufferAddLit(&buf
, "localhost");
11533 else if (!sockpath
&& strchr(listen_addr
, ':'))
11534 virBufferAsprintf(&buf
, "[%s]", listen_addr
);
11536 virBufferAsprintf(&buf
, "%s", sockpath
);
11538 virBufferAsprintf(&buf
, "%s", listen_addr
);
11540 /* Free socket to prepare the pointer for the next iteration */
11541 VIR_FREE(sockpath
);
11545 if (STREQ(scheme
[iter
], "vnc")) {
11546 /* VNC protocol handlers take their port number as
11551 virBufferAsprintf(&buf
, ":%d", port
);
11556 virBufferAsprintf(&buf
,
11562 if (STREQ(scheme
[iter
], "spice") && passwd
) {
11563 virBufferAsprintf(&buf
,
11565 params
? "&" : "?",
11570 /* Ensure we can print our URI */
11571 if (virBufferError(&buf
)) {
11572 vshError(ctl
, "%s", _("Failed to create display URI"));
11576 /* Print out our full URI */
11578 output
= virBufferContentAndReset(&buf
);
11579 vshPrint(ctl
, "%s", output
);
11581 /* We got what we came for so return successfully */
11586 vshPrint(ctl
, "\n");
11592 vshError(ctl
, _("No graphical display with type '%s' found"), type
);
11594 vshError(ctl
, _("No graphical display found"));
11599 VIR_FREE(type_conn
);
11600 VIR_FREE(sockpath
);
11602 VIR_FREE(listen_addr
);
11604 xmlXPathFreeContext(ctxt
);
11606 virshDomainFree(dom
);
11611 * "vncdisplay" command
11613 static const vshCmdInfo info_vncdisplay
[] = {
11615 .data
= N_("vnc display")
11618 .data
= N_("Output the IP address and port number for the VNC display.")
11623 static const vshCmdOptDef opts_vncdisplay
[] = {
11624 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11629 cmdVNCDisplay(vshControl
*ctl
, const vshCmd
*cmd
)
11631 xmlDocPtr xml
= NULL
;
11632 xmlXPathContextPtr ctxt
= NULL
;
11636 char *listen_addr
= NULL
;
11638 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11641 /* Check if the domain is active and don't rely on -1 for this */
11642 if (!virDomainIsActive(dom
)) {
11643 vshError(ctl
, _("Domain is not running"));
11647 if (virshDomainGetXMLFromDom(ctl
, dom
, 0, &xml
, &ctxt
) < 0)
11650 /* Get the VNC port */
11651 if (virXPathInt("string(/domain/devices/graphics[@type='vnc']/@port)",
11653 vshError(ctl
, _("Failed to get VNC port. Is this domain using VNC?"));
11657 listen_addr
= virXPathString("string(/domain/devices/graphics"
11658 "[@type='vnc']/@listen)", ctxt
);
11659 if (!listen_addr
) {
11660 /* The subelement address - <listen address='xyz'/> -
11661 * *should* have been automatically backfilled into its
11662 * parent <graphics listen='xyz'> (which we just tried to
11663 * retrieve into listen_addr above) but in some cases it
11664 * isn't, so we also do an explicit check for the
11665 * subelement (which, by the way, doesn't exist on libvirt
11666 * < 0.9.4, so we really do need to check both places)
11668 listen_addr
= virXPathString("string(/domain/devices/graphics"
11669 "[@type='vnc']/listen/@address)", ctxt
);
11671 if (listen_addr
== NULL
|| STREQ(listen_addr
, "0.0.0.0"))
11672 vshPrint(ctl
, ":%d\n", port
-5900);
11674 vshPrint(ctl
, "%s:%d\n", listen_addr
, port
-5900);
11679 VIR_FREE(listen_addr
);
11680 xmlXPathFreeContext(ctxt
);
11682 virshDomainFree(dom
);
11687 * "ttyconsole" command
11689 static const vshCmdInfo info_ttyconsole
[] = {
11691 .data
= N_("tty console")
11694 .data
= N_("Output the device for the TTY console.")
11699 static const vshCmdOptDef opts_ttyconsole
[] = {
11700 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
11705 cmdTTYConsole(vshControl
*ctl
, const vshCmd
*cmd
)
11707 xmlDocPtr xml
= NULL
;
11708 xmlXPathContextPtr ctxt
= NULL
;
11712 if (virshDomainGetXML(ctl
, cmd
, 0, &xml
, &ctxt
) < 0)
11715 if (!(tty
= virXPathString("string(/domain/devices/console/@tty)", ctxt
)))
11718 vshPrint(ctl
, "%s\n", tty
);
11722 xmlXPathFreeContext(ctxt
);
11729 * "domhostname" command
11731 static const vshCmdInfo info_domhostname
[] = {
11733 .data
= N_("print the domain's hostname")
11741 static const vshCmdOptDef opts_domhostname
[] = {
11742 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
11747 cmdDomHostname(vshControl
*ctl
, const vshCmd
*cmd
)
11753 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11756 hostname
= virDomainGetHostname(dom
, 0);
11757 if (hostname
== NULL
) {
11758 vshError(ctl
, "%s", _("failed to get hostname"));
11762 vshPrint(ctl
, "%s\n", hostname
);
11766 VIR_FREE(hostname
);
11767 virshDomainFree(dom
);
11772 * Check if n1 is superset of n2, meaning n1 contains all elements and
11773 * attributes as n2 at least. Including children.
11776 * returns true in case n1 covers n2, false otherwise.
11780 virshNodeIsSuperset(xmlNodePtr n1
, xmlNodePtr n2
)
11782 xmlNodePtr child1
, child2
;
11784 char *prop1
, *prop2
;
11788 long n1_child_size
, n2_child_size
, n1_iter
;
11789 virBitmapPtr bitmap
;
11797 if (!xmlStrEqual(n1
->name
, n2
->name
))
11800 /* Iterate over n2 attributes and check if n1 contains them*/
11801 attr
= n2
->properties
;
11803 if (attr
->type
== XML_ATTRIBUTE_NODE
) {
11804 prop1
= virXMLPropString(n1
, (const char *) attr
->name
);
11805 prop2
= virXMLPropString(n2
, (const char *) attr
->name
);
11806 if (STRNEQ_NULLABLE(prop1
, prop2
)) {
11817 n1_child_size
= virXMLChildElementCount(n1
);
11818 n2_child_size
= virXMLChildElementCount(n2
);
11819 if (n1_child_size
< 0 || n2_child_size
< 0 ||
11820 n1_child_size
< n2_child_size
)
11823 if (n1_child_size
== 0 && n2_child_size
== 0)
11826 if (!(bitmap
= virBitmapNew(n1_child_size
)))
11829 child2
= n2
->children
;
11831 if (child2
->type
!= XML_ELEMENT_NODE
) {
11832 child2
= child2
->next
;
11836 child1
= n1
->children
;
11840 if (child1
->type
!= XML_ELEMENT_NODE
) {
11841 child1
= child1
->next
;
11845 if (virBitmapGetBit(bitmap
, n1_iter
, &visited
) < 0) {
11846 vshError(NULL
, "%s", _("Bad child elements counting."));
11851 child1
= child1
->next
;
11856 if (xmlStrEqual(child1
->name
, child2
->name
)) {
11858 if (virBitmapSetBit(bitmap
, n1_iter
) < 0) {
11859 vshError(NULL
, "%s", _("Bad child elements counting."));
11863 if (!virshNodeIsSuperset(child1
, child2
))
11869 child1
= child1
->next
;
11876 child2
= child2
->next
;
11882 virBitmapFree(bitmap
);
11888 * "detach-device" command
11890 static const vshCmdInfo info_detach_device
[] = {
11892 .data
= N_("detach device from an XML file")
11895 .data
= N_("Detach device from an XML <file>")
11900 static const vshCmdOptDef opts_detach_device
[] = {
11901 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
11902 VIRSH_COMMON_OPT_FILE(N_("XML file")),
11903 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
11904 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
11905 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
11906 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
11911 cmdDetachDevice(vshControl
*ctl
, const vshCmd
*cmd
)
11913 virDomainPtr dom
= NULL
;
11914 const char *from
= NULL
;
11915 char *buffer
= NULL
;
11917 bool funcRet
= false;
11918 bool current
= vshCommandOptBool(cmd
, "current");
11919 bool config
= vshCommandOptBool(cmd
, "config");
11920 bool live
= vshCommandOptBool(cmd
, "live");
11921 bool persistent
= vshCommandOptBool(cmd
, "persistent");
11922 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
11924 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
11926 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
11927 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
11929 if (config
|| persistent
)
11930 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
11932 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
11934 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
11938 virDomainIsActive(dom
) == 1)
11939 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
11941 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
11944 if (virFileReadAll(from
, VSH_MAX_XML_FILE
, &buffer
) < 0) {
11945 vshReportError(ctl
);
11949 if (flags
!= 0 || current
)
11950 ret
= virDomainDetachDeviceFlags(dom
, buffer
, flags
);
11952 ret
= virDomainDetachDevice(dom
, buffer
);
11955 vshError(ctl
, _("Failed to detach device from %s"), from
);
11959 vshPrintExtra(ctl
, "%s", _("Device detached successfully\n"));
11964 virshDomainFree(dom
);
11970 * "detach-device-alias" command
11972 static const vshCmdInfo info_detach_device_alias
[] = {
11974 .data
= N_("detach device from an alias")
11977 .data
= N_("Detach device identified by the given alias from a domain")
11982 static const vshCmdOptDef opts_detach_device_alias
[] = {
11983 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
11985 .type
= VSH_OT_DATA
,
11986 .flags
= VSH_OFLAG_REQ
,
11987 .completer
= virshDomainDeviceAliasCompleter
,
11988 .help
= N_("device alias")
11990 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
11991 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
11992 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
11997 cmdDetachDeviceAlias(vshControl
*ctl
, const vshCmd
*cmd
)
11999 virDomainPtr dom
= NULL
;
12000 const char *alias
= NULL
;
12001 bool current
= vshCommandOptBool(cmd
, "current");
12002 bool config
= vshCommandOptBool(cmd
, "config");
12003 bool live
= vshCommandOptBool(cmd
, "live");
12004 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
12007 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
12008 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
12011 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
12013 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12015 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
12018 if (vshCommandOptStringReq(ctl
, cmd
, "alias", &alias
) < 0)
12021 if (virDomainDetachDeviceAlias(dom
, alias
, flags
) < 0) {
12022 vshError(ctl
, _("Failed to detach device with alias %s"), alias
);
12026 vshPrintExtra(ctl
, "%s", _("Device detach request sent successfully\n"));
12030 virshDomainFree(dom
);
12036 * "update-device" command
12038 static const vshCmdInfo info_update_device
[] = {
12040 .data
= N_("update device from an XML file")
12043 .data
= N_("Update device from an XML <file>.")
12048 static const vshCmdOptDef opts_update_device
[] = {
12049 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
12050 VIRSH_COMMON_OPT_FILE(N_("XML file")),
12051 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
12052 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
12053 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
12054 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
12056 .type
= VSH_OT_BOOL
,
12057 .help
= N_("force device update")
12063 cmdUpdateDevice(vshControl
*ctl
, const vshCmd
*cmd
)
12066 const char *from
= NULL
;
12067 char *buffer
= NULL
;
12069 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
12070 bool current
= vshCommandOptBool(cmd
, "current");
12071 bool config
= vshCommandOptBool(cmd
, "config");
12072 bool live
= vshCommandOptBool(cmd
, "live");
12073 bool persistent
= vshCommandOptBool(cmd
, "persistent");
12075 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
12077 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
12078 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
12080 if (config
|| persistent
)
12081 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
12083 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12085 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
12088 if (vshCommandOptStringReq(ctl
, cmd
, "file", &from
) < 0)
12092 virDomainIsActive(dom
) == 1)
12093 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12095 if (virFileReadAll(from
, VSH_MAX_XML_FILE
, &buffer
) < 0) {
12096 vshReportError(ctl
);
12100 if (vshCommandOptBool(cmd
, "force"))
12101 flags
|= VIR_DOMAIN_DEVICE_MODIFY_FORCE
;
12103 if (virDomainUpdateDeviceFlags(dom
, buffer
, flags
) < 0) {
12104 vshError(ctl
, _("Failed to update device from %s"), from
);
12108 vshPrintExtra(ctl
, "%s", _("Device updated successfully\n"));
12113 virshDomainFree(dom
);
12118 * "detach-interface" command
12120 static const vshCmdInfo info_detach_interface
[] = {
12122 .data
= N_("detach network interface")
12125 .data
= N_("Detach network interface.")
12130 static const vshCmdOptDef opts_detach_interface
[] = {
12131 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
12133 .type
= VSH_OT_DATA
,
12134 .flags
= VSH_OFLAG_REQ
,
12135 .help
= N_("network interface type")
12138 .type
= VSH_OT_STRING
,
12139 .completer
= virshDomainInterfaceCompleter
,
12140 .completer_flags
= VIRSH_DOMAIN_INTERFACE_COMPLETER_MAC
,
12141 .help
= N_("MAC address")
12143 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
12144 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
12145 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
12146 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
12151 virshDomainDetachInterface(char *doc
,
12152 unsigned int flags
,
12159 xmlDocPtr xml
= NULL
;
12160 xmlXPathObjectPtr obj
= NULL
;
12161 xmlXPathContextPtr ctxt
= NULL
;
12162 xmlNodePtr cur
= NULL
, matchNode
= NULL
;
12163 char *detach_xml
= NULL
, buf
[64];
12164 int diff_mac
, ret
= -1;
12167 if (!(xml
= virXMLParseStringCtxt(doc
, _("(domain_definition)"), &ctxt
))) {
12168 vshError(ctl
, "%s", _("Failed to get interface information"));
12172 snprintf(buf
, sizeof(buf
), "/domain/devices/interface[@type='%s']", type
);
12173 obj
= xmlXPathEval(BAD_CAST buf
, ctxt
);
12174 if (obj
== NULL
|| obj
->type
!= XPATH_NODESET
||
12175 obj
->nodesetval
== NULL
|| obj
->nodesetval
->nodeNr
== 0) {
12176 vshError(ctl
, _("No interface found whose type is %s"), type
);
12180 if (!mac
&& obj
->nodesetval
->nodeNr
> 1) {
12181 vshError(ctl
, _("Domain has %d interfaces. Please specify which one "
12182 "to detach using --mac"), obj
->nodesetval
->nodeNr
);
12187 matchNode
= obj
->nodesetval
->nodeTab
[0];
12191 /* multiple possibilities, so search for matching mac */
12192 for (i
= 0; i
< obj
->nodesetval
->nodeNr
; i
++) {
12193 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
12194 while (cur
!= NULL
) {
12195 if (cur
->type
== XML_ELEMENT_NODE
&&
12196 virXMLNodeNameEqual(cur
, "mac")) {
12197 char *tmp_mac
= virXMLPropString(cur
, "address");
12198 diff_mac
= virMacAddrCompare(tmp_mac
, mac
);
12202 /* this is the 2nd match, so it's ambiguous */
12203 vshError(ctl
, _("Domain has multiple interfaces matching "
12204 "MAC address %s. You must use detach-device and "
12205 "specify the device pci address to remove it."),
12209 matchNode
= obj
->nodesetval
->nodeTab
[i
];
12216 vshError(ctl
, _("No interface with MAC address %s was found"), mac
);
12221 if (!(detach_xml
= virXMLNodeToString(xml
, matchNode
))) {
12222 vshSaveLibvirtError();
12226 if (flags
!= 0 || current
)
12227 ret
= virDomainDetachDeviceFlags(dom
, detach_xml
, flags
);
12229 ret
= virDomainDetachDevice(dom
, detach_xml
);
12232 VIR_FREE(detach_xml
);
12234 xmlXPathFreeObject(obj
);
12235 xmlXPathFreeContext(ctxt
);
12241 cmdDetachInterface(vshControl
*ctl
, const vshCmd
*cmd
)
12243 virDomainPtr dom
= NULL
;
12244 char *doc_live
= NULL
, *doc_config
= NULL
;
12245 const char *mac
= NULL
, *type
= NULL
;
12247 bool ret
= false, affect_config
, affect_live
;
12248 bool current
= vshCommandOptBool(cmd
, "current");
12249 bool config
= vshCommandOptBool(cmd
, "config");
12250 bool live
= vshCommandOptBool(cmd
, "live");
12251 bool persistent
= vshCommandOptBool(cmd
, "persistent");
12253 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
12255 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
12256 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
12258 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
12261 if (vshCommandOptStringReq(ctl
, cmd
, "type", &type
) < 0)
12264 if (vshCommandOptStringReq(ctl
, cmd
, "mac", &mac
) < 0)
12267 affect_config
= (config
|| persistent
);
12269 if (affect_config
) {
12270 if (!(doc_config
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
)))
12272 if (!(ret
= virshDomainDetachInterface(doc_config
,
12273 flags
| VIR_DOMAIN_AFFECT_CONFIG
,
12274 dom
, ctl
, current
, type
, mac
)))
12278 affect_live
= (live
|| (persistent
&& virDomainIsActive(dom
) == 1));
12280 if (affect_live
|| !affect_config
) {
12284 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12286 if (!(doc_live
= virDomainGetXMLDesc(dom
, 0)))
12289 ret
= virshDomainDetachInterface(doc_live
, flags
,
12290 dom
, ctl
, current
, type
, mac
);
12295 vshError(ctl
, "%s", _("Failed to detach interface"));
12297 vshPrintExtra(ctl
, "%s", _("Interface detached successfully\n"));
12299 VIR_FREE(doc_live
);
12300 VIR_FREE(doc_config
);
12301 virshDomainFree(dom
);
12307 virshDiskDropBackingStore(xmlNodePtr disk_node
)
12311 for (tmp
= disk_node
->children
; tmp
; tmp
= tmp
->next
) {
12312 if (tmp
->type
!= XML_ELEMENT_NODE
)
12315 if (virXMLNodeNameEqual(tmp
, "backingStore")) {
12316 xmlUnlinkNode(tmp
);
12326 VIRSH_FIND_DISK_NORMAL
,
12327 VIRSH_FIND_DISK_CHANGEABLE
,
12328 } virshFindDiskType
;
12330 /* Helper function to find disk device in XML doc. Returns the disk
12331 * node on success, or NULL on failure. Caller must free the result
12332 * @path: Fully-qualified path or target of disk device.
12333 * @type: Either VIRSH_FIND_DISK_NORMAL or VIRSH_FIND_DISK_CHANGEABLE.
12336 virshFindDisk(const char *doc
,
12340 xmlDocPtr xml
= NULL
;
12341 xmlXPathObjectPtr obj
= NULL
;
12342 xmlXPathContextPtr ctxt
= NULL
;
12343 xmlNodePtr cur
= NULL
;
12344 xmlNodePtr ret
= NULL
;
12347 xml
= virXMLParseStringCtxt(doc
, _("(domain_definition)"), &ctxt
);
12349 vshError(NULL
, "%s", _("Failed to get disk information"));
12353 obj
= xmlXPathEval(BAD_CAST
"/domain/devices/disk", ctxt
);
12355 obj
->type
!= XPATH_NODESET
||
12356 obj
->nodesetval
== NULL
||
12357 obj
->nodesetval
->nodeNr
== 0) {
12358 vshError(NULL
, "%s", _("Failed to get disk information"));
12362 /* search disk using @path */
12363 for (i
= 0; i
< obj
->nodesetval
->nodeNr
; i
++) {
12364 bool is_supported
= true;
12366 if (type
== VIRSH_FIND_DISK_CHANGEABLE
) {
12367 xmlNodePtr n
= obj
->nodesetval
->nodeTab
[i
];
12368 is_supported
= false;
12370 /* Check if the disk is CDROM or floppy disk */
12371 if (virXMLNodeNameEqual(n
, "disk")) {
12372 char *device_value
= virXMLPropString(n
, "device");
12374 if (STREQ(device_value
, "cdrom") ||
12375 STREQ(device_value
, "floppy"))
12376 is_supported
= true;
12378 VIR_FREE(device_value
);
12385 cur
= obj
->nodesetval
->nodeTab
[i
]->children
;
12386 while (cur
!= NULL
) {
12387 if (cur
->type
== XML_ELEMENT_NODE
) {
12390 if (virXMLNodeNameEqual(cur
, "source")) {
12391 if ((tmp
= virXMLPropString(cur
, "file")) ||
12392 (tmp
= virXMLPropString(cur
, "dev")) ||
12393 (tmp
= virXMLPropString(cur
, "dir")) ||
12394 (tmp
= virXMLPropString(cur
, "name"))) {
12396 } else if (virXMLNodeNameEqual(cur
, "target")) {
12397 tmp
= virXMLPropString(cur
, "dev");
12400 if (STREQ_NULLABLE(tmp
, path
)) {
12401 ret
= xmlCopyNode(obj
->nodesetval
->nodeTab
[i
], 1);
12402 /* drop backing store since they are not needed here */
12403 virshDiskDropBackingStore(ret
);
12413 vshError(NULL
, _("No disk found whose source path or target is %s"), path
);
12416 xmlXPathFreeObject(obj
);
12417 xmlXPathFreeContext(ctxt
);
12423 VIRSH_UPDATE_DISK_XML_EJECT
,
12424 VIRSH_UPDATE_DISK_XML_INSERT
,
12425 VIRSH_UPDATE_DISK_XML_UPDATE
,
12426 } virshUpdateDiskXMLType
;
12428 /* Helper function to prepare disk XML. Could be used for disk
12429 * detaching, media changing(ejecting, inserting, updating)
12430 * for changeable disk. Returns the processed XML as string on
12431 * success, or NULL on failure. Caller must free the result.
12434 virshUpdateDiskXML(xmlNodePtr disk_node
,
12435 const char *new_source
,
12437 const char *target
,
12438 virshUpdateDiskXMLType type
)
12440 xmlNodePtr tmp
= NULL
;
12441 xmlNodePtr source
= NULL
;
12442 xmlNodePtr target_node
= NULL
;
12443 xmlNodePtr text_node
= NULL
;
12444 char *device_type
= NULL
;
12446 char *startupPolicy
= NULL
;
12447 char *source_path
= NULL
;
12452 device_type
= virXMLPropString(disk_node
, "device");
12454 if (!(STREQ_NULLABLE(device_type
, "cdrom") ||
12455 STREQ_NULLABLE(device_type
, "floppy"))) {
12456 vshError(NULL
, _("The disk device '%s' is not removable"), target
);
12460 /* find the current source subelement */
12461 for (tmp
= disk_node
->children
; tmp
; tmp
= tmp
->next
) {
12463 * Save the last text node before the <target/>. The
12464 * reasoning behind this is that the target node will be
12465 * present in this case and also has a proper indentation.
12467 if (!target_node
&& tmp
->type
== XML_TEXT_NODE
)
12471 * We need only element nodes from now on.
12473 if (tmp
->type
!= XML_ELEMENT_NODE
)
12476 if (virXMLNodeNameEqual(tmp
, "source"))
12479 if (virXMLNodeNameEqual(tmp
, "target"))
12483 * We've found all we needed.
12485 if (source
&& target_node
)
12489 if (type
== VIRSH_UPDATE_DISK_XML_EJECT
) {
12491 vshError(NULL
, _("The disk device '%s' doesn't have media"), target
);
12495 /* forcibly switch to empty file cdrom */
12496 source_block
= false;
12498 } else if (!new_source
) {
12499 vshError(NULL
, _("New disk media source was not specified"));
12504 if (!(source_path
= virXMLPropString(source
, "file")) &&
12505 !(source_path
= virXMLPropString(source
, "dev")) &&
12506 !(source_path
= virXMLPropString(source
, "dir")) &&
12507 !(source_path
= virXMLPropString(source
, "pool")))
12508 source_path
= virXMLPropString(source
, "name");
12510 if (source_path
&& type
== VIRSH_UPDATE_DISK_XML_INSERT
) {
12511 vshError(NULL
, _("The disk device '%s' already has media"), target
);
12515 startupPolicy
= virXMLPropString(source
, "startupPolicy");
12517 /* remove current source */
12518 xmlUnlinkNode(source
);
12519 xmlFreeNode(source
);
12523 /* set the correct disk type */
12525 xmlSetProp(disk_node
, BAD_CAST
"type", BAD_CAST
"block");
12527 xmlSetProp(disk_node
, BAD_CAST
"type", BAD_CAST
"file");
12530 /* create new source subelement */
12531 if (!(source
= xmlNewNode(NULL
, BAD_CAST
"source"))) {
12532 vshError(NULL
, _("Failed to allocate new source node"));
12537 xmlNewProp(source
, BAD_CAST
"dev", BAD_CAST new_source
);
12539 xmlNewProp(source
, BAD_CAST
"file", BAD_CAST new_source
);
12542 xmlNewProp(source
, BAD_CAST
"startupPolicy", BAD_CAST startupPolicy
);
12545 * So that the output XML looks nice in case anyone calls
12546 * 'change-media' with '--print-xml', let's attach the source
12549 xmlAddPrevSibling(target_node
, source
);
12552 * ... and duplicate the text node doing the indentation just
12553 * so it's more easily readable. And don't make it fatal.
12555 if ((tmp
= xmlCopyNode(text_node
, 0))) {
12556 if (!xmlAddPrevSibling(target_node
, tmp
))
12561 if (!(ret
= virXMLNodeToString(NULL
, disk_node
))) {
12562 vshSaveLibvirtError();
12567 VIR_FREE(device_type
);
12568 VIR_FREE(startupPolicy
);
12569 VIR_FREE(source_path
);
12575 * "detach-disk" command
12577 static const vshCmdInfo info_detach_disk
[] = {
12579 .data
= N_("detach disk device")
12582 .data
= N_("Detach disk device.")
12587 static const vshCmdOptDef opts_detach_disk
[] = {
12588 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
12590 .type
= VSH_OT_DATA
,
12591 .flags
= VSH_OFLAG_REQ
,
12592 .completer
= virshDomainDiskTargetCompleter
,
12593 .help
= N_("target of disk device")
12595 VIRSH_COMMON_OPT_DOMAIN_PERSISTENT
,
12596 VIRSH_COMMON_OPT_DOMAIN_CONFIG
,
12597 VIRSH_COMMON_OPT_DOMAIN_LIVE
,
12598 VIRSH_COMMON_OPT_DOMAIN_CURRENT
,
12599 {.name
= "print-xml",
12600 .type
= VSH_OT_BOOL
,
12601 .help
= N_("print XML document rather than detach the disk")
12607 cmdDetachDisk(vshControl
*ctl
, const vshCmd
*cmd
)
12609 char *disk_xml
= NULL
;
12610 virDomainPtr dom
= NULL
;
12611 const char *target
= NULL
;
12614 bool functionReturn
= false;
12615 xmlNodePtr disk_node
= NULL
;
12616 bool current
= vshCommandOptBool(cmd
, "current");
12617 bool config
= vshCommandOptBool(cmd
, "config");
12618 bool live
= vshCommandOptBool(cmd
, "live");
12619 bool persistent
= vshCommandOptBool(cmd
, "persistent");
12620 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
12622 VSH_EXCLUSIVE_OPTIONS_VAR(persistent
, current
);
12624 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
12625 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
12627 if (config
|| persistent
)
12628 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
12630 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12632 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
12635 if (vshCommandOptStringReq(ctl
, cmd
, "target", &target
) < 0)
12638 if (flags
== VIR_DOMAIN_AFFECT_CONFIG
)
12639 doc
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
12641 doc
= virDomainGetXMLDesc(dom
, 0);
12647 virDomainIsActive(dom
) == 1)
12648 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
12650 if (!(disk_node
= virshFindDisk(doc
, target
, VIRSH_FIND_DISK_NORMAL
)))
12653 if (!(disk_xml
= virXMLNodeToString(NULL
, disk_node
))) {
12654 vshSaveLibvirtError();
12658 if (vshCommandOptBool(cmd
, "print-xml")) {
12659 vshPrint(ctl
, "%s", disk_xml
);
12660 functionReturn
= true;
12664 if (flags
!= 0 || current
)
12665 ret
= virDomainDetachDeviceFlags(dom
, disk_xml
, flags
);
12667 ret
= virDomainDetachDevice(dom
, disk_xml
);
12670 vshError(ctl
, "%s", _("Failed to detach disk"));
12674 vshPrintExtra(ctl
, "%s", _("Disk detached successfully\n"));
12675 functionReturn
= true;
12678 xmlFreeNode(disk_node
);
12679 VIR_FREE(disk_xml
);
12681 virshDomainFree(dom
);
12682 return functionReturn
;
12688 static const vshCmdInfo info_edit
[] = {
12690 .data
= N_("edit XML configuration for a domain")
12693 .data
= N_("Edit the XML configuration for a domain.")
12698 static const vshCmdOptDef opts_edit
[] = {
12699 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
12700 {.name
= "skip-validate",
12701 .type
= VSH_OT_BOOL
,
12702 .help
= N_("skip validation of the XML against the schema")
12708 cmdEdit(vshControl
*ctl
, const vshCmd
*cmd
)
12711 virDomainPtr dom
= NULL
;
12712 virDomainPtr dom_edited
= NULL
;
12713 unsigned int query_flags
= VIR_DOMAIN_XML_SECURE
| VIR_DOMAIN_XML_INACTIVE
;
12714 unsigned int define_flags
= VIR_DOMAIN_DEFINE_VALIDATE
;
12715 virshControlPtr priv
= ctl
->privData
;
12717 dom
= virshCommandOptDomain(ctl
, cmd
, NULL
);
12721 if (vshCommandOptBool(cmd
, "skip-validate"))
12722 define_flags
&= ~VIR_DOMAIN_DEFINE_VALIDATE
;
12724 #define EDIT_GET_XML virDomainGetXMLDesc(dom, query_flags)
12725 #define EDIT_NOT_CHANGED \
12727 vshPrintExtra(ctl, _("Domain %s XML configuration not changed.\n"), \
12728 virDomainGetName(dom)); \
12730 goto edit_cleanup; \
12732 #define EDIT_DEFINE \
12733 (dom_edited = virshDomainDefine(priv->conn, doc_edited, define_flags))
12734 #define EDIT_RELAX \
12736 define_flags &= ~VIR_DOMAIN_DEFINE_VALIDATE; \
12739 #include "virsh-edit.c"
12742 vshPrintExtra(ctl
, _("Domain %s XML configuration edited.\n"),
12743 virDomainGetName(dom_edited
));
12748 virshDomainFree(dom
);
12749 virshDomainFree(dom_edited
);
12758 VIR_ENUM_DECL(virshDomainEvent
);
12759 VIR_ENUM_IMPL(virshDomainEvent
,
12760 VIR_DOMAIN_EVENT_LAST
,
12771 static const char *
12772 virshDomainEventToString(int event
)
12774 const char *str
= virshDomainEventTypeToString(event
);
12775 return str
? _(str
) : _("unknown");
12778 VIR_ENUM_DECL(virshDomainEventDefined
);
12779 VIR_ENUM_IMPL(virshDomainEventDefined
,
12780 VIR_DOMAIN_EVENT_DEFINED_LAST
,
12786 VIR_ENUM_DECL(virshDomainEventUndefined
);
12787 VIR_ENUM_IMPL(virshDomainEventUndefined
,
12788 VIR_DOMAIN_EVENT_UNDEFINED_LAST
,
12792 VIR_ENUM_DECL(virshDomainEventStarted
);
12793 VIR_ENUM_IMPL(virshDomainEventStarted
,
12794 VIR_DOMAIN_EVENT_STARTED_LAST
,
12799 N_("Event wakeup"));
12801 VIR_ENUM_DECL(virshDomainEventSuspended
);
12802 VIR_ENUM_IMPL(virshDomainEventSuspended
,
12803 VIR_DOMAIN_EVENT_SUSPENDED_LAST
,
12812 N_("Post-copy Error"));
12814 VIR_ENUM_DECL(virshDomainEventResumed
);
12815 VIR_ENUM_IMPL(virshDomainEventResumed
,
12816 VIR_DOMAIN_EVENT_RESUMED_LAST
,
12822 VIR_ENUM_DECL(virshDomainEventStopped
);
12823 VIR_ENUM_IMPL(virshDomainEventStopped
,
12824 VIR_DOMAIN_EVENT_STOPPED_LAST
,
12833 VIR_ENUM_DECL(virshDomainEventShutdown
);
12834 VIR_ENUM_IMPL(virshDomainEventShutdown
,
12835 VIR_DOMAIN_EVENT_SHUTDOWN_LAST
,
12837 N_("Finished after guest request"),
12838 N_("Finished after host request"));
12840 VIR_ENUM_DECL(virshDomainEventPMSuspended
);
12841 VIR_ENUM_IMPL(virshDomainEventPMSuspended
,
12842 VIR_DOMAIN_EVENT_PMSUSPENDED_LAST
,
12846 VIR_ENUM_DECL(virshDomainEventCrashed
);
12847 VIR_ENUM_IMPL(virshDomainEventCrashed
,
12848 VIR_DOMAIN_EVENT_CRASHED_LAST
,
12851 static const char *
12852 virshDomainEventDetailToString(int event
, int detail
)
12854 const char *str
= NULL
;
12855 switch ((virDomainEventType
) event
) {
12856 case VIR_DOMAIN_EVENT_DEFINED
:
12857 str
= virshDomainEventDefinedTypeToString(detail
);
12859 case VIR_DOMAIN_EVENT_UNDEFINED
:
12860 str
= virshDomainEventUndefinedTypeToString(detail
);
12862 case VIR_DOMAIN_EVENT_STARTED
:
12863 str
= virshDomainEventStartedTypeToString(detail
);
12865 case VIR_DOMAIN_EVENT_SUSPENDED
:
12866 str
= virshDomainEventSuspendedTypeToString(detail
);
12868 case VIR_DOMAIN_EVENT_RESUMED
:
12869 str
= virshDomainEventResumedTypeToString(detail
);
12871 case VIR_DOMAIN_EVENT_STOPPED
:
12872 str
= virshDomainEventStoppedTypeToString(detail
);
12874 case VIR_DOMAIN_EVENT_SHUTDOWN
:
12875 str
= virshDomainEventShutdownTypeToString(detail
);
12877 case VIR_DOMAIN_EVENT_PMSUSPENDED
:
12878 str
= virshDomainEventPMSuspendedTypeToString(detail
);
12880 case VIR_DOMAIN_EVENT_CRASHED
:
12881 str
= virshDomainEventCrashedTypeToString(detail
);
12883 case VIR_DOMAIN_EVENT_LAST
:
12886 return str
? _(str
) : _("unknown");
12889 VIR_ENUM_DECL(virshDomainEventWatchdog
);
12890 VIR_ENUM_IMPL(virshDomainEventWatchdog
,
12891 VIR_DOMAIN_EVENT_WATCHDOG_LAST
,
12900 static const char *
12901 virshDomainEventWatchdogToString(int action
)
12903 const char *str
= virshDomainEventWatchdogTypeToString(action
);
12904 return str
? _(str
) : _("unknown");
12907 VIR_ENUM_DECL(virshDomainEventIOError
);
12908 VIR_ENUM_IMPL(virshDomainEventIOError
,
12909 VIR_DOMAIN_EVENT_IO_ERROR_LAST
,
12914 static const char *
12915 virshDomainEventIOErrorToString(int action
)
12917 const char *str
= virshDomainEventIOErrorTypeToString(action
);
12918 return str
? _(str
) : _("unknown");
12921 VIR_ENUM_DECL(virshGraphicsPhase
);
12922 VIR_ENUM_IMPL(virshGraphicsPhase
,
12923 VIR_DOMAIN_EVENT_GRAPHICS_LAST
,
12928 static const char *
12929 virshGraphicsPhaseToString(int phase
)
12931 const char *str
= virshGraphicsPhaseTypeToString(phase
);
12932 return str
? _(str
) : _("unknown");
12935 VIR_ENUM_DECL(virshGraphicsAddress
);
12936 VIR_ENUM_IMPL(virshGraphicsAddress
,
12937 VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_LAST
,
12942 static const char *
12943 virshGraphicsAddressToString(int family
)
12945 const char *str
= virshGraphicsAddressTypeToString(family
);
12946 return str
? _(str
) : _("unknown");
12949 VIR_ENUM_DECL(virshDomainBlockJobStatus
);
12950 VIR_ENUM_IMPL(virshDomainBlockJobStatus
,
12951 VIR_DOMAIN_BLOCK_JOB_LAST
,
12957 static const char *
12958 virshDomainBlockJobStatusToString(int status
)
12960 const char *str
= virshDomainBlockJobStatusTypeToString(status
);
12961 return str
? _(str
) : _("unknown");
12964 VIR_ENUM_DECL(virshDomainEventDiskChange
);
12965 VIR_ENUM_IMPL(virshDomainEventDiskChange
,
12966 VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
,
12970 static const char *
12971 virshDomainEventDiskChangeToString(int reason
)
12973 const char *str
= virshDomainEventDiskChangeTypeToString(reason
);
12974 return str
? _(str
) : _("unknown");
12977 VIR_ENUM_DECL(virshDomainEventTrayChange
);
12978 VIR_ENUM_IMPL(virshDomainEventTrayChange
,
12979 VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST
,
12983 static const char *
12984 virshDomainEventTrayChangeToString(int reason
)
12986 const char *str
= virshDomainEventTrayChangeTypeToString(reason
);
12987 return str
? _(str
) : _("unknown");
12990 struct virshDomEventData
{
12995 virshDomainEventCallback
*cb
;
12998 typedef struct virshDomEventData virshDomEventData
;
13003 * @data: opaque data passed to all event callbacks
13004 * @buf: string buffer describing the event
13006 * Print the event description found in @buf and update virshDomEventData.
13008 * This function resets @buf and frees all memory consumed by its content.
13011 virshEventPrint(virshDomEventData
*data
,
13016 if (!(msg
= virBufferContentAndReset(buf
)))
13019 if (!data
->loop
&& *data
->count
)
13022 if (data
->timestamp
) {
13023 char timestamp
[VIR_TIME_STRING_BUFLEN
];
13025 if (virTimeStringNowRaw(timestamp
) < 0)
13026 timestamp
[0] = '\0';
13028 vshPrint(data
->ctl
, "%s: %s", timestamp
, msg
);
13030 vshPrint(data
->ctl
, "%s", msg
);
13035 vshEventDone(data
->ctl
);
13042 virshEventGenericPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13046 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13048 virBufferAsprintf(&buf
, _("event '%s' for domain %s\n"),
13049 ((virshDomEventData
*) opaque
)->cb
->name
,
13050 virDomainGetName(dom
));
13051 virshEventPrint(opaque
, &buf
);
13055 virshEventLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13061 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13063 virBufferAsprintf(&buf
, _("event 'lifecycle' for domain %s: %s %s\n"),
13064 virDomainGetName(dom
),
13065 virshDomainEventToString(event
),
13066 virshDomainEventDetailToString(event
, detail
));
13067 virshEventPrint(opaque
, &buf
);
13071 virshEventRTCChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13073 long long utcoffset
,
13076 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13078 virBufferAsprintf(&buf
, _("event 'rtc-change' for domain %s: %lld\n"),
13079 virDomainGetName(dom
),
13081 virshEventPrint(opaque
, &buf
);
13085 virshEventWatchdogPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13090 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13092 virBufferAsprintf(&buf
, _("event 'watchdog' for domain %s: %s\n"),
13093 virDomainGetName(dom
),
13094 virshDomainEventWatchdogToString(action
));
13095 virshEventPrint(opaque
, &buf
);
13099 virshEventIOErrorPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13101 const char *srcPath
,
13102 const char *devAlias
,
13106 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13108 virBufferAsprintf(&buf
, _("event 'io-error' for domain %s: %s (%s) %s\n"),
13109 virDomainGetName(dom
),
13112 virshDomainEventIOErrorToString(action
));
13113 virshEventPrint(opaque
, &buf
);
13117 virshEventGraphicsPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13120 const virDomainEventGraphicsAddress
*local
,
13121 const virDomainEventGraphicsAddress
*remote
,
13122 const char *authScheme
,
13123 const virDomainEventGraphicsSubject
*subject
,
13126 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13129 virBufferAsprintf(&buf
, _("event 'graphics' for domain %s: "
13130 "%s local[%s %s %s] remote[%s %s %s] %s\n"),
13131 virDomainGetName(dom
),
13132 virshGraphicsPhaseToString(phase
),
13133 virshGraphicsAddressToString(local
->family
),
13136 virshGraphicsAddressToString(remote
->family
),
13140 for (i
= 0; i
< subject
->nidentity
; i
++) {
13141 virBufferAsprintf(&buf
, "\t%s=%s\n",
13142 subject
->identities
[i
].type
,
13143 subject
->identities
[i
].name
);
13145 virshEventPrint(opaque
, &buf
);
13149 virshEventIOErrorReasonPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13151 const char *srcPath
,
13152 const char *devAlias
,
13154 const char *reason
,
13157 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13159 virBufferAsprintf(&buf
, _("event 'io-error-reason' for domain %s: "
13160 "%s (%s) %s due to %s\n"),
13161 virDomainGetName(dom
),
13164 virshDomainEventIOErrorToString(action
),
13166 virshEventPrint(opaque
, &buf
);
13170 virshEventBlockJobPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13177 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13179 virBufferAsprintf(&buf
, _("event '%s' for domain %s: %s for %s %s\n"),
13180 ((virshDomEventData
*) opaque
)->cb
->name
,
13181 virDomainGetName(dom
),
13182 virshDomainBlockJobToString(type
),
13184 virshDomainBlockJobStatusToString(status
));
13185 virshEventPrint(opaque
, &buf
);
13189 virshEventDiskChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13191 const char *oldSrc
,
13192 const char *newSrc
,
13197 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13199 virBufferAsprintf(&buf
, _("event 'disk-change' for domain %s disk %s: "
13201 virDomainGetName(dom
),
13205 virshDomainEventDiskChangeToString(reason
));
13206 virshEventPrint(opaque
, &buf
);
13210 virshEventTrayChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13216 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13218 virBufferAsprintf(&buf
, _("event 'tray-change' for domain %s disk %s: %s\n"),
13219 virDomainGetName(dom
),
13221 virshDomainEventTrayChangeToString(reason
));
13222 virshEventPrint(opaque
, &buf
);
13226 virshEventPMChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13228 int reason ATTRIBUTE_UNUSED
,
13231 /* As long as libvirt.h doesn't define any reasons, we might as
13232 * well treat all PM state changes as generic events. */
13233 virshEventGenericPrint(conn
, dom
, opaque
);
13237 virshEventBalloonChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13239 unsigned long long actual
,
13242 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13244 virBufferAsprintf(&buf
, _("event 'balloon-change' for domain %s: %lluKiB\n"),
13245 virDomainGetName(dom
),
13247 virshEventPrint(opaque
, &buf
);
13251 virshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13256 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13258 virBufferAsprintf(&buf
, _("event 'device-removed' for domain %s: %s\n"),
13259 virDomainGetName(dom
),
13261 virshEventPrint(opaque
, &buf
);
13265 virshEventDeviceAddedPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13270 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13272 virBufferAsprintf(&buf
, _("event 'device-added' for domain %s: %s\n"),
13273 virDomainGetName(dom
),
13275 virshEventPrint(opaque
, &buf
);
13279 virshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13281 virTypedParameterPtr params
,
13285 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13289 virBufferAsprintf(&buf
, _("event 'tunable' for domain %s:\n"),
13290 virDomainGetName(dom
));
13291 for (i
= 0; i
< nparams
; i
++) {
13292 value
= virTypedParameterToString(¶ms
[i
]);
13294 virBufferAsprintf(&buf
, "\t%s: %s\n", params
[i
].field
, value
);
13298 virshEventPrint(opaque
, &buf
);
13301 VIR_ENUM_DECL(virshEventAgentLifecycleState
);
13302 VIR_ENUM_IMPL(virshEventAgentLifecycleState
,
13303 VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_LAST
,
13306 N_("disconnected"));
13308 VIR_ENUM_DECL(virshEventAgentLifecycleReason
);
13309 VIR_ENUM_IMPL(virshEventAgentLifecycleReason
,
13310 VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_REASON_LAST
,
13312 N_("domain started"),
13313 N_("channel event"));
13315 #define UNKNOWNSTR(str) (str ? str : N_("unsupported value"))
13317 virshEventAgentLifecyclePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13323 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13325 virBufferAsprintf(&buf
, _("event 'agent-lifecycle' for domain %s: state: "
13326 "'%s' reason: '%s'\n"),
13327 virDomainGetName(dom
),
13328 UNKNOWNSTR(virshEventAgentLifecycleStateTypeToString(state
)),
13329 UNKNOWNSTR(virshEventAgentLifecycleReasonTypeToString(reason
)));
13330 virshEventPrint(opaque
, &buf
);
13334 virshEventMigrationIterationPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13339 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13341 virBufferAsprintf(&buf
, _("event 'migration-iteration' for domain %s: "
13342 "iteration: '%d'\n"),
13343 virDomainGetName(dom
),
13346 virshEventPrint(opaque
, &buf
);
13350 virshEventJobCompletedPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13352 virTypedParameterPtr params
,
13356 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13360 virBufferAsprintf(&buf
, _("event 'job-completed' for domain %s:\n"),
13361 virDomainGetName(dom
));
13362 for (i
= 0; i
< nparams
; i
++) {
13363 value
= virTypedParameterToString(¶ms
[i
]);
13365 virBufferAsprintf(&buf
, "\t%s: %s\n", params
[i
].field
, value
);
13369 virshEventPrint(opaque
, &buf
);
13374 virshEventDeviceRemovalFailedPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13379 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13381 virBufferAsprintf(&buf
, _("event 'device-removal-failed' for domain %s: %s\n"),
13382 virDomainGetName(dom
),
13384 virshEventPrint(opaque
, &buf
);
13387 VIR_ENUM_DECL(virshEventMetadataChangeType
);
13388 VIR_ENUM_IMPL(virshEventMetadataChangeType
,
13389 VIR_DOMAIN_METADATA_LAST
,
13395 virshEventMetadataChangePrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13401 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13403 virBufferAsprintf(&buf
, _("event 'metdata-change' for domain %s: %s %s\n"),
13404 virDomainGetName(dom
),
13405 UNKNOWNSTR(virshEventMetadataChangeTypeTypeToString(type
)),
13407 virshEventPrint(opaque
, &buf
);
13412 virshEventBlockThresholdPrint(virConnectPtr conn ATTRIBUTE_UNUSED
,
13416 unsigned long long threshold
,
13417 unsigned long long excess
,
13420 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
13422 virBufferAsprintf(&buf
, _("event 'block-threshold' for domain %s: "
13423 "dev: %s(%s) %llu %llu\n"),
13424 virDomainGetName(dom
),
13425 dev
, NULLSTR(path
), threshold
, excess
);
13426 virshEventPrint(opaque
, &buf
);
13430 virshDomainEventCallback virshDomainEventCallbacks
[] = {
13432 VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint
), },
13433 { "reboot", virshEventGenericPrint
, },
13435 VIR_DOMAIN_EVENT_CALLBACK(virshEventRTCChangePrint
), },
13437 VIR_DOMAIN_EVENT_CALLBACK(virshEventWatchdogPrint
), },
13439 VIR_DOMAIN_EVENT_CALLBACK(virshEventIOErrorPrint
), },
13441 VIR_DOMAIN_EVENT_CALLBACK(virshEventGraphicsPrint
), },
13442 { "io-error-reason",
13443 VIR_DOMAIN_EVENT_CALLBACK(virshEventIOErrorReasonPrint
), },
13444 { "control-error", virshEventGenericPrint
, },
13446 VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobPrint
), },
13448 VIR_DOMAIN_EVENT_CALLBACK(virshEventDiskChangePrint
), },
13450 VIR_DOMAIN_EVENT_CALLBACK(virshEventTrayChangePrint
), },
13452 VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint
), },
13454 VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint
), },
13455 { "balloon-change",
13456 VIR_DOMAIN_EVENT_CALLBACK(virshEventBalloonChangePrint
), },
13457 { "pm-suspend-disk",
13458 VIR_DOMAIN_EVENT_CALLBACK(virshEventPMChangePrint
), },
13459 { "device-removed",
13460 VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovedPrint
), },
13462 VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockJobPrint
), },
13464 VIR_DOMAIN_EVENT_CALLBACK(virshEventTunablePrint
), },
13465 { "agent-lifecycle",
13466 VIR_DOMAIN_EVENT_CALLBACK(virshEventAgentLifecyclePrint
), },
13468 VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceAddedPrint
), },
13469 { "migration-iteration",
13470 VIR_DOMAIN_EVENT_CALLBACK(virshEventMigrationIterationPrint
), },
13472 VIR_DOMAIN_EVENT_CALLBACK(virshEventJobCompletedPrint
), },
13473 { "device-removal-failed",
13474 VIR_DOMAIN_EVENT_CALLBACK(virshEventDeviceRemovalFailedPrint
), },
13475 { "metadata-change",
13476 VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint
), },
13477 { "block-threshold",
13478 VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint
), },
13480 verify(VIR_DOMAIN_EVENT_ID_LAST
== ARRAY_CARDINALITY(virshDomainEventCallbacks
));
13482 static const vshCmdInfo info_event
[] = {
13484 .data
= N_("Domain Events")
13487 .data
= N_("List event types, or wait for domain events to occur")
13492 static const vshCmdOptDef opts_event
[] = {
13493 VIRSH_COMMON_OPT_DOMAIN_OT_STRING(N_("filter by domain name, id or uuid"),
13496 .type
= VSH_OT_STRING
,
13497 .completer
= virshDomainEventNameCompleter
,
13498 .help
= N_("which event type to wait for")
13501 .type
= VSH_OT_BOOL
,
13502 .help
= N_("wait for all events instead of just one type")
13505 .type
= VSH_OT_BOOL
,
13506 .help
= N_("loop until timeout or interrupt, rather than one-shot")
13508 {.name
= "timeout",
13509 .type
= VSH_OT_INT
,
13510 .help
= N_("timeout seconds")
13513 .type
= VSH_OT_BOOL
,
13514 .help
= N_("list valid event types")
13516 {.name
= "timestamp",
13517 .type
= VSH_OT_BOOL
,
13518 .help
= N_("show timestamp for each printed event")
13524 cmdEvent(vshControl
*ctl
, const vshCmd
*cmd
)
13526 virDomainPtr dom
= NULL
;
13529 virshDomEventData
*data
= NULL
;
13531 const char *eventName
= NULL
;
13533 bool all
= vshCommandOptBool(cmd
, "all");
13534 bool loop
= vshCommandOptBool(cmd
, "loop");
13535 bool timestamp
= vshCommandOptBool(cmd
, "timestamp");
13537 virshControlPtr priv
= ctl
->privData
;
13539 if (vshCommandOptBool(cmd
, "list")) {
13540 for (event
= 0; event
< VIR_DOMAIN_EVENT_ID_LAST
; event
++)
13541 vshPrint(ctl
, "%s\n", virshDomainEventCallbacks
[event
].name
);
13545 if (vshCommandOptStringReq(ctl
, cmd
, "event", &eventName
) < 0)
13548 for (event
= 0; event
< VIR_DOMAIN_EVENT_ID_LAST
; event
++)
13549 if (STREQ(eventName
, virshDomainEventCallbacks
[event
].name
))
13551 if (event
== VIR_DOMAIN_EVENT_ID_LAST
) {
13552 vshError(ctl
, _("unknown event type %s"), eventName
);
13556 vshError(ctl
, "%s",
13557 _("one of --list, --all, or --event <type> is required"));
13562 if (VIR_ALLOC_N(data
, VIR_DOMAIN_EVENT_ID_LAST
) < 0)
13564 for (i
= 0; i
< VIR_DOMAIN_EVENT_ID_LAST
; i
++) {
13566 data
[i
].loop
= loop
;
13567 data
[i
].count
= &count
;
13568 data
[i
].timestamp
= timestamp
;
13569 data
[i
].cb
= &virshDomainEventCallbacks
[i
];
13573 if (VIR_ALLOC_N(data
, 1) < 0)
13576 data
[0].loop
= vshCommandOptBool(cmd
, "loop");
13577 data
[0].count
= &count
;
13578 data
[0].timestamp
= timestamp
;
13579 data
[0].cb
= &virshDomainEventCallbacks
[event
];
13582 if (vshCommandOptTimeoutToMs(ctl
, cmd
, &timeout
) < 0)
13585 if (vshCommandOptBool(cmd
, "domain"))
13586 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13589 if (vshEventStart(ctl
, timeout
) < 0)
13592 for (i
= 0; i
< (all
? VIR_DOMAIN_EVENT_ID_LAST
: 1); i
++) {
13593 if ((data
[i
].id
= virConnectDomainEventRegisterAny(priv
->conn
, dom
,
13598 /* When registering for all events: if the first
13599 * registration succeeds, silently ignore failures on all
13600 * later registrations on the assumption that the server
13601 * is older and didn't know quite as many events. */
13603 vshResetLibvirtError();
13608 switch (vshEventWait(ctl
)) {
13609 case VSH_EVENT_INTERRUPT
:
13610 vshPrint(ctl
, "%s", _("event loop interrupted\n"));
13612 case VSH_EVENT_TIMEOUT
:
13613 vshPrint(ctl
, "%s", _("event loop timed out\n"));
13615 case VSH_EVENT_DONE
:
13620 vshPrint(ctl
, _("events received: %d\n"), count
);
13625 vshEventCleanup(ctl
);
13627 for (i
= 0; i
< (all
? VIR_DOMAIN_EVENT_ID_LAST
: 1); i
++) {
13628 if (data
[i
].id
>= 0 &&
13629 virConnectDomainEventDeregisterAny(priv
->conn
, data
[i
].id
) < 0)
13634 virshDomainFree(dom
);
13640 * "change-media" command
13642 static const vshCmdInfo info_change_media
[] = {
13644 .data
= N_("Change media of CD or floppy drive")
13647 .data
= N_("Change media of CD or floppy drive.")
13652 static const vshCmdOptDef opts_change_media
[] = {
13653 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
13655 .type
= VSH_OT_DATA
,
13656 .flags
= VSH_OFLAG_REQ
,
13657 .completer
= virshDomainDiskTargetCompleter
,
13658 .help
= N_("Fully-qualified path or target of disk device")
13661 .type
= VSH_OT_STRING
,
13662 .help
= N_("source of the media")
13665 .type
= VSH_OT_BOOL
,
13666 .help
= N_("Eject the media")
13669 .type
= VSH_OT_BOOL
,
13670 .help
= N_("Insert the media")
13673 .type
= VSH_OT_BOOL
,
13674 .help
= N_("Update the media")
13676 VIRSH_COMMON_OPT_CURRENT(N_("can be either or both of --live and "
13677 "--config, depends on implementation "
13678 "hypervisor driver")),
13679 VIRSH_COMMON_OPT_LIVE(N_("alter live configuration of running domain")),
13680 VIRSH_COMMON_OPT_CONFIG(N_("alter persistent configuration, effect "
13681 "observed on next boot")),
13683 .type
= VSH_OT_BOOL
,
13684 .help
= N_("force media changing")
13686 {.name
= "print-xml",
13687 .type
= VSH_OT_BOOL
,
13688 .help
= N_("print XML document rather than change media")
13691 .type
= VSH_OT_BOOL
,
13692 .help
= N_("source media is a block device")
13698 cmdChangeMedia(vshControl
*ctl
, const vshCmd
*cmd
)
13700 virDomainPtr dom
= NULL
;
13701 const char *source
= NULL
;
13702 const char *path
= NULL
;
13704 xmlNodePtr disk_node
= NULL
;
13705 char *disk_xml
= NULL
;
13707 virshUpdateDiskXMLType update_type
;
13708 const char *action
= NULL
;
13709 const char *success_msg
= NULL
;
13710 bool config
= vshCommandOptBool(cmd
, "config");
13711 bool live
= vshCommandOptBool(cmd
, "live");
13712 bool current
= vshCommandOptBool(cmd
, "current");
13713 bool force
= vshCommandOptBool(cmd
, "force");
13714 bool eject
= vshCommandOptBool(cmd
, "eject");
13715 bool insert
= vshCommandOptBool(cmd
, "insert");
13716 bool update
= vshCommandOptBool(cmd
, "update");
13717 bool block
= vshCommandOptBool(cmd
, "block");
13718 unsigned int flags
= VIR_DOMAIN_AFFECT_CURRENT
;
13720 VSH_EXCLUSIVE_OPTIONS_VAR(eject
, insert
);
13721 VSH_EXCLUSIVE_OPTIONS_VAR(eject
, update
);
13722 VSH_EXCLUSIVE_OPTIONS_VAR(insert
, update
);
13724 VSH_EXCLUSIVE_OPTIONS_VAR(eject
, block
);
13726 if (vshCommandOptStringReq(ctl
, cmd
, "source", &source
) < 0)
13729 /* Docs state that update without source is eject */
13730 if (update
&& !source
) {
13736 update_type
= VIRSH_UPDATE_DISK_XML_EJECT
;
13738 success_msg
= _("Successfully ejected media.");
13742 update_type
= VIRSH_UPDATE_DISK_XML_INSERT
;
13744 success_msg
= _("Successfully inserted media.");
13747 if (update
|| (!eject
&& !insert
)) {
13748 update_type
= VIRSH_UPDATE_DISK_XML_UPDATE
;
13750 success_msg
= _("Successfully updated media.");
13753 VSH_EXCLUSIVE_OPTIONS_VAR(current
, live
);
13754 VSH_EXCLUSIVE_OPTIONS_VAR(current
, config
);
13757 flags
|= VIR_DOMAIN_AFFECT_CONFIG
;
13759 flags
|= VIR_DOMAIN_AFFECT_LIVE
;
13761 flags
|= VIR_DOMAIN_DEVICE_MODIFY_FORCE
;
13763 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13766 if (vshCommandOptStringReq(ctl
, cmd
, "path", &path
) < 0)
13769 if (flags
& VIR_DOMAIN_AFFECT_CONFIG
)
13770 doc
= virDomainGetXMLDesc(dom
, VIR_DOMAIN_XML_INACTIVE
);
13772 doc
= virDomainGetXMLDesc(dom
, 0);
13776 if (!(disk_node
= virshFindDisk(doc
, path
, VIRSH_FIND_DISK_CHANGEABLE
)))
13779 if (!(disk_xml
= virshUpdateDiskXML(disk_node
, source
, block
, path
,
13783 if (vshCommandOptBool(cmd
, "print-xml")) {
13784 vshPrint(ctl
, "%s", disk_xml
);
13786 if (virDomainUpdateDeviceFlags(dom
, disk_xml
, flags
) != 0) {
13787 vshError(ctl
, _("Failed to complete action %s on media"), action
);
13791 vshPrint(ctl
, "%s", success_msg
);
13798 xmlFreeNode(disk_node
);
13799 VIR_FREE(disk_xml
);
13800 virshDomainFree(dom
);
13804 static const vshCmdInfo info_domfstrim
[] = {
13806 .data
= N_("Invoke fstrim on domain's mounted filesystems.")
13809 .data
= N_("Invoke fstrim on domain's mounted filesystems.")
13814 static const vshCmdOptDef opts_domfstrim
[] = {
13815 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
13816 {.name
= "minimum",
13817 .type
= VSH_OT_INT
,
13818 .help
= N_("Just a hint to ignore contiguous "
13819 "free ranges smaller than this (Bytes)")
13821 {.name
= "mountpoint",
13822 .type
= VSH_OT_STRING
,
13823 .help
= N_("which mount point to trim")
13828 cmdDomFSTrim(vshControl
*ctl
, const vshCmd
*cmd
)
13830 virDomainPtr dom
= NULL
;
13832 unsigned long long minimum
= 0;
13833 const char *mountPoint
= NULL
;
13834 unsigned int flags
= 0;
13836 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13839 if (vshCommandOptULongLong(ctl
, cmd
, "minimum", &minimum
) < 0)
13842 if (vshCommandOptStringReq(ctl
, cmd
, "mountpoint", &mountPoint
) < 0)
13845 if (virDomainFSTrim(dom
, mountPoint
, minimum
, flags
) < 0) {
13846 vshError(ctl
, _("Unable to invoke fstrim"));
13853 virshDomainFree(dom
);
13857 static const vshCmdInfo info_domfsfreeze
[] = {
13859 .data
= N_("Freeze domain's mounted filesystems.")
13862 .data
= N_("Freeze domain's mounted filesystems.")
13867 static const vshCmdOptDef opts_domfsfreeze
[] = {
13868 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
13869 {.name
= "mountpoint",
13870 .type
= VSH_OT_ARGV
,
13871 .help
= N_("mountpoint path to be frozen")
13876 cmdDomFSFreeze(vshControl
*ctl
, const vshCmd
*cmd
)
13878 virDomainPtr dom
= NULL
;
13880 const vshCmdOpt
*opt
= NULL
;
13881 const char **mountpoints
= NULL
;
13882 size_t nmountpoints
= 0;
13884 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13887 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
))) {
13888 if (VIR_EXPAND_N(mountpoints
, nmountpoints
, 1) < 0) {
13889 vshError(ctl
, _("%s: %d: failed to allocate mountpoints"),
13890 __FILE__
, __LINE__
);
13893 mountpoints
[nmountpoints
-1] = opt
->data
;
13896 ret
= virDomainFSFreeze(dom
, mountpoints
, nmountpoints
, 0);
13898 vshError(ctl
, _("Unable to freeze filesystems"));
13902 vshPrintExtra(ctl
, _("Froze %d filesystem(s)\n"), ret
);
13905 VIR_FREE(mountpoints
);
13906 virshDomainFree(dom
);
13910 static const vshCmdInfo info_domfsthaw
[] = {
13912 .data
= N_("Thaw domain's mounted filesystems.")
13915 .data
= N_("Thaw domain's mounted filesystems.")
13920 static const vshCmdOptDef opts_domfsthaw
[] = {
13921 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
13922 {.name
= "mountpoint",
13923 .type
= VSH_OT_ARGV
,
13924 .help
= N_("mountpoint path to be thawed")
13929 cmdDomFSThaw(vshControl
*ctl
, const vshCmd
*cmd
)
13931 virDomainPtr dom
= NULL
;
13933 const vshCmdOpt
*opt
= NULL
;
13934 const char **mountpoints
= NULL
;
13935 size_t nmountpoints
= 0;
13937 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13940 while ((opt
= vshCommandOptArgv(ctl
, cmd
, opt
))) {
13941 if (VIR_EXPAND_N(mountpoints
, nmountpoints
, 1) < 0) {
13942 vshError(ctl
, _("%s: %d: failed to allocate mountpoints"),
13943 __FILE__
, __LINE__
);
13946 mountpoints
[nmountpoints
-1] = opt
->data
;
13949 ret
= virDomainFSThaw(dom
, mountpoints
, nmountpoints
, 0);
13951 vshError(ctl
, _("Unable to thaw filesystems"));
13955 vshPrintExtra(ctl
, _("Thawed %d filesystem(s)\n"), ret
);
13958 VIR_FREE(mountpoints
);
13959 virshDomainFree(dom
);
13963 static const vshCmdInfo info_domfsinfo
[] = {
13965 .data
= N_("Get information of domain's mounted filesystems.")
13968 .data
= N_("Get information of domain's mounted filesystems.")
13973 static const vshCmdOptDef opts_domfsinfo
[] = {
13974 VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE
),
13979 cmdDomFSInfo(vshControl
*ctl
, const vshCmd
*cmd
)
13981 virDomainPtr dom
= NULL
;
13984 virDomainFSInfoPtr
*info
= NULL
;
13985 vshTablePtr table
= NULL
;
13989 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
13992 rc
= virDomainGetFSInfo(dom
, &info
, 0);
13994 vshError(ctl
, _("Unable to get filesystem information"));
14001 vshPrintExtra(ctl
, _("No filesystems are mounted in the domain"));
14006 table
= vshTableNew(_("Mountpoint"), _("Name"), _("Type"), _("Target"), NULL
);
14010 for (i
= 0; i
< ninfos
; i
++) {
14011 virBuffer targetsBuff
= VIR_BUFFER_INITIALIZER
;
14012 VIR_AUTOFREE(char *) targets
= NULL
;
14014 for (j
= 0; j
< info
[i
]->ndevAlias
; j
++)
14015 virBufferAsprintf(&targetsBuff
, "%s,", info
[i
]->devAlias
[j
]);
14016 virBufferTrim(&targetsBuff
, ",", -1);
14018 targets
= virBufferContentAndReset(&targetsBuff
);
14020 if (vshTableRowAppend(table
,
14021 info
[i
]->mountpoint
,
14024 targets
? targets
: "",
14029 vshTablePrintToStdout(table
, ctl
);
14036 for (i
= 0; i
< ninfos
; i
++)
14037 virDomainFSInfoFree(info
[i
]);
14040 vshTableFree(table
);
14041 virshDomainFree(dom
);
14047 * "backup-begin" command
14049 static const vshCmdInfo info_backup_begin
[] = {
14051 .data
= N_("Start a disk backup of a live domain")
14054 .data
= N_("Use XML to start a full or incremental disk backup of a live "
14055 "domain, optionally creating a checkpoint")
14060 static const vshCmdOptDef opts_backup_begin
[] = {
14061 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
14062 {.name
= "xmlfile",
14063 .type
= VSH_OT_STRING
,
14064 .help
= N_("domain backup XML"),
14066 {.name
= "checkpointxml",
14067 .type
= VSH_OT_STRING
,
14068 .help
= N_("domain checkpoint XML"),
14070 {.name
= "no-metadata",
14071 .type
= VSH_OT_BOOL
,
14072 .help
= N_("create checkpoint but don't track metadata"),
14074 {.name
= "quiesce",
14075 .type
= VSH_OT_BOOL
,
14076 .help
= N_("quiesce guest's file systems"),
14078 /* TODO: --wait/--verbose/--timeout flags for push model backups? */
14083 cmdBackupBegin(vshControl
*ctl
,
14086 virDomainPtr dom
= NULL
;
14088 const char *backup_from
= NULL
;
14089 char *backup_buffer
= NULL
;
14090 const char *check_from
= NULL
;
14091 char *check_buffer
= NULL
;
14092 unsigned int flags
= 0;
14095 if (vshCommandOptBool(cmd
, "no-metadata"))
14096 flags
|= VIR_DOMAIN_BACKUP_BEGIN_NO_METADATA
;
14097 if (vshCommandOptBool(cmd
, "quiesce"))
14098 flags
|= VIR_DOMAIN_BACKUP_BEGIN_QUIESCE
;
14100 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
14103 if (vshCommandOptStringReq(ctl
, cmd
, "xmlfile", &backup_from
) < 0)
14105 if (!backup_from
) {
14106 backup_buffer
= vshStrdup(ctl
, "<domainbackup/>");
14108 if (virFileReadAll(backup_from
, VSH_MAX_XML_FILE
, &backup_buffer
) < 0) {
14109 vshSaveLibvirtError();
14114 if (vshCommandOptStringReq(ctl
, cmd
, "checkpointxml", &check_from
) < 0)
14117 if (virFileReadAll(check_from
, VSH_MAX_XML_FILE
, &check_buffer
) < 0) {
14118 vshSaveLibvirtError();
14123 id
= virDomainBackupBegin(dom
, backup_buffer
, check_buffer
, flags
);
14128 vshPrint(ctl
, _("Backup id %d started\n"), id
);
14130 vshPrintExtra(ctl
, _("backup used description from '%s'\n"),
14133 vshPrintExtra(ctl
, _("checkpoint created from '%s'\n"), check_from
);
14138 VIR_FREE(backup_buffer
);
14139 VIR_FREE(check_buffer
);
14140 virshDomainFree(dom
);
14145 /* TODO: backup-begin-as? */
14148 * "backup-dumpxml" command
14150 static const vshCmdInfo info_backup_dumpxml
[] = {
14152 .data
= N_("Dump XML for an ongoing domain block backup job")
14155 .data
= N_("Backup Dump XML")
14160 static const vshCmdOptDef opts_backup_dumpxml
[] = {
14161 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
14163 .type
= VSH_OT_INT
,
14164 .help
= N_("backup job id"),
14165 /* TODO: Add API for listing active jobs, then adding a completer? */
14167 /* TODO - worth adding this flag?
14168 {.name = "checkpoint",
14169 .type = VSH_OT_BOOL,
14170 .help = N_("if the backup created a checkpoint, also dump that XML")
14177 cmdBackupDumpXML(vshControl
*ctl
,
14180 virDomainPtr dom
= NULL
;
14183 unsigned int flags
= 0;
14186 if (vshCommandOptBool(cmd
, "security-info"))
14187 flags
|= VIR_DOMAIN_XML_SECURE
;
14189 if (vshCommandOptInt(ctl
, cmd
, "id", &id
) < 0)
14192 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
14195 if (!(xml
= virDomainBackupGetXMLDesc(dom
, id
, flags
)))
14198 vshPrint(ctl
, "%s", xml
);
14203 virshDomainFree(dom
);
14210 * "backup-end" command
14212 static const vshCmdInfo info_backup_end
[] = {
14214 .data
= N_("Conclude a disk backup of a live domain")
14217 .data
= N_("End a domain block backup job")
14222 static const vshCmdOptDef opts_backup_end
[] = {
14223 VIRSH_COMMON_OPT_DOMAIN_FULL(0),
14225 .type
= VSH_OT_INT
,
14226 .help
= N_("backup job id"),
14227 /* TODO: Add API for listing active jobs, then adding a completer? */
14230 .type
= VSH_OT_BOOL
,
14231 .help
= N_("abandon a push model backup that has not yet completed")
14237 cmdBackupEnd(vshControl
*ctl
, const vshCmd
*cmd
)
14239 virDomainPtr dom
= NULL
;
14241 unsigned int flags
= 0;
14245 if (vshCommandOptBool(cmd
, "abort"))
14246 flags
|= VIR_DOMAIN_BACKUP_END_ABORT
;
14248 if (vshCommandOptInt(ctl
, cmd
, "id", &id
) < 0)
14251 if (!(dom
= virshCommandOptDomain(ctl
, cmd
, NULL
)))
14254 rc
= virDomainBackupEnd(dom
, id
, flags
);
14259 vshPrint(ctl
, _("Backup id %d aborted"), id
);
14261 vshPrint(ctl
, _("Backup id %d completed"), id
);
14266 virshDomainFree(dom
);
14272 const vshCmdDef domManagementCmds
[] = {
14273 {.name
= "attach-device",
14274 .handler
= cmdAttachDevice
,
14275 .opts
= opts_attach_device
,
14276 .info
= info_attach_device
,
14279 {.name
= "attach-disk",
14280 .handler
= cmdAttachDisk
,
14281 .opts
= opts_attach_disk
,
14282 .info
= info_attach_disk
,
14285 {.name
= "attach-interface",
14286 .handler
= cmdAttachInterface
,
14287 .opts
= opts_attach_interface
,
14288 .info
= info_attach_interface
,
14291 {.name
= "autostart",
14292 .handler
= cmdAutostart
,
14293 .opts
= opts_autostart
,
14294 .info
= info_autostart
,
14297 {.name
= "backup-begin",
14298 .handler
= cmdBackupBegin
,
14299 .opts
= opts_backup_begin
,
14300 .info
= info_backup_begin
,
14303 {.name
= "backup-dumpxml",
14304 .handler
= cmdBackupDumpXML
,
14305 .opts
= opts_backup_dumpxml
,
14306 .info
= info_backup_dumpxml
,
14309 {.name
= "backup-end",
14310 .handler
= cmdBackupEnd
,
14311 .opts
= opts_backup_end
,
14312 .info
= info_backup_end
,
14315 {.name
= "blkdeviotune",
14316 .handler
= cmdBlkdeviotune
,
14317 .opts
= opts_blkdeviotune
,
14318 .info
= info_blkdeviotune
,
14321 {.name
= "blkiotune",
14322 .handler
= cmdBlkiotune
,
14323 .opts
= opts_blkiotune
,
14324 .info
= info_blkiotune
,
14327 {.name
= "blockcommit",
14328 .handler
= cmdBlockcommit
,
14329 .opts
= opts_blockcommit
,
14330 .info
= info_blockcommit
,
14333 {.name
= "blockcopy",
14334 .handler
= cmdBlockcopy
,
14335 .opts
= opts_blockcopy
,
14336 .info
= info_blockcopy
,
14339 {.name
= "blockjob",
14340 .handler
= cmdBlockjob
,
14341 .opts
= opts_blockjob
,
14342 .info
= info_blockjob
,
14345 {.name
= "blockpull",
14346 .handler
= cmdBlockpull
,
14347 .opts
= opts_blockpull
,
14348 .info
= info_blockpull
,
14351 {.name
= "blockresize",
14352 .handler
= cmdBlockresize
,
14353 .opts
= opts_blockresize
,
14354 .info
= info_blockresize
,
14357 {.name
= "change-media",
14358 .handler
= cmdChangeMedia
,
14359 .opts
= opts_change_media
,
14360 .info
= info_change_media
,
14364 {.name
= "console",
14365 .handler
= cmdConsole
,
14366 .opts
= opts_console
,
14367 .info
= info_console
,
14371 {.name
= "cpu-stats",
14372 .handler
= cmdCPUStats
,
14373 .opts
= opts_cpu_stats
,
14374 .info
= info_cpu_stats
,
14378 .handler
= cmdCreate
,
14379 .opts
= opts_create
,
14380 .info
= info_create
,
14384 .handler
= cmdDefine
,
14385 .opts
= opts_define
,
14386 .info
= info_define
,
14390 .handler
= cmdDesc
,
14395 {.name
= "destroy",
14396 .handler
= cmdDestroy
,
14397 .opts
= opts_destroy
,
14398 .info
= info_destroy
,
14401 {.name
= "detach-device",
14402 .handler
= cmdDetachDevice
,
14403 .opts
= opts_detach_device
,
14404 .info
= info_detach_device
,
14407 {.name
= "detach-device-alias",
14408 .handler
= cmdDetachDeviceAlias
,
14409 .opts
= opts_detach_device_alias
,
14410 .info
= info_detach_device_alias
,
14413 {.name
= "detach-disk",
14414 .handler
= cmdDetachDisk
,
14415 .opts
= opts_detach_disk
,
14416 .info
= info_detach_disk
,
14419 {.name
= "detach-interface",
14420 .handler
= cmdDetachInterface
,
14421 .opts
= opts_detach_interface
,
14422 .info
= info_detach_interface
,
14425 {.name
= "domdisplay",
14426 .handler
= cmdDomDisplay
,
14427 .opts
= opts_domdisplay
,
14428 .info
= info_domdisplay
,
14431 {.name
= "domfsfreeze",
14432 .handler
= cmdDomFSFreeze
,
14433 .opts
= opts_domfsfreeze
,
14434 .info
= info_domfsfreeze
,
14437 {.name
= "domfsthaw",
14438 .handler
= cmdDomFSThaw
,
14439 .opts
= opts_domfsthaw
,
14440 .info
= info_domfsthaw
,
14443 {.name
= "domfsinfo",
14444 .handler
= cmdDomFSInfo
,
14445 .opts
= opts_domfsinfo
,
14446 .info
= info_domfsinfo
,
14449 {.name
= "domfstrim",
14450 .handler
= cmdDomFSTrim
,
14451 .opts
= opts_domfstrim
,
14452 .info
= info_domfstrim
,
14455 {.name
= "domhostname",
14456 .handler
= cmdDomHostname
,
14457 .opts
= opts_domhostname
,
14458 .info
= info_domhostname
,
14462 .handler
= cmdDomid
,
14463 .opts
= opts_domid
,
14464 .info
= info_domid
,
14467 {.name
= "domif-setlink",
14468 .handler
= cmdDomIfSetLink
,
14469 .opts
= opts_domif_setlink
,
14470 .info
= info_domif_setlink
,
14473 {.name
= "domiftune",
14474 .handler
= cmdDomIftune
,
14475 .opts
= opts_domiftune
,
14476 .info
= info_domiftune
,
14479 {.name
= "domjobabort",
14480 .handler
= cmdDomjobabort
,
14481 .opts
= opts_domjobabort
,
14482 .info
= info_domjobabort
,
14485 {.name
= "domjobinfo",
14486 .handler
= cmdDomjobinfo
,
14487 .opts
= opts_domjobinfo
,
14488 .info
= info_domjobinfo
,
14491 {.name
= "domname",
14492 .handler
= cmdDomname
,
14493 .opts
= opts_domname
,
14494 .info
= info_domname
,
14497 {.name
= "domrename",
14498 .handler
= cmdDomrename
,
14499 .opts
= opts_domrename
,
14500 .info
= info_domrename
,
14503 {.name
= "dompmsuspend",
14504 .handler
= cmdDomPMSuspend
,
14505 .opts
= opts_dom_pm_suspend
,
14506 .info
= info_dom_pm_suspend
,
14509 {.name
= "dompmwakeup",
14510 .handler
= cmdDomPMWakeup
,
14511 .opts
= opts_dom_pm_wakeup
,
14512 .info
= info_dom_pm_wakeup
,
14515 {.name
= "domuuid",
14516 .handler
= cmdDomuuid
,
14517 .opts
= opts_domuuid
,
14518 .info
= info_domuuid
,
14521 {.name
= "domxml-from-native",
14522 .handler
= cmdDomXMLFromNative
,
14523 .opts
= opts_domxmlfromnative
,
14524 .info
= info_domxmlfromnative
,
14527 {.name
= "domxml-to-native",
14528 .handler
= cmdDomXMLToNative
,
14529 .opts
= opts_domxmltonative
,
14530 .info
= info_domxmltonative
,
14534 .handler
= cmdDump
,
14539 {.name
= "dumpxml",
14540 .handler
= cmdDumpXML
,
14541 .opts
= opts_dumpxml
,
14542 .info
= info_dumpxml
,
14546 .handler
= cmdEdit
,
14552 .handler
= cmdEvent
,
14553 .opts
= opts_event
,
14554 .info
= info_event
,
14557 {.name
= "inject-nmi",
14558 .handler
= cmdInjectNMI
,
14559 .opts
= opts_inject_nmi
,
14560 .info
= info_inject_nmi
,
14563 {.name
= "iothreadinfo",
14564 .handler
= cmdIOThreadInfo
,
14565 .opts
= opts_iothreadinfo
,
14566 .info
= info_iothreadinfo
,
14569 {.name
= "iothreadpin",
14570 .handler
= cmdIOThreadPin
,
14571 .opts
= opts_iothreadpin
,
14572 .info
= info_iothreadpin
,
14575 {.name
= "iothreadadd",
14576 .handler
= cmdIOThreadAdd
,
14577 .opts
= opts_iothreadadd
,
14578 .info
= info_iothreadadd
,
14581 {.name
= "iothreadset",
14582 .handler
= cmdIOThreadSet
,
14583 .opts
= opts_iothreadset
,
14584 .info
= info_iothreadset
,
14587 {.name
= "iothreaddel",
14588 .handler
= cmdIOThreadDel
,
14589 .opts
= opts_iothreaddel
,
14590 .info
= info_iothreaddel
,
14593 {.name
= "send-key",
14594 .handler
= cmdSendKey
,
14595 .opts
= opts_send_key
,
14596 .info
= info_send_key
,
14599 {.name
= "send-process-signal",
14600 .handler
= cmdSendProcessSignal
,
14601 .opts
= opts_send_process_signal
,
14602 .info
= info_send_process_signal
,
14605 {.name
= "lxc-enter-namespace",
14606 .handler
= cmdLxcEnterNamespace
,
14607 .opts
= opts_lxc_enter_namespace
,
14608 .info
= info_lxc_enter_namespace
,
14611 {.name
= "managedsave",
14612 .handler
= cmdManagedSave
,
14613 .opts
= opts_managedsave
,
14614 .info
= info_managedsave
,
14617 {.name
= "managedsave-remove",
14618 .handler
= cmdManagedSaveRemove
,
14619 .opts
= opts_managedsaveremove
,
14620 .info
= info_managedsaveremove
,
14623 {.name
= "managedsave-edit",
14624 .handler
= cmdManagedSaveEdit
,
14625 .opts
= opts_managed_save_edit
,
14626 .info
= info_managed_save_edit
,
14629 {.name
= "managedsave-dumpxml",
14630 .handler
= cmdManagedSaveDumpxml
,
14631 .opts
= opts_managed_save_dumpxml
,
14632 .info
= info_managed_save_dumpxml
,
14635 {.name
= "managedsave-define",
14636 .handler
= cmdManagedSaveDefine
,
14637 .opts
= opts_managed_save_define
,
14638 .info
= info_managed_save_define
,
14641 {.name
= "memtune",
14642 .handler
= cmdMemtune
,
14643 .opts
= opts_memtune
,
14644 .info
= info_memtune
,
14648 .handler
= cmdPerf
,
14653 {.name
= "metadata",
14654 .handler
= cmdMetadata
,
14655 .opts
= opts_metadata
,
14656 .info
= info_metadata
,
14659 {.name
= "migrate",
14660 .handler
= cmdMigrate
,
14661 .opts
= opts_migrate
,
14662 .info
= info_migrate
,
14665 {.name
= "migrate-setmaxdowntime",
14666 .handler
= cmdMigrateSetMaxDowntime
,
14667 .opts
= opts_migrate_setmaxdowntime
,
14668 .info
= info_migrate_setmaxdowntime
,
14671 {.name
= "migrate-getmaxdowntime",
14672 .handler
= cmdMigrateGetMaxDowntime
,
14673 .opts
= opts_migrate_getmaxdowntime
,
14674 .info
= info_migrate_getmaxdowntime
,
14677 {.name
= "migrate-compcache",
14678 .handler
= cmdMigrateCompCache
,
14679 .opts
= opts_migrate_compcache
,
14680 .info
= info_migrate_compcache
,
14683 {.name
= "migrate-setspeed",
14684 .handler
= cmdMigrateSetMaxSpeed
,
14685 .opts
= opts_migrate_setspeed
,
14686 .info
= info_migrate_setspeed
,
14689 {.name
= "migrate-getspeed",
14690 .handler
= cmdMigrateGetMaxSpeed
,
14691 .opts
= opts_migrate_getspeed
,
14692 .info
= info_migrate_getspeed
,
14695 {.name
= "migrate-postcopy",
14696 .handler
= cmdMigratePostCopy
,
14697 .opts
= opts_migrate_postcopy
,
14698 .info
= info_migrate_postcopy
,
14701 {.name
= "numatune",
14702 .handler
= cmdNumatune
,
14703 .opts
= opts_numatune
,
14704 .info
= info_numatune
,
14707 {.name
= "qemu-attach",
14708 .handler
= cmdQemuAttach
,
14709 .opts
= opts_qemu_attach
,
14710 .info
= info_qemu_attach
,
14713 {.name
= "qemu-monitor-command",
14714 .handler
= cmdQemuMonitorCommand
,
14715 .opts
= opts_qemu_monitor_command
,
14716 .info
= info_qemu_monitor_command
,
14719 {.name
= "qemu-monitor-event",
14720 .handler
= cmdQemuMonitorEvent
,
14721 .opts
= opts_qemu_monitor_event
,
14722 .info
= info_qemu_monitor_event
,
14725 {.name
= "qemu-agent-command",
14726 .handler
= cmdQemuAgentCommand
,
14727 .opts
= opts_qemu_agent_command
,
14728 .info
= info_qemu_agent_command
,
14732 .handler
= cmdReboot
,
14733 .opts
= opts_reboot
,
14734 .info
= info_reboot
,
14738 .handler
= cmdReset
,
14739 .opts
= opts_reset
,
14740 .info
= info_reset
,
14743 {.name
= "restore",
14744 .handler
= cmdRestore
,
14745 .opts
= opts_restore
,
14746 .info
= info_restore
,
14750 .handler
= cmdResume
,
14751 .opts
= opts_resume
,
14752 .info
= info_resume
,
14756 .handler
= cmdSave
,
14761 {.name
= "save-image-define",
14762 .handler
= cmdSaveImageDefine
,
14763 .opts
= opts_save_image_define
,
14764 .info
= info_save_image_define
,
14767 {.name
= "save-image-dumpxml",
14768 .handler
= cmdSaveImageDumpxml
,
14769 .opts
= opts_save_image_dumpxml
,
14770 .info
= info_save_image_dumpxml
,
14773 {.name
= "save-image-edit",
14774 .handler
= cmdSaveImageEdit
,
14775 .opts
= opts_save_image_edit
,
14776 .info
= info_save_image_edit
,
14779 {.name
= "schedinfo",
14780 .handler
= cmdSchedinfo
,
14781 .opts
= opts_schedinfo
,
14782 .info
= info_schedinfo
,
14785 {.name
= "screenshot",
14786 .handler
= cmdScreenshot
,
14787 .opts
= opts_screenshot
,
14788 .info
= info_screenshot
,
14791 {.name
= "set-lifecycle-action",
14792 .handler
= cmdSetLifecycleAction
,
14793 .opts
= opts_setLifecycleAction
,
14794 .info
= info_setLifecycleAction
,
14797 {.name
= "set-user-password",
14798 .handler
= cmdSetUserPassword
,
14799 .opts
= opts_set_user_password
,
14800 .info
= info_set_user_password
,
14803 {.name
= "setmaxmem",
14804 .handler
= cmdSetmaxmem
,
14805 .opts
= opts_setmaxmem
,
14806 .info
= info_setmaxmem
,
14810 .handler
= cmdSetmem
,
14811 .opts
= opts_setmem
,
14812 .info
= info_setmem
,
14815 {.name
= "setvcpus",
14816 .handler
= cmdSetvcpus
,
14817 .opts
= opts_setvcpus
,
14818 .info
= info_setvcpus
,
14821 {.name
= "shutdown",
14822 .handler
= cmdShutdown
,
14823 .opts
= opts_shutdown
,
14824 .info
= info_shutdown
,
14828 .handler
= cmdStart
,
14829 .opts
= opts_start
,
14830 .info
= info_start
,
14833 {.name
= "suspend",
14834 .handler
= cmdSuspend
,
14835 .opts
= opts_suspend
,
14836 .info
= info_suspend
,
14839 {.name
= "ttyconsole",
14840 .handler
= cmdTTYConsole
,
14841 .opts
= opts_ttyconsole
,
14842 .info
= info_ttyconsole
,
14845 {.name
= "undefine",
14846 .handler
= cmdUndefine
,
14847 .opts
= opts_undefine
,
14848 .info
= info_undefine
,
14851 {.name
= "update-device",
14852 .handler
= cmdUpdateDevice
,
14853 .opts
= opts_update_device
,
14854 .info
= info_update_device
,
14857 {.name
= "vcpucount",
14858 .handler
= cmdVcpucount
,
14859 .opts
= opts_vcpucount
,
14860 .info
= info_vcpucount
,
14863 {.name
= "vcpuinfo",
14864 .handler
= cmdVcpuinfo
,
14865 .opts
= opts_vcpuinfo
,
14866 .info
= info_vcpuinfo
,
14869 {.name
= "vcpupin",
14870 .handler
= cmdVcpuPin
,
14871 .opts
= opts_vcpupin
,
14872 .info
= info_vcpupin
,
14875 {.name
= "emulatorpin",
14876 .handler
= cmdEmulatorPin
,
14877 .opts
= opts_emulatorpin
,
14878 .info
= info_emulatorpin
,
14881 {.name
= "vncdisplay",
14882 .handler
= cmdVNCDisplay
,
14883 .opts
= opts_vncdisplay
,
14884 .info
= info_vncdisplay
,
14887 {.name
= "guestvcpus",
14888 .handler
= cmdGuestvcpus
,
14889 .opts
= opts_guestvcpus
,
14890 .info
= info_guestvcpus
,
14893 {.name
= "setvcpu",
14894 .handler
= cmdSetvcpu
,
14895 .opts
= opts_setvcpu
,
14896 .info
= info_setvcpu
,
14899 {.name
= "domblkthreshold",
14900 .handler
= cmdDomblkthreshold
,
14901 .opts
= opts_domblkthreshold
,
14902 .info
= info_domblkthreshold
,