mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-12 14:41:29 +00:00
qemu: Avoid assigning unavailable migration ports
https://bugzilla.redhat.com/show_bug.cgi?id=1019053 When we migrate vms concurrently, there's a chance that libvirtd on destination assigns the same port for different migrations, which will lead to migration failure during prepare phase on destination. So we use virPortAllocator here to solve the problem. Signed-off-by: Wang Yufei <james.wangyufei@huawei.com> Signed-off-by: Jiri Denemark <jdenemar@redhat.com> (cherry picked from commit 0196845d3abd0d914cf11f7ad6c19df8b47c32ed) Conflicts: missing support for WebSockets and listen address virAsprintf doesn't report OOM src/qemu/qemu_command.h src/qemu/qemu_conf.h src/qemu/qemu_driver.c src/qemu/qemu_migration.c
This commit is contained in:
parent
05700f6045
commit
1359673e42
@ -48,6 +48,8 @@
|
|||||||
# define QEMU_REMOTE_PORT_MIN 5900
|
# define QEMU_REMOTE_PORT_MIN 5900
|
||||||
# define QEMU_REMOTE_PORT_MAX 65535
|
# define QEMU_REMOTE_PORT_MAX 65535
|
||||||
|
|
||||||
|
# define QEMU_MIGRATION_PORT_MIN 49152
|
||||||
|
# define QEMU_MIGRATION_PORT_MAX 49215
|
||||||
|
|
||||||
virCommandPtr qemuBuildCommandLine(virConnectPtr conn,
|
virCommandPtr qemuBuildCommandLine(virConnectPtr conn,
|
||||||
virQEMUDriverPtr driver,
|
virQEMUDriverPtr driver,
|
||||||
|
@ -210,6 +210,9 @@ struct _virQEMUDriver {
|
|||||||
/* Immutable pointer, self-locking APIs */
|
/* Immutable pointer, self-locking APIs */
|
||||||
virPortAllocatorPtr remotePorts;
|
virPortAllocatorPtr remotePorts;
|
||||||
|
|
||||||
|
/* Immutable pointer, self-locking APIs */
|
||||||
|
virPortAllocatorPtr migrationPorts;
|
||||||
|
|
||||||
/* Immutable pointer, lockless APIs*/
|
/* Immutable pointer, lockless APIs*/
|
||||||
virSysinfoDefPtr hostsysinfo;
|
virSysinfoDefPtr hostsysinfo;
|
||||||
|
|
||||||
@ -231,9 +234,6 @@ struct _qemuDomainCmdlineDef {
|
|||||||
char **env_value;
|
char **env_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Port numbers used for KVM migration. */
|
|
||||||
# define QEMUD_MIGRATION_FIRST_PORT 49152
|
|
||||||
# define QEMUD_MIGRATION_NUM_PORTS 64
|
|
||||||
|
|
||||||
|
|
||||||
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged);
|
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged);
|
||||||
|
@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate {
|
|||||||
unsigned long migMaxBandwidth;
|
unsigned long migMaxBandwidth;
|
||||||
char *origname;
|
char *origname;
|
||||||
int nbdPort; /* Port used for migration with NBD */
|
int nbdPort; /* Port used for migration with NBD */
|
||||||
|
unsigned short migrationPort;
|
||||||
|
|
||||||
virChrdevsPtr devs;
|
virChrdevsPtr devs;
|
||||||
|
|
||||||
|
@ -662,6 +662,11 @@ qemuStateInitialize(bool privileged,
|
|||||||
cfg->remotePortMax)) == NULL)
|
cfg->remotePortMax)) == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if ((qemu_driver->migrationPorts =
|
||||||
|
virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
|
||||||
|
QEMU_MIGRATION_PORT_MAX)) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (qemuSecurityInit(qemu_driver) < 0)
|
if (qemuSecurityInit(qemu_driver) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -951,6 +956,7 @@ qemuStateCleanup(void) {
|
|||||||
|
|
||||||
virObjectUnref(qemu_driver->domains);
|
virObjectUnref(qemu_driver->domains);
|
||||||
virObjectUnref(qemu_driver->remotePorts);
|
virObjectUnref(qemu_driver->remotePorts);
|
||||||
|
virObjectUnref(qemu_driver->migrationPorts);
|
||||||
|
|
||||||
virObjectUnref(qemu_driver->xmlopt);
|
virObjectUnref(qemu_driver->xmlopt);
|
||||||
|
|
||||||
|
@ -1998,6 +1998,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
|
|||||||
qemuDomainJobTypeToString(priv->job.active),
|
qemuDomainJobTypeToString(priv->job.active),
|
||||||
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
|
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
|
||||||
|
|
||||||
|
virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
|
||||||
|
priv->migrationPort = 0;
|
||||||
|
|
||||||
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
|
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
|
||||||
return;
|
return;
|
||||||
qemuDomainObjDiscardAsyncJob(driver, vm);
|
qemuDomainObjDiscardAsyncJob(driver, vm);
|
||||||
@ -2013,7 +2016,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
|
|||||||
const char *dname,
|
const char *dname,
|
||||||
const char *dom_xml,
|
const char *dom_xml,
|
||||||
virStreamPtr st,
|
virStreamPtr st,
|
||||||
unsigned int port,
|
unsigned short port,
|
||||||
|
bool autoPort,
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
virDomainDefPtr def = NULL;
|
virDomainDefPtr def = NULL;
|
||||||
@ -2277,6 +2281,8 @@ done:
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (autoPort)
|
||||||
|
priv->migrationPort = port;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -2340,7 +2346,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
||||||
cookieout, cookieoutlen, dname, dom_xml,
|
cookieout, cookieoutlen, dname, dom_xml,
|
||||||
st, 0, flags);
|
st, 0, false, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2358,8 +2364,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|||||||
const char *dom_xml,
|
const char *dom_xml,
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
static int port = 0;
|
unsigned short port = 0;
|
||||||
int this_port;
|
bool autoPort = true;
|
||||||
char *hostname = NULL;
|
char *hostname = NULL;
|
||||||
const char *p;
|
const char *p;
|
||||||
char *uri_str = NULL;
|
char *uri_str = NULL;
|
||||||
@ -2384,8 +2390,14 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|||||||
* to be a correct hostname which refers to the target machine).
|
* to be a correct hostname which refers to the target machine).
|
||||||
*/
|
*/
|
||||||
if (uri_in == NULL) {
|
if (uri_in == NULL) {
|
||||||
this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
|
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
|
||||||
if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
|
goto cleanup;
|
||||||
|
} else if (!port) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("No migration port available within the "
|
||||||
|
"configured range"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get hostname */
|
/* Get hostname */
|
||||||
if ((hostname = virGetHostname(NULL)) == NULL)
|
if ((hostname = virGetHostname(NULL)) == NULL)
|
||||||
@ -2404,7 +2416,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|||||||
* new targets accept both syntaxes though.
|
* new targets accept both syntaxes though.
|
||||||
*/
|
*/
|
||||||
/* Caller frees */
|
/* Caller frees */
|
||||||
if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
|
if (virAsprintf(uri_out, "tcp:%s:%d", hostname, port) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -2444,19 +2456,24 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uri->port == 0) {
|
if (uri->port == 0) {
|
||||||
/* Generate a port */
|
if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
|
||||||
this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
|
goto cleanup;
|
||||||
if (port == QEMUD_MIGRATION_NUM_PORTS)
|
} else if (!port) {
|
||||||
port = 0;
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("No migration port available within the "
|
||||||
|
"configured range"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Caller frees */
|
/* Caller frees */
|
||||||
if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0) {
|
if (virAsprintf(uri_out, "%s:%d", uri_in, port) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this_port = uri->port;
|
port = uri->port;
|
||||||
|
autoPort = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2465,12 +2482,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
||||||
cookieout, cookieoutlen, dname, dom_xml,
|
cookieout, cookieoutlen, dname, dom_xml,
|
||||||
NULL, this_port, flags);
|
NULL, port, autoPort, flags);
|
||||||
cleanup:
|
cleanup:
|
||||||
virURIFree(uri);
|
virURIFree(uri);
|
||||||
VIR_FREE(hostname);
|
VIR_FREE(hostname);
|
||||||
if (ret != 0)
|
if (ret != 0) {
|
||||||
VIR_FREE(*uri_out);
|
VIR_FREE(*uri_out);
|
||||||
|
if (autoPort)
|
||||||
|
virPortAllocatorRelease(driver->migrationPorts, port);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3962,6 +3982,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
qemuMigrationStopNBDServer(driver, vm, mig);
|
qemuMigrationStopNBDServer(driver, vm, mig);
|
||||||
|
virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
|
||||||
|
priv->migrationPort = 0;
|
||||||
|
|
||||||
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
||||||
virDomainDefPtr vmdef;
|
virDomainDefPtr vmdef;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user