On Mon, Aug 15, 2011 at 09:58:16AM +0200, Jiri Denemark wrote:
By opening a connection to remote qemu process ourselves and passing
the
socket to qemu we get much better errors than just "migration failed"
when the connection is opened by qemu.
---
src/qemu/qemu_migration.c | 128 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 98 insertions(+), 30 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index c29ea9e..537e57e 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -1269,6 +1269,7 @@ cleanup:
enum qemuMigrationDestinationType {
MIGRATION_DEST_HOST,
MIGRATION_DEST_UNIX,
+ MIGRATION_DEST_FD,
};
enum qemuMigrationForwardType {
@@ -1287,9 +1288,14 @@ struct _qemuMigrationSpec {
} host;
struct {
- const char *file;
+ char *file;
int sock;
} unics; /* this sucks but "unix" is a macro defined to 1 */
+
+ struct {
+ int qemu;
+ int local;
+ } fd;
} dest;
enum qemuMigrationForwardType fwdType;
@@ -1472,6 +1478,14 @@ qemuMigrationRun(struct qemud_driver *driver,
ret = qemuMonitorMigrateToCommand(priv->mon, migrate_flags, args);
}
break;
+
+ case MIGRATION_DEST_FD:
+ if (spec->fwdType != MIGRATION_FWD_DIRECT)
+ fd = spec->dest.fd.local;
+ ret = qemuMonitorMigrateToFd(priv->mon, migrate_flags,
+ spec->dest.fd.qemu);
+ VIR_FORCE_CLOSE(spec->dest.fd.qemu);
Hum, I find dubious that we set up fd variable before
calling qemuMonitorMigrateToFd but don't use that variable, smells fishy
but I could be wrong since I don't get the full function context, so
to double check.
+ break;
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0)
@@ -1568,9 +1582,11 @@ static int doNativeMigrate(struct qemud_driver *driver,
unsigned int flags,
unsigned long resource)
{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
xmlURIPtr uribits = NULL;
- int ret;
+ int ret = -1;
qemuMigrationSpec spec;
+ char *tmp = NULL;
VIR_DEBUG("driver=%p, vm=%p, uri=%s, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%x, resource=%lu",
@@ -1579,13 +1595,12 @@ static int doNativeMigrate(struct qemud_driver *driver,
if (STRPREFIX(uri, "tcp:") && !STRPREFIX(uri, "tcp://"))
{
/* HACK: source host generates bogus URIs, so fix them up */
- char *tmpuri;
- if (virAsprintf(&tmpuri, "tcp://%s", uri +
strlen("tcp:")) < 0) {
+ if (virAsprintf(&tmp, "tcp://%s", uri + strlen("tcp:"))
< 0) {
virReportOOMError();
return -1;
}
- uribits = xmlParseURI(tmpuri);
- VIR_FREE(tmpuri);
+ uribits = xmlParseURI(tmp);
+ VIR_FREE(tmp);
} else {
uribits = xmlParseURI(uri);
}
@@ -1595,13 +1610,38 @@ static int doNativeMigrate(struct qemud_driver *driver,
return -1;
}
- spec.destType = MIGRATION_DEST_HOST;
- spec.dest.host.name = uribits->server;
- spec.dest.host.port = uribits->port;
spec.fwdType = MIGRATION_FWD_DIRECT;
+ if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD)) {
+ virNetSocketPtr sock;
+
+ spec.destType = MIGRATION_DEST_FD;
+ spec.dest.fd.qemu = -1;
+
+ if (virAsprintf(&tmp, "%d", uribits->port) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (virNetSocketNewConnectTCP(uribits->server, tmp, &sock) == 0) {
+ spec.dest.fd.qemu = virNetSocketDupFD(sock, true);
+ virNetSocketFree(sock);
+ }
+ if (spec.dest.fd.qemu == -1)
+ goto cleanup;
+ } else {
+ spec.destType = MIGRATION_DEST_HOST;
+ spec.dest.host.name = uribits->server;
+ spec.dest.host.port = uribits->port;
+ }
+
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
cookieoutlen, flags, resource, &spec);
+
+cleanup:
+ if (spec.destType == MIGRATION_DEST_FD)
+ VIR_FORCE_CLOSE(spec.dest.fd.qemu);
+
+ VIR_FREE(tmp);
xmlFreeURI(uribits);
return ret;
@@ -1619,7 +1659,6 @@ static int doTunnelMigrate(struct qemud_driver *driver,
unsigned long resource)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
- char *unixfile = NULL;
virNetSocketPtr sock = NULL;
int ret = -1;
qemuMigrationSpec spec;
@@ -1629,36 +1668,65 @@ static int doTunnelMigrate(struct qemud_driver *driver,
driver, vm, st, NULLSTR(cookiein), cookieinlen,
cookieout, cookieoutlen, flags, resource);
- if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) &&
+ if (!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD) &&
+ !qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_UNIX) &&
!qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_EXEC)) {
- qemuReportError(VIR_ERR_OPERATION_FAILED,
- "%s", _("Source qemu is too old to support
tunnelled migration"));
- goto cleanup;
- }
-
- if (virAsprintf(&unixfile, "%s/qemu.tunnelmigrate.src.%s",
- driver->libDir, vm->def->name) < 0) {
- virReportOOMError();
- goto cleanup;
+ qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("Source qemu is too old to support tunnelled
migration"));
+ return -1;
}
- if (virNetSocketNewListenUNIX(unixfile, 0700,
- driver->user, driver->group, &sock) < 0
||
- virNetSocketListen(sock, 1) < 0)
- goto cleanup;
-
- spec.destType = MIGRATION_DEST_UNIX;
- spec.dest.unics.file = unixfile;
- spec.dest.unics.sock = virNetSocketGetFD(sock);
spec.fwdType = MIGRATION_FWD_STREAM;
spec.fwd.stream = st;
+ if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATE_QEMU_FD)) {
+ int fds[2];
+
+ spec.destType = MIGRATION_DEST_FD;
+ spec.dest.fd.qemu = -1;
+ spec.dest.fd.local = -1;
+
+ if (pipe(fds) == 0) {
+ spec.dest.fd.qemu = fds[1];
+ spec.dest.fd.local = fds[0];
+ }
+ if (spec.dest.fd.qemu == -1 ||
+ virSetCloseExec(spec.dest.fd.qemu) < 0 ||
+ virSetCloseExec(spec.dest.fd.local) < 0) {
+ virReportSystemError(errno, "%s",
+ _("cannot create pipe for tunnelled migration"));
+ goto cleanup;
+ }
+ } else {
+ spec.destType = MIGRATION_DEST_UNIX;
+ spec.dest.unics.sock = -1;
+ spec.dest.unics.file = NULL;
+
+ if (virAsprintf(&spec.dest.unics.file,
"%s/qemu.tunnelmigrate.src.%s",
+ driver->libDir, vm->def->name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virNetSocketNewListenUNIX(spec.dest.unics.file, 0700, driver->user,
+ driver->group, &sock) < 0 ||
+ virNetSocketListen(sock, 1) < 0)
+ goto cleanup;
+
+ spec.dest.unics.sock = virNetSocketGetFD(sock);
+ }
+
ret = qemuMigrationRun(driver, vm, cookiein, cookieinlen, cookieout,
cookieoutlen, flags, resource, &spec);
cleanup:
- virNetSocketFree(sock);
- VIR_FREE(unixfile);
+ if (spec.destType == MIGRATION_DEST_FD) {
+ VIR_FORCE_CLOSE(spec.dest.fd.qemu);
+ VIR_FORCE_CLOSE(spec.dest.fd.local);
+ } else {
+ virNetSocketFree(sock);
+ VIR_FREE(spec.dest.unics.file);
+ }
return ret;
}
Okay, I guess the best is to apply and run the verious test suites on
it ! Out of curiosity did you ran dan's migration suite with those
patches ?
ACK,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine
http://rpmfind.net/
http://veillard.com/ | virtualization library
http://libvirt.org/