<div dir="ltr">Resent the email below. Thanks.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Aug 31, 2014 at 2:05 PM, Hongbin Lu <span dir="ltr"><<a href="mailto:hongbin034@gmail.com" target="_blank">hongbin034@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch adds initial migration support to the OpenVZ driver,<br>
using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration<br>
functions.<br>
---<br>
src/openvz/openvz_conf.h | 5 +-<br>
src/openvz/openvz_driver.c | 348 ++++++++++++++++++++++++++++++++++++++++++++<br>
src/openvz/openvz_driver.h | 10 ++<br>
3 files changed, 361 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h<br>
index a7de7d2..33998d6 100644<br>
--- a/src/openvz/openvz_conf.h<br>
+++ b/src/openvz/openvz_conf.h<br>
@@ -35,8 +35,9 @@<br>
<br>
<br>
/* OpenVZ commands - Replace with wrapper scripts later? */<br>
-# define VZLIST "/usr/sbin/vzlist"<br>
-# define VZCTL "/usr/sbin/vzctl"<br>
+# define VZLIST "/usr/sbin/vzlist"<br>
+# define VZCTL "/usr/sbin/vzctl"<br>
+# define VZMIGRATE "/usr/sbin/vzmigrate"<br>
# define VZ_CONF_FILE "/etc/vz/vz.conf"<br>
<br>
# define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)<br>
diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c<br>
index 851ed30..0f46872 100644<br>
--- a/src/openvz/openvz_driver.c<br>
+++ b/src/openvz/openvz_driver.c<br>
@@ -2207,6 +2207,348 @@ openvzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,<br>
}<br>
<br>
<br>
+static int<br>
+openvzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)<br>
+{<br>
+ switch (feature) {<br>
+ case VIR_DRV_FEATURE_MIGRATION_PARAMS:<br>
+ case VIR_DRV_FEATURE_MIGRATION_V3:<br>
+ return 1;<br>
+ default:<br>
+ return 0;<br>
+ }<br>
+}<br>
+<br>
+<br>
+static char *<br>
+openvzDomainMigrateBegin3Params(virDomainPtr domain,<br>
+ virTypedParameterPtr params,<br>
+ int nparams,<br>
+ char **cookieout ATTRIBUTE_UNUSED,<br>
+ int *cookieoutlen ATTRIBUTE_UNUSED,<br>
+ unsigned int flags)<br>
+{<br>
+ virDomainObjPtr vm = NULL;<br>
+ struct openvz_driver *driver = domain->conn->privateData;<br>
+ char *xml = NULL;<br>
+ int status;<br>
+<br>
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);<br>
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
+ return NULL;<br>
+<br>
+ openvzDriverLock(driver);<br>
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
+ openvzDriverUnlock(driver);<br>
+<br>
+ if (!vm) {<br>
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
+ _("no domain with matching uuid"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ if (!virDomainObjIsActive(vm)) {<br>
+ virReportError(VIR_ERR_OPERATION_INVALID,<br>
+ "%s", _("domain is not running"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
+ goto cleanup;<br>
+<br>
+ if (status != VIR_DOMAIN_RUNNING) {<br>
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
+ _("domain is not in running state"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);<br>
+<br>
+ cleanup:<br>
+ if (vm)<br>
+ virObjectUnlock(vm);<br>
+ return xml;<br>
+}<br>
+<br>
+static int<br>
+openvzDomainMigratePrepare3Params(virConnectPtr dconn,<br>
+ virTypedParameterPtr params,<br>
+ int nparams,<br>
+ const char *cookiein ATTRIBUTE_UNUSED,<br>
+ int cookieinlen ATTRIBUTE_UNUSED,<br>
+ char **cookieout ATTRIBUTE_UNUSED,<br>
+ int *cookieoutlen ATTRIBUTE_UNUSED,<br>
+ char **uri_out,<br>
+ unsigned int fflags ATTRIBUTE_UNUSED)<br>
+{<br>
+ struct openvz_driver *driver = dconn->privateData;<br>
+ const char *dom_xml = NULL;<br>
+ const char *uri_in = NULL;<br>
+ virDomainDefPtr def = NULL;<br>
+ virDomainObjPtr vm = NULL;<br>
+ char *hostname = NULL;<br>
+ virURIPtr uri = NULL;<br>
+ int ret = -1;<br>
+<br>
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
+ goto error;<br>
+<br>
+ if (virTypedParamsGetString(params, nparams,<br>
+ VIR_MIGRATE_PARAM_DEST_XML,<br>
+ &dom_xml) < 0 ||<br>
+ virTypedParamsGetString(params, nparams,<br>
+ VIR_MIGRATE_PARAM_URI,<br>
+ &uri_in) < 0)<br>
+ goto error;<br>
+<br>
+ if (!dom_xml) {<br>
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
+ _("no domain XML passed"));<br>
+ goto error;<br>
+ }<br>
+<br>
+ if (!(def = virDomainDefParseString(dom_xml, driver->caps, driver->xmlopt,<br>
+ 1 << VIR_DOMAIN_VIRT_OPENVZ,<br>
+ VIR_DOMAIN_XML_INACTIVE)))<br>
+ goto error;<br>
+<br>
+ if (!(vm = virDomainObjListAdd(driver->domains, def,<br>
+ driver->xmlopt,<br>
+ VIR_DOMAIN_OBJ_LIST_ADD_LIVE |<br>
+ VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,<br>
+ NULL)))<br>
+ goto error;<br>
+ def = NULL;<br>
+<br>
+ if (!uri_in) {<br>
+ if ((hostname = virGetHostname()) == NULL)<br>
+ goto error;<br>
+<br>
+ if (STRPREFIX(hostname, "localhost")) {<br>
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
+ _("hostname on destination resolved to localhost,"<br>
+ " but migration requires an FQDN"));<br>
+ goto error;<br>
+ }<br>
+ } else {<br>
+ uri = virURIParse(uri_in);<br>
+<br>
+ if (uri == NULL) {<br>
+ virReportError(VIR_ERR_INVALID_ARG,<br>
+ _("unable to parse URI: %s"),<br>
+ uri_in);<br>
+ goto error;<br>
+ }<br>
+<br>
+ if (uri->server == NULL) {<br>
+ virReportError(VIR_ERR_INVALID_ARG,<br>
+ _("missing host in migration URI: %s"),<br>
+ uri_in);<br>
+ goto error;<br>
+ } else {<br>
+ hostname = uri->server;<br>
+ }<br>
+ }<br>
+<br>
+ if (virAsprintf(uri_out, "tcp://%s", hostname) < 0)<br>
+ goto error;<br>
+<br>
+ ret = 0;<br>
+ goto done;<br>
+<br>
+ error:<br>
+ virDomainDefFree(def);<br>
+ if (vm) {<br>
+ virDomainObjListRemove(driver->domains, vm);<br>
+ vm = NULL;<br>
+ }<br>
+<br>
+ done:<br>
+ virURIFree(uri);<br>
+ if (vm)<br>
+ virObjectUnlock(vm);<br>
+ return ret;<br>
+}<br>
+<br>
+static int<br>
+openvzDomainMigratePerform3Params(virDomainPtr domain,<br>
+ const char *dconnuri ATTRIBUTE_UNUSED,<br>
+ virTypedParameterPtr params,<br>
+ int nparams,<br>
+ const char *cookiein ATTRIBUTE_UNUSED,<br>
+ int cookieinlen ATTRIBUTE_UNUSED,<br>
+ char **cookieout ATTRIBUTE_UNUSED,<br>
+ int *cookieoutlen ATTRIBUTE_UNUSED,<br>
+ unsigned int flags)<br>
+{<br>
+ struct openvz_driver *driver = domain->conn->privateData;<br>
+ virDomainObjPtr vm = NULL;<br>
+ const char *uri_str = NULL;<br>
+ virURIPtr uri = NULL;<br>
+ virCommandPtr cmd = virCommandNew(VZMIGRATE);<br>
+ int ret = -1;<br>
+<br>
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);<br>
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
+ goto cleanup;<br>
+<br>
+ if (virTypedParamsGetString(params, nparams,<br>
+ VIR_MIGRATE_PARAM_URI,<br>
+ &uri_str) < 0)<br>
+ goto cleanup;<br>
+<br>
+ openvzDriverLock(driver);<br>
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
+ openvzDriverUnlock(driver);<br>
+<br>
+ if (!vm) {<br>
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
+ _("no domain with matching uuid"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ /* parse dst host:port from uri */<br>
+ uri = virURIParse(uri_str);<br>
+ if (uri == NULL || uri->server == NULL)<br>
+ goto cleanup;<br>
+<br>
+ if (flags & VIR_MIGRATE_LIVE)<br>
+ virCommandAddArg(cmd, "--live");<br>
+ virCommandAddArg(cmd, uri->server);<br>
+ virCommandAddArg(cmd, vm->def->name);<br>
+<br>
+ if (virCommandRun(cmd, NULL) < 0)<br>
+ goto cleanup;<br>
+<br>
+ ret = 0;<br>
+<br>
+ cleanup:<br>
+ virCommandFree(cmd);<br>
+ virURIFree(uri);<br>
+ if (vm)<br>
+ virObjectUnlock(vm);<br>
+ return ret;<br>
+}<br>
+<br>
+static virDomainPtr<br>
+openvzDomainMigrateFinish3Params(virConnectPtr dconn,<br>
+ virTypedParameterPtr params,<br>
+ int nparams,<br>
+ const char *cookiein ATTRIBUTE_UNUSED,<br>
+ int cookieinlen ATTRIBUTE_UNUSED,<br>
+ char **cookieout ATTRIBUTE_UNUSED,<br>
+ int *cookieoutlen ATTRIBUTE_UNUSED,<br>
+ unsigned int flags,<br>
+ int cancelled)<br>
+{<br>
+ struct openvz_driver *driver = dconn->privateData;<br>
+ virDomainObjPtr vm = NULL;<br>
+ const char *dname = NULL;<br>
+ virDomainPtr dom = NULL;<br>
+ int status;<br>
+<br>
+ if (cancelled)<br>
+ goto cleanup;<br>
+<br>
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);<br>
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
+ goto cleanup;<br>
+<br>
+ if (virTypedParamsGetString(params, nparams,<br>
+ VIR_MIGRATE_PARAM_DEST_NAME,<br>
+ &dname) < 0)<br>
+ goto cleanup;<br>
+<br>
+ if (!dname ||<br>
+ !(vm = virDomainObjListFindByName(driver->domains, dname))) {<br>
+ /* Migration obviously failed if the domain doesn't exist */<br>
+ virReportError(VIR_ERR_OPERATION_FAILED,<br>
+ _("Migration failed. No domain on destination host "<br>
+ "with matching name '%s'"),<br>
+ NULLSTR(dname));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
+ goto cleanup;<br>
+<br>
+ if (status != VIR_DOMAIN_RUNNING) {<br>
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",<br>
+ _("domain is not running on destination host"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ vm->def->id = strtoI(vm->def->name);<br>
+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_MIGRATED);<br>
+<br>
+ dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);<br>
+ if (dom)<br>
+ dom->id = vm->def->id;<br>
+<br>
+ cleanup:<br>
+ if (vm)<br>
+ virObjectUnlock(vm);<br>
+ return dom;<br>
+}<br>
+<br>
+static int<br>
+openvzDomainMigrateConfirm3Params(virDomainPtr domain,<br>
+ virTypedParameterPtr params,<br>
+ int nparams,<br>
+ const char *cookiein ATTRIBUTE_UNUSED,<br>
+ int cookieinlen ATTRIBUTE_UNUSED,<br>
+ unsigned int flags,<br>
+ int cancelled)<br>
+{<br>
+ struct openvz_driver *driver = domain->conn->privateData;<br>
+ virDomainObjPtr vm = NULL;<br>
+ int status;<br>
+ int ret = -1;<br>
+<br>
+ virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);<br>
+ if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)<br>
+ goto cleanup;<br>
+<br>
+ openvzDriverLock(driver);<br>
+ vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);<br>
+ openvzDriverUnlock(driver);<br>
+<br>
+ if (!vm) {<br>
+ virReportError(VIR_ERR_NO_DOMAIN, "%s",<br>
+ _("no domain with matching uuid"));<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ if (cancelled) {<br>
+ if (openvzGetVEStatus(vm, &status, NULL) == -1)<br>
+ goto cleanup;<br>
+<br>
+ if (status == VIR_DOMAIN_RUNNING) {<br>
+ ret = 0;<br>
+ } else {<br>
+ VIR_DEBUG("Domain '%s' does not recover after failed migration",<br>
+ vm->def->name);<br>
+ }<br>
+<br>
+ goto cleanup;<br>
+ }<br>
+<br>
+ vm->def->id = -1;<br>
+<br>
+ VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);<br>
+<br>
+ virDomainObjListRemove(driver->domains, vm);<br>
+ vm = NULL;<br>
+<br>
+ ret = 0;<br>
+<br>
+ cleanup:<br>
+ if (vm)<br>
+ virObjectUnlock(vm);<br>
+ return ret;<br>
+}<br>
+<br>
+<br>
static virDriver openvzDriver = {<br>
.no = VIR_DRV_OPENVZ,<br>
.name = "OPENVZ",<br>
@@ -2265,6 +2607,12 @@ static virDriver openvzDriver = {<br>
.connectIsAlive = openvzConnectIsAlive, /* 0.9.8 */<br>
.domainUpdateDeviceFlags = openvzDomainUpdateDeviceFlags, /* 0.9.13 */<br>
.domainGetHostname = openvzDomainGetHostname, /* 0.10.0 */<br>
+ .connectSupportsFeature = openvzConnectSupportsFeature, /* 1.2.8 */<br>
+ .domainMigrateBegin3Params = openvzDomainMigrateBegin3Params, /* 1.2.8 */<br>
+ .domainMigratePrepare3Params = openvzDomainMigratePrepare3Params, /* 1.2.8 */<br>
+ .domainMigratePerform3Params = openvzDomainMigratePerform3Params, /* 1.2.8 */<br>
+ .domainMigrateFinish3Params = openvzDomainMigrateFinish3Params, /* 1.2.8 */<br>
+ .domainMigrateConfirm3Params = openvzDomainMigrateConfirm3Params, /* 1.2.8 */<br>
};<br>
<br>
int openvzRegister(void)<br>
diff --git a/src/openvz/openvz_driver.h b/src/openvz/openvz_driver.h<br>
index b39e81c..0c7a070 100644<br>
--- a/src/openvz/openvz_driver.h<br>
+++ b/src/openvz/openvz_driver.h<br>
@@ -31,6 +31,16 @@<br>
<br>
# include "internal.h"<br>
<br>
+# define OPENVZ_MIGRATION_FLAGS \<br>
+ (VIR_MIGRATE_LIVE)<br>
+<br>
+/* All supported migration parameters and their types. */<br>
+# define OPENVZ_MIGRATION_PARAMETERS \<br>
+ VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \<br>
+ VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \<br>
+ VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \<br>
+ NULL<br>
+<br>
int openvzRegister(void);<br>
<br>
#endif<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.1<br>
<br>
</font></span></blockquote></div><br></div>