[libvirt] Modern CPU models cannot be used with libvirt
by Jiri Denemark
Hi,
Recently I realized that all modern CPU models defined in
/etc/qemu/target-x86_64.conf are useless when qemu is used through libvirt.
That's because we start qemu with -nodefconfig which results in qemu ignoring
that file with CPU model definitions. We have a very good reason for using
-nodefconfig because we need to control the ABI presented to a guest OS and we
don't want any configuration file that can contain lots of things including
device definitions to be read by qemu. However, we would really like the new
CPU models to be understood by qemu even if used through libvirt. What would
be the best way to solve this?
I suspect this could have been already discussed in the past but obviously a
workable solution was either not found or just not implemented.
Jirka
12 years, 8 months
[libvirt] [PATCH v2 0/5] Allow hibernation on guests
by Michal Privoznik
As we've added guest agent recently, the whole world
of new functionality has opened. As this patch set,
which allows domains to enter S4 state.
What is needed for this?
Patched qemu. As this is not in qemu git, but patches
are await to be pushed in very short future. They can
be found here:
http://lists.gnu.org/archive/html/qemu-devel/2012-01/msg03261.html
Despite that, if anybody is willing to give me review
if I am going the right way, I'd appreciate it.
One thing, that you'll probably notice is this
'set-support-level' command. Basically, it tells GA what qemu version
is it running on. Ideally, this should be done as soon as
GA starts up. However, that cannot be determined from outside
world as GA doesn't emit any events yet.
Ideally^2 this command should be left out as it should be qemu
who tells its own agent this kind of information.
Anyway, I was going to call this command in qemuProcess{Startup,
Reconnect,Attach}, but it won't work. We need to un-pause guest CPUs
so guest can boot and start GA, but that implies returning from qemuProcess*.
So I am setting this just before 'guest-suspend' command, as
there is one more thing about GA. It is unable to remember anything
upon its restart (GA process). Which has BTW show flaw
in our current code with FS freeze & thaw. If we freeze guest
FS, and somebody restart GA, the simple FS Thaw will not succeed as
GA thinks FS are not frozen. But that's a different cup of tea.
Because of what written above, we need to call set-level
on every suspend.
diff to v1:
-move from misusing virDomainSuspend to brand new
virDomainSuspendForDuration API
Michal Privoznik (5):
qemu-agent: Allow setting supported level
qemu-agent: Create suspend function
Introduce virDomainSuspendForDuration API
qemu: Wire up virDomainSuspendForDuration API
virsh: Expose new virDomainSuspendForDuration API
include/libvirt/libvirt.h.in | 5 ++-
src/driver.h | 6 ++
src/libvirt.c | 58 +++++++++++++++++++++++
src/libvirt_public.syms | 1 +
src/qemu/qemu_agent.c | 105 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 13 +++++
src/qemu/qemu_driver.c | 93 +++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 45 +++++++++++++++++-
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 11 ++++-
src/remote_protocol-structs | 7 +++
tools/virsh.c | 67 +++++++++++++++++++++++++++
tools/virsh.pod | 8 +++
13 files changed, 415 insertions(+), 5 deletions(-)
--
1.7.3.4
12 years, 8 months
Re: [libvirt] Using Libvirt to change the bridge a virtual network card of a running vm is connected to
by Hendrik Schwartke
I wrote a patch to change the mapping between a virtual bridge interface
and the host bridge while the host is up. It's based on commit
6fba577e505611e6c25c68e322942eab7754de7e. The host and the interface
definition I used for testing are also attached.
I would be glad if the patch could be added to the repo.
Patch:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4b60839..f791795 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -40,6 +40,7 @@
#include "qemu_cgroup.h"
#include "locking/domain_lock.h"
#include "network/bridge_driver.h"
+#include "util/virnetdevbridge.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1163,6 +1164,28 @@ static virDomainNetDefPtr
qemuDomainFindNet(virDomainObjPtr vm,
return NULL;
}
+int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev,
+ virDomainNetDefPtr newdev)
+{
+ const char *oldbridge=olddev->data.bridge.brname;
+ const char *newbridge=newdev->data.bridge.brname;
+ VIR_DEBUG("Change bridge for interface %s: %s -> %s",
olddev->ifname, oldbridge, newbridge);
+ if(virNetDevBridgeRemovePort(oldbridge, olddev->ifname)<0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("unable to remove port from bridge"));
+ return -1;
+ }
+ if(virNetDevBridgeAddPort(newbridge, newdev->ifname)<0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("unable to add port to bridge"));
+ return -1;
+ }
+ VIR_FREE(olddev->data.bridge.brname);
+ olddev->data.bridge.brname=strdup(newbridge);
+ return 0;
+}
+
+
int qemuDomainChangeNetLinkState(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainNetDefPtr dev,
@@ -1293,6 +1316,12 @@ int qemuDomainChangeNet(struct qemud_driver *driver,
return -1;
}
+ if(olddev->type==VIR_DOMAIN_NET_TYPE_BRIDGE
+ && dev->type==VIR_DOMAIN_NET_TYPE_BRIDGE
+ && STRNEQ(olddev->data.bridge.brname, dev->data.bridge.brname)) {
+ qemuDomainChangeNetBridge(olddev, dev);
+ }
+
if (olddev->linkstate != dev->linkstate) {
if ((ret = qemuDomainChangeNetLinkState(driver, vm, olddev,
dev->linkstate)) < 0)
return ret;
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 0310361..1e1f75c 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -80,6 +80,8 @@ int qemuDomainChangeNetLinkState(struct qemud_driver
*driver,
virDomainObjPtr vm,
virDomainNetDefPtr dev,
int linkstate);
+int qemuDomainChangeNetBridge(virDomainNetDefPtr olddev,
+ virDomainNetDefPtr newdev);
int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev);
Host definition:
<domain type='kvm'>
<name>test</name>
<memory>32768</memory>
<currentMemory>32768</currentMemory>
<vcpu>1</vcpu>
<os>
<type arch='x86_64' machine='pc-0.12'>hvm</type>
<boot dev='cdrom'/>
<bootmenu enable='no'/>
</os>
<features>
<acpi/>
<apic/>
<pae/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<interface type='bridge'>
<mac address='52:54:00:ab:cd:02'/>
<source bridge='br0'/>
<target dev='testif'/>
<link state='up'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
<graphics type='vnc' port='-1' autoport='yes'/>
<video>
<model type='cirrus' vram='9216' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
</devices>
</domain>
Interface definition:
<interface type="bridge">
<mac address="52:54:00:ab:cd:02"/>
<source bridge="br1"/>
<target dev="testif"/>
<link state="up"/>
<alias name="net0"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0"/>
</interface>
Best regards
Hendrik Schwartke
12 years, 8 months
[libvirt] [PATCH v2 0/3] Use guest agent to quiesce disks
by Michal Privoznik
Since we have qemu guest agent support in libvirt,
we can start wiring up some things that GA already
knows how to do. One of them is file system freeze
and thaw. Domain snapshots can profit from this
functionality.
Michal Privoznik (3):
qemu_agent: Create file system freeze and thaw functions
snapshots: Introduce VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag
virsh: Expose new VIR_DOMAIN_SNAPSHOT_CREATE_QUIESCE flag
include/libvirt/libvirt.h.in | 4 ++
src/libvirt.c | 6 +++
src/qemu/qemu_agent.c | 74 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 3 +
src/qemu/qemu_driver.c | 87 ++++++++++++++++++++++++++++++++++++++----
tools/virsh.c | 6 +++
tools/virsh.pod | 16 +++++++-
7 files changed, 186 insertions(+), 10 deletions(-)
--
1.7.3.4
12 years, 8 months
[libvirt] [PATCH] qemu: Copy console definition from serial
by Michal Privoznik
Now, when we support multiple consoles per domain,
the vm->def->console[0] can still remain an alias
for vm->def->serial[0]; However, we need to copy
it's source definition as well otherwise we'll regress
on virDomainOpenConsole.
---
src/conf/domain_conf.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_process.c | 19 +++++++++--
4 files changed, 90 insertions(+), 4 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6b78d97..9b2eb86 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -956,6 +956,78 @@ virDomainChrSourceDefClear(virDomainChrSourceDefPtr def)
}
}
+int
+virDomainChrSourceDefCopy(virDomainChrSourceDefPtr dest,
+ virDomainChrSourceDefPtr src)
+{
+ if (!dest || !src)
+ return -1;
+
+ switch (src->type) {
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ if (src->data.file.path &&
+ !(dest->data.file.path = strdup(src->data.file.path))) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UDP:
+ if (src->data.udp.bindHost &&
+ !(dest->data.udp.bindHost = strdup(src->data.udp.bindHost))) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (src->data.udp.bindService &&
+ !(dest->data.udp.bindService = strdup(src->data.udp.bindService))) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (src->data.udp.connectHost &&
+ !(dest->data.udp.connectHost = strdup(src->data.udp.connectHost))) {
+ virReportOOMError();
+ return -1;
+ }
+
+
+ if (src->data.udp.connectService &&
+ !(dest->data.udp.connectService = strdup(src->data.udp.connectService))) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ if (src->data.tcp.host &&
+ !(dest->data.tcp.host = strdup(src->data.tcp.host))) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (src->data.tcp.service &&
+ !(dest->data.tcp.service = strdup(src->data.tcp.service))) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ if (src->data.nix.path &&
+ !(dest->data.nix.path = strdup(src->data.nix.path))) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+ }
+
+ return 0;
+}
+
void virDomainChrSourceDefFree(virDomainChrSourceDefPtr def)
{
if (!def)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c360674..76a8dd7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1662,6 +1662,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def);
void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def);
void virDomainChrDefFree(virDomainChrDefPtr def);
void virDomainChrSourceDefFree(virDomainChrSourceDefPtr def);
+int virDomainChrSourceDefCopy(virDomainChrSourceDefPtr src,
+ virDomainChrSourceDefPtr dest);
void virDomainSoundDefFree(virDomainSoundDefPtr def);
void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def);
void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b9d537e..e6ccf9d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -242,6 +242,7 @@ virDomainChrConsoleTargetTypeToString;
virDomainChrDefForeach;
virDomainChrDefFree;
virDomainChrDefNew;
+virDomainChrSourceDefCopy;
virDomainChrSourceDefFree;
virDomainChrSpicevmcTypeFromString;
virDomainChrSpicevmcTypeToString;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2882ef8..e0b1824 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1163,11 +1163,22 @@ qemuProcessFindCharDevicePTYs(virDomainObjPtr vm,
for (i = 0 ; i < vm->def->nconsoles ; i++) {
virDomainChrDefPtr chr = vm->def->consoles[i];
- if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
- chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
- if ((ret = qemuProcessExtractTTYPath(output, &offset,
- &chr->source.data.file.path)) != 0)
+ /* For historical reasons, console[0] can be just an alias
+ * for serial[0]; That's why we need to update it as well */
+ if (i == 0 && vm->def->nserials &&
+ chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+ chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
+ if ((ret = virDomainChrSourceDefCopy(&chr->source,
+ &((vm->def->serials[0])->source))) != 0)
return ret;
+ chr->source.type = VIR_DOMAIN_CHR_TYPE_PTY;
+ } else {
+ if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
+ chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
+ if ((ret = qemuProcessExtractTTYPath(output, &offset,
+ &chr->source.data.file.path)) != 0)
+ return ret;
+ }
}
}
--
1.7.3.4
12 years, 8 months
[libvirt] [PATCH 0/5 0/1 0/1 V3] Add new public API virDomainGetPcpusUsage() and pcpuinfo command in virsh
by Lai Jiangshan
"virt-top -1" can call virDomainGetPcpusUsage() periodically and get
the CPU activities per CPU. (See the last patch in this series).
virsh is also added a pcpuinfo command which calls virDomainGetPcpusUsage(),
it gets information about the physical CPUs, such as the usage of
CPUs, the current attached vCPUs.
# virsh pcpuinfo rhel6
CPU: 0
Curr VCPU: -
Usage: 47.3
CPU: 1
Curr VCPU: 1
Usage: 46.8
CPU: 2
Curr VCPU: 0
Usage: 52.7
CPU: 3
Curr VCPU: -
Usage: 44.1
Changed from V2:
Simple cleanup
Add python implementation of virDomainGetPcpusUsage()
Acked-by: "Richard W.M. Jones" <rjones(a)redhat.com>
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
Patch for libvirt(5 patches):
daemon/remote.c | 68 ++++++++++++++++++++++++++++
include/libvirt/libvirt.h.in | 5 ++
python/generator.py | 1 +
python/libvirt-override-api.xml | 6 +++
python/libvirt-override.c | 33 ++++++++++++++
src/driver.h | 7 +++
src/libvirt.c | 51 +++++++++++++++++++++
src/libvirt_public.syms | 5 ++
src/qemu/qemu.conf | 5 +-
src/qemu/qemu_conf.c | 3 +-
src/qemu/qemu_driver.c | 74 +++++++++++++++++++++++++++++++
src/remote/remote_driver.c | 51 +++++++++++++++++++++
src/remote/remote_protocol.x | 17 +++++++-
src/remote_protocol-structs | 13 +++++
src/util/cgroup.c | 7 +++
src/util/cgroup.h | 1 +
tools/virsh.c | 93 +++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 5 ++
18 files changed, 441 insertions(+), 4 deletions(-)
Patch for ocaml-libvirt (1 patch):
libvirt/libvirt.ml | 1 +
libvirt/libvirt.mli | 4 ++++
libvirt/libvirt_c_oneoffs.c | 25 +++++++++++++++++++++++++
3 files changed, 30 insertions(+), 0 deletions(-)
Patch for virt-top (1 patch):
virt-top/virt_top.ml | 75 +++++++++++++++++--------------------------------
1 files changed, 26 insertions(+), 49 deletions(-)
--
1.7.4.4
12 years, 8 months
[libvirt] [PATCH] Support for cpu64-rhel* qemu cpu models
by Martin Kletzander
In qemu there are 2 cpu models (cpu64-rhel5 and cpu64-rhel6) not
supported by libvirt. This patch adds the support with the flags
specifications from /usr/share/qemu-kvm/cpu-model/cpu-x86_64.conf
---
src/cpu/cpu_map.xml | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 94 insertions(+), 0 deletions(-)
diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
index 693caf1..be41253 100644
--- a/src/cpu/cpu_map.xml
+++ b/src/cpu/cpu_map.xml
@@ -327,6 +327,100 @@
<feature name='svm'/>
</model>
+ <model name='cpu64-rhel5'>
+ <vendor name='AMD'/>
+ <feature name='sse2'/>
+ <feature name='sse'/>
+ <feature name='fxsr'/>
+ <feature name='mmx'/>
+ <feature name='clflush'/>
+ <feature name='pse36'/>
+ <feature name='pat'/>
+ <feature name='cmov'/>
+ <feature name='mca'/>
+ <feature name='pge'/>
+ <feature name='mtrr'/>
+ <feature name='sep'/>
+ <feature name='apic'/>
+ <feature name='cx8'/>
+ <feature name='mce'/>
+ <feature name='pae'/>
+ <feature name='msr'/>
+ <feature name='tsc'/>
+ <feature name='pse'/>
+ <feature name='de'/>
+ <feature name='fpu'/>
+ <feature name='sse3'/>
+ <feature name='3dnow'/>
+ <feature name='3dnowext'/>
+ <feature name='lm'/>
+ <feature name='fxsr'/>
+ <feature name='mmx'/>
+ <feature name='nx'/>
+ <feature name='pat'/>
+ <feature name='cmov'/>
+ <feature name='pge'/>
+ <feature name='syscall'/>
+ <feature name='apic'/>
+ <feature name='cx8'/>
+ <feature name='mce'/>
+ <feature name='pae'/>
+ <feature name='msr'/>
+ <feature name='tsc'/>
+ <feature name='pse'/>
+ <feature name='de'/>
+ <feature name='fpu'/>
+ <feature name='svm'/>
+ </model>
+
+ <model name='cpu64-rhel6'>
+ <vendor name='AMD'/>
+ <feature name='sse2'/>
+ <feature name='sse'/>
+ <feature name='fxsr'/>
+ <feature name='mmx'/>
+ <feature name='clflush'/>
+ <feature name='pse36'/>
+ <feature name='pat'/>
+ <feature name='cmov'/>
+ <feature name='mca'/>
+ <feature name='pge'/>
+ <feature name='mtrr'/>
+ <feature name='sep'/>
+ <feature name='apic'/>
+ <feature name='cx8'/>
+ <feature name='mce'/>
+ <feature name='pae'/>
+ <feature name='msr'/>
+ <feature name='tsc'/>
+ <feature name='pse'/>
+ <feature name='de'/>
+ <feature name='fpu'/>
+ <feature name='cx16'/>
+ <feature name='sse3'/>
+ <feature name='lm'/>
+ <feature name='fxsr'/>
+ <feature name='mmx'/>
+ <feature name='nx'/>
+ <feature name='pat'/>
+ <feature name='cmov'/>
+ <feature name='pge'/>
+ <feature name='syscall'/>
+ <feature name='apic'/>
+ <feature name='cx8'/>
+ <feature name='mce'/>
+ <feature name='pae'/>
+ <feature name='msr'/>
+ <feature name='tsc'/>
+ <feature name='pse'/>
+ <feature name='de'/>
+ <feature name='fpu'/>
+ <feature name='sse4a'/>
+ <feature name='abm'/>
+ <feature name='svm'/>
+ <feature name='lahf_lm'/>
+ </model>
+
<model name='core2duo'>
<model name='pentiumpro'/>
<feature name='mtrr'/>
--
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, 9 months
[libvirt] virsh bash completion file
by Serge E. Hallyn
Hi,
I've been trying out a bash autocompletion file by Geoff Low (slight hack
by me, don't blame him for my hack), and it's working pretty nicely.
I'm not sure where to put it in the git tree, but it seems like it'd be
nice to have upstream?
thanks,
-serge
====================================================
#!/bin/bash
#############################################################################
#
# virsh bash completion
# Author: Geoff Low (glow(a)cmedresearch.com)
#
############################################################################
VIRSH=$(which virsh)
function get_main_option_list
{
# assume options are specified as [--option1 | --option2 | ...]
OPTIONS=$(${VIRSH} help | grep '|' | sed -e 's/.*\[\(.*\)\]/\1/g;s/|//g')
}
function get_option_list
{
# get the options for a choice
local option=$1;
# assume options are specified as [--option1 | --option2 | ...]
OPTIONS=$(${VIRSH} help ${option} 2> /dev/null | grep '|' | sed -e 's/.*\[\(.*\)\]/\1/g;s/|//g')
}
function _virsh_complete()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cnxn=""
i=0
while [[ $i -lt $COMP_CWORD ]]; do
if [ ${COMP_WORDS[i]} = "-c" ]; then
tgt=`echo ${COMP_LINE} | sed -e 's/^.* -c \([^ \t]*\).*$/\1/'`
cnxn="-c $tgt"
break
fi
let i++
done
if [ ! -z $tgt ]; then
if [ $COMP_CWORD -eq 5 ]; then
prev="${COMP_WORDS[0]}"
fi
fi
_all_domains=$(${VIRSH} ${cnxn} --q list --all 2> /dev/null | grep -E "(running|shut off)$" | awk '{print $2,$3}')
all_domains=$(echo "$_all_domains" | cut -d " " -f 1)
all_networks=$(${VIRSH} --q net-list --all 2> /dev/null | grep 'active' | cut -d " " -f 1)
live_domains=$(echo "$_all_domains" | grep -E "running$" | awk '{print $1}')
shutoff_domains=$(echo "$_all_domains" | grep -E "shut$" | awk '{print $1}')
case "${prev}" in
virsh | --help)
get_main_option_list
ALL_OPTS=$(${VIRSH} -q help 2> /dev/null | sed '1,2d' | awk '{print $1}')
COMPREPLY=( $(compgen -W "$OPTIONS $ALL_OPTS" -- ${cur}) )
;;
list)
get_option_list ${prev}
COMPREPLY=( $(compgen -W "$OPTIONS" -- ${cur}) )
;;
autostart | dominfo | domuuid | domid | dominfo | domname | dumpxml | setmem )
get_option_list ${prev}
COMPREPLY=( $(compgen -W "$OPTIONS $all_domains" -- ${cur}) )
;;
start | undefine)
get_option_list ${prev}
COMPREPLY=( $(compgen -W "$OPTIONS $shutoff_domains" -- ${cur}) )
;;
create | define)
get_option_list ${prev}
xml_files=$(ls *.xml)
COMPREPLY=( $(compgen -W "$OPTIONS $xml_files" -- ${cur}) )
;;
shutdown | domstate | console | destroy | reboot | save | suspend | resume | vcpuinfo | vncdisplay)
get_option_list ${prev}
COMPREPLY=( $(compgen -W "$OPTIONS $live_domains" -- ${cur}) )
;;
connect)
get_option_list ${prev}
URI_TEMPLATES="xen:// qemu:// test:// xen+ssh:// test+tcp:// qemu+unix:// qemu+tls:// qemu+ssh://"
COMPREPLY=( $(compgen -W "$OPTIONS $URI_TEMPLATES" -- ${cur}) )
;;
*)
COMPREPLY=( $(compgen -f -- ${cur}) )
return 0
;;
esac
}
complete -F _virsh_complete virsh
12 years, 9 months
[libvirt] [PATCH 0/2] add ibmvscsi and virtio-scsi controller models
by Paolo Bonzini
Hi, these patches let you specify explicitly all supported controller
models for QEMU, and add the new virtio-scsi model.
Paolo Bonzini (2):
qemu: add ibmvscsi controller model
qemu: add virtio-scsi controller model
docs/formatdomain.html.in | 4 +-
docs/schemas/domaincommon.rng | 2 +
src/conf/domain_conf.c | 4 ++-
src/conf/domain_conf.h | 2 +
src/qemu/qemu_command.c | 26 ++++++++++++++--
src/vmx/vmx.c | 10 ++++--
.../qemuxml2argv-disk-scsi-virtio-scsi.args | 9 ++++++
.../qemuxml2argv-disk-scsi-virtio-scsi.xml | 31 ++++++++++++++++++++
.../qemuxml2argv-disk-scsi-vscsi.args | 8 +++++
.../qemuxml2argv-disk-scsi-vscsi.xml | 31 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 4 ++
tests/qemuxml2xmltest.c | 2 +
12 files changed, 123 insertions(+), 10 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-virtio-scsi.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-virtio-scsi.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-vscsi.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-vscsi.xml
--
1.7.7.1
12 years, 9 months