[libvirt] [PATCH] tests: don't fail with newer gnutls
by Martin Kletzander
gnutls-3.3.0 and newer leaves 2 FDs open in order to be backwards
compatible when it comes to chrooted binaries [1]. Linking
commandhelper with gnutls then leaves these two FDs open and
commandtest fails thanks to that. This patch does not link
commandhelper with libvirt.la, but rather only the utilities making
the test pass.
Based on suggestion from Daniel [2].
[1] http://lists.gnutls.org/pipermail/gnutls-help/2014-April/003429.html
[2] https://www.redhat.com/archives/libvir-list/2014-April/msg01119.html
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
Notes:
Pushed as a 'build-breaker'.
tests/Makefile.am | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4a5e14b..7ffb44e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -782,7 +782,13 @@ commandtest_LDADD = $(LDADDS)
commandhelper_SOURCES = \
commandhelper.c
-commandhelper_LDADD = $(LDADDS)
+commandhelper_LDADD = \
+ $(WARN_CFLAGS) \
+ $(NO_INDIRECT_LDFLAGS) \
+ $(PROBES_O) \
+ ../src/libvirt_util.la \
+ $(GNULIB_LIBS)
+
commandhelper_LDFLAGS = -static
virnetdevbandwidthtest_SOURCES = \
--
1.9.2
10 years, 6 months
[libvirt] [PATCH] fix build with older gcc
by Ján Tomko
Older gcc (4.1.2-55.el5, 4.2.1 on FreeBSD) reports bogus warnings:
../../src/conf/nwfilter_conf.c:2111: warning: 'protocol' may be used
uninitialized in this function
../../src/conf/nwfilter_conf.c:2110: warning: 'dataProtocolID' may be
used uninitialized in this function
Initialize them to NULL to make the compiler happy.
---
Pushed as a build-breaker fix.
src/conf/nwfilter_conf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index 67b5482..b9f6d51 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -2107,8 +2107,8 @@ virNWFilterRuleValidate(virNWFilterRuleDefPtr rule)
{
int ret = 0;
portDataDefPtr portData = NULL;
- nwItemDescPtr dataProtocolID;
- const char *protocol;
+ nwItemDescPtr dataProtocolID = NULL;
+ const char *protocol = NULL;
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_IP:
--
1.8.3.2
10 years, 6 months
[libvirt] Libvirt API
by Vikas Kokare
We are seeing issues(data is unavailable) with usage of the following
Libvirt APIs, on RHEL5, while they are working Ok with RHEL 6, SLES10/11.
CPU dumpxml from Domain.getXMLDesc() returns no xml nodes for CPU model and
topology and its sub-elements such as sockets, cores, threads.
Domain.memoryStats(int) : added since 0.5.0
Please guide.
10 years, 6 months
[libvirt] Test failures with newest gnutls
by Martin Kletzander
Hi everyone,
after upgrade to gnutls-3.3.0, I discovered (commandtest fails) that
any code linked with -lgnutls will have not 3, but 5 open file
descriptors upon the entry into main(). I asked on gnutls-help [1] if
they know they are leaking file descriptors. The response was, that
this is intended with the explanation being that these FDs (pointing
to /dev/urandom) are kept open for backward compatibility with
programs that may chroot into environment without /dev/urandom as the
previous version didn't require to have access to /dev/urandom when
calling gnutls code.
Does that seem like our bug that we're relying on fixed number of open
file descriptors? Or that we're linking to gnutls when we don't need
it in commandhelper? Or should this be fixed somewhere else?
Have a nice day,
Martin
[1] http://lists.gnutls.org/pipermail/gnutls-help/2014-April/003415.html
10 years, 6 months
[libvirt] [PATCH] php: implement libvirt_node_get_free_memory.
by Dawid Zamirski
This patch adds support for virNodeGetFreeMemory which is available in
libvirt since v0.3.3. While the php bindings alredy provide
libvirt_node_get_mem_stats from which such info could be obtained, not
all hypervisors support it, e.g. vbox and esx driver don't have it but
they do implement virNodeGetFreeMemory.
Since virNodeGetFreeMemory returns free bytes as unsigned long long
which PHP cannot handle, I've added LONGLONG_RETURN_AS_STRING macro
which returns the amount bytes as a string - similarly to how bcmath
handles such numbers.
---
src/libvirt-php.c | 30 ++++++++++++++++++++++++++++++
src/libvirt-php.h | 1 +
2 files changed, 31 insertions(+)
diff --git a/src/libvirt-php.c b/src/libvirt-php.c
index 07ae137..94a0c6b 100644
--- a/src/libvirt-php.c
+++ b/src/libvirt-php.c
@@ -198,6 +198,7 @@ static zend_function_entry libvirt_functions[] = {
PHP_FE(libvirt_node_get_cpu_stats, NULL)
PHP_FE(libvirt_node_get_cpu_stats_for_each_cpu, NULL)
PHP_FE(libvirt_node_get_mem_stats, NULL)
+ PHP_FE(libvirt_node_get_free_memory, NULL)
/* Nodedev functions */
PHP_FE(libvirt_nodedev_get, NULL)
PHP_FE(libvirt_nodedev_capabilities, NULL)
@@ -1428,6 +1429,11 @@ str_out = estrndup(str_in, strlen(str_in)); \
add_index_long(out, key,in); \
}
+#define LONGLONG_RETURN_AS_STRING(in) \
+ snprintf(tmpnumber, 63, "%llu", in); \
+ RETURN_STRING(tmpnumber, 1);
+
+
/* Authentication callback function. Should receive list of credentials via cbdata and pass the requested one to libvirt */
static int libvirt_virConnectAuthCallback(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
{
@@ -1889,6 +1895,30 @@ PHP_FUNCTION(libvirt_node_get_mem_stats)
}
#endif
+/*
+ Function name: libvirt_node_get_free_memory
+ Since version: 0.5.1
+ Description: Function is used to get free memory available on the node.
+ Arguments: @conn [resource]: resource for connection.
+ Returns: the available free memery in bytes as string or FALSE for error.
+*/
+PHP_FUNCTION(libvirt_node_get_free_memory)
+{
+ php_libvirt_connection *conn = NULL;
+ zval *zconn;
+ unsigned long long ret;
+ LONGLONG_INIT
+
+ GET_CONNECTION_FROM_ARGS("r", &zconn);
+
+ if ((ret = virNodeGetFreeMemory(conn->conn)) != 0) {
+ LONGLONG_RETURN_AS_STRING(ret);
+ } else {
+ set_error("Cannot get the free memory for the node" TSRMLS_CC);
+ RETURN_FALSE
+ }
+}
+
//virsh capabilities | xpath '//capabilities/guest/arch[@name="x86_64"]/machine[@maxCpus=1]'
/*
diff --git a/src/libvirt-php.h b/src/libvirt-php.h
index 450fbea..737c47d 100644
--- a/src/libvirt-php.h
+++ b/src/libvirt-php.h
@@ -347,6 +347,7 @@ PHP_FUNCTION(libvirt_node_get_info);
PHP_FUNCTION(libvirt_node_get_cpu_stats);
PHP_FUNCTION(libvirt_node_get_cpu_stats_for_each_cpu);
PHP_FUNCTION(libvirt_node_get_mem_stats);
+PHP_FUNCTION(libvirt_node_get_free_memory);
/* Domain functions */
PHP_FUNCTION(libvirt_domain_new);
PHP_FUNCTION(libvirt_domain_new_get_vnc);
--
1.9.0
10 years, 6 months
[libvirt] [PATCH] Misc error reporting bugs in QEMU cli builder
by Daniel P. Berrange
A couple of places in the QEMU XML -> ARGV conversion code
raised an error but then forgot to return an error status
due to missing gotos. While fixing this also tweak style
of a couple of other error reports
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/qemu/qemu_command.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 961c679..96072cf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8153,7 +8153,8 @@ qemuBuildCommandLine(virConnectPtr conn,
is to raise an error if present="yes" */
if (def->clock.timers[i]->present == 1) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- "%s", _("pit timer is not supported"));
+ "%s", _("hpet timer is not supported"));
+ goto error;
}
}
break;
@@ -8197,7 +8198,7 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->pm.s4) {
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DISABLE_S4)) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
"%s", _("setting ACPI S4 not supported"));
goto error;
}
@@ -8669,6 +8670,7 @@ qemuBuildCommandLine(virConnectPtr conn,
} else if (disk->src.type == VIR_STORAGE_TYPE_NETWORK) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("network disks are only supported with -drive"));
+ goto error;
} else {
if (VIR_STRDUP(file, disk->src.path) < 0) {
goto error;
@@ -10451,7 +10453,7 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr xmlopt,
_("invalid device name '%s'"), def->dst);
virDomainDiskDefFree(def);
def = NULL;
- /* fall through to "cleanup" */
+ goto cleanup;
}
cleanup:
--
1.9.0
10 years, 6 months
[libvirt] Reg : failing to attach iscsi disk from virsh to running VM on xen
by Prapulla Kumar
Hi,
I'm using libvirt 1.2.3 and xen 4.3.1
I'm trying to attach a volume to VM which is running on xen.
While attaching it is giving error at libvirtd log is
* error : libxlDomainAttachDeviceDiskLive:2567 : unsupported configuration:
disk bus 'scsi' cannot be hotplugged.*
can you suggest any configuration need to hotplug the device to attach to vm
With Regards
Prapulla Kumar R
10 years, 6 months
[libvirt] [PATCH V6] libxl: add migration support
by Jim Fehlig
This patch adds initial migration support to the libxl driver,
using the VIR_DRV_FEATURE_MIGRATION_PARAMS family of migration
functions.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
V5 here
https://www.redhat.com/archives/libvir-list/2014-April/msg01123.html
In V6:
Change receive migration args to a virObject so it can be ref conunted
and properly freed only when all users are done with it.
po/POTFILES.in | 1 +
src/Makefile.am | 3 +-
src/libxl/libxl_conf.h | 6 +
src/libxl/libxl_domain.h | 1 +
src/libxl/libxl_driver.c | 235 ++++++++++++++++++
src/libxl/libxl_migration.c | 577 ++++++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_migration.h | 78 ++++++
7 files changed, 900 insertions(+), 1 deletion(-)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e35eb82..a72dc1e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -73,6 +73,7 @@ src/lxc/lxc_process.c
src/libxl/libxl_domain.c
src/libxl/libxl_driver.c
src/libxl/libxl_conf.c
+src/libxl/libxl_migration.c
src/network/bridge_driver.c
src/network/bridge_driver_linux.c
src/node_device/node_device_driver.c
diff --git a/src/Makefile.am b/src/Makefile.am
index e9dc9e0..0dbda7f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -706,7 +706,8 @@ XENAPI_DRIVER_SOURCES = \
LIBXL_DRIVER_SOURCES = \
libxl/libxl_conf.c libxl/libxl_conf.h \
libxl/libxl_domain.c libxl/libxl_domain.h \
- libxl/libxl_driver.c libxl/libxl_driver.h
+ libxl/libxl_driver.c libxl/libxl_driver.h \
+ libxl/libxl_migration.c libxl/libxl_migration.h
UML_DRIVER_SOURCES = \
uml/uml_conf.c uml/uml_conf.h \
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 24e1720..b798567 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -43,6 +43,9 @@
# define LIBXL_VNC_PORT_MIN 5900
# define LIBXL_VNC_PORT_MAX 65535
+# define LIBXL_MIGRATION_PORT_MIN 49152
+# define LIBXL_MIGRATION_PORT_MAX 49216
+
# define LIBXL_CONFIG_DIR SYSCONFDIR "/libvirt/libxl"
# define LIBXL_AUTOSTART_DIR LIBXL_CONFIG_DIR "/autostart"
# define LIBXL_STATE_DIR LOCALSTATEDIR "/run/libvirt/libxl"
@@ -115,6 +118,9 @@ struct _libxlDriverPrivate {
/* Immutable pointer, self-locking APIs */
virPortAllocatorPtr reservedVNCPorts;
+ /* Immutable pointer, self-locking APIs */
+ virPortAllocatorPtr migrationPorts;
+
/* Immutable pointer, lockless APIs*/
virSysinfoDefPtr hostsysinfo;
};
diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h
index 979ce2a..9d48049 100644
--- a/src/libxl/libxl_domain.h
+++ b/src/libxl/libxl_domain.h
@@ -69,6 +69,7 @@ struct _libxlDomainObjPrivate {
virChrdevsPtr devs;
libxl_evgen_domain_death *deathW;
libxlDriverPrivatePtr driver;
+ unsigned short migrationPort;
struct libxlDomainJobObj job;
};
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index dcc3ac2..77f860c 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -45,6 +45,7 @@
#include "libxl_domain.h"
#include "libxl_driver.h"
#include "libxl_conf.h"
+#include "libxl_migration.h"
#include "xen_xm.h"
#include "xen_sxpr.h"
#include "virtypedparam.h"
@@ -209,6 +210,7 @@ libxlStateCleanup(void)
virObjectUnref(libxl_driver->xmlopt);
virObjectUnref(libxl_driver->domains);
virObjectUnref(libxl_driver->reservedVNCPorts);
+ virObjectUnref(libxl_driver->migrationPorts);
virObjectEventStateFree(libxl_driver->domainEventState);
virSysinfoDefFree(libxl_driver->hostsysinfo);
@@ -301,6 +303,13 @@ libxlStateInitialize(bool privileged,
LIBXL_VNC_PORT_MAX)))
goto error;
+ /* Allocate bitmap for migration port reservation */
+ if (!(libxl_driver->migrationPorts =
+ virPortAllocatorNew(_("migration"),
+ LIBXL_MIGRATION_PORT_MIN,
+ LIBXL_MIGRATION_PORT_MAX)))
+ goto error;
+
if (!(libxl_driver->domains = virDomainObjListNew()))
goto error;
@@ -4131,6 +4140,7 @@ libxlConnectSupportsFeature(virConnectPtr conn, int feature)
switch (feature) {
case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
+ case VIR_DRV_FEATURE_MIGRATION_PARAMS:
return 1;
default:
return 0;
@@ -4309,6 +4319,226 @@ libxlNodeDeviceReset(virNodeDevicePtr dev)
return ret;
}
+static char *
+libxlDomainMigrateBegin3Params(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int nparams,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ const char *xmlin = NULL;
+ virDomainObjPtr vm = NULL;
+
+ virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
+ if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
+ return NULL;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_XML,
+ &xmlin) < 0)
+ return NULL;
+
+ if (!(vm = libxlDomObjFromDomain(domain)))
+ return NULL;
+
+ if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
+ virObjectUnlock(vm);
+ return NULL;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ virObjectUnlock(vm);
+ return NULL;
+ }
+
+ return libxlDomainMigrationBegin(domain->conn, vm, xmlin);
+}
+
+static int
+libxlDomainMigratePrepare3Params(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 flags)
+{
+ libxlDriverPrivatePtr driver = dconn->privateData;
+ virDomainDefPtr def = NULL;
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
+ const char *uri_in = NULL;
+
+ virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+ if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
+ goto error;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_XML,
+ &dom_xml) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME,
+ &dname) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_URI,
+ &uri_in) < 0)
+
+ goto error;
+
+ if (!(def = libxlDomainMigrationPrepareDef(driver, dom_xml, dname)))
+ goto error;
+
+ if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
+ goto error;
+
+ if (libxlDomainMigrationPrepare(dconn, def, uri_in, uri_out) < 0)
+ goto error;
+
+ return 0;
+
+ error:
+ virDomainDefFree(def);
+ return -1;
+}
+
+static int
+libxlDomainMigratePerform3Params(virDomainPtr dom,
+ const char *dconnuri,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ char **cookieout ATTRIBUTE_UNUSED,
+ int *cookieoutlen ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ libxlDriverPrivatePtr driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ const char *dom_xml = NULL;
+ const char *dname = NULL;
+ const char *uri = NULL;
+ int ret = -1;
+
+ virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+ if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
+ goto cleanup;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_XML,
+ &dom_xml) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME,
+ &dname) < 0 ||
+ virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_URI,
+ &uri) < 0)
+
+ goto cleanup;
+
+ if (!(vm = libxlDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
+ uri, dname, flags) < 0) {
+ /* Job terminated and vm unlocked if MigrationPerform failed */
+ vm = NULL;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+static virDomainPtr
+libxlDomainMigrateFinish3Params(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)
+{
+ libxlDriverPrivatePtr driver = dconn->privateData;
+ virDomainObjPtr vm = NULL;
+ const char *dname = NULL;
+
+ virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
+ if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
+ return NULL;
+
+ if (virTypedParamsGetString(params, nparams,
+ VIR_MIGRATE_PARAM_DEST_NAME,
+ &dname) < 0)
+ return NULL;
+
+ 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));
+ return NULL;
+ }
+
+ if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
+ virObjectUnlock(vm);
+ return NULL;
+ }
+
+ if (!virDomainObjIsActive(vm)) {
+ /* Migration failed if domain is inactive */
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ "%s", _("Migration failed. Domain is not running "
+ "on destination host"));
+ virObjectUnlock(vm);
+ return NULL;
+ }
+
+ return libxlDomainMigrationFinish(dconn, vm, flags, cancelled);
+}
+
+static int
+libxlDomainMigrateConfirm3Params(virDomainPtr domain,
+ virTypedParameterPtr params,
+ int nparams,
+ const char *cookiein ATTRIBUTE_UNUSED,
+ int cookieinlen ATTRIBUTE_UNUSED,
+ unsigned int flags,
+ int cancelled)
+{
+ libxlDriverPrivatePtr driver = domain->conn->privateData;
+ virDomainObjPtr vm = NULL;
+
+ virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
+ if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
+ return -1;
+
+ if (!(vm = libxlDomObjFromDomain(domain)))
+ return -1;
+
+ if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
+ virObjectUnlock(vm);
+ return -1;
+ }
+
+ return libxlDomainMigrationConfirm(driver, vm, flags, cancelled);
+}
+
static virDriver libxlDriver = {
.no = VIR_DRV_LIBXL,
@@ -4399,6 +4629,11 @@ static virDriver libxlDriver = {
.nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
.nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
.nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
+ .domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.3 */
+ .domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.3 */
+ .domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.3 */
+ .domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.3 */
+ .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.3 */
};
static virStateDriver libxlStateDriver = {
diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
new file mode 100644
index 0000000..d2dd94a
--- /dev/null
+++ b/src/libxl/libxl_migration.c
@@ -0,0 +1,577 @@
+/*
+ * libxl_migration.c: methods for handling migration with libxenlight
+ *
+ * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Jim Fehlig <jfehlig(a)suse.com>
+ * Chunyan Liu <cyliu(a)suse.com>
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virlog.h"
+#include "virerror.h"
+#include "virconf.h"
+#include "datatypes.h"
+#include "virfile.h"
+#include "viralloc.h"
+#include "viruuid.h"
+#include "vircommand.h"
+#include "virstring.h"
+#include "virobject.h"
+#include "rpc/virnetsocket.h"
+#include "libxl_domain.h"
+#include "libxl_driver.h"
+#include "libxl_conf.h"
+#include "libxl_migration.h"
+
+#define VIR_FROM_THIS VIR_FROM_LIBXL
+
+VIR_LOG_INIT("libxl.libxl_migration");
+
+typedef struct _libxlMigrationDstArgs {
+ virObject parent;
+
+ virConnectPtr conn;
+ virDomainObjPtr vm;
+
+ /* for freeing listen sockets */
+ virNetSocketPtr *socks;
+ size_t nsocks;
+} libxlMigrationDstArgs;
+
+static virClassPtr libxlMigrationDstArgsClass;
+
+static void
+libxlMigrationDstArgsDispose(void *obj)
+{
+ libxlMigrationDstArgs *args = obj;
+
+ VIR_FREE(args->socks);
+}
+
+static int
+libxlMigrationDstArgsOnceInit(void)
+{
+ if (!(libxlMigrationDstArgsClass = virClassNew(virClassForObject(),
+ "libxlMigrationDstArgs",
+ sizeof(libxlMigrationDstArgs),
+ libxlMigrationDstArgsDispose)))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(libxlMigrationDstArgs)
+
+static void
+libxlDoMigrateReceive(virNetSocketPtr sock,
+ int events ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ libxlMigrationDstArgs *args = opaque;
+ virConnectPtr conn = args->conn;
+ virDomainObjPtr vm = args->vm;
+ virNetSocketPtr *socks = args->socks;
+ size_t nsocks = args->nsocks;
+ libxlDriverPrivatePtr driver = conn->privateData;
+ virNetSocketPtr client_sock;
+ int recvfd = -1;
+ size_t i;
+ int ret;
+
+ virNetSocketAccept(sock, &client_sock);
+ if (client_sock == NULL) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Fail to accept migration connection"));
+ goto cleanup;
+ }
+ VIR_DEBUG("Accepted migration connection\n");
+ recvfd = virNetSocketDupFD(client_sock, true);
+ virObjectUnref(client_sock);
+
+ virObjectLock(vm);
+ ret = libxlDomainStart(driver, vm, false, recvfd);
+ virObjectUnlock(vm);
+
+ if (ret < 0 && !vm->persistent)
+ virDomainObjListRemove(driver->domains, vm);
+
+ cleanup:
+ /* Remove all listen socks from event handler, and close them. */
+ for (i = 0; i < nsocks; i++) {
+ virNetSocketUpdateIOCallback(socks[i], 0);
+ virNetSocketRemoveIOCallback(socks[i]);
+ virNetSocketClose(socks[i]);
+ virObjectUnref(socks[i]);
+ }
+
+ VIR_FORCE_CLOSE(recvfd);
+}
+
+static int
+libxlDoMigrateSend(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ unsigned long flags,
+ int sockfd)
+{
+ libxlDomainObjPrivatePtr priv;
+ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
+ virObjectEventPtr event = NULL;
+ int xl_flags = 0;
+ int ret;
+
+ if (flags & VIR_MIGRATE_LIVE)
+ xl_flags = LIBXL_SUSPEND_LIVE;
+
+ priv = vm->privateData;
+ ret = libxl_domain_suspend(priv->ctx, vm->def->id, sockfd,
+ xl_flags, NULL);
+ if (ret != 0) {
+ /* attempt to resume the domain on failure */
+ if (libxl_domain_resume(priv->ctx, vm->def->id, 0, 0) != 0) {
+ VIR_DEBUG("Failed to resume domain following failed migration");
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
+ VIR_DOMAIN_PAUSED_MIGRATION);
+ event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
+ ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm));
+ }
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to send migration data to destination host"));
+ ret = -1;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (event)
+ libxlDomainEventQueue(driver, event);
+ virObjectUnref(cfg);
+ return ret;
+}
+
+static bool
+libxlDomainMigrationIsAllowed(virDomainDefPtr def)
+{
+ /* Migration is not allowed if definition contains any hostdevs */
+ if (def->nhostdevs > 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("domain has assigned host devices"));
+ return false;
+ }
+
+ return true;
+}
+
+char *
+libxlDomainMigrationBegin(virConnectPtr conn,
+ virDomainObjPtr vm,
+ const char *xmlin)
+{
+ libxlDriverPrivatePtr driver = conn->privateData;
+ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
+ virDomainDefPtr tmpdef = NULL;
+ virDomainDefPtr def;
+ char *xml = NULL;
+
+ if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (xmlin) {
+ if (!(tmpdef = virDomainDefParseString(xmlin, cfg->caps,
+ driver->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_XEN,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto endjob;
+
+ def = tmpdef;
+ } else {
+ def = vm->def;
+ }
+
+ if (!libxlDomainMigrationIsAllowed(def))
+ goto endjob;
+
+ xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE);
+
+ cleanup:
+ if (vm)
+ virObjectUnlock(vm);
+
+ virDomainDefFree(tmpdef);
+ virObjectUnref(cfg);
+ return xml;
+
+ endjob:
+ if (!libxlDomainObjEndJob(driver, vm))
+ vm = NULL;
+ goto cleanup;
+}
+
+virDomainDefPtr
+libxlDomainMigrationPrepareDef(libxlDriverPrivatePtr driver,
+ const char *dom_xml,
+ const char *dname)
+{
+ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
+ virDomainDefPtr def;
+ char *name = NULL;
+
+ if (!dom_xml) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("no domain XML passed"));
+ return NULL;
+ }
+
+ if (!(def = virDomainDefParseString(dom_xml, cfg->caps, driver->xmlopt,
+ 1 << VIR_DOMAIN_VIRT_XEN,
+ VIR_DOMAIN_XML_INACTIVE)))
+ goto cleanup;
+
+ if (dname) {
+ name = def->name;
+ if (VIR_STRDUP(def->name, dname) < 0) {
+ virDomainDefFree(def);
+ def = NULL;
+ }
+ }
+
+ cleanup:
+ virObjectUnref(cfg);
+ VIR_FREE(name);
+ return def;
+}
+
+int
+libxlDomainMigrationPrepare(virConnectPtr dconn,
+ virDomainDefPtr def,
+ const char *uri_in,
+ char **uri_out)
+{
+ libxlDriverPrivatePtr driver = dconn->privateData;
+ virDomainObjPtr vm = NULL;
+ char *hostname = NULL;
+ unsigned short port;
+ char portstr[100];
+ virURIPtr uri = NULL;
+ virNetSocketPtr *socks = NULL;
+ size_t nsocks = 0;
+ int nsocks_listen = 0;
+ libxlMigrationDstArgs *args;
+ size_t i;
+ int ret = -1;
+
+ if (!(vm = virDomainObjListAdd(driver->domains, def,
+ driver->xmlopt,
+ VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
+ VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
+ NULL)))
+ goto cleanup;
+
+ /* Create socket connection to receive migration data */
+ if (!uri_in) {
+ if ((hostname = virGetHostname()) == NULL)
+ goto cleanup;
+
+ if (STRPREFIX(hostname, "localhost")) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("hostname on destination resolved to localhost,"
+ " but migration requires an FQDN"));
+ goto cleanup;
+ }
+
+ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
+ goto cleanup;
+
+ if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
+ goto cleanup;
+ } else {
+ if (!(STRPREFIX(uri_in, "tcp://"))) {
+ /* not full URI, add prefix tcp:// */
+ char *tmp;
+ if (virAsprintf(&tmp, "tcp://%s", uri_in) < 0)
+ goto cleanup;
+ uri = virURIParse(tmp);
+ VIR_FREE(tmp);
+ } else {
+ uri = virURIParse(uri_in);
+ }
+
+ if (uri == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unable to parse URI: %s"),
+ uri_in);
+ goto cleanup;
+ }
+
+ if (uri->server == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("missing host in migration URI: %s"),
+ uri_in);
+ goto cleanup;
+ } else {
+ hostname = uri->server;
+ }
+
+ if (uri->port == 0) {
+ if (virPortAllocatorAcquire(driver->migrationPorts, &port) < 0)
+ goto cleanup;
+
+ } else {
+ port = uri->port;
+ }
+
+ if (virAsprintf(uri_out, "tcp://%s:%d", hostname, port) < 0)
+ goto cleanup;
+ }
+
+ snprintf(portstr, sizeof(portstr), "%d", port);
+
+ if (virNetSocketNewListenTCP(hostname, portstr, &socks, &nsocks) < 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("Fail to create socket for incoming migration"));
+ goto cleanup;
+ }
+
+ if (libxlMigrationDstArgsInitialize() < 0)
+ goto cleanup;
+
+ if (!(args = virObjectNew(libxlMigrationDstArgsClass)))
+ goto cleanup;
+
+ args->conn = dconn;
+ args->vm = vm;
+ args->socks = socks;
+ args->nsocks = nsocks;
+
+ for (i = 0; i < nsocks; i++) {
+ if (virNetSocketSetBlocking(socks[i], true) < 0)
+ continue;
+
+ if (virNetSocketListen(socks[i], 1) < 0)
+ continue;
+
+ if (virNetSocketAddIOCallback(socks[i],
+ VIR_EVENT_HANDLE_READABLE,
+ libxlDoMigrateReceive,
+ args,
+ virObjectFreeCallback) < 0)
+ continue;
+
+ /*
+ * Successfully added sock to event loop. Take a ref on args to
+ * ensure it is not freed until sock is removed from the event loop.
+ * Ref is dropped in virObjectFreeCallback after being removed
+ * from the event loop.
+ */
+ virObjectRef(args);
+ nsocks_listen++;
+ }
+
+ /* Done with args in this function, drop reference */
+ virObjectUnref(args);
+
+ if (!nsocks_listen)
+ goto cleanup;
+
+ ret = 0;
+ goto done;
+
+ cleanup:
+ for (i = 0; i < nsocks; i++) {
+ virNetSocketClose(socks[i]);
+ virObjectUnref(socks[i]);
+ }
+
+ done:
+ virURIFree(uri);
+ if (vm)
+ virObjectUnlock(vm);
+ return ret;
+}
+
+int
+libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ const char *dom_xml ATTRIBUTE_UNUSED,
+ const char *dconnuri ATTRIBUTE_UNUSED,
+ const char *uri_str,
+ const char *dname ATTRIBUTE_UNUSED,
+ unsigned int flags)
+{
+ char *hostname = NULL;
+ unsigned short port = 0;
+ char portstr[100];
+ virURIPtr uri = NULL;
+ virNetSocketPtr sock;
+ int sockfd = -1;
+ int saved_errno = EINVAL;
+ int ret = -1;
+
+ /* parse dst host:port from uri */
+ uri = virURIParse(uri_str);
+ if (uri == NULL || uri->server == NULL || uri->port == 0)
+ goto cleanup;
+
+ hostname = uri->server;
+ port = uri->port;
+ snprintf(portstr, sizeof(portstr), "%d", port);
+
+ /* socket connect to dst host:port */
+ if (virNetSocketNewConnectTCP(hostname, portstr, &sock) < 0) {
+ virReportSystemError(saved_errno,
+ _("unable to connect to '%s:%s'"),
+ hostname, portstr);
+ goto cleanup;
+ }
+
+ if (virNetSocketSetBlocking(sock, true) < 0) {
+ virObjectUnref(sock);
+ goto cleanup;
+ }
+
+ sockfd = virNetSocketDupFD(sock, true);
+ virObjectUnref(sock);
+
+ /* suspend vm and send saved data to dst through socket fd */
+ virObjectUnlock(vm);
+ ret = libxlDoMigrateSend(driver, vm, flags, sockfd);
+ virObjectLock(vm);
+
+ cleanup:
+ /* If failure, terminate the job started in MigrationBegin */
+ if (ret == -1) {
+ if (libxlDomainObjEndJob(driver, vm))
+ virObjectUnlock(vm);
+ }
+ VIR_FORCE_CLOSE(sockfd);
+ virURIFree(uri);
+ return ret;
+}
+
+virDomainPtr
+libxlDomainMigrationFinish(virConnectPtr dconn,
+ virDomainObjPtr vm,
+ unsigned int flags,
+ int cancelled)
+{
+ libxlDriverPrivatePtr driver = dconn->privateData;
+ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
+ libxlDomainObjPrivatePtr priv = vm->privateData;
+ virObjectEventPtr event = NULL;
+ virDomainPtr dom = NULL;
+
+ virPortAllocatorRelease(driver->migrationPorts, priv->migrationPort);
+ priv->migrationPort = 0;
+
+ if (cancelled)
+ goto cleanup;
+
+ if (!(flags & VIR_MIGRATE_PAUSED)) {
+ if (libxl_domain_unpause(priv->ctx, vm->def->id) != 0) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("Failed to unpause domain"));
+ goto cleanup;
+ }
+
+ virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
+ VIR_DOMAIN_RUNNING_MIGRATED);
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_RESUMED,
+ VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
+ } else {
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
+ }
+
+ if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+ goto cleanup;
+
+ dom = virGetDomain(dconn, vm->def->name, vm->def->uuid);
+
+ if (dom == NULL) {
+ libxl_domain_destroy(priv->ctx, vm->def->id, NULL);
+ libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
+ event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_FAILED);
+ libxlDomainEventQueue(driver, event);
+ }
+
+ cleanup:
+ if (event)
+ libxlDomainEventQueue(driver, event);
+ if (vm)
+ virObjectUnlock(vm);
+ virObjectUnref(cfg);
+ return dom;
+}
+
+int
+libxlDomainMigrationConfirm(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ unsigned int flags,
+ int cancelled)
+{
+ libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
+ libxlDomainObjPrivatePtr priv = vm->privateData;
+ virObjectEventPtr event = NULL;
+ int ret = -1;
+
+ if (cancelled) {
+ if (libxl_domain_resume(priv->ctx, vm->def->id, 1, 0) == 0) {
+ ret = 0;
+ } else {
+ VIR_DEBUG("Unable to resume domain '%s' after failed migration",
+ vm->def->name);
+ virDomainObjSetState(vm, VIR_DOMAIN_PAUSED,
+ VIR_DOMAIN_PAUSED_MIGRATION);
+ event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
+ VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
+ ignore_value(virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm));
+ }
+ goto cleanup;
+ }
+
+ libxl_domain_destroy(priv->ctx, vm->def->id, NULL);
+ libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_MIGRATED);
+ event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
+ VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
+
+ VIR_DEBUG("Domain '%s' successfully migrated", vm->def->name);
+
+ if (flags & VIR_MIGRATE_UNDEFINE_SOURCE)
+ virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm);
+
+ if (!vm->persistent || (flags & VIR_MIGRATE_UNDEFINE_SOURCE))
+ virDomainObjListRemove(driver->domains, vm);
+
+ ret = 0;
+
+ cleanup:
+ if (!libxlDomainObjEndJob(driver, vm))
+ vm = NULL;
+ if (event)
+ libxlDomainEventQueue(driver, event);
+ if (vm)
+ virObjectUnlock(vm);
+ virObjectUnref(cfg);
+ return ret;
+}
diff --git a/src/libxl/libxl_migration.h b/src/libxl/libxl_migration.h
new file mode 100644
index 0000000..63d8bdc
--- /dev/null
+++ b/src/libxl/libxl_migration.h
@@ -0,0 +1,78 @@
+/*
+ * libxl_migration.h: methods for handling migration with libxenlight
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Jim Fehlig <jfehlig(a)suse.com>
+ */
+
+#ifndef LIBXL_MIGRATION_H
+# define LIBXL_MIGRATION_H
+
+# include "libxl_conf.h"
+
+# define LIBXL_MIGRATION_FLAGS \
+ (VIR_MIGRATE_LIVE | \
+ VIR_MIGRATE_UNDEFINE_SOURCE | \
+ VIR_MIGRATE_PAUSED)
+
+/* All supported migration parameters and their types. */
+# define LIBXL_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
+
+char *
+libxlDomainMigrationBegin(virConnectPtr conn,
+ virDomainObjPtr vm,
+ const char *xmlin);
+
+virDomainDefPtr
+libxlDomainMigrationPrepareDef(libxlDriverPrivatePtr driver,
+ const char *dom_xml,
+ const char *dname);
+
+int
+libxlDomainMigrationPrepare(virConnectPtr dconn,
+ virDomainDefPtr def,
+ const char *uri_in,
+ char **uri_out);
+
+int
+libxlDomainMigrationPerform(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ const char *dom_xml,
+ const char *dconnuri,
+ const char *uri_str,
+ const char *dname,
+ unsigned int flags);
+
+virDomainPtr
+libxlDomainMigrationFinish(virConnectPtr dconn,
+ virDomainObjPtr vm,
+ unsigned int flags,
+ int cancelled);
+
+int
+libxlDomainMigrationConfirm(libxlDriverPrivatePtr driver,
+ virDomainObjPtr vm,
+ unsigned int flags,
+ int cancelled);
+
+#endif /* LIBXL_DRIVER_H */
--
1.8.1.4
10 years, 6 months
[libvirt] [PATCH v6 0/6] Expose FSFreeze/FSThaw within the guest as API
by Tomoki Sekiyama
Hello,
This is patchset v6 to add FSFreeze/FSThaw API for custom disk snapshotting.
Changes since v5:
* replace disks and ndisks parameter with mountpoints and nmountpoints
to specify filesystem to be frozen/thawed, so that we can specify
non-disk-backed filesystems
* add PATCH 6 to support 'mountpoints' argument for
'guest-fsfreeze-freeze' command of qemu-guest-agent.
(This requires a patch for qemu-guest-agent, which isn't merged yet:
https://lists.gnu.org/archive/html/qemu-devel/2014-04/msg04434.html )
* drop nested fsfreeze request feature
* change API version to 1.2.5
(v5: https://www.redhat.com/archives/libvir-list/2014-April/msg00140.html )
=== Description ===
Currently FSFreeze and FSThaw are supported by qemu guest agent and they
are used internally in snapshot-create command with --quiesce option.
However, when users want to utilize the native snapshot feature of storage
devices (such as LVM over iSCSI, enterprise storage appliances, etc.),
they need to issue fsfreeze command separately from libvirt-driven snapshots.
(OpenStack cinder provides these storages' snapshot feature, but it cannot
quiesce the guest filesystems automatically for now.)
Although virDomainQemuGuestAgent() API could be used for this purpose, it
is only for debugging and is not supported officially.
This patchset adds virDomainFSFreeze()/virDomainFSThaw() APIs and virsh
domfsfreeze/domfsthaw commands to enable the users to freeze and thaw
domain's filesystems cleanly.
<updated>
The APIs take disks and ndisks parameters, which is a list of mountpoints
of filesystems to be frozen/thawed. If the option is not provided, or
guest agent doesn't support the 'mountpoints' argument, every mounted
filesystem is frozen/thawed.
</updated>
The APIs have flags option currently unsupported for future extension.
---
Tomoki Sekiyama (6):
Introduce virDomainFSFreeze() and virDomainFSThaw() public API
remote: Implement virDomainFSFreeze and virDomainFSThaw
qemu: track quiesced status in qemuDomainSnapshotFSFreeze
qemu: Implement virDomainFSFreeze and virDomainFSThaw
virsh: Expose new virDomainFSFreeze and virDomainFSThaw API
qemu: Support mountpoints option of guest-fsfreeze-freeze
include/libvirt/libvirt.h.in | 10 +++
src/access/viraccessperm.c | 2 -
src/access/viraccessperm.h | 6 ++
src/driver.h | 14 ++++
src/libvirt.c | 93 ++++++++++++++++++++++++
src/libvirt_public.syms | 6 ++
src/qemu/qemu_agent.c | 47 +++++++++++-
src/qemu/qemu_agent.h | 3 +
src/qemu/qemu_domain.c | 5 +
src/qemu/qemu_domain.h | 2 +
src/qemu/qemu_driver.c | 160 ++++++++++++++++++++++++++++++++++++++----
src/remote/remote_driver.c | 2 +
src/remote/remote_protocol.x | 38 +++++++++-
src/remote_protocol-structs | 18 +++++
src/rpc/gendispatch.pl | 2 +
tests/qemuagenttest.c | 8 +-
tools/virsh-domain.c | 130 ++++++++++++++++++++++++++++++++++
tools/virsh.pod | 23 ++++++
18 files changed, 544 insertions(+), 25 deletions(-)
10 years, 6 months
[libvirt] [PATCH] qemu: fix crash when removing <filterref> from interface with update-device
by Laine Stump
If a domain network interface that contains a <filterref> is modified
"live" using "virsh update-device --live", libvirtd would crash. This
was because the code supporting live update of an interface's
filterref was assuming that a filterref might be added or modified,
but didn't account for removing the filterref, resulting in a null
dereference of the filter name.
Introduced with commit 258fb278, which was first in libvirt v1.0.1.
This addresses https://bugzilla.redhat.com/show_bug.cgi?id=1093301
---
src/qemu/qemu_hotplug.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index ccfb358..cdf9eac 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1815,7 +1815,8 @@ qemuDomainChangeNetFilter(virConnectPtr conn,
virDomainConfNWFilterTeardown(olddev);
- if (virDomainConfNWFilterInstantiate(conn, vm->def->uuid, newdev) < 0) {
+ if (newdev->filter &&
+ virDomainConfNWFilterInstantiate(conn, vm->def->uuid, newdev) < 0) {
virErrorPtr errobj;
virReportError(VIR_ERR_OPERATION_FAILED,
--
1.9.0
10 years, 6 months