提交 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,90 +1423,63 @@ cleanup: ...@@ -1423,90 +1423,63 @@ cleanup:
} }
static int doTunnelMigrate2(struct qemud_driver *driver, /* This is essentially a re-impl of virDomainMigrateVersion2
virConnectPtr dconn, * from libvirt.c, but running in source libvirtd context,
virDomainObjPtr vm, * instead of client app context & also adding in tunnel
const char *dom_xml, * handling */
const char *uri, static int doPeer2PeerMigrate2(struct qemud_driver *driver,
unsigned long flags, virConnectPtr sconn,
const char *dname,
unsigned long resource)
{
virDomainPtr ddomain = NULL;
int retval = -1;
virStreamPtr st = NULL;
int internalret;
/*
* Tunnelled Migrate Version 2 does not support cookies
* due to missing parameters in the prepareTunnel() API.
*/
if (!(st = virStreamNew(dconn, 0)))
goto cleanup;
qemuDomainObjEnterRemoteWithDriver(driver, vm);
internalret = dconn->driver->domainMigratePrepareTunnel(dconn, st,
flags, dname,
resource, dom_xml);
qemuDomainObjExitRemoteWithDriver(driver, vm);
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, virConnectPtr dconn,
virDomainObjPtr vm, virDomainObjPtr vm,
const char *dom_xml, const char *uri,
const char *uri ATTRIBUTE_UNUSED,
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 *uri_out = NULL;
char *cookie = NULL; char *cookie = NULL;
int cookielen = 0; char *dom_xml = NULL;
int rc; int cookielen = 0, ret;
virErrorPtr orig_err = NULL;
int cancelled;
virStreamPtr st = NULL;
qemuDomainObjEnterRemoteWithDriver(driver, vm); /* In version 2 of the protocol, the prepare step is slightly
/* NB we don't pass 'uri' into this, since that's the libvirtd * different. We fetch the domain XML of the source domain
* URI in this context - so we let dest pick it */ * and pass it to Prepare2.
rc = dconn->driver->domainMigratePrepare2(dconn, */
&cookie, if (!(dom_xml = qemuDomainFormatXML(driver, vm,
&cookielen, VIR_DOMAIN_XML_SECURE |
NULL, /* uri */ VIR_DOMAIN_XML_UPDATE_CPU)))
&uri_out, return -1;
flags, dname,
resource, dom_xml); if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED)
qemuDomainObjExitRemoteWithDriver(driver, vm); flags |= VIR_MIGRATE_PAUSED;
if (rc < 0)
/* domainMigratePrepare2 sets the error for us */ VIR_DEBUG("Prepare2 %p", dconn);
if (flags & VIR_MIGRATE_TUNNELLED) {
/*
* Tunnelled Migrate Version 2 does not support cookies
* due to missing parameters in the prepareTunnel() API.
*/
if (!(st = virStreamNew(dconn, 0)))
goto cleanup;
qemuDomainObjEnterRemoteWithDriver(driver, vm);
ret = dconn->driver->domainMigratePrepareTunnel
(dconn, st, flags, dname, resource, dom_xml);
qemuDomainObjExitRemoteWithDriver(driver, vm);
} else {
qemuDomainObjEnterRemoteWithDriver(driver, vm);
ret = dconn->driver->domainMigratePrepare2
(dconn, &cookie, &cookielen, NULL, &uri_out,
flags, dname, resource, dom_xml);
qemuDomainObjExitRemoteWithDriver(driver, vm);
}
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
cookie, cookielen, * until the migration is complete.
NULL, NULL, /* No out cookie with v2 migration */ */
flags, dname, resource) < 0) VIR_DEBUG("Perform %p", sconn);
goto finish; if (flags & VIR_MIGRATE_TUNNELLED)
ret = doTunnelMigrate(driver, vm, st, flags, resource);
else
ret = doNativeMigrate(driver, vm, uri_out,
cookie, cookielen,
NULL, NULL, /* No out cookie with v2 migration */
flags, dname, resource);
/* Perform failed. Make sure Finish doesn't overwrite the error */
if (ret < 0)
orig_err = virSaveLastError();
retval = 0; /* 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.
先完成此消息的编辑!
想要评论请 注册