--- src/qemu/qemu_migration.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 99fc8ce..f3414b0 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -31,6 +31,7 @@ #include "qemu_monitor.h" #include "qemu_domain.h" #include "qemu_process.h" +#include "qemu_hotplug.h" #include "qemu_capabilities.h" #include "qemu_cgroup.h" @@ -49,6 +50,7 @@ #include "storage_file.h" #include "viruri.h" #include "hooks.h" +#include "network/bridge_driver.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -122,6 +124,79 @@ struct _qemuMigrationCookie { virDomainDefPtr persistent; }; +static void +qemuMigrationRemoveEphemeralDevices(struct qemud_driver *driver, + virDomainObjPtr vm) +{ + virDomainHostdevDefPtr dev; + virDomainDeviceDef def; + unsigned int i; + + for (i = 0; i < vm->def->nhostdevs; i++) { + dev = vm->def->hostdevs[i]; + if (dev->ephemeral == 1) { + def.type = VIR_DOMAIN_DEVICE_HOSTDEV; + def.data.hostdev = dev; + + if (qemuDomainDetachHostDevice(driver, vm, &def) >= 0) { + continue; /* nhostdevs reduced */ + } + } + } +} + +static void +qemuMigrationRestoreEphemeralDevices(struct qemud_driver *driver, + virDomainObjPtr vm) +{ + virDomainNetDefPtr net; + unsigned int i; + + /* Do nothing if ephemeral devices are present in which case this + function was called before qemuMigrationRemoveEphemeralDevices */ + + for (i = 0; i < vm->def->nhostdevs; i++) { + if (vm->def->hostdevs[i]->ephemeral == 1) + return; + } + + for (i = 0; i < vm->def->nnets; i++) { + net = vm->def->nets[i]; + + if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + if (qemuDomainAttachHostDevice(driver, vm, + virDomainNetGetActualHostdev(net)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Hostdev cannot be restored")); + networkReleaseActualDevice(net); + } + } + return; + } +} + +static void +qemuMigrationAttachEphemeralDevices(struct qemud_driver *driver, + virDomainObjPtr vm) +{ + virDomainNetDefPtr net; + unsigned int i; + + for (i = 0; i < vm->def->nnets; i++) { + net = vm->def->nets[i]; + + if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) { + if (qemuDomainAttachHostDevice(driver, vm, + virDomainNetGetActualHostdev(net)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Hostdev cannot be attached after migration")); + networkReleaseActualDevice(net); + } + } + } + return; +} + static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap) { if (!grap) @@ -800,6 +875,7 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, virDomainDefPtr def) { int nsnapshots; + unsigned int i; if (vm) { if (qemuProcessAutoDestroyActive(driver, vm)) { @@ -817,10 +893,12 @@ qemuMigrationIsAllowed(struct qemud_driver *driver, virDomainObjPtr vm, def = vm->def; } - if (def->nhostdevs > 0) { - virReportError(VIR_ERR_OPERATION_INVALID, - "%s", _("Domain with assigned host devices cannot be migrated")); - return false; + for (i = 0; i < def->nhostdevs; i++) { + if (def->hostdevs[i]->ephemeral == 0) { + virReportError(VIR_ERR_OPERATION_INVALID, + "%s", _("Domain with assigned non-ephemeral host devices cannot be migrated")); + return false; + } } return true; @@ -2042,6 +2120,7 @@ static int doNativeMigrate(struct qemud_driver *driver, "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu", driver, vm, uri, NULLSTR(cookiein), cookieinlen, cookieout, cookieoutlen, flags, resource); + qemuMigrationRemoveEphemeralDevices(driver, vm); if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://")) { char *tmp; @@ -2069,6 +2148,9 @@ static int doNativeMigrate(struct qemud_driver *driver, ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource, &spec, dconn); + if (ret != 0) + qemuMigrationRestoreEphemeralDevices(driver, vm); + if (spec.destType == MIGRATION_DEST_FD) VIR_FORCE_CLOSE(spec.dest.fd.qemu); @@ -2107,6 +2189,8 @@ static int doTunnelMigrate(struct qemud_driver *driver, return -1; } + qemuMigrationRemoveEphemeralDevices(driver, vm); + spec.fwdType = MIGRATION_FWD_STREAM; spec.fwd.stream = st; @@ -2153,6 +2237,8 @@ static int doTunnelMigrate(struct qemud_driver *driver, cookieoutlen, flags, resource, &spec, dconn); cleanup: + if (ret != 0) + qemuMigrationRestoreEphemeralDevices(driver, vm); if (spec.destType == MIGRATION_DEST_FD) { VIR_FORCE_CLOSE(spec.dest.fd.qemu); VIR_FORCE_CLOSE(spec.dest.fd.local); @@ -3057,6 +3143,8 @@ qemuMigrationFinish(struct qemud_driver *driver, goto endjob; } + qemuMigrationAttachEphemeralDevices(driver, vm); + /* Guest is successfully running, so cancel previous auto destroy */ qemuProcessAutoDestroyRemove(driver, vm); } else { @@ -3154,6 +3242,8 @@ int qemuMigrationConfirm(struct qemud_driver *driver, VIR_WARN("Failed to save status on vm %s", vm->def->name); goto cleanup; } + + qemuMigrationRestoreEphemeralDevices(driver, vm); } qemuMigrationCookieFree(mig); -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list