We need to start NBD server and feed it with all non-<shared/>, RW and source-full disks. Moreover, with new virPortAllocator we must ensure the borrowed port for NBD server will be returned if either migration completes or qemu process is teared down. --- src/qemu/qemu_migration.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_process.c | 5 +++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 82c3f97..876e81b 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -35,6 +35,7 @@ #include "qemu_domain.h" #include "qemu_process.h" #include "qemu_capabilities.h" +#include "qemu_command.h" #include "qemu_cgroup.h" #include "domain_audit.h" @@ -1097,6 +1098,80 @@ error: return NULL; } +/** + * qemuMigrationStartNBDServer: + * @driver: qemu driver + * @vm: domain + * + * Starts NBD server. This is a newer method to copy + * storage during migration than using 'blk' and 'inc' + * arguments in 'migrate' monitor command. + * Error is reported here. + * + * Returns 0 on success, -1 otherwise. + */ +static int +qemuMigrationStartNBDServer(virQEMUDriverPtr driver, + virDomainObjPtr vm) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + unsigned short port = 0; + const char *listen = "0.0.0.0"; + char *diskAlias = NULL; + size_t i; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk = vm->def->disks[i]; + + /* skip shared, RO and source-less disks */ + if (disk->shared || disk->readonly || !disk->src) + continue; + + VIR_FREE(diskAlias); + if (virAsprintf(&diskAlias, "%s%s", + QEMU_DRIVE_HOST_PREFIX, disk->info.alias) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (qemuDomainObjEnterMonitorAsync(driver, vm, + QEMU_ASYNC_JOB_MIGRATION_IN) < 0) + goto cleanup; + + if (!port) { + if (virPortAllocatorAcquire(driver->remotePorts, &port) < 0) + goto cleanup; + + if (qemuMonitorNBDServerStart(priv->mon, listen, port) < 0) { + qemuDomainObjExitMonitor(driver, vm); + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Unable to start nbd server")); + goto cleanup; + } + } + + if (qemuMonitorNBDServerAdd(priv->mon, diskAlias, true) < 0) { + qemuDomainObjExitMonitor(driver, vm); + + virReportError(VIR_ERR_OPERATION_FAILED, + _("Unable to add '%s' to NDB server"), diskAlias); + goto cleanup; + } + qemuDomainObjExitMonitor(driver, vm); + } + + priv->nbdPort = port; + ret = 0; + +cleanup: + VIR_FREE(diskAlias); + if (ret < 0) + virPortAllocatorRelease(driver->remotePorts, port); + return ret; +} + + /* Validate whether the domain is safe to migrate. If vm is NULL, * then this is being run in the v2 Prepare stage on the destination * (where we only have the target xml); if vm is provided, then this @@ -1822,8 +1897,11 @@ done: if (flags & VIR_MIGRATE_TUNNELLED) VIR_DEBUG("NBD in tunnelled migration is currently not supported"); else { + if (qemuMigrationStartNBDServer(driver, vm) < 0) { + /* error already reported */ + goto endjob; + } cookieFlags |= QEMU_MIGRATION_COOKIE_NBD; - priv->nbdPort = 0; } } @@ -1870,6 +1948,10 @@ cleanup: virObjectUnlock(vm); else qemuDomainRemoveInactive(driver, vm); + if (ret < 0 && priv->nbdPort) { + virPortAllocatorRelease(driver->remotePorts, priv->nbdPort); + priv->nbdPort = 0; + } } if (event) qemuDomainEventQueue(driver, event); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4251c34..e6874e2 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4237,6 +4237,11 @@ void qemuProcessStop(virQEMUDriverPtr driver, } } + if (priv->nbdPort) { + virPortAllocatorRelease(driver->remotePorts, priv->nbdPort); + priv->nbdPort = 0; + } + if (priv->agent) { qemuAgentClose(priv->agent); priv->agent = NULL; -- 1.8.0.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list