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/ dan...@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list