mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
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:
parent
93d56e9df1
commit
2c4ba8b4f3
@ -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[] = {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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__ */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -161,4 +161,5 @@
|
||||
<flag name='rtl8139'/>
|
||||
<flag name='e1000'/>
|
||||
<flag name='virtio-net'/>
|
||||
<flag name='incoming-defer'/>
|
||||
</qemuCaps>
|
||||
|
Loading…
x
Reference in New Issue
Block a user