This patch is mainly to solve the migration problem:
After the media is ejected inside guest, and one removes the
source of the media outside, migration will fail early, as we
start the qemu daemon on dest host with the source of the removable
block still existing, this causes failure when trying to do cgroup
setting on the media source then.
All the migration functions try to get the domain XML before
doing preparation on dest host. Except one specify the domain
XML externally (e.g. option "--xml" of "virsh migrate"). So this
patch changes the function "qemuDomainFormatXML" to check the
media status of removable block using the new introduced monitor
functions, and clear the source path if the media ejected, so
that it won't start the qemu daemon on dest host along with the
media path.
Public migration APIs invokes "driver->domainGetXMLDesc";
"driver->domainMigratePeer2Peer" uses "qemuDomainFormatXML"
for v2 migration protocol and "qemuDomainBegin" for v3 migration
protocol, to get the domain XML before preparation on dest host.
All of these 3 functions are based on "qemuDomainFormatXML", that's
why making changes on it.
The changes affect the running domain config, (e.g. for a running
domain, "virsh dumpxml" won't display the source path of the media
anymore once it's ejected inside guest. But think it's reasonable
to do like so.
But the migration will still fail even with this patch when one
specified the domain XML externally. However, think this is not
what we should care about. It's fault of user?
---
src/qemu/qemu_domain.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 675c6df..968af69 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1063,12 +1063,49 @@ char *qemuDomainFormatXML(struct qemud_driver *driver,
unsigned int flags)
{
virDomainDefPtr def;
+ unsigned int ejected = 0;
+ int err, i;
+ qemuDomainObjPrivatePtr priv = NULL;
+
if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
def = vm->newDef;
else
def = vm->def;
+ /* Check if the media of removable block is ejected, and clear the
+ * source path if it's ejected.
+ */
+ if (virDomainObjIsActive(vm)) {
+ priv = vm->privateData;
+
+ if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_QUERY) < 0)
+ return NULL;
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ if (vm->def->disks[i]->src &&
+ (vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
+ vm->def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)) {
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ err = qemuMonitorGetRemovableBlockMediaStatus(priv->mon,
+
vm->def->disks[i]->info.alias,
+ &ejected);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ if (err == -1)
+ return NULL;
+
+ if (ejected == 1)
+ VIR_FREE(vm->def->disks[i]->src);
+ }
+ }
+
+ if (qemuDomainObjEndJob(driver, vm) == 0) {
+ vm = NULL;
+ return NULL;
+ }
+ }
+
return qemuDomainDefFormatXML(driver, def, flags);
}
--
1.7.6