add migration support for OpenVZ driver

This patch adds initial migration support to the OpenVZ driver,
using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration
functions.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Hongbin Lu 2014-09-04 22:25:06 -04:00 committed by Michal Privoznik
parent d00c6fd258
commit 7e649c5450
3 changed files with 362 additions and 3 deletions

View File

@ -35,9 +35,10 @@
/* OpenVZ commands - Replace with wrapper scripts later? */
# define VZLIST "/usr/sbin/vzlist"
# define VZCTL "/usr/sbin/vzctl"
# define VZ_CONF_FILE "/etc/vz/vz.conf"
# define VZLIST "/usr/sbin/vzlist"
# define VZCTL "/usr/sbin/vzctl"
# define VZMIGRATE "/usr/sbin/vzmigrate"
# define VZ_CONF_FILE "/etc/vz/vz.conf"
# define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)

View File

@ -2207,6 +2207,348 @@ openvzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
}
static int
openvzConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
{
switch (feature) {
case VIR_DRV_FEATURE_MIGRATION_PARAMS:
case VIR_DRV_FEATURE_MIGRATION_V3:
return 1;
default:
return 0;
}
}
static char *
openvzDomainMigrateBegin3Params(virDomainPtr domain,
virTypedParameterPtr params,
int nparams,
char **cookieout ATTRIBUTE_UNUSED,
int *cookieoutlen ATTRIBUTE_UNUSED,
unsigned int flags)
{
virDomainObjPtr vm = NULL;
struct openvz_driver *driver = domain->conn->privateData;
char *xml = NULL;
int status;
virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);
if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
return NULL;
openvzDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
openvzDriverUnlock(driver);
if (!vm) {
virReportError(VIR_ERR_NO_DOMAIN, "%s",
_("no domain with matching uuid"));
goto cleanup;
}
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto cleanup;
}
if (openvzGetVEStatus(vm, &status, NULL) == -1)
goto cleanup;
if (status != VIR_DOMAIN_RUNNING) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain is not in running state"));
goto cleanup;
}
xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE);
cleanup:
if (vm)
virObjectUnlock(vm);
return xml;
}
static int
openvzDomainMigratePrepare3Params(virConnectPtr dconn,
virTypedParameterPtr params,
int nparams,
const char *cookiein ATTRIBUTE_UNUSED,
int cookieinlen ATTRIBUTE_UNUSED,
char **cookieout ATTRIBUTE_UNUSED,
int *cookieoutlen ATTRIBUTE_UNUSED,
char **uri_out,
unsigned int fflags ATTRIBUTE_UNUSED)
{
struct openvz_driver *driver = dconn->privateData;
const char *dom_xml = NULL;
const char *uri_in = NULL;
virDomainDefPtr def = NULL;
virDomainObjPtr vm = NULL;
char *hostname = NULL;
virURIPtr uri = NULL;
int ret = -1;
if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
goto error;
if (virTypedParamsGetString(params, nparams,
VIR_MIGRATE_PARAM_DEST_XML,
&dom_xml) < 0 ||
virTypedParamsGetString(params, nparams,
VIR_MIGRATE_PARAM_URI,
&uri_in) < 0)
goto error;
if (!dom_xml) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("no domain XML passed"));
goto error;
}
if (!(def = virDomainDefParseString(dom_xml, driver->caps, driver->xmlopt,
1 << VIR_DOMAIN_VIRT_OPENVZ,
VIR_DOMAIN_XML_INACTIVE)))
goto error;
if (!(vm = virDomainObjListAdd(driver->domains, def,
driver->xmlopt,
VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
NULL)))
goto error;
def = NULL;
if (!uri_in) {
if ((hostname = virGetHostname()) == NULL)
goto error;
if (STRPREFIX(hostname, "localhost")) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("hostname on destination resolved to localhost,"
" but migration requires an FQDN"));
goto error;
}
} else {
uri = virURIParse(uri_in);
if (uri == NULL) {
virReportError(VIR_ERR_INVALID_ARG,
_("unable to parse URI: %s"),
uri_in);
goto error;
}
if (uri->server == NULL) {
virReportError(VIR_ERR_INVALID_ARG,
_("missing host in migration URI: %s"),
uri_in);
goto error;
} else {
hostname = uri->server;
}
}
if (virAsprintf(uri_out, "ssh://%s", hostname) < 0)
goto error;
ret = 0;
goto done;
error:
virDomainDefFree(def);
if (vm) {
virDomainObjListRemove(driver->domains, vm);
vm = NULL;
}
done:
virURIFree(uri);
if (vm)
virObjectUnlock(vm);
return ret;
}
static int
openvzDomainMigratePerform3Params(virDomainPtr domain,
const char *dconnuri ATTRIBUTE_UNUSED,
virTypedParameterPtr params,
int nparams,
const char *cookiein ATTRIBUTE_UNUSED,
int cookieinlen ATTRIBUTE_UNUSED,
char **cookieout ATTRIBUTE_UNUSED,
int *cookieoutlen ATTRIBUTE_UNUSED,
unsigned int flags)
{
struct openvz_driver *driver = domain->conn->privateData;
virDomainObjPtr vm = NULL;
const char *uri_str = NULL;
virURIPtr uri = NULL;
virCommandPtr cmd = virCommandNew(VZMIGRATE);
int ret = -1;
virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);
if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
goto cleanup;
if (virTypedParamsGetString(params, nparams,
VIR_MIGRATE_PARAM_URI,
&uri_str) < 0)
goto cleanup;
openvzDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
openvzDriverUnlock(driver);
if (!vm) {
virReportError(VIR_ERR_NO_DOMAIN, "%s",
_("no domain with matching uuid"));
goto cleanup;
}
/* parse dst host:port from uri */
uri = virURIParse(uri_str);
if (uri == NULL || uri->server == NULL)
goto cleanup;
if (flags & VIR_MIGRATE_LIVE)
virCommandAddArg(cmd, "--live");
virCommandAddArg(cmd, uri->server);
virCommandAddArg(cmd, vm->def->name);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
ret = 0;
cleanup:
virCommandFree(cmd);
virURIFree(uri);
if (vm)
virObjectUnlock(vm);
return ret;
}
static virDomainPtr
openvzDomainMigrateFinish3Params(virConnectPtr dconn,
virTypedParameterPtr params,
int nparams,
const char *cookiein ATTRIBUTE_UNUSED,
int cookieinlen ATTRIBUTE_UNUSED,
char **cookieout ATTRIBUTE_UNUSED,
int *cookieoutlen ATTRIBUTE_UNUSED,
unsigned int flags,
int cancelled)
{
struct openvz_driver *driver = dconn->privateData;
virDomainObjPtr vm = NULL;
const char *dname = NULL;
virDomainPtr dom = NULL;
int status;
if (cancelled)
goto cleanup;
virCheckFlags(OPENVZ_MIGRATION_FLAGS, NULL);
if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
goto cleanup;
if (virTypedParamsGetString(params, nparams,
VIR_MIGRATE_PARAM_DEST_NAME,
&dname) < 0)
goto cleanup;
if (!dname ||
!(vm = virDomainObjListFindByName(driver->domains, dname))) {
/* Migration obviously failed if the domain doesn't exist */
virReportError(VIR_ERR_OPERATION_FAILED,
_("Migration failed. No domain on destination host "
"with matching name '%s'"),
NULLSTR(dname));
goto cleanup;
}
if (openvzGetVEStatus(vm, &status, NULL) == -1)
goto cleanup;
if (status != VIR_DOMAIN_RUNNING) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain is not running on destination host"));
goto cleanup;
}
vm->def->id = strtoI(vm->def->name);
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_MIGRATED);
dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
if (dom)
dom->id = vm->def->id;
cleanup:
if (vm)
virObjectUnlock(vm);
return dom;
}
static int
openvzDomainMigrateConfirm3Params(virDomainPtr domain,
virTypedParameterPtr params,
int nparams,
const char *cookiein ATTRIBUTE_UNUSED,
int cookieinlen ATTRIBUTE_UNUSED,
unsigned int flags,
int cancelled)
{
struct openvz_driver *driver = domain->conn->privateData;
virDomainObjPtr vm = NULL;
int status;
int ret = -1;
virCheckFlags(OPENVZ_MIGRATION_FLAGS, -1);
if (virTypedParamsValidate(params, nparams, OPENVZ_MIGRATION_PARAMETERS) < 0)
goto cleanup;
openvzDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, domain->uuid);
openvzDriverUnlock(driver);
if (!vm) {
virReportError(VIR_ERR_NO_DOMAIN, "%s",
_("no domain with matching uuid"));
goto cleanup;
}
if (cancelled) {
if (openvzGetVEStatus(vm, &status, NULL) == -1)
goto cleanup;
if (status == VIR_DOMAIN_RUNNING) {
ret = 0;
} else {
VIR_DEBUG("Domain '%s' does not recover after failed migration",
vm->def->name);
}
goto cleanup;
}
vm->def->id = -1;
VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);
virDomainObjListRemove(driver->domains, vm);
vm = NULL;
ret = 0;
cleanup:
if (vm)
virObjectUnlock(vm);
return ret;
}
static virDriver openvzDriver = {
.no = VIR_DRV_OPENVZ,
.name = "OPENVZ",
@ -2265,6 +2607,12 @@ static virDriver openvzDriver = {
.connectIsAlive = openvzConnectIsAlive, /* 0.9.8 */
.domainUpdateDeviceFlags = openvzDomainUpdateDeviceFlags, /* 0.9.13 */
.domainGetHostname = openvzDomainGetHostname, /* 0.10.0 */
.connectSupportsFeature = openvzConnectSupportsFeature, /* 1.2.8 */
.domainMigrateBegin3Params = openvzDomainMigrateBegin3Params, /* 1.2.8 */
.domainMigratePrepare3Params = openvzDomainMigratePrepare3Params, /* 1.2.8 */
.domainMigratePerform3Params = openvzDomainMigratePerform3Params, /* 1.2.8 */
.domainMigrateFinish3Params = openvzDomainMigrateFinish3Params, /* 1.2.8 */
.domainMigrateConfirm3Params = openvzDomainMigrateConfirm3Params, /* 1.2.8 */
};
int openvzRegister(void)

View File

@ -31,6 +31,16 @@
# include "internal.h"
# define OPENVZ_MIGRATION_FLAGS \
(VIR_MIGRATE_LIVE)
/* All supported migration parameters and their types. */
# define OPENVZ_MIGRATION_PARAMETERS \
VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING, \
VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING, \
NULL
int openvzRegister(void);
#endif