提交 636ee926 编写于 作者: D Daniel P. Berrange

Merge tunnel & non-tunnel migration impl into one

Merge the doNonTunnelMigrate2 and doTunnelMigrate2 methods
into one doPeer2PeerMigrate2 method, since they are substantially
the same. With the introduction of v3 migration, this will be
even more important, to avoid massive code duplication.

* src/qemu/qemu_migration.c: Merge tunnel & non-tunnel migration
上级 6b0fa703
...@@ -1423,20 +1423,42 @@ cleanup: ...@@ -1423,20 +1423,42 @@ cleanup:
} }
static int doTunnelMigrate2(struct qemud_driver *driver, /* This is essentially a re-impl of virDomainMigrateVersion2
* from libvirt.c, but running in source libvirtd context,
* instead of client app context & also adding in tunnel
* handling */
static int doPeer2PeerMigrate2(struct qemud_driver *driver,
virConnectPtr sconn,
virConnectPtr dconn, virConnectPtr dconn,
virDomainObjPtr vm, virDomainObjPtr vm,
const char *dom_xml,
const char *uri, const char *uri,
unsigned long flags, unsigned long flags,
const char *dname, const char *dname,
unsigned long resource) unsigned long resource)
{ {
virDomainPtr ddomain = NULL; virDomainPtr ddomain = NULL;
int retval = -1; char *uri_out = NULL;
char *cookie = NULL;
char *dom_xml = NULL;
int cookielen = 0, ret;
virErrorPtr orig_err = NULL;
int cancelled;
virStreamPtr st = NULL; virStreamPtr st = NULL;
int internalret;
/* In version 2 of the protocol, the prepare step is slightly
* different. We fetch the domain XML of the source domain
* and pass it to Prepare2.
*/
if (!(dom_xml = qemuDomainFormatXML(driver, vm,
VIR_DOMAIN_XML_SECURE |
VIR_DOMAIN_XML_UPDATE_CPU)))
return -1;
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
flags |= VIR_MIGRATE_PAUSED;
VIR_DEBUG("Prepare2 %p", dconn);
if (flags & VIR_MIGRATE_TUNNELLED) {
/* /*
* Tunnelled Migrate Version 2 does not support cookies * Tunnelled Migrate Version 2 does not support cookies
* due to missing parameters in the prepareTunnel() API. * due to missing parameters in the prepareTunnel() API.
...@@ -1446,67 +1468,18 @@ static int doTunnelMigrate2(struct qemud_driver *driver, ...@@ -1446,67 +1468,18 @@ static int doTunnelMigrate2(struct qemud_driver *driver,
goto cleanup; goto cleanup;
qemuDomainObjEnterRemoteWithDriver(driver, vm); qemuDomainObjEnterRemoteWithDriver(driver, vm);
internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st, ret = dconn->driver->domainMigratePrepareTunnel
flags, dname, (dconn, st, flags, dname, resource, dom_xml);
resource, dom_xml);
qemuDomainObjExitRemoteWithDriver(driver, vm); qemuDomainObjExitRemoteWithDriver(driver, vm);
} else {
if (internalret < 0)
/* domainMigratePrepareTunnel sets the error for us */
goto cleanup;
retval = doTunnelMigrate(driver, vm, st, flags, resource);
dname = dname ? dname : vm->def->name;
qemuDomainObjEnterRemoteWithDriver(driver, vm);
ddomain = dconn->driver->domainMigrateFinish2
(dconn, dname, NULL, 0, uri, flags, retval);
qemuDomainObjExitRemoteWithDriver(driver, vm);
cleanup:
if (ddomain)
virUnrefDomain(ddomain);
if (st)
/* don't call virStreamFree(), because that resets any pending errors */
virUnrefStream(st);
return retval;
}
/* This is essentially a simplified re-impl of
* virDomainMigrateVersion2 from libvirt.c, but running in source
* libvirtd context, instead of client app context */
static int doNonTunnelMigrate2(struct qemud_driver *driver,
virConnectPtr dconn,
virDomainObjPtr vm,
const char *dom_xml,
const char *uri ATTRIBUTE_UNUSED,
unsigned long flags,
const char *dname,
unsigned long resource)
{
virDomainPtr ddomain = NULL;
int retval = -1;
char *uri_out = NULL;
char *cookie = NULL;
int cookielen = 0;
int rc;
qemuDomainObjEnterRemoteWithDriver(driver, vm); qemuDomainObjEnterRemoteWithDriver(driver, vm);
/* NB we don't pass 'uri' into this, since that's the libvirtd ret = dconn->driver->domainMigratePrepare2
* URI in this context - so we let dest pick it */ (dconn, &cookie, &cookielen, NULL, &uri_out,
rc = dconn->driver->domainMigratePrepare2(dconn, flags, dname, resource, dom_xml);
&cookie,
&cookielen,
NULL, /* uri */
&uri_out,
flags, dname,
resource, dom_xml);
qemuDomainObjExitRemoteWithDriver(driver, vm); qemuDomainObjExitRemoteWithDriver(driver, vm);
if (rc < 0) }
/* domainMigratePrepare2 sets the error for us */ VIR_FREE(dom_xml);
if (ret == -1)
goto cleanup; goto cleanup;
/* the domain may have shutdown or crashed while we had the locks dropped /* the domain may have shutdown or crashed while we had the locks dropped
...@@ -1518,37 +1491,72 @@ static int doNonTunnelMigrate2(struct qemud_driver *driver, ...@@ -1518,37 +1491,72 @@ static int doNonTunnelMigrate2(struct qemud_driver *driver,
goto cleanup; goto cleanup;
} }
if (uri_out == NULL) { if (!(flags & VIR_MIGRATE_TUNNELLED) &&
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", (uri_out == NULL)) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("domainMigratePrepare2 did not set uri")); _("domainMigratePrepare2 did not set uri"));
goto cleanup; cancelled = 1;
goto finish;
} }
if (doNativeMigrate(driver, vm, uri_out, /* Perform the migration. The driver isn't supposed to return
* until the migration is complete.
*/
VIR_DEBUG("Perform %p", sconn);
if (flags & VIR_MIGRATE_TUNNELLED)
ret = doTunnelMigrate(driver, vm, st, flags, resource);
else
ret = doNativeMigrate(driver, vm, uri_out,
cookie, cookielen, cookie, cookielen,
NULL, NULL, /* No out cookie with v2 migration */ NULL, NULL, /* No out cookie with v2 migration */
flags, dname, resource) < 0) flags, dname, resource);
goto finish;
retval = 0; /* Perform failed. Make sure Finish doesn't overwrite the error */
if (ret < 0)
orig_err = virSaveLastError();
/* If Perform returns < 0, then we need to cancel the VM
* startup on the destination
*/
cancelled = ret < 0 ? 1 : 0;
finish: finish:
/* In version 2 of the migration protocol, we pass the
* status code from the sender to the destination host,
* so it can do any cleanup if the migration failed.
*/
dname = dname ? dname : vm->def->name; dname = dname ? dname : vm->def->name;
VIR_DEBUG("Finish2 %p ret=%d", dconn, ret);
qemuDomainObjEnterRemoteWithDriver(driver, vm); qemuDomainObjEnterRemoteWithDriver(driver, vm);
ddomain = dconn->driver->domainMigrateFinish2 ddomain = dconn->driver->domainMigrateFinish2
(dconn, dname, cookie, cookielen, uri_out, flags, retval); (dconn, dname, cookie, cookielen,
uri_out ? uri_out : uri, flags, cancelled);
qemuDomainObjExitRemoteWithDriver(driver, vm); qemuDomainObjExitRemoteWithDriver(driver, vm);
if (ddomain) cleanup:
if (ddomain) {
virUnrefDomain(ddomain); virUnrefDomain(ddomain);
ret = 0;
} else {
ret = -1;
}
cleanup: if (st)
virUnrefStream(st);
if (orig_err) {
virSetError(orig_err);
virFreeError(orig_err);
}
VIR_FREE(uri_out);
VIR_FREE(cookie); VIR_FREE(cookie);
return retval;
return ret;
} }
static int doPeer2PeerMigrate(struct qemud_driver *driver, static int doPeer2PeerMigrate(struct qemud_driver *driver,
virConnectPtr sconn,
virDomainObjPtr vm, virDomainObjPtr vm,
const char *uri, const char *uri,
unsigned long flags, unsigned long flags,
...@@ -1557,7 +1565,6 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, ...@@ -1557,7 +1565,6 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver,
{ {
int ret = -1; int ret = -1;
virConnectPtr dconn = NULL; virConnectPtr dconn = NULL;
char *dom_xml;
bool p2p; bool p2p;
/* the order of operations is important here; we make sure the /* the order of operations is important here; we make sure the
...@@ -1590,22 +1597,10 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver, ...@@ -1590,22 +1597,10 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver,
goto cleanup; goto cleanup;
} }
dom_xml = qemuDomainFormatXML(driver, vm, ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm,
VIR_DOMAIN_XML_SECURE | uri, flags, dname, resource);
VIR_DOMAIN_XML_UPDATE_CPU);
if (!dom_xml) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to get domain xml"));
goto cleanup;
}
if (flags & VIR_MIGRATE_TUNNELLED)
ret = doTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource);
else
ret = doNonTunnelMigrate2(driver, dconn, vm, dom_xml, uri, flags, dname, resource);
cleanup: cleanup:
VIR_FREE(dom_xml);
/* don't call virConnectClose(), because that resets any pending errors */ /* don't call virConnectClose(), because that resets any pending errors */
qemuDomainObjEnterRemoteWithDriver(driver, vm); qemuDomainObjEnterRemoteWithDriver(driver, vm);
virUnrefConnect(dconn); virUnrefConnect(dconn);
...@@ -1659,7 +1654,7 @@ int qemuMigrationPerform(struct qemud_driver *driver, ...@@ -1659,7 +1654,7 @@ int qemuMigrationPerform(struct qemud_driver *driver,
goto endjob; goto endjob;
} }
if (doPeer2PeerMigrate(driver, vm, uri, flags, dname, resource) < 0) if (doPeer2PeerMigrate(driver, conn, vm, uri, flags, dname, resource) < 0)
/* doPeer2PeerMigrate already set the error, so just get out */ /* doPeer2PeerMigrate already set the error, so just get out */
goto endjob; goto endjob;
} else { } else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册