|
|
43fe83 |
From ac2a6bb565013f8fce9f36d3eac1ffa7d9523e9a Mon Sep 17 00:00:00 2001
|
|
|
43fe83 |
Message-Id: <ac2a6bb565013f8fce9f36d3eac1ffa7d9523e9a.1382534061.git.jdenemar@redhat.com>
|
|
|
43fe83 |
From: Wang Yufei <james.wangyufei@huawei.com>
|
|
|
43fe83 |
Date: Tue, 22 Oct 2013 16:24:46 +0100
|
|
|
43fe83 |
Subject: [PATCH] qemu: Avoid assigning unavailable migration ports
|
|
|
43fe83 |
|
|
|
43fe83 |
https://bugzilla.redhat.com/show_bug.cgi?id=1019237
|
|
|
43fe83 |
|
|
|
43fe83 |
When we migrate vms concurrently, there's a chance that libvirtd on
|
|
|
43fe83 |
destination assigns the same port for different migrations, which will
|
|
|
43fe83 |
lead to migration failure during prepare phase on destination. So we use
|
|
|
43fe83 |
virPortAllocator here to solve the problem.
|
|
|
43fe83 |
|
|
|
43fe83 |
Signed-off-by: Wang Yufei <james.wangyufei@huawei.com>
|
|
|
43fe83 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
43fe83 |
(cherry picked from commit 0196845d3abd0d914cf11f7ad6c19df8b47c32ed)
|
|
|
43fe83 |
---
|
|
|
43fe83 |
src/qemu/qemu_command.h | 3 +++
|
|
|
43fe83 |
src/qemu/qemu_conf.h | 6 +++---
|
|
|
43fe83 |
src/qemu/qemu_domain.h | 1 +
|
|
|
43fe83 |
src/qemu/qemu_driver.c | 6 ++++++
|
|
|
43fe83 |
src/qemu/qemu_migration.c | 53 +++++++++++++++++++++++++++++++++--------------
|
|
|
43fe83 |
5 files changed, 50 insertions(+), 19 deletions(-)
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
|
|
|
43fe83 |
index 47022e6..decc940 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_command.h
|
|
|
43fe83 |
+++ b/src/qemu/qemu_command.h
|
|
|
43fe83 |
@@ -51,6 +51,9 @@
|
|
|
43fe83 |
# define QEMU_WEBSOCKET_PORT_MIN 5700
|
|
|
43fe83 |
# define QEMU_WEBSOCKET_PORT_MAX 65535
|
|
|
43fe83 |
|
|
|
43fe83 |
+# define QEMU_MIGRATION_PORT_MIN 49152
|
|
|
43fe83 |
+# define QEMU_MIGRATION_PORT_MAX 49215
|
|
|
43fe83 |
+
|
|
|
43fe83 |
typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
|
|
|
43fe83 |
typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
|
|
|
43fe83 |
struct _qemuBuildCommandLineCallbacks {
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
|
|
|
43fe83 |
index 356e501..4acc67b 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_conf.h
|
|
|
43fe83 |
+++ b/src/qemu/qemu_conf.h
|
|
|
43fe83 |
@@ -224,6 +224,9 @@ struct _virQEMUDriver {
|
|
|
43fe83 |
/* Immutable pointer, self-locking APIs */
|
|
|
43fe83 |
virPortAllocatorPtr webSocketPorts;
|
|
|
43fe83 |
|
|
|
43fe83 |
+ /* Immutable pointer, self-locking APIs */
|
|
|
43fe83 |
+ virPortAllocatorPtr migrationPorts;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
/* Immutable pointer, lockless APIs*/
|
|
|
43fe83 |
virSysinfoDefPtr hostsysinfo;
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -245,9 +248,6 @@ struct _qemuDomainCmdlineDef {
|
|
|
43fe83 |
char **env_value;
|
|
|
43fe83 |
};
|
|
|
43fe83 |
|
|
|
43fe83 |
-/* Port numbers used for KVM migration. */
|
|
|
43fe83 |
-# define QEMUD_MIGRATION_FIRST_PORT 49152
|
|
|
43fe83 |
-# define QEMUD_MIGRATION_NUM_PORTS 64
|
|
|
43fe83 |
|
|
|
43fe83 |
|
|
|
43fe83 |
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged);
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
|
43fe83 |
index 21f116c..04f08a3 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_domain.h
|
|
|
43fe83 |
+++ b/src/qemu/qemu_domain.h
|
|
|
43fe83 |
@@ -160,6 +160,7 @@ struct _qemuDomainObjPrivate {
|
|
|
43fe83 |
unsigned long migMaxBandwidth;
|
|
|
43fe83 |
char *origname;
|
|
|
43fe83 |
int nbdPort; /* Port used for migration with NBD */
|
|
|
43fe83 |
+ unsigned short migrationPort;
|
|
|
43fe83 |
|
|
|
43fe83 |
virChrdevsPtr devs;
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
43fe83 |
index c2445d9..4a4880c 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_driver.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_driver.c
|
|
|
43fe83 |
@@ -687,6 +687,11 @@ qemuStateInitialize(bool privileged,
|
|
|
43fe83 |
cfg->webSocketPortMax)) == NULL)
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
|
|
|
43fe83 |
+ if ((qemu_driver->migrationPorts =
|
|
|
43fe83 |
+ virPortAllocatorNew(QEMU_MIGRATION_PORT_MIN,
|
|
|
43fe83 |
+ QEMU_MIGRATION_PORT_MAX)) == NULL)
|
|
|
43fe83 |
+ goto error;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
if (qemuSecurityInit(qemu_driver) < 0)
|
|
|
43fe83 |
goto error;
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -993,6 +998,7 @@ qemuStateCleanup(void) {
|
|
|
43fe83 |
virObjectUnref(qemu_driver->domains);
|
|
|
43fe83 |
virObjectUnref(qemu_driver->remotePorts);
|
|
|
43fe83 |
virObjectUnref(qemu_driver->webSocketPorts);
|
|
|
43fe83 |
+ virObjectUnref(qemu_driver->migrationPorts);
|
|
|
43fe83 |
|
|
|
43fe83 |
virObjectUnref(qemu_driver->xmlopt);
|
|
|
43fe83 |
|
|
|
43fe83 |
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
|
|
|
43fe83 |
index 047fad9..4222a10 100644
|
|
|
43fe83 |
--- a/src/qemu/qemu_migration.c
|
|
|
43fe83 |
+++ b/src/qemu/qemu_migration.c
|
|
|
43fe83 |
@@ -2145,6 +2145,9 @@ qemuMigrationPrepareCleanup(virQEMUDriverPtr driver,
|
|
|
43fe83 |
qemuDomainJobTypeToString(priv->job.active),
|
|
|
43fe83 |
qemuDomainAsyncJobTypeToString(priv->job.asyncJob));
|
|
|
43fe83 |
|
|
|
43fe83 |
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
|
|
|
43fe83 |
+ priv->migrationPort = 0;
|
|
|
43fe83 |
+
|
|
|
43fe83 |
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_IN))
|
|
|
43fe83 |
return;
|
|
|
43fe83 |
qemuDomainObjDiscardAsyncJob(driver, vm);
|
|
|
43fe83 |
@@ -2160,7 +2163,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver,
|
|
|
43fe83 |
virDomainDefPtr *def,
|
|
|
43fe83 |
const char *origname,
|
|
|
43fe83 |
virStreamPtr st,
|
|
|
43fe83 |
- unsigned int port,
|
|
|
43fe83 |
+ unsigned short port,
|
|
|
43fe83 |
+ bool autoPort,
|
|
|
43fe83 |
const char *listenAddress,
|
|
|
43fe83 |
unsigned long flags)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
@@ -2440,6 +2444,8 @@ done:
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
+ if (autoPort)
|
|
|
43fe83 |
+ priv->migrationPort = port;
|
|
|
43fe83 |
ret = 0;
|
|
|
43fe83 |
|
|
|
43fe83 |
cleanup:
|
|
|
43fe83 |
@@ -2507,7 +2513,7 @@ qemuMigrationPrepareTunnel(virQEMUDriverPtr driver,
|
|
|
43fe83 |
|
|
|
43fe83 |
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
|
|
43fe83 |
cookieout, cookieoutlen, def, origname,
|
|
|
43fe83 |
- st, 0, NULL, flags);
|
|
|
43fe83 |
+ st, 0, false, NULL, flags);
|
|
|
43fe83 |
return ret;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -2526,8 +2532,8 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|
|
43fe83 |
const char *listenAddress,
|
|
|
43fe83 |
unsigned long flags)
|
|
|
43fe83 |
{
|
|
|
43fe83 |
- static int port = 0;
|
|
|
43fe83 |
- int this_port;
|
|
|
43fe83 |
+ unsigned short port = 0;
|
|
|
43fe83 |
+ bool autoPort = true;
|
|
|
43fe83 |
char *hostname = NULL;
|
|
|
43fe83 |
const char *p;
|
|
|
43fe83 |
char *uri_str = NULL;
|
|
|
43fe83 |
@@ -2554,10 +2560,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|
|
43fe83 |
* to be a correct hostname which refers to the target machine).
|
|
|
43fe83 |
*/
|
|
|
43fe83 |
if (uri_in == NULL) {
|
|
|
43fe83 |
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
|
|
|
43fe83 |
- if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0;
|
|
|
43fe83 |
+ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ } else if (!port) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("No migration port available within the "
|
|
|
43fe83 |
+ "configured range"));
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
|
|
|
43fe83 |
- /* Get hostname */
|
|
|
43fe83 |
if ((hostname = virGetHostname()) == NULL)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -2574,7 +2585,7 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|
|
43fe83 |
* new targets accept both syntaxes though.
|
|
|
43fe83 |
*/
|
|
|
43fe83 |
/* Caller frees */
|
|
|
43fe83 |
- if (virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0)
|
|
|
43fe83 |
+ if (virAsprintf(uri_out, "tcp:%s:%d", hostname, port) < 0)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
} else {
|
|
|
43fe83 |
/* Check the URI starts with "tcp:". We will escape the
|
|
|
43fe83 |
@@ -2610,17 +2621,22 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
if (uri->port == 0) {
|
|
|
43fe83 |
- /* Generate a port */
|
|
|
43fe83 |
- this_port = QEMUD_MIGRATION_FIRST_PORT + port++;
|
|
|
43fe83 |
- if (port == QEMUD_MIGRATION_NUM_PORTS)
|
|
|
43fe83 |
- port = 0;
|
|
|
43fe83 |
+ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0) {
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ } else if (!port) {
|
|
|
43fe83 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
43fe83 |
+ _("No migration port available within the "
|
|
|
43fe83 |
+ "configured range"));
|
|
|
43fe83 |
+ goto cleanup;
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
|
|
|
43fe83 |
/* Caller frees */
|
|
|
43fe83 |
- if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0)
|
|
|
43fe83 |
+ if (virAsprintf(uri_out, "%s:%d", uri_in, port) < 0)
|
|
|
43fe83 |
goto cleanup;
|
|
|
43fe83 |
|
|
|
43fe83 |
} else {
|
|
|
43fe83 |
- this_port = uri->port;
|
|
|
43fe83 |
+ port = uri->port;
|
|
|
43fe83 |
+ autoPort = false;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -2629,12 +2645,15 @@ qemuMigrationPrepareDirect(virQEMUDriverPtr driver,
|
|
|
43fe83 |
|
|
|
43fe83 |
ret = qemuMigrationPrepareAny(driver, dconn, cookiein, cookieinlen,
|
|
|
43fe83 |
cookieout, cookieoutlen, def, origname,
|
|
|
43fe83 |
- NULL, this_port, listenAddress, flags);
|
|
|
43fe83 |
+ NULL, port, autoPort, listenAddress, flags);
|
|
|
43fe83 |
cleanup:
|
|
|
43fe83 |
virURIFree(uri);
|
|
|
43fe83 |
VIR_FREE(hostname);
|
|
|
43fe83 |
- if (ret != 0)
|
|
|
43fe83 |
+ if (ret != 0) {
|
|
|
43fe83 |
VIR_FREE(*uri_out);
|
|
|
43fe83 |
+ if (autoPort)
|
|
|
43fe83 |
+ virPortAllocatorRelease(driver->migrationPorts, port);
|
|
|
43fe83 |
+ }
|
|
|
43fe83 |
return ret;
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
@@ -4414,6 +4433,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
|
|
|
43fe83 |
}
|
|
|
43fe83 |
|
|
|
43fe83 |
qemuMigrationStopNBDServer(driver, vm, mig);
|
|
|
43fe83 |
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
|
|
|
43fe83 |
+ priv->migrationPort = 0;
|
|
|
43fe83 |
|
|
|
43fe83 |
if (flags & VIR_MIGRATE_PERSIST_DEST) {
|
|
|
43fe83 |
virDomainDefPtr vmdef;
|
|
|
43fe83 |
--
|
|
|
43fe83 |
1.8.4
|
|
|
43fe83 |
|