From: nshirokovskiy(a)virtuozzo.com <nshirokovskiy(a)virtuozzo.com>
Migration API has a lot of options. This patch intention is to provide
support for those options that can be trivially supported and give
estimation for other options support in this commit message.
I. Supported.
1. VIR_MIGRATE_COMPRESSED. Means 'use compression when migration domain
memory'. It is supported but quite uncommon way: vz migration demands that this
option should be set. This is due to vz is hardcoded to moving VMs memory using
compression. So anyone who wants to migrate vz domain should set this option
thus declaring it knows it uses compression.
Why bother? May be just support this option and ignore if it is not set or
don't support at all as we can't change behaviour in this aspect. Well I
believe that this option is, first, inherent to hypervisor implementation as
we have a task of moving domain memory to different place and, second, we have
a tradeoff here between cpu and network resources and some managment should
choose the stratery via this option. If we choose ignoring or unsupporting
implementation than this option has a too vague meaning. Let's go into more
detail.
First if we ignore situation where option is not set than we put user into
fallacy that vz hypervisor don't use compression and thus have lower cpu
usage. Second approach is to not support the option. The main reason not to
follow this way is that 'not supported and not set' is indistinguishable from
'supported and not set' and thus again fool the user.
2. VIR_MIGRATE_LIVE. Means 'don't pause domain before migration'.
Vz doesn give this option but we can emulate it easily making
pause/unpause in libvirt itself. However as this is rather
unnatural addon its implementation is delayed until futher
request. So this option is demanded.
One may be fooled by vz sdk flags of migration api: PVMT_HOT_MIGRATION(aka
live) and PVMT_WARM_MIGRATION(aka normal). Current implementation ignore these
flags and always use live migration.
3. VIR_MIGRATE_PERSIST_DEST, VIR_MIGRATE_UNDEFINE_SOURCE. This two comes
together. Vz domain are always persistent so we have to demand that options
VIR_MIGRATE_PERSIST_DEST and VIR_MIGRATE_UNDEFINE_SOURCE are both set.
4. VIR_MIGRATE_PAUSED. Means 'don't resume domain on destination'. This is
trivially supported as we have a corresponding option in vz migration.
5. VIR_MIGRATE_OFFLINE. Means 'migrate only XML definition of a domain'. It is
a forcing option that is it is ignored if domain is running and must be set
to migrate stopped domain. Vz implemenation follows this unformal definition
with one exception: non-shared disks will be migrated too. This desicion is on
par with VIR_MIGRATE_NON_SHARED_DISK condideration(see last part of this
notes).
All that said the minimal command to migrate vz domain looks like next:
migrate $DOMAIN $DESTINATION --compressed --live --persistent --undefinesource
Not good. Say if you want to just migrate a domain without further
details you will get error messages until you add these options to
command line. I think there is a lack of notion 'default' behaviour
in all these aspects. If we have it we could just issue:
migrate $DOMAIN $DESTINATION
For vz this would give default compression for example, for qemu - default
no-compression. Then we could have flags --compressed and -no-compressed
and for vz the latter would give unsupported error.
II. Unsupported.
1. VIR_MIGRATE_UNSAFE. Vz disks are always have 'cache=none' set (this
is not reflected in current version of vz driver and will be fixed
soon). So we need not to support this option.
2. VIR_MIGRATE_CHANGE_PROTECTION. Unsupported as we have no appopriate
support from vz sdk. Although we have locks they are advisory and
cant help us.
3. VIR_MIGRATE_TUNNELLED. Means 'use libvirtd to libvirtd connection
to pass hypervisor migration traffic'. Unsupported as not among
vz hypervisor usecases.
4. Direct migration. Which is exposed via *toURI* interface with
VIR_MIGRATE_PEER2PEER flag unset. Means 'migrate without using
libvirtd on the other side'. To support it we should add authN
means to vz driver as mentioned in 'backbone patch' which looks
ugly.
5. VIR_MIGRATE_ABORT_ON_ERROR, VIR_MIGRATE_AUTO_CONVERGE,
VIR_MIGRATE_RDMA_PIN_ALL, VIR_MIGRATE_NON_SHARED_INC,
VIR_MIGRATE_PARAM_DEST_XML, VIR_MIGRATE_PARAM_BANDWIDTH,
VIR_MIGRATE_PARAM_GRAPHICS_URI, VIR_MIGRATE_PARAM_LISTEN_ADDRESS,
VIR_MIGRATE_PARAM_MIGRATE_DISKS.
Without further discussion. They are just not usecases of vz hypevisor.
III. Incompatible options.
6. VIR_MIGRATE_NON_SHARED_DISK. Means 'force to migrate if domain has
non-shared disks'. Without this option we should refuse to migrate with
non-shared disks. Unfortunately this behaviour is incompatible with vz as vz
doesn't demand any user awareness of disk sharedness.
Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy(a)virtuozzo.com>
---
src/vz/vz_driver.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/vz/vz_sdk.c | 8 +++-
src/vz/vz_sdk.h | 3 +-
3 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c
index e9ca611..d708ca4 100644
--- a/src/vz/vz_driver.c
+++ b/src/vz/vz_driver.c
@@ -1394,7 +1394,14 @@ vzParseCookie(const char *xml, unsigned char *session_uuid)
return ret;
}
-#define VZ_MIGRATION_FLAGS (VIR_MIGRATE_PEER2PEER)
+#define VZ_MIGRATION_FLAGS \
+ (VIR_MIGRATE_PEER2PEER | \
+ VIR_MIGRATE_OFFLINE | \
+ VIR_MIGRATE_LIVE | \
+ VIR_MIGRATE_COMPRESSED | \
+ VIR_MIGRATE_PERSIST_DEST | \
+ VIR_MIGRATE_UNDEFINE_SOURCE | \
+ VIR_MIGRATE_PAUSED)
#define VZ_MIGRATION_PARAMETERS \
VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING, \
@@ -1522,6 +1529,82 @@ vzParseVzURI(const char *uri_str)
return uri;
}
+/* TODO this code should be in common place as these
+ rules follows from options (informal) definitions.
+ Qemu makes some of these checks on begin phase but not all. */
+int vzCheckOfflineFlags(int flags)
+{
+ if (!(flags & VIR_MIGRATE_OFFLINE)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ return -1;
+ }
+
+ if (flags & VIR_MIGRATE_LIVE) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("live offline migration does not "
+ "make sense"));
+ return -1;
+ }
+
+ if (flags & VIR_MIGRATE_COMPRESSED) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("compressed offline migration does not "
+ "make sense"));
+ return -1;
+ }
+
+ if (flags & VIR_MIGRATE_PAUSED) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("paused offline migration does not "
+ "make sense"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int vzCheckCommonFlags(int flags)
+{
+ virCheckFlags(VZ_MIGRATION_FLAGS, -1);
+
+ if (!(flags & VIR_MIGRATE_PERSIST_DEST)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("flags VIR_MIGRATE_PERSIST_DEST must be set"
+ " for vz migration"));
+ return -1;
+ }
+
+ if (!(flags & VIR_MIGRATE_UNDEFINE_SOURCE)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("flags VIR_MIGRATE_UNDEFINE_SOURCE must be set"
+ " for vz migration"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int vzCheckOnlineFlags(int flags)
+{
+
+ if (!(flags & VIR_MIGRATE_LIVE)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("flags VIR_MIGRATE_LIVE must be set"
+ " for online vz migration"));
+ return -1;
+ }
+
+ if (!(flags & VIR_MIGRATE_COMPRESSED)) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("flags VIR_MIGRATE_COMPRESSED must be set"
+ " for online vz migration"));
+ return -1;
+ }
+
+ return 0;
+}
+
static int
vzDomainMigratePerform3Params(virDomainPtr domain,
const char *dconnuri,
@@ -1533,7 +1616,7 @@ vzDomainMigratePerform3Params(virDomainPtr domain,
int *cookieoutlen ATTRIBUTE_UNUSED,
unsigned int flags)
{
- int ret = -1;
+ int ret = -1, tmpret;
virDomainObjPtr dom = NULL;
virConnectPtr dconn = NULL;
virURIPtr vzuri = NULL;
@@ -1544,7 +1627,8 @@ vzDomainMigratePerform3Params(virDomainPtr domain,
const char *miguri = NULL;
const char *dname = NULL;
- virCheckFlags(VZ_MIGRATION_FLAGS, -1);
+ if (vzCheckCommonFlags(flags))
+ goto cleanup;
if (virTypedParamsValidate(params, nparams, VZ_MIGRATION_PARAMETERS) < 0)
goto cleanup;
@@ -1557,6 +1641,14 @@ vzDomainMigratePerform3Params(virDomainPtr domain,
if (!(dom = vzDomObjFromDomain(domain)))
goto cleanup;
+ if (virDomainObjIsActive(dom))
+ tmpret = vzCheckOnlineFlags(flags);
+ else
+ tmpret = vzCheckOfflineFlags(flags);
+
+ if (tmpret < 0)
+ goto cleanup;
+
dconn = virConnectOpen(dconnuri);
if (dconn == NULL) {
virReportError(VIR_ERR_OPERATION_FAILED,
@@ -1586,7 +1678,7 @@ vzDomainMigratePerform3Params(virDomainPtr domain,
if (!(vzuri = vzParseVzURI(miguri)))
goto cleanup;
- if (prlsdkMigrate(dom, vzuri, session_uuid, dname) < 0)
+ if (prlsdkMigrate(dom, vzuri, session_uuid, dname, flags) < 0)
goto cleanup;
virDomainObjListRemove(privconn->domains, dom);
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
index 89a2429..9a2b5df 100644
--- a/src/vz/vz_sdk.c
+++ b/src/vz/vz_sdk.c
@@ -4065,18 +4065,22 @@ prlsdkGetMemoryStats(virDomainObjPtr dom,
int prlsdkMigrate(virDomainObjPtr dom, virURIPtr uri,
const unsigned char *session_uuid,
- const char *dname)
+ const char *dname, unsigned int flags)
{
int ret = -1;
vzDomObjPtr privdom = dom->privateData;
PRL_HANDLE job = PRL_INVALID_HANDLE;
char uuidstr[VIR_UUID_STRING_BUFLEN + 2];
+ PRL_UINT32 vzflags = PRLSDK_MIGRATION_FLAGS;
+
+ if (flags & VIR_MIGRATE_PAUSED)
+ vzflags |= PVMT_DONT_RESUME_VM;
prlsdkUUIDFormat(session_uuid, uuidstr);
job = PrlVm_MigrateWithRenameEx(privdom->sdkdom, uri->server, uri->port,
uuidstr,
dname == NULL ? "" : dname,
"", /* use default dir for migrated
instance bundle */
- PRLSDK_MIGRATION_FLAGS,
+ vzflags,
0, /* reserved flags */
PRL_TRUE /* don't ask for confirmations */
);
diff --git a/src/vz/vz_sdk.h b/src/vz/vz_sdk.h
index 0aa70b3..5b26b70 100644
--- a/src/vz/vz_sdk.h
+++ b/src/vz/vz_sdk.h
@@ -80,4 +80,5 @@ int
prlsdkMigrate(virDomainObjPtr dom,
virURIPtr uri,
const char unsigned *session_uuid,
- const char *dname);
+ const char *dname,
+ unsigned int flags);
--
1.7.1