mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
libxl: fix job handling across migration phases on dst
The libxlDomainMigrationDst* functions are a bit flawed in their handling of modify jobs. A job begins when the destination host begins receiving the incoming VM and ends after the VM is started. The finish phase contains another BeginJob/EndJob sequence. This patch changes the logic to begin a job for the incoming VM in the prepare phase and end the job in the finish phase. Signed-off-by: Jim Fehlig <jfehlig@suse.com> ACKed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
47da84e090
commit
0149464afc
@ -6154,15 +6154,8 @@ libxlDomainMigrateFinish3Params(virConnectPtr dconn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
|
|
||||||
virDomainObjEndAPI(&vm);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = libxlDomainMigrationDstFinish(dconn, vm, flags, cancelled);
|
ret = libxlDomainMigrationDstFinish(dconn, vm, flags, cancelled);
|
||||||
|
|
||||||
libxlDomainObjEndJob(driver, vm);
|
|
||||||
|
|
||||||
virDomainObjEndAPI(&vm);
|
virDomainObjEndAPI(&vm);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -266,9 +266,6 @@ libxlDoMigrateDstReceive(void *opaque)
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
virObjectRef(vm);
|
virObjectRef(vm);
|
||||||
virObjectLock(vm);
|
|
||||||
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always start the domain paused. If needed, unpause in the
|
* Always start the domain paused. If needed, unpause in the
|
||||||
@ -288,10 +285,6 @@ libxlDoMigrateDstReceive(void *opaque)
|
|||||||
args->nsocks = 0;
|
args->nsocks = 0;
|
||||||
VIR_FORCE_CLOSE(recvfd);
|
VIR_FORCE_CLOSE(recvfd);
|
||||||
virObjectUnref(args);
|
virObjectUnref(args);
|
||||||
|
|
||||||
libxlDomainObjEndJob(driver, vm);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
virDomainObjEndAPI(&vm);
|
virDomainObjEndAPI(&vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,6 +576,13 @@ libxlDomainMigrationDstPrepareTunnel3(virConnectPtr dconn,
|
|||||||
goto error;
|
goto error;
|
||||||
*def = NULL;
|
*def = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unless an error is encountered in this function, the job will
|
||||||
|
* be terminated in the finish phase.
|
||||||
|
*/
|
||||||
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
priv = vm->privateData;
|
priv = vm->privateData;
|
||||||
|
|
||||||
if (taint_hook) {
|
if (taint_hook) {
|
||||||
@ -595,18 +595,18 @@ libxlDomainMigrationDstPrepareTunnel3(virConnectPtr dconn,
|
|||||||
* stream -> pipe -> recvfd of libxlDomainStartRestore
|
* stream -> pipe -> recvfd of libxlDomainStartRestore
|
||||||
*/
|
*/
|
||||||
if (pipe(dataFD) < 0)
|
if (pipe(dataFD) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
/* Stream data will be written to pipeIn */
|
/* Stream data will be written to pipeIn */
|
||||||
if (virFDStreamOpen(st, dataFD[1]) < 0)
|
if (virFDStreamOpen(st, dataFD[1]) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
dataFD[1] = -1; /* 'st' owns the FD now & will close it */
|
dataFD[1] = -1; /* 'st' owns the FD now & will close it */
|
||||||
|
|
||||||
if (libxlMigrationDstArgsInitialize() < 0)
|
if (libxlMigrationDstArgsInitialize() < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
|
if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
args->conn = virObjectRef(dconn);
|
args->conn = virObjectRef(dconn);
|
||||||
args->vm = virObjectRef(vm);
|
args->vm = virObjectRef(vm);
|
||||||
@ -620,12 +620,15 @@ libxlDomainMigrationDstPrepareTunnel3(virConnectPtr dconn,
|
|||||||
if (virThreadCreate(&thread, false, libxlDoMigrateDstReceive, args) < 0) {
|
if (virThreadCreate(&thread, false, libxlDoMigrateDstReceive, args) < 0) {
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
||||||
_("Failed to create thread for receiving migration data"));
|
_("Failed to create thread for receiving migration data"));
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
libxlDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
libxlMigrationCookieFree(mig);
|
libxlMigrationCookieFree(mig);
|
||||||
VIR_FORCE_CLOSE(dataFD[1]);
|
VIR_FORCE_CLOSE(dataFD[1]);
|
||||||
@ -679,6 +682,13 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
goto error;
|
goto error;
|
||||||
*def = NULL;
|
*def = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unless an error is encountered in this function, the job will
|
||||||
|
* be terminated in the finish phase.
|
||||||
|
*/
|
||||||
|
if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
priv = vm->privateData;
|
priv = vm->privateData;
|
||||||
|
|
||||||
if (taint_hook) {
|
if (taint_hook) {
|
||||||
@ -689,27 +699,27 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
/* Create socket connection to receive migration data */
|
/* Create socket connection to receive migration data */
|
||||||
if (!uri_in) {
|
if (!uri_in) {
|
||||||
if ((hostname = virGetHostname()) == NULL)
|
if ((hostname = virGetHostname()) == NULL)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
if (STRPREFIX(hostname, "localhost")) {
|
if (STRPREFIX(hostname, "localhost")) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("hostname on destination resolved to localhost,"
|
_("hostname on destination resolved to localhost,"
|
||||||
" but migration requires an FQDN"));
|
" but migration requires an FQDN"));
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
|
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
priv->migrationPort = port;
|
priv->migrationPort = port;
|
||||||
if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
|
if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
} else {
|
} else {
|
||||||
if (!(STRPREFIX(uri_in, "tcp://"))) {
|
if (!(STRPREFIX(uri_in, "tcp://"))) {
|
||||||
/* not full URI, add prefix tcp:// */
|
/* not full URI, add prefix tcp:// */
|
||||||
char *tmp;
|
char *tmp;
|
||||||
if (virAsprintf(&tmp, "tcp://%s", uri_in) < 0)
|
if (virAsprintf(&tmp, "tcp://%s", uri_in) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
uri = virURIParse(tmp);
|
uri = virURIParse(tmp);
|
||||||
VIR_FREE(tmp);
|
VIR_FREE(tmp);
|
||||||
} else {
|
} else {
|
||||||
@ -720,20 +730,20 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("unable to parse URI: %s"),
|
_("unable to parse URI: %s"),
|
||||||
uri_in);
|
uri_in);
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri->server == NULL) {
|
if (uri->server == NULL) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG,
|
virReportError(VIR_ERR_INVALID_ARG,
|
||||||
_("missing host in migration URI: %s"),
|
_("missing host in migration URI: %s"),
|
||||||
uri_in);
|
uri_in);
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
hostname = uri->server;
|
hostname = uri->server;
|
||||||
|
|
||||||
if (uri->port == 0) {
|
if (uri->port == 0) {
|
||||||
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
|
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
priv->migrationPort = port;
|
priv->migrationPort = port;
|
||||||
} else {
|
} else {
|
||||||
@ -741,7 +751,7 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
|
if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(portstr, sizeof(portstr), "%d", port);
|
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||||
@ -751,14 +761,14 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
&socks, &nsocks) < 0) {
|
&socks, &nsocks) < 0) {
|
||||||
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
||||||
_("Fail to create socket for incoming migration"));
|
_("Fail to create socket for incoming migration"));
|
||||||
goto error;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libxlMigrationDstArgsInitialize() < 0)
|
if (libxlMigrationDstArgsInitialize() < 0)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
|
if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
args->conn = virObjectRef(dconn);
|
args->conn = virObjectRef(dconn);
|
||||||
args->vm = virObjectRef(vm);
|
args->vm = virObjectRef(vm);
|
||||||
@ -786,11 +796,14 @@ libxlDomainMigrationDstPrepare(virConnectPtr dconn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!nsocks_listen)
|
if (!nsocks_listen)
|
||||||
goto error;
|
goto endjob;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
libxlDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
for (i = 0; i < nsocks; i++) {
|
for (i = 0; i < nsocks; i++) {
|
||||||
virNetSocketClose(socks[i]);
|
virNetSocketClose(socks[i]);
|
||||||
@ -1354,6 +1367,8 @@ libxlDomainMigrationDstFinish(virConnectPtr dconn,
|
|||||||
virDomainObjListRemove(driver->domains, vm);
|
virDomainObjListRemove(driver->domains, vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EndJob for corresponding BeginJob in prepare phase */
|
||||||
|
libxlDomainObjEndJob(driver, vm);
|
||||||
virObjectEventStateQueue(driver->domainEventState, event);
|
virObjectEventStateQueue(driver->domainEventState, event);
|
||||||
virObjectUnref(cfg);
|
virObjectUnref(cfg);
|
||||||
return dom;
|
return dom;
|
||||||
|
Loading…
Reference in New Issue
Block a user