qemu: Use -incoming defer for migrations

Traditionally, we pass incoming migration URI on QEMU command line,
which has some drawbacks. Depending on the URI QEMU may initialize its
migration state immediately without giving us a chance to set any
additional migration parameters (this applies mainly for fd: URIs). For
some URIs the monitor may be completely blocked from the beginning until
migration is finished, which means we may be stuck in qmp_capabilities
command without being able to send any QMP commands.

QEMU solved this by introducing "defer" parameter for -incoming command
line option. This will tell QEMU to prepare for an incoming migration
while the actual incoming URI is sent using migrate-incoming QMP
command. Before calling this command we can normally talk to the
monitor and even set any migration parameters which will be honored by
the incoming migration.

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
This commit is contained in:
Jiri Denemark 2015-11-11 18:02:23 +01:00
parent 93d56e9df1
commit 2c4ba8b4f3
7 changed files with 61 additions and 0 deletions

View File

@ -299,6 +299,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"e1000",
"virtio-net",
"gic-version",
"incoming-defer", /* 200 */
);
@ -1458,6 +1460,7 @@ struct virQEMUCapsStringFlags virQEMUCapsCommands[] = {
{ "nbd-server-start", QEMU_CAPS_NBD_SERVER },
{ "change-backing-file", QEMU_CAPS_CHANGE_BACKING_FILE },
{ "rtc-reset-reinjection", QEMU_CAPS_RTC_RESET_REINJECTION },
{ "migrate-incoming", QEMU_CAPS_INCOMING_DEFER },
};
struct virQEMUCapsStringFlags virQEMUCapsMigration[] = {

View File

@ -325,6 +325,9 @@ typedef enum {
QEMU_CAPS_DEVICE_VIRTIO_NET, /* -device virtio-net-* */
QEMU_CAPS_MACH_VIRT_GIC_VERSION, /* -machine virt,gic-version */
/* 200 */
QEMU_CAPS_INCOMING_DEFER, /* -incoming defer and migrate_incoming */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;

View File

@ -2951,6 +2951,42 @@ qemuMigrationIncomingURI(const char *migrateFrom,
}
int
qemuMigrationRunIncoming(virQEMUDriverPtr driver,
virDomainObjPtr vm,
const char *uri,
qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int ret = -1;
int rv;
VIR_DEBUG("Setting up incoming migration with URI %s", uri);
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
rv = qemuMonitorMigrateIncoming(priv->mon, uri);
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
goto cleanup;
if (asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN) {
/* qemuMigrationWaitForDestCompletion is called from the Finish phase */
ret = 0;
goto cleanup;
}
if (qemuMigrationWaitForDestCompletion(driver, vm, asyncJob) < 0)
goto cleanup;
ret = 0;
cleanup:
return ret;
}
/* This is called for outgoing non-p2p migrations when a connection to the
* client which initiated the migration was closed but we were waiting for it
* to follow up with the next phase, that is, in between

View File

@ -205,4 +205,9 @@ int qemuMigrationCheckIncoming(virQEMUCapsPtr qemuCaps,
char *qemuMigrationIncomingURI(const char *migrateFrom,
int migrateFd);
int qemuMigrationRunIncoming(virQEMUDriverPtr driver,
virDomainObjPtr vm,
const char *uri,
qemuDomainAsyncJob asyncJob);
#endif /* __QEMU_MIGRATION_H__ */

View File

@ -4168,6 +4168,7 @@ qemuProcessIncomingDefFree(qemuProcessIncomingDefPtr inc)
return;
VIR_FREE(inc->launchURI);
VIR_FREE(inc->deferredURI);
VIR_FREE(inc);
}
@ -4195,6 +4196,12 @@ qemuProcessIncomingDefNew(virQEMUCapsPtr qemuCaps,
if (!inc->launchURI)
goto error;
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_INCOMING_DEFER)) {
inc->deferredURI = inc->launchURI;
if (VIR_STRDUP(inc->launchURI, "defer") < 0)
goto error;
}
inc->fd = fd;
inc->path = path;
@ -4940,6 +4947,11 @@ int qemuProcessStart(virConnectPtr conn,
if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0)
goto error;
if (incoming &&
incoming->deferredURI &&
qemuMigrationRunIncoming(driver, vm, incoming->deferredURI, asyncJob) < 0)
goto error;
if (!(flags & VIR_QEMU_PROCESS_START_PAUSED)) {
VIR_DEBUG("Starting domain CPUs");
/* Allow the CPUS to start executing */

View File

@ -48,6 +48,7 @@ typedef struct _qemuProcessIncomingDef qemuProcessIncomingDef;
typedef qemuProcessIncomingDef *qemuProcessIncomingDefPtr;
struct _qemuProcessIncomingDef {
char *launchURI; /* used as a parameter for -incoming command line option */
char *deferredURI; /* used when calling migrate-incoming QMP command */
int fd; /* for fd:N URI */
const char *path; /* path associated with fd */
};

View File

@ -161,4 +161,5 @@
<flag name='rtl8139'/>
<flag name='e1000'/>
<flag name='virtio-net'/>
<flag name='incoming-defer'/>
</qemuCaps>