[libvirt] [PATCH] virsh: Break long lines in virsh.pod
by Osier Yang
No content changes, just breaking long lines.
Pushed under trivial rule.
---
tools/virsh.pod | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/tools/virsh.pod b/tools/virsh.pod
index aa4c560..c306a38 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -468,7 +468,8 @@ Flags I<--live> or I<--config> select whether this command works on live
or persistent definitions of the domain. If both I<--live> and I<--config>
are specified, the I<--config> option takes precedence on getting the current
description and both live configuration and config are updated while setting
-the description. I<--current> is exclusive and implied if none of these was specified.
+the description. I<--current> is exclusive and implied if none of these was
+specified.
Flag I<--edit> specifies that an editor with the contents of current
description or title should be opened and the contents saved back afterwards.
@@ -1471,7 +1472,8 @@ address.
[I<--persistent>] [I<--inbound average,peak,burst>] [I<--outbound average,peak,burst>]
Attach a new network interface to the domain.
-I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
+I<type> can be either I<network> to indicate a physical network device or
+I<bridge> to indicate a bridge to a device.
I<source> indicates the source device.
I<target> allows to indicate the target device in the guest.
I<mac> allows to specify the MAC address of the network interface.
@@ -1502,9 +1504,10 @@ from the domain.
=item B<detach-interface> I<domain-id> I<type> [I<--mac mac>]
Detach a network interface from a domain.
-I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
-It is recommended to use the I<mac> option to distinguish between the interfaces
-if more than one are present on the domain.
+I<type> can be either I<network> to indicate a physical network device or
+I<bridge> to indicate a bridge to a device. It is recommended to use the
+I<mac> option to distinguish between the interfaces if more than one are
+present on the domain.
=item B<update-device> I<domain-id> I<file> [I<--persistent>] [I<--force>]
--
1.7.7.3
12 years, 8 months
[libvirt] [PATCH 0/3 v4] New command for changing media
by Osier Yang
[PATCH 0/3] introduces two new helper functions: vshFindDisk is to find
the disk XML node in xml doc with the type (indicates it's normal disk
or changeable disk). VshPrepareDiskXML is to prepare the disk XML for
disk changing commands' use, such as detach-disk. The purpose of this
patch is to prepare for upcoming new command "change-disk", which will
use the two helper functions too.
Please see [PATCH 3/3] for a overall description of the new command.
v2 - v3
* Update vshFindDisk to support search the disk node with both
the source path and target name.
* Change names of the two new enums ([PATCH 1/3]).
* Use virXMLParseStringCtxt instead of xmlReadDoc
* Use VIR_ALLOC_N instead of vshCalloc.
* [PATCH 3/4] and [PATCH 4/4] are merged into [PATCH 3/3]
* Change option "--target" into "--path".
* Defaults to use "--update" if none of "--eject", "--insert",
and "--update" is specified.
* Update docs to be consistent with the changes on codes.
* Other nits.
v3 - v4:
* No changes.
Osier Yang (3)
virsh: Two new helper functions for disk device changes
virsh: Use vshFindDisk and vshPrepareDiskXML in
virsh: New command cmdChangeMedia
tools/virsh.c | 418 ++++++++++++++++++++++++++++++++++++++++++++++++-------
tools/virsh.pod | 33 ++++-
2 files changed, 395 insertions(+), 56 deletions(-)
Regards,
Osier
12 years, 8 months
[libvirt] [PATCH 0/7 v2] virtio-scsi: New device address logic for SCSI devices
by Osier Yang
This patch series completed the support for the first 3 parts
of Paolo's proposal:
http://permalink.gmane.org/gmane.comp.emulators.libvirt/50428
The 3 parts are:
* SCSI controller models
* Stable addressing for SCSI devices
* LUN passthrough: block devices
[PATCH 1/10] and [PATCH 2/10] add two new "scsi" controllers,
"ibmvscsi" and "virtio-scsi".
[PATCH 3/10] adds a helper functions to get a disk controller's
model.
[PATCH 4/10] introduces attribute "target" for device addressing
XML. Updates lots of tests to be consistent with the newly introduced
attribute.
[PATCH 6/10] builds the qemu command line for the new addressing
format. The logic is:
1) If the disk controller model is "lsilogic":
-drive file=/dev/sda,if=none,id=drive-scsi0-0-3,\
format=raw -device scsi-disk,bus=scsi0.0,\
scsi-id=0,drive=drive-scsi0-0-3-0,id=scsi0-0-3-0
libvirt attrs --> qdev properties:
bus=scsi<controller>.0
scsi-id=<unit>
2) If the disk controller model is other else:
The command line will be like:
-drive file=/dev/sda,if=none,id=drive-scsi0-0-3-0,\
format=raw -device scsi-disk,bus=scsi0.0,channel=0,\
scsi-id=3,lun=0,drive=drive-scsi0-0-3-0,id=scsi0-0-3-0
libvirt attrs --> qdev properties:
bus=scsi<controller>.0
channel=<bus>
scsi-id=<target>
lun=<unit>
Paolo Bonzini (2)
qemu: add ibmvscsi controller model
qemu: add virtio-scsi controller model
Osier Yang (5)
conf: Add helper function to look up disk controller
conf: Introduce new attribute for device address format
qemu: New cap flag to indicate if channel is supported
qemu: Build command line for the new address format
tests: Add tests for virtio-scsi and ibmvscsi
v1 ~ v2:
* [PATCH 3/10] is removed
* "target" will be formated to all bus type, once it's
device address is of type "drive".
* Error if "target != 0" and the disk bus is not SCSI or
the scsi controller model is "lsilogic".
* [PATCH 9/10] and [PATCH 8/10] are meged into [PATCH 4/7]
docs/formatdomain.html.in | 16 ++-
docs/schemas/domaincommon.rng | 12 ++
src/conf/domain_conf.c | 38 ++++-
src/conf/domain_conf.h | 6 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 4 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_command.c | 156 +++++++++++++++++---
src/qemu/qemu_command.h | 7 +-
src/qemu/qemu_hotplug.c | 12 +-
src/vmx/vmx.c | 4 +-
tests/domainsnapshotxml2xmlout/disk_snapshot.xml | 12 +-
tests/domainsnapshotxml2xmlout/full_domain.xml | 2 +-
tests/domainsnapshotxml2xmlout/metadata.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-bios.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-blkdeviotune.xml | 4 +-
.../qemuxml2argv-blkiotune-device.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-blkiotune.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-boot-cdrom.xml | 2 +-
.../qemuxml2argv-boot-complex-bootindex.xml | 10 +-
.../qemuxml2argvdata/qemuxml2argv-boot-complex.xml | 10 +-
.../qemuxml2argvdata/qemuxml2argv-boot-floppy.xml | 4 +-
...uxml2argv-boot-menu-disable-drive-bootindex.xml | 2 +-
.../qemuxml2argv-boot-menu-disable-drive.xml | 2 +-
.../qemuxml2argv-boot-menu-disable.xml | 2 +-
.../qemuxml2argv-boot-menu-enable.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-boot-multi.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-boot-network.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-boot-order.xml | 6 +-
tests/qemuxml2argvdata/qemuxml2argv-bootloader.xml | 2 +-
.../qemuxml2argv-channel-guestfwd.xml | 2 +-
.../qemuxml2argv-channel-spicevmc-old.xml | 2 +-
.../qemuxml2argv-channel-spicevmc.xml | 2 +-
.../qemuxml2argv-channel-virtio-auto.xml | 2 +-
.../qemuxml2argv-channel-virtio.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-clock-france.xml | 2 +-
.../qemuxml2argv-clock-localtime.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-clock-utc.xml | 2 +-
.../qemuxml2argv-clock-variable.xml | 2 +-
.../qemuxml2argv-console-compat-auto.xml | 2 +-
.../qemuxml2argv-console-compat-chardev.xml | 2 +-
.../qemuxml2argv-console-compat.xml | 2 +-
.../qemuxml2argv-console-virtio-many.xml | 2 +-
.../qemuxml2argv-console-virtio.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-cputune.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-disk-aio.xml | 4 +-
.../qemuxml2argv-disk-cdrom-empty.xml | 4 +-
tests/qemuxml2argvdata/qemuxml2argv-disk-cdrom.xml | 4 +-
.../qemuxml2argv-disk-copy_on_read.xml | 2 +-
.../qemuxml2argv-disk-drive-boot-cdrom.xml | 4 +-
.../qemuxml2argv-disk-drive-boot-disk.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-directsync.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-unsafe.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v1-none.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v1-wb.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v1-wt.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v2-none.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v2-wb.xml | 4 +-
.../qemuxml2argv-disk-drive-cache-v2-wt.xml | 4 +-
...muxml2argv-disk-drive-error-policy-enospace.xml | 4 +-
.../qemuxml2argv-disk-drive-error-policy-stop.xml | 4 +-
...rgv-disk-drive-error-policy-wreport-rignore.xml | 4 +-
.../qemuxml2argv-disk-drive-fat.xml | 2 +-
.../qemuxml2argv-disk-drive-fmt-qcow.xml | 4 +-
.../qemuxml2argv-disk-drive-network-nbd.xml | 2 +-
.../qemuxml2argv-disk-drive-network-rbd-auth.xml | 2 +-
...emuxml2argv-disk-drive-network-rbd-ceph-env.xml | 2 +-
.../qemuxml2argv-disk-drive-network-rbd.xml | 2 +-
.../qemuxml2argv-disk-drive-network-sheepdog.xml | 2 +-
.../qemuxml2argv-disk-drive-no-boot.xml | 6 +-
.../qemuxml2argv-disk-drive-readonly-disk.xml | 4 +-
.../qemuxml2argv-disk-drive-readonly-no-device.xml | 4 +-
.../qemuxml2argv-disk-drive-shared.xml | 4 +-
.../qemuxml2argvdata/qemuxml2argv-disk-floppy.xml | 6 +-
.../qemuxml2argv-disk-ioeventfd.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-disk-many.xml | 8 +-
.../qemuxml2argv-disk-sata-device.xml | 2 +-
.../qemuxml2argv-disk-scsi-device.xml | 6 +-
.../qemuxml2argv-disk-scsi-virtio-scsi.args | 9 +
.../qemuxml2argv-disk-scsi-virtio-scsi.xml | 32 ++++
.../qemuxml2argv-disk-scsi-vscsi.args | 8 +
.../qemuxml2argv-disk-scsi-vscsi.xml | 32 ++++
.../qemuxml2argv-disk-snapshot.xml | 6 +-
.../qemuxml2argv-disk-transient.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-disk-usb.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-disk-virtio.xml | 4 +-
.../qemuxml2argvdata/qemuxml2argv-disk-xenvbd.xml | 4 +-
tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml | 2 +-
.../qemuxml2argv-floppy-drive-fat.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml | 2 +-
.../qemuxml2argv-graphics-listen-network.xml | 2 +-
.../qemuxml2argv-graphics-listen-network2.xml | 2 +-
.../qemuxml2argv-graphics-sdl-fullscreen.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-graphics-sdl.xml | 2 +-
.../qemuxml2argv-graphics-spice-compression.xml | 2 +-
.../qemuxml2argv-graphics-spice-qxl-vga.xml | 2 +-
.../qemuxml2argv-graphics-spice-timeout.xml | 2 +-
.../qemuxml2argv-graphics-spice.xml | 2 +-
.../qemuxml2argv-graphics-vnc-sasl.xml | 2 +-
.../qemuxml2argv-graphics-vnc-socket.xml | 2 +-
.../qemuxml2argv-graphics-vnc-tls.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-graphics-vnc.xml | 2 +-
.../qemuxml2argv-hostdev-pci-address.xml | 2 +-
.../qemuxml2argv-hostdev-usb-address.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-hugepages.xml | 2 +-
.../qemuxml2argv-input-usbmouse-addr.xml | 2 +-
.../qemuxml2argv-input-usbmouse.xml | 2 +-
.../qemuxml2argv-input-usbtablet.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-input-xen.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-lease.xml | 4 +-
.../qemuxml2argv-machine-aliases1.xml | 2 +-
.../qemuxml2argv-machine-aliases2.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-memtune.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-metadata.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-migrate.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-minimal.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-misc-acpi.xml | 2 +-
.../qemuxml2argv-misc-no-reboot.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-misc-uuid.xml | 2 +-
.../qemuxml2argv-multifunction-pci-device.xml | 2 +-
.../qemuxml2argv-net-bandwidth.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-client.xml | 2 +-
.../qemuxml2argv-net-eth-ifname.xml | 2 +-
.../qemuxml2argv-net-eth-names.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-eth.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-mcast.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-server.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-user.xml | 2 +-
.../qemuxml2argv-net-virtio-device.xml | 2 +-
.../qemuxml2argv-net-virtio-network-portgroup.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-net-virtio.xml | 2 +-
.../qemuxml2argv-nographics-vga.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-nographics.xml | 2 +-
.../qemuxml2argv-numatune-memory.xml | 2 +-
.../qemuxml2argv-parallel-tcp-chardev.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-parallel-tcp.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-pci-rom.xml | 2 +-
.../qemuxml2argv-pseries-vio-user-assigned.args | 13 ++-
.../qemuxml2argvdata/qemuxml2argv-pseries-vio.args | 13 ++-
.../qemuxml2argv-qemu-ns-no-env.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-qemu-ns.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-restore-v1.xml | 2 +-
.../qemuxml2argv-restore-v2-fd.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-restore-v2.xml | 2 +-
.../qemuxml2argv-seclabel-dynamic-baselabel.xml | 2 +-
.../qemuxml2argv-seclabel-dynamic-override.xml | 4 +-
.../qemuxml2argv-seclabel-dynamic.xml | 2 +-
.../qemuxml2argv-seclabel-none.xml | 2 +-
.../qemuxml2argv-seclabel-static-relabel.xml | 2 +-
.../qemuxml2argv-seclabel-static.xml | 2 +-
.../qemuxml2argv-serial-dev-chardev.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-dev.xml | 2 +-
.../qemuxml2argv-serial-file-chardev.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-serial-file.xml | 2 +-
.../qemuxml2argv-serial-many-chardev.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-serial-many.xml | 2 +-
.../qemuxml2argv-serial-pty-chardev.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-pty.xml | 2 +-
.../qemuxml2argv-serial-target-port-auto.xml | 2 +-
.../qemuxml2argv-serial-tcp-chardev.xml | 2 +-
.../qemuxml2argv-serial-tcp-telnet-chardev.xml | 2 +-
.../qemuxml2argv-serial-tcp-telnet.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-tcp.xml | 2 +-
.../qemuxml2argv-serial-udp-chardev.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-udp.xml | 2 +-
.../qemuxml2argv-serial-unix-chardev.xml | 2 +-
.../qemuxml2argvdata/qemuxml2argv-serial-unix.xml | 2 +-
.../qemuxml2argv-serial-vc-chardev.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-serial-vc.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-smbios.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-smp.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-sound.xml | 2 +-
tests/qemuxml2argvdata/qemuxml2argv-watchdog.xml | 2 +-
tests/qemuxml2argvtest.c | 4 +
.../qemuxml2xmlout-balloon-device-auto.xml | 2 +-
.../qemuxml2xmlout-channel-virtio-auto.xml | 2 +-
.../qemuxml2xmlout-console-compat-auto.xml | 2 +-
.../qemuxml2xmlout-console-virtio.xml | 2 +-
.../qemuxml2xmlout-disk-cdrom-empty.xml | 4 +-
.../qemuxml2xmlout-disk-scsi-device-auto.xml | 4 +-
.../qemuxml2xmlout-graphics-listen-network2.xml | 2 +-
.../qemuxml2xmlout-graphics-spice-timeout.xml | 2 +-
.../qemuxml2xmloutdata/qemuxml2xmlout-metadata.xml | 2 +-
.../qemuxml2xmlout-serial-target-port-auto.xml | 2 +-
tests/qemuxml2xmltest.c | 4 +-
tests/vmx2xmldata/vmx2xml-case-insensitive-1.xml | 2 +-
tests/vmx2xmldata/vmx2xml-case-insensitive-2.xml | 2 +-
tests/vmx2xmldata/vmx2xml-cdrom-ide-device.xml | 2 +-
tests/vmx2xmldata/vmx2xml-cdrom-ide-file.xml | 2 +-
tests/vmx2xmldata/vmx2xml-cdrom-scsi-device.xml | 2 +-
tests/vmx2xmldata/vmx2xml-cdrom-scsi-file.xml | 2 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-1.xml | 2 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-2.xml | 12 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-3.xml | 6 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-4.xml | 2 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml | 4 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-6.xml | 4 +-
tests/vmx2xmldata/vmx2xml-floppy-device.xml | 2 +-
tests/vmx2xmldata/vmx2xml-floppy-file.xml | 2 +-
tests/vmx2xmldata/vmx2xml-gsx-in-the-wild-1.xml | 2 +-
tests/vmx2xmldata/vmx2xml-gsx-in-the-wild-2.xml | 2 +-
tests/vmx2xmldata/vmx2xml-gsx-in-the-wild-3.xml | 2 +-
tests/vmx2xmldata/vmx2xml-gsx-in-the-wild-4.xml | 2 +-
tests/vmx2xmldata/vmx2xml-harddisk-ide-file.xml | 2 +-
tests/vmx2xmldata/vmx2xml-harddisk-scsi-file.xml | 2 +-
tests/vmx2xmldata/vmx2xml-scsi-driver.xml | 8 +-
tests/vmx2xmldata/vmx2xml-scsi-writethrough.xml | 2 +-
tests/vmx2xmldata/vmx2xml-ws-in-the-wild-1.xml | 4 +-
tests/vmx2xmldata/vmx2xml-ws-in-the-wild-2.xml | 4 +-
209 files changed, 588 insertions(+), 300 deletions(-)
Regards,
Osier
12 years, 8 months
[libvirt] [PATCH] qemu: unescape HMP commands before converting them to json
by Josh Durgin
QMP commands don't need to be escaped since converting them to json
also escapes special characters. When a QMP command fails, however,
libvirt falls back to HMP commands. These fallback functions
(qemuMonitorText*) do their own escaping, and pass the result directly
to qemuMonitorHMPCommandWithFd. If the monitor is in json mode, these
pre-escaped commands will be escaped again when converted to json,
which can result in the wrong arguments being sent.
For example, a filename test\file would be sent in json as
test\\file.
This prevented attaching an image file with a " or \ in its name in
qemu 1.0.50, and also broke rbd attachment (which uses backslashes to
escape some internal arguments.)
Reported-by: Masuko Tomoya <tomoya.masuko(a)gmail.com>
Signed-off-by: Josh Durgin <josh.durgin(a)dreamhost.com>
---
.gitignore | 1 +
src/qemu/qemu_monitor.c | 59 +++++++++++++++++++++++-
src/qemu/qemu_monitor.h | 1 +
tests/Makefile.am | 12 ++++-
tests/qemumonitortest.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 181 insertions(+), 6 deletions(-)
create mode 100644 tests/qemumonitortest.c
diff --git a/.gitignore b/.gitignore
index b7561dc..264a419 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,6 +128,7 @@
/tests/openvzutilstest
/tests/qemuargv2xmltest
/tests/qemuhelptest
+/tests/qemumonitortest
/tests/qemuxmlnstest
/tests/qparamtest
/tests/reconnect
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 93f3505..85212a7 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -153,6 +153,49 @@ char *qemuMonitorEscapeArg(const char *in)
return out;
}
+char *qemuMonitorUnescapeArg(const char *in)
+{
+ int i, j;
+ char *out;
+ int len = strlen(in) + 1;
+ char next;
+
+ if (VIR_ALLOC_N(out, len) < 0)
+ return NULL;
+
+ for (i = j = 0; i < len; ++i) {
+ next = in[i];
+ if (in[i] == '\\') {
+ if (len < i + 1) {
+ // trailing backslash shouldn't be possible
+ VIR_FREE(out);
+ return NULL;
+ }
+ ++i;
+ switch(in[i]) {
+ case 'r':
+ next = '\r';
+ break;
+ case 'n':
+ next = '\n';
+ break;
+ case '"':
+ case '\\':
+ next = in[i];
+ break;
+ default:
+ // invalid input
+ VIR_FREE(out);
+ return NULL;
+ }
+ }
+ out[j++] = next;
+ }
+ out[j] = '\0';
+
+ return out;
+}
+
#if DEBUG_RAW_IO
# include <c-ctype.h>
static char * qemuMonitorEscapeNonPrintable(const char *text)
@@ -852,10 +895,20 @@ int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
int scm_fd,
char **reply)
{
- if (mon->json)
- return qemuMonitorJSONHumanCommandWithFd(mon, cmd, scm_fd, reply);
- else
+ char *json_cmd = NULL;
+ if (mon->json) {
+ // hack to avoid complicating each call to text monitor functions
+ json_cmd = qemuMonitorUnescapeArg(cmd);
+ if (!json_cmd) {
+ VIR_DEBUG("Could not unescape command: %s", cmd);
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to unescape command"));
+ return -1;
+ }
+ return qemuMonitorJSONHumanCommandWithFd(mon, json_cmd, scm_fd, reply);
+ } else {
return qemuMonitorTextCommandWithFd(mon, cmd, scm_fd, reply);
+ }
}
/* Ensure proper locking around callbacks. */
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 7c6c52b..9768457 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -128,6 +128,7 @@ struct _qemuMonitorCallbacks {
char *qemuMonitorEscapeArg(const char *in);
+char *qemuMonitorUnescapeArg(const char *in);
qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm,
virDomainChrSourceDefPtr config,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9974c2f..3e505a5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -72,6 +72,7 @@ EXTRA_DIST = \
nwfilterxml2xmlout \
oomtrace.pl \
qemuhelpdata \
+ qemumonitortest \
qemuxml2argvdata \
qemuxml2xmloutdata \
qemuxmlnsdata \
@@ -110,7 +111,8 @@ check_PROGRAMS += xml2sexprtest sexpr2xmltest \
endif
if WITH_QEMU
check_PROGRAMS += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \
- qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest
+ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \
+ qemumonitortest
endif
if WITH_OPENVZ
@@ -237,7 +239,8 @@ endif
if WITH_QEMU
TESTS += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest qemuargv2xmltest \
- qemuhelptest domainsnapshotxml2xmltest nwfilterxml2xmltest
+ qemuhelptest domainsnapshotxml2xmltest nwfilterxml2xmltest \
+ qemumonitortest
endif
if WITH_OPENVZ
@@ -365,6 +368,9 @@ qemuargv2xmltest_LDADD = $(qemu_LDADDS) $(LDADDS)
qemuhelptest_SOURCES = qemuhelptest.c testutils.c testutils.h
qemuhelptest_LDADD = $(qemu_LDADDS) $(LDADDS)
+qemumonitortest_SOURCES = qemumonitortest.c testutils.c testutils.h
+qemumonitortest_LDADD = $(qemu_LDADDS) $(LDADDS)
+
domainsnapshotxml2xmltest_SOURCES = \
domainsnapshotxml2xmltest.c testutilsqemu.c testutilsqemu.h \
testutils.c testutils.h
@@ -372,7 +378,7 @@ domainsnapshotxml2xmltest_LDADD = $(qemu_LDADDS) $(LDADDS)
else
EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \
qemuxmlnstest.c qemuhelptest.c domainsnapshotxml2xmltest.c \
- testutilsqemu.c testutilsqemu.h
+ qemumonitortest.c testutilsqemu.c testutilsqemu.h
endif
if WITH_OPENVZ
diff --git a/tests/qemumonitortest.c b/tests/qemumonitortest.c
new file mode 100644
index 0000000..bf90502
--- /dev/null
+++ b/tests/qemumonitortest.c
@@ -0,0 +1,114 @@
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef WITH_QEMU
+
+# include "internal.h"
+# include "memory.h"
+# include "testutils.h"
+# include "util.h"
+# include "qemu/qemu_monitor.h"
+
+struct testEscapeString
+{
+ const char* unescaped;
+ const char* escaped;
+};
+
+static struct testEscapeString escapeStrings[] = {
+ { "", "" },
+ { " ", " " },
+ { "\\", "\\\\" },
+ { "\n", "\\n" },
+ { "\r", "\\r" },
+ { "\"", "\\\"" },
+ { "\"\"\"\\\\\n\r\\\\\n\r\"\"\"", "\\\"\\\"\\\"\\\\\\\\\\n\\r\\\\\\\\\\n\\r\\\"\\\"\\\"" },
+ { "drive_add dummy file=foo\\", "drive_add dummy file=foo\\\\" },
+ { "block info", "block info" },
+ { "set_password \":\\\"\"", "set_password \\\":\\\\\\\"\\\"" },
+};
+
+static int testEscapeArg(const void *data ATTRIBUTE_UNUSED)
+{
+ int i;
+ char *escaped = NULL;
+ for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
+ escaped = qemuMonitorEscapeArg(escapeStrings[i].unescaped);
+ if (!escaped) {
+ if (virTestGetDebug() > 0) {
+ fprintf(stderr, "\nUnescaped string [%s]\n", escapeStrings[i].unescaped);
+ fprintf(stderr, "Expect result [%s]\n", escapeStrings[i].escaped);
+ fprintf(stderr, "Actual result [%s]\n", escaped);
+ }
+ return -1;
+ }
+ if (STRNEQ(escapeStrings[i].escaped, escaped)) {
+ virtTestDifference(stderr, escapeStrings[i].escaped, escaped);
+ VIR_FREE(escaped);
+ return -1;
+ }
+ VIR_FREE(escaped);
+ }
+
+ return 0;
+}
+
+static int testUnescapeArg(const void *data ATTRIBUTE_UNUSED)
+{
+ int i;
+ char *unescaped = NULL;
+ for (i = 0; i < ARRAY_CARDINALITY(escapeStrings); ++i) {
+ unescaped = qemuMonitorUnescapeArg(escapeStrings[i].escaped);
+ if (!unescaped) {
+ if (virTestGetDebug() > 0) {
+ fprintf(stderr, "\nEscaped string [%s]\n", escapeStrings[i].escaped);
+ fprintf(stderr, "Expect result [%s]\n", escapeStrings[i].unescaped);
+ fprintf(stderr, "Actual result [%s]\n", unescaped);
+ }
+ return -1;
+ }
+ if (STRNEQ(escapeStrings[i].unescaped, unescaped)) {
+ virtTestDifference(stderr, escapeStrings[i].unescaped, unescaped);
+ VIR_FREE(unescaped);
+ return -1;
+ }
+ VIR_FREE(unescaped);
+ }
+
+ return 0;
+}
+
+static int
+mymain(void)
+{
+ int result = 0;
+
+#define DO_TEST(_name) \
+ do { \
+ if (virtTestRun("qemu monitor "#_name, 1, test##_name, \
+ NULL) < 0) { \
+ result = -1; \
+ } \
+ } while (0)
+
+ DO_TEST(EscapeArg);
+ DO_TEST(UnescapeArg);
+
+ return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN(mymain)
+
+#else
+# include "testutils.h"
+
+int main(void)
+{
+ return EXIT_AM_SKIP;
+}
+
+#endif /* WITH_QEMU */
--
1.7.1
12 years, 8 months
[libvirt] [virsh] [PATCH BZ#732364] please add a .virsh/rc file
by Feniks Gordon Freeman
Hi, libvirt developers
I found very interesting libvirt and i wrote patch for BZ#732264
I added support for parsing ~/.virsh/rc file.
rc file in format KEY = VALUE
symbol '#' - comment
Now, only one value added for parsing - VIRSH_DEFAULT_CONNECT_URI.
This value can be overwrite by env variable VIRSH_DEFAULT_CONNECT_URI.
Thanks
P.S. How to add patch file? As attached file or in mail body?
P.P.S. I am using irc, my nick - fenksa
---
diff --git a/tools/virsh.c b/tools/virsh.c
index e712e53..8360c57 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -33,6 +33,7 @@
#include <signal.h>
#include <poll.h>
#include <strings.h>
+#include <pwd.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -19313,6 +19314,132 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
return true;
}
+#define DEFAULT_RC_FILENAME ".virsh/rc"
+
+static const char*
+vshRcPath(vshControl* ctl) {
+ const char* home;
+ char* path;
+
+ home = virGetUserDirectory(getuid());
+ path = vshMalloc(ctl, strlen(home) + strlen(DEFAULT_RC_FILENAME) + 2);
+
+ memcpy(path, home, strlen(home));
+ path[strlen(home)] = '/';
+ memcpy(path + strlen(home) + 1, DEFAULT_RC_FILENAME,
strlen(DEFAULT_RC_FILENAME));
+
+ VIR_FREE(home);
+
+ return path;
+}
+
+typedef struct {
+ char* buf;
+ int len;
+ int p;
+} RcParseBuffer;
+
+static void
+vshClearRcParseBuffer(RcParseBuffer* buf) {
+ buf->p = 0;
+ bzero(buf->buf, buf->len);
+}
+
+static void
+vshInitRcParseBuffer(vshControl* ctl, RcParseBuffer* buf, int len) {
+ buf->buf = vshMalloc(ctl, len);
+ buf->len = len;
+ vshClearRcParseBuffer(buf);
+};
+
+static void
+vshAddCharRcParseBuffer(RcParseBuffer* buf, char ch) {
+ if (buf->p < buf->len) {
+ buf->buf[buf->p] = ch;
+ buf->p = buf->p + 1;
+ }
+}
+
+static void
+vshParseRc(vshControl *ctl)
+{
+ int fd;
+ const char* fileName = vshRcPath(ctl);
+ bool parseValue = false;
+
+ RcParseBuffer keyBuffer;
+ RcParseBuffer valueBuffer;
+ char buffer[1024];
+
+ vshInitRcParseBuffer(ctl, &keyBuffer, 255);
+ vshInitRcParseBuffer(ctl, &valueBuffer, 255);
+
+ /* open ~/.virsh/rc file */
+ if ((fd = open(fileName, O_RDONLY)) <= 0) {
+ vshDebug(ctl, VSH_ERR_INFO, "can't open file %s\n", fileName);
+ goto cleanup;
+ }
+
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) == -1) {
+ vshDebug(ctl, VSH_ERR_INFO, "file %s not stated\n", fileName);
+ goto cleanup;
+ }
+
+ if (!S_ISREG(statBuf.st_mode)) {
+ vshError(ctl, _("file %s is not regular\n"), fileName);
+ goto cleanup;
+ }
+
+ int bytesRead;
+ while ((bytesRead = read(fd, buffer, sizeof(buffer))) > 0) {
+ for (int i = 0; i < bytesRead; i++) {
+ /* ignore empty spaces and comments */
+ if (buffer[i] == ' ' || buffer[i] == '#') {
+ continue;
+ }
+
+ /* found separator = */
+ if (buffer[i] == '=') {
+ if (!parseValue) {
+ parseValue = true;
+ continue;
+ }
+ }
+
+ /* end of line*/
+ if (buffer[i] == '\n') {
+ if (STREQ(keyBuffer.buf, "VIRSH_DEFAULT_CONNECT_URI")) {
+ ctl->name = vshStrdup(ctl, valueBuffer.buf);
+ }
+
+ vshClearRcParseBuffer(&keyBuffer);
+ vshClearRcParseBuffer(&valueBuffer);
+
+ parseValue = false;
+ continue;
+ }
+
+ if (parseValue) {
+ vshAddCharRcParseBuffer(&valueBuffer, buffer[i]);
+ } else {
+ vshAddCharRcParseBuffer(&keyBuffer, buffer[i]);
+ }
+ }
+ }
+
+cleanup:
+ if (fd >= 0) {
+ if (close(fd) < 0) {
+ vshError(ctl, _("cannot close file %s"), fileName);
+ }
+ }
+ VIR_FREE(fileName);
+ VIR_FREE(keyBuffer.buf);
+ VIR_FREE(valueBuffer.buf);
+}
+
+
int
main(int argc, char **argv)
{
@@ -19355,6 +19482,8 @@ main(int argc, char **argv)
else
progname++;
+ vshParseRc(ctl);
+
if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
ctl->name = vshStrdup(ctl, defaultConn);
}
--
With best wishes, Maxim Sditanov
12 years, 8 months
[libvirt] [PATCH v5 0/7] Console corruption patchset
by Peter Krempa
Yet another spin of the console corruption patches.
Current state:
* 1/7 - pidfile: Make checking binary path in virPidFileRead optional
- No changes to v4.
- ACKed by Eric
* 2/7 - Add flags for virDomainOpenConsole
- No changes to v4.
- ACKed by Eric
* 3/7 - virsh: add support for VIR_DOMAIN_CONSOLE_* flags
- No changes to v4.
- ACKed by Eric
* 4/7 - fdstream: Emit stream abort callback even if poll() doesnt.
- Tweaked according to Eric's review
* 5/7 - fdstream: Add internal callback on stream close
- Tweaked according to Eric's review
* 6/7 - util: Add helpers for safe domain console operations
- Tweaked according to Eric's review
* 7/7 - qemu: Add ability to abort existing console while creating new one
- No changes to v4.
- ACKed by Eric
Peter Krempa (7):
pidfile: Make checking binary path in virPidFileRead optional
Add flags for virDomainOpenConsole
virsh: add support for VIR_DOMAIN_CONSOLE_* flags
fdstream: Emit stream abort callback even if poll() doesnt.
fdstream: Add internal callback on stream close
util: Add helpers for safe domain console operations
qemu: Add ability to abort existing console while creating new one
configure.ac | 25 +++
include/libvirt/libvirt.h.in | 12 ++
po/POTFILES.in | 1 +
src/Makefile.am | 6 +-
src/conf/virconsole.c | 408 ++++++++++++++++++++++++++++++++++++++++++
src/conf/virconsole.h | 36 ++++
src/fdstream.c | 97 ++++++++++-
src/fdstream.h | 13 ++-
src/libvirt.c | 18 ++-
src/libvirt_private.syms | 6 +
src/qemu/qemu_domain.c | 5 +
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_driver.c | 21 ++-
src/util/virpidfile.c | 21 ++-
tools/console.c | 5 +-
tools/console.h | 3 +-
tools/virsh.c | 24 ++-
tools/virsh.pod | 8 +-
18 files changed, 680 insertions(+), 32 deletions(-)
create mode 100644 src/conf/virconsole.c
create mode 100644 src/conf/virconsole.h
--
1.7.3.4
12 years, 8 months
[libvirt] [virsh] [PATCH BZ#732364] please add a .virsh/rc file
by Feniks Gordon Freeman
Hi, libvirt developers
I found very interesting libvirt and i wrote patch for BZ#732264
I added support for parsing ~/.virsh/rc file.
rc file in format KEY = VALUE
symbol '#' - comment
Now, only one value added for parsing - VIRSH_DEFAULT_CONNECT_URI.
This value can be overwrite by env variable VIRSH_DEFAULT_CONNECT_URI.
Thanks
P.S. How to add patch file? As attached file or in mail body?
P.P.S. I am using irc, my nick - fenksa
---
diff --git a/tools/virsh.c b/tools/virsh.c
index e712e53..8360c57 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -33,6 +33,7 @@
#include <signal.h>
#include <poll.h>
#include <strings.h>
+#include <pwd.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -19313,6 +19314,132 @@ vshParseArgv(vshControl *ctl, int argc, char **argv)
return true;
}
+#define DEFAULT_RC_FILENAME ".virsh/rc"
+
+static const char*
+vshRcPath(vshControl* ctl) {
+ const char* home;
+ char* path;
+
+ home = virGetUserDirectory(getuid());
+ path = vshMalloc(ctl, strlen(home) + strlen(DEFAULT_RC_FILENAME) + 2);
+
+ memcpy(path, home, strlen(home));
+ path[strlen(home)] = '/';
+ memcpy(path + strlen(home) + 1, DEFAULT_RC_FILENAME,
strlen(DEFAULT_RC_FILENAME));
+
+ VIR_FREE(home);
+
+ return path;
+}
+
+typedef struct {
+ char* buf;
+ int len;
+ int p;
+} RcParseBuffer;
+
+static void
+vshClearRcParseBuffer(RcParseBuffer* buf) {
+ buf->p = 0;
+ bzero(buf->buf, buf->len);
+}
+
+static void
+vshInitRcParseBuffer(vshControl* ctl, RcParseBuffer* buf, int len) {
+ buf->buf = vshMalloc(ctl, len);
+ buf->len = len;
+ vshClearRcParseBuffer(buf);
+};
+
+static void
+vshAddCharRcParseBuffer(RcParseBuffer* buf, char ch) {
+ if (buf->p < buf->len) {
+ buf->buf[buf->p] = ch;
+ buf->p = buf->p + 1;
+ }
+}
+
+static void
+vshParseRc(vshControl *ctl)
+{
+ int fd;
+ const char* fileName = vshRcPath(ctl);
+ bool parseValue = false;
+
+ RcParseBuffer keyBuffer;
+ RcParseBuffer valueBuffer;
+ char buffer[1024];
+
+ vshInitRcParseBuffer(ctl, &keyBuffer, 255);
+ vshInitRcParseBuffer(ctl, &valueBuffer, 255);
+
+ /* open ~/.virsh/rc file */
+ if ((fd = open(fileName, O_RDONLY)) <= 0) {
+ vshDebug(ctl, VSH_ERR_INFO, "can't open file %s\n", fileName);
+ goto cleanup;
+ }
+
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) == -1) {
+ vshDebug(ctl, VSH_ERR_INFO, "file %s not stated\n", fileName);
+ goto cleanup;
+ }
+
+ if (!S_ISREG(statBuf.st_mode)) {
+ vshError(ctl, _("file %s is not regular\n"), fileName);
+ goto cleanup;
+ }
+
+ int bytesRead;
+ while ((bytesRead = read(fd, buffer, sizeof(buffer))) > 0) {
+ for (int i = 0; i < bytesRead; i++) {
+ /* ignore empty spaces and comments */
+ if (buffer[i] == ' ' || buffer[i] == '#') {
+ continue;
+ }
+
+ /* found separator = */
+ if (buffer[i] == '=') {
+ if (!parseValue) {
+ parseValue = true;
+ continue;
+ }
+ }
+
+ /* end of line*/
+ if (buffer[i] == '\n') {
+ if (STREQ(keyBuffer.buf, "VIRSH_DEFAULT_CONNECT_URI")) {
+ ctl->name = vshStrdup(ctl, valueBuffer.buf);
+ }
+
+ vshClearRcParseBuffer(&keyBuffer);
+ vshClearRcParseBuffer(&valueBuffer);
+
+ parseValue = false;
+ continue;
+ }
+
+ if (parseValue) {
+ vshAddCharRcParseBuffer(&valueBuffer, buffer[i]);
+ } else {
+ vshAddCharRcParseBuffer(&keyBuffer, buffer[i]);
+ }
+ }
+ }
+
+cleanup:
+ if (fd >= 0) {
+ if (close(fd) < 0) {
+ vshError(ctl, _("cannot close file %s"), fileName);
+ }
+ }
+ VIR_FREE(fileName);
+ VIR_FREE(keyBuffer.buf);
+ VIR_FREE(valueBuffer.buf);
+}
+
+
int
main(int argc, char **argv)
{
@@ -19355,6 +19482,8 @@ main(int argc, char **argv)
else
progname++;
+ vshParseRc(ctl);
+
if ((defaultConn = getenv("VIRSH_DEFAULT_CONNECT_URI"))) {
ctl->name = vshStrdup(ctl, defaultConn);
}
--
With best wishes, Maxim Sditanov
12 years, 8 months
[libvirt] [PATCH v2 0/3] Introduce virDomainPMWakeup API
by Michal Privoznik
This is counterpart for virDomainPMSuspendForDuration API which
we have already in. It allows user to wake up guest from S3 state.
1/3 is already ACKed, but I am sending it for the completeness sake.
Michal Privoznik (3):
Introduce virDomainPMWakeup API
virsh: Expose virDomainPMWakeup
qemu: Implement virDomainPMWakeup API
include/libvirt/libvirt.h.in | 2 +
src/driver.h | 4 +++
src/libvirt.c | 50 ++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/qemu/qemu_driver.c | 55 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 19 ++++++++++++++
src/qemu/qemu_monitor.h | 2 +
src/qemu/qemu_monitor_json.c | 21 ++++++++++++++++
src/qemu/qemu_monitor_json.h | 2 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 8 +++++-
src/remote_protocol-structs | 5 ++++
tools/virsh.c | 46 +++++++++++++++++++++++++++++++++++
tools/virsh.pod | 6 ++++
14 files changed, 221 insertions(+), 1 deletions(-)
--
1.7.3.4
12 years, 8 months
[libvirt] [PATCH] BlockJob: Support sync/async virDomainBlockJobAbort
by Adam Litke
Qemu has changed the semantics of the "block_job_cancel" API. Originally, the
operation was synchronous (ie. upon command completion, the operation was
guaranteed to be completely stopped). With the new semantics, a
"block_job_cancel" merely requests that the operation be cancelled and an event
is triggered once the cancellation request has been honored.
To adopt the new semantics while preserving compatibility I propose the
following updates to the virDomainBlockJob API:
A new block job event type VIR_DOMAIN_BLOCK_JOB_CANCELLED will be recognized by
libvirt. Regardless of the flags used with virDomainBlockJobAbort, this event
will be raised whenever it is received from qemu. This event indicates that a
block job has been successfully cancelled.
A new extension flag VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC will be added to the
virDomainBlockJobAbort API. When enabled, this function will operate
asynchronously (ie, it can return before the job has actually been cancelled).
When the API is used in this mode, it is the responsibility of the caller to
wait for a VIR_DOMAIN_BLOCK_JOB_CANCELLED event or poll via the
virDomainGetBlockJobInfo API to check the cancellation status.
Without the VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag, libvirt will internally poll
using qemu's "query-block-jobs" API and will not return until the operation has
been completed. API users are advised that this operation is unbounded and
further interaction with the domain during this period may block.
This patch implements the new event type, the API flag, and the polling. The
main outstanding issue is whether we should bound the amount of time we will
wait for cancellation and return an error.
Comments on this proposal?
Signed-off-by: Adam Litke <agl(a)us.ibm.com>
Cc: Stefan Hajnoczi <stefanha(a)gmail.com>
Cc: Eric Blake <eblake(a)redhat.com>
---
include/libvirt/libvirt.h.in | 10 ++++++++++
src/libvirt.c | 9 ++++++++-
src/qemu/qemu_driver.c | 24 +++++++++++++++++-------
src/qemu/qemu_monitor.c | 24 ++++++++++++++++++++++++
src/qemu/qemu_monitor.h | 2 ++
src/qemu/qemu_monitor_json.c | 36 +++++++++++++++++++++++++++++-------
6 files changed, 90 insertions(+), 15 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index e436f3c..fc7f028 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1776,6 +1776,15 @@ typedef enum {
VIR_DOMAIN_BLOCK_JOB_TYPE_PULL = 1,
} virDomainBlockJobType;
+/**
+ * virDomainBlockJobAbortFlags:
+ *
+ * VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC: Request only, do not wait for completion
+ */
+typedef enum {
+ VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC = 1,
+} virDomainBlockJobAbortFlags;
+
/* An iterator for monitoring block job operations */
typedef unsigned long long virDomainBlockJobCursor;
@@ -3293,6 +3302,7 @@ typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
typedef enum {
VIR_DOMAIN_BLOCK_JOB_COMPLETED = 0,
VIR_DOMAIN_BLOCK_JOB_FAILED = 1,
+ VIR_DOMAIN_BLOCK_JOB_CANCELLED = 2,
} virConnectDomainEventBlockJobStatus;
/**
diff --git a/src/libvirt.c b/src/libvirt.c
index a540424..0e886f5 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -17299,7 +17299,7 @@ error:
* virDomainBlockJobAbort:
* @dom: pointer to domain object
* @disk: path to the block device, or device shorthand
- * @flags: extra flags; not used yet, so callers should always pass 0
+ * @flags: bitwise or of virDomainBlockJobAbortFlags
*
* Cancel the active block job on the given disk.
*
@@ -17310,6 +17310,13 @@ error:
* can be found by calling virDomainGetXMLDesc() and inspecting
* elements within //domain/devices/disk.
*
+ * By default, this function performs a synchronous operation and the caller
+ * may assume that the operation has completed when 0 is returned. However,
+ * BlockJob operations may take a long time to complete, and during this time
+ * further domain interactions may be unresponsive. To avoid this problem, pass
+ * VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC in the flags argument to enable asynchronous
+ * behavior. When the job has been cancelled, a BlockJob event will be emitted.
+ *
* Returns -1 in case of failure, 0 when successful.
*/
int virDomainBlockJobAbort(virDomainPtr dom, const char *disk,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 712f1fc..d971a5f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11379,7 +11379,7 @@ cleanup:
static int
qemuDomainBlockJobImpl(virDomainPtr dom, const char *path,
unsigned long bandwidth, virDomainBlockJobInfoPtr info,
- int mode)
+ int flags, int mode)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
@@ -11420,6 +11420,15 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path,
qemuDomainObjEnterMonitorWithDriver(driver, vm);
priv = vm->privateData;
ret = qemuMonitorBlockJob(priv->mon, device, bandwidth, info, mode);
+ /*
+ * Qemu provides asynchronous block job cancellation but without the
+ * VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC flag libvirt guarantees a synchronous
+ * operation. Provide this behavior by waiting here (with the monitor
+ * locked) so we don't get confused by newly scheduled block jobs.
+ */
+ if (ret == 0 && mode == BLOCK_JOB_ABORT &&
+ !(flags & VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC))
+ ret = qemuMonitorBlockJobCancelWait(priv->mon, device);
qemuDomainObjExitMonitorWithDriver(driver, vm);
endjob:
@@ -11439,8 +11448,7 @@ cleanup:
static int
qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
{
- virCheckFlags(0, -1);
- return qemuDomainBlockJobImpl(dom, path, 0, NULL, BLOCK_JOB_ABORT);
+ return qemuDomainBlockJobImpl(dom, path, 0, NULL, flags, BLOCK_JOB_ABORT);
}
static int
@@ -11448,7 +11456,7 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path,
virDomainBlockJobInfoPtr info, unsigned int flags)
{
virCheckFlags(0, -1);
- return qemuDomainBlockJobImpl(dom, path, 0, info, BLOCK_JOB_INFO);
+ return qemuDomainBlockJobImpl(dom, path, 0, info, flags, BLOCK_JOB_INFO);
}
static int
@@ -11456,7 +11464,8 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
unsigned long bandwidth, unsigned int flags)
{
virCheckFlags(0, -1);
- return qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, BLOCK_JOB_SPEED);
+ return qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, flags,
+ BLOCK_JOB_SPEED);
}
static int
@@ -11466,9 +11475,10 @@ qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth,
int ret;
virCheckFlags(0, -1);
- ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, BLOCK_JOB_PULL);
+ ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, flags,
+ BLOCK_JOB_PULL);
if (ret == 0 && bandwidth != 0)
- ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL,
+ ret = qemuDomainBlockJobImpl(dom, path, bandwidth, NULL, flags,
BLOCK_JOB_SPEED);
return ret;
}
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index ad7e2a5..5c22486 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2585,6 +2585,30 @@ int qemuMonitorScreendump(qemuMonitorPtr mon,
return ret;
}
+/* Poll the monitor to wait for the block job on a given disk to end.
+ * We don't need to worry about another block job starting since we have the
+ * driver locked. */
+int
+qemuMonitorBlockJobCancelWait(qemuMonitorPtr mon, const char *device)
+{
+ VIR_DEBUG("mon=%p, device=%p", mon, device);
+ /* XXX: Should we provide some sort of escape hatch for this wait? */
+ while (1) {
+ /* Poll every 100ms */
+ int ret;
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000ull };
+ virDomainBlockJobInfo info;
+
+ ret = qemuMonitorBlockJob(mon, device, 0, &info, BLOCK_JOB_INFO);
+ if (ret < 0)
+ return -1;
+ else if (ret == 0)
+ return 0;
+ else
+ nanosleep(&ts, NULL);
+ }
+}
+
int qemuMonitorBlockJob(qemuMonitorPtr mon,
const char *device,
unsigned long bandwidth,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 15acf8b..afc081e 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -510,6 +510,8 @@ typedef enum {
BLOCK_JOB_PULL = 3,
} BLOCK_JOB_CMD;
+int qemuMonitorBlockJobCancelWait(qemuMonitorPtr mon, const char *device);
+
int qemuMonitorBlockJob(qemuMonitorPtr mon,
const char *device,
unsigned long bandwidth,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7eb2a92..2ca8eeb 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -57,7 +57,8 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat
static void qemuMonitorJSONHandleVNCConnect(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleVNCInitialize(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValuePtr data);
-static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleBlockJobCancelled(qemuMonitorPtr mon, virJSONValuePtr data);
struct {
const char *type;
@@ -73,7 +74,8 @@ struct {
{ "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
{ "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
{ "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
- { "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJob, },
+ { "BLOCK_JOB_COMPLETED", qemuMonitorJSONHandleBlockJobCompleted, },
+ { "BLOCK_JOB_CANCELLED", qemuMonitorJSONHandleBlockJobCancelled, },
};
@@ -685,13 +687,14 @@ static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitorPtr mon, virJSONValueP
qemuMonitorJSONHandleVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
}
-static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr data)
+static void qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
+ virJSONValuePtr data,
+ int event)
{
const char *device;
const char *type_str;
int type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
unsigned long long offset, len;
- int status = VIR_DOMAIN_BLOCK_JOB_FAILED;
if ((device = virJSONValueObjectGetString(data, "device")) == NULL) {
VIR_WARN("missing device in block job event");
@@ -716,13 +719,32 @@ static void qemuMonitorJSONHandleBlockJob(qemuMonitorPtr mon, virJSONValuePtr da
if (STREQ(type_str, "stream"))
type = VIR_DOMAIN_BLOCK_JOB_TYPE_PULL;
- if (offset != 0 && offset == len)
- status = VIR_DOMAIN_BLOCK_JOB_COMPLETED;
+ switch (event) {
+ case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
+ /* Make sure the whole device has been processed */
+ if (offset != len)
+ event = VIR_DOMAIN_BLOCK_JOB_FAILED;
+ break;
+ case VIR_DOMAIN_BLOCK_JOB_FAILED:
+ case VIR_DOMAIN_BLOCK_JOB_CANCELLED:
+ break;
+ }
out:
- qemuMonitorEmitBlockJob(mon, device, type, status);
+ qemuMonitorEmitBlockJob(mon, device, type, event);
+}
+
+static void qemuMonitorJSONHandleBlockJobCompleted(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleBlockJobImpl(mon, data, VIR_DOMAIN_BLOCK_JOB_COMPLETED);
}
+static void qemuMonitorJSONHandleBlockJobCancelled(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ qemuMonitorJSONHandleBlockJobImpl(mon, data, VIR_DOMAIN_BLOCK_JOB_CANCELLED);
+}
int
qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
--
1.7.5.rc1
12 years, 8 months
[libvirt] [libvirt-sandbox PATCH 1/2] main: Don't free error twice
by Guido Günther
It's already being cleared in cleanup. Otherwise we see:
Unknown option -D
Run 'libvirt-sandbox --help' to see a full list of available command line options
*** glibc detected *** /var/scratch/debian/libvirt-sandbox/libvirt-sandbox/bin/.libs/lt-virt-sandbox: double free or corruption (fasttop): 0x08d888b0 ***
======= Backtrace: =========
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x6e221)[0xb7255221]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(+0x6fa88)[0xb7256a88]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(cfree+0x6d)[0xb7259b3d]
/lib/i386-linux-gnu/libglib-2.0.so.0(+0x4c38b)[0xb73c038b]
/lib/i386-linux-gnu/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb71fde46]
---
bin/virt-sandbox.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/bin/virt-sandbox.c b/bin/virt-sandbox.c
index b24b24b..00b2a29 100644
--- a/bin/virt-sandbox.c
+++ b/bin/virt-sandbox.c
@@ -112,7 +112,6 @@ int main(int argc, char **argv) {
g_printerr("%s\n%s\n",
error->message,
gettext(help_msg));
- g_error_free(error);
goto cleanup;
}
--
1.7.9.1
12 years, 8 months