提交 97e7e266 编写于 作者: W Wang Yufei 提交者: Ján Tomko

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: NWang Yufei <james.wangyufei@huawei.com>
Signed-off-by: NJiri Denemark <jdenemar@redhat.com>
(cherry picked from commit 0196845d)

Conflicts:
  missing support for changing the migration listen address
	src/qemu/qemu_migration.c
上级 5904ba60
...@@ -51,6 +51,9 @@ ...@@ -51,6 +51,9 @@
# define QEMU_WEBSOCKET_PORT_MIN 5700 # define QEMU_WEBSOCKET_PORT_MIN 5700
# define QEMU_WEBSOCKET_PORT_MAX 65535 # define QEMU_WEBSOCKET_PORT_MAX 65535
# define QEMU_MIGRATION_PORT_MIN 49152
# define QEMU_MIGRATION_PORT_MAX 49215
typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks; typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr; typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
struct _qemuBuildCommandLineCallbacks { struct _qemuBuildCommandLineCallbacks {
......
...@@ -221,6 +221,9 @@ struct _virQEMUDriver { ...@@ -221,6 +221,9 @@ struct _virQEMUDriver {
/* Immutable pointer, self-locking APIs */ /* Immutable pointer, self-locking APIs */
virPortAllocatorPtr webSocketPorts; virPortAllocatorPtr webSocketPorts;
/* Immutable pointer, self-locking APIs */
virPortAllocatorPtr migrationPorts;
/* Immutable pointer, lockless APIs*/ /* Immutable pointer, lockless APIs*/
virSysinfoDefPtr hostsysinfo; virSysinfoDefPtr hostsysinfo;
...@@ -242,9 +245,6 @@ struct _qemuDomainCmdlineDef { ...@@ -242,9 +245,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
void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def); void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def);
......
...@@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate { ...@@ -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;
......
...@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged, ...@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged,
cfg->webSocketPortMax)) == NULL) cfg->webSocketPortMax)) == 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;
...@@ -992,6 +997,7 @@ qemuStateCleanup(void) { ...@@ -992,6 +997,7 @@ qemuStateCleanup(void) {
virObjectUnref(qemu_driver->domains); virObjectUnref(qemu_driver->domains);
virObjectUnref(qemu_driver->remotePorts); virObjectUnref(qemu_driver->remotePorts);
virObjectUnref(qemu_driver->webSocketPorts); virObjectUnref(qemu_driver->webSocketPorts);
virObjectUnref(qemu_driver->migrationPorts);
virObjectUnref(qemu_driver->xmlopt); virObjectUnref(qemu_driver->xmlopt);
......
...@@ -2151,6 +2151,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver, ...@@ -2151,6 +2151,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);
...@@ -2166,7 +2169,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, ...@@ -2166,7 +2169,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
virDomainDefPtr *def, virDomainDefPtr *def,
const char *origname, const char *origname,
virStreamPtr st, virStreamPtr st,
unsigned int port, unsigned short port,
bool autoPort,
unsigned long flags) unsigned long flags)
{ {
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
...@@ -2412,6 +2416,8 @@ done: ...@@ -2412,6 +2416,8 @@ done:
goto cleanup; goto cleanup;
} }
if (autoPort)
priv->migrationPort = port;
ret = 0; ret = 0;
cleanup: cleanup:
...@@ -2479,7 +2485,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver, ...@@ -2479,7 +2485,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
cookieout, cookieoutlen, def, origname, cookieout, cookieoutlen, def, origname,
st, 0, flags); st, 0, false, flags);
return ret; return ret;
} }
...@@ -2497,8 +2503,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, ...@@ -2497,8 +2503,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
const char *origname, const char *origname,
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;
...@@ -2525,10 +2531,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, ...@@ -2525,10 +2531,15 @@ 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 */
if ((hostname = virGetHostname()) == NULL) if ((hostname = virGetHostname()) == NULL)
goto cleanup; goto cleanup;
...@@ -2545,7 +2556,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, ...@@ -2545,7 +2556,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)
goto cleanup; goto cleanup;
} else { } else {
/* Check the URI starts with "tcp:". We will escape the /* Check the URI starts with "tcp:". We will escape the
...@@ -2581,17 +2592,22 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, ...@@ -2581,17 +2592,22 @@ 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)
goto cleanup; goto cleanup;
} else { } else {
this_port = uri->port; port = uri->port;
autoPort = false;
} }
} }
...@@ -2600,12 +2616,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver, ...@@ -2600,12 +2616,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen, ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
cookieout, cookieoutlen, def, origname, cookieout, cookieoutlen, def, origname,
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;
} }
...@@ -4374,6 +4393,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver, ...@@ -4374,6 +4393,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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册