[libvirt] [libvirt-sandbox PATCH] Only set SELinux seclabel if supported by the host.
by Cédric Bosdonnat
This code depends on new API in libvirt-gconfig to extract the
secmodels handled by the host.
---
libvirt-sandbox/libvirt-sandbox-builder.c | 68 ++++++++++++++++++++-----------
1 file changed, 45 insertions(+), 23 deletions(-)
diff --git a/libvirt-sandbox/libvirt-sandbox-builder.c b/libvirt-sandbox/libvirt-sandbox-builder.c
index 48b3acc..547b1c7 100644
--- a/libvirt-sandbox/libvirt-sandbox-builder.c
+++ b/libvirt-sandbox/libvirt-sandbox-builder.c
@@ -323,38 +323,60 @@ static gboolean gvir_sandbox_builder_construct_devices(GVirSandboxBuilder *build
}
-static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *builder G_GNUC_UNUSED,
+static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *builder,
GVirSandboxConfig *config G_GNUC_UNUSED,
const gchar *statedir G_GNUC_UNUSED,
GVirConfigDomain *domain,
- GError **error G_GNUC_UNUSED)
+ GError **error)
{
GVirConfigDomainSeclabel *sec = gvir_config_domain_seclabel_new();
const char *label = gvir_sandbox_config_get_security_label(config);
+ GVirConnection *connection = gvir_sandbox_builder_get_connection(builder);
+ GVirConfigCapabilities *configCapabilities;
+ GVirConfigCapabilitiesHost *hostCapabilities;
+ GList *secmodels, *iter;
+ gboolean supportsSelinux = FALSE;
+
+ /* What security models are available on the host? */
+ if (!(configCapabilities = gvir_connection_get_capabilities(connection, error))) {
+ g_object_unref(sec);
+ return FALSE;
+ }
+
+ hostCapabilities = gvir_config_capabilities_get_host(configCapabilities);
- gvir_config_domain_seclabel_set_model(sec, "selinux");
- if (gvir_sandbox_config_get_security_dynamic(config)) {
- gvir_config_domain_seclabel_set_type(sec,
- GVIR_CONFIG_DOMAIN_SECLABEL_DYNAMIC);
- if (label)
- gvir_config_domain_seclabel_set_baselabel(sec, label);
- else if (gvir_config_domain_get_virt_type(domain) ==
- GVIR_CONFIG_DOMAIN_VIRT_LXC)
- gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_lxc_net_t:s0");
- else if (gvir_config_domain_get_virt_type(domain) ==
- GVIR_CONFIG_DOMAIN_VIRT_QEMU)
- gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_tcg_t:s0");
- else if (gvir_config_domain_get_virt_type(domain) ==
- GVIR_CONFIG_DOMAIN_VIRT_KVM)
- gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_t:s0");
- } else {
- gvir_config_domain_seclabel_set_type(sec,
- GVIR_CONFIG_DOMAIN_SECLABEL_STATIC);
- if (label)
- gvir_config_domain_seclabel_set_label(sec, label);
+ secmodels = gvir_config_capabilities_host_get_secmodels(hostCapabilities);
+ for (iter = secmodels; iter != NULL; iter = iter->next) {
+ supportsSelinux = g_str_equal(gvir_config_capabilities_secmodel_get_model(
+ GVIR_CONFIG_CAPABILITIES_SECMODEL(iter->data)), "selinux");
+ g_object_unref(iter->data);
}
- gvir_config_domain_set_seclabel(domain, sec);
+ if (supportsSelinux) {
+ gvir_config_domain_seclabel_set_model(sec, "selinux");
+ if (gvir_sandbox_config_get_security_dynamic(config)) {
+ gvir_config_domain_seclabel_set_type(sec,
+ GVIR_CONFIG_DOMAIN_SECLABEL_DYNAMIC);
+ if (label)
+ gvir_config_domain_seclabel_set_baselabel(sec, label);
+ else if (gvir_config_domain_get_virt_type(domain) ==
+ GVIR_CONFIG_DOMAIN_VIRT_LXC)
+ gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_lxc_net_t:s0");
+ else if (gvir_config_domain_get_virt_type(domain) ==
+ GVIR_CONFIG_DOMAIN_VIRT_QEMU)
+ gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_tcg_t:s0");
+ else if (gvir_config_domain_get_virt_type(domain) ==
+ GVIR_CONFIG_DOMAIN_VIRT_KVM)
+ gvir_config_domain_seclabel_set_baselabel(sec, "system_u:system_r:svirt_t:s0");
+ } else {
+ gvir_config_domain_seclabel_set_type(sec,
+ GVIR_CONFIG_DOMAIN_SECLABEL_STATIC);
+ if (label)
+ gvir_config_domain_seclabel_set_label(sec, label);
+ }
+
+ gvir_config_domain_set_seclabel(domain, sec);
+ }
g_object_unref(sec);
return TRUE;
--
1.8.4.5
10 years, 5 months
[libvirt] [PATCH] maint: detect VPATH builds when checking for gnulib update
by Eric Blake
I accidentally typed 'make' in the srcdir of a VPATH build, and
was surprised to see this:
$ make
/bin/sh: s/^[ +-]//;s/ .*//: No such file or directory
INFO: gnulib update required; running ./autogen.sh first
make: -n: Command not found
./autogen.sh
I am going to run ./configure with no arguments - if you wish
to pass any to it, please specify them on the ./autogen.sh command line.
running bootstrap...
./bootstrap: Bootstrapping from checked-out libvirt sources...
./bootstrap: getting gnulib files...
Oops - we're trying to execute some fairly bogus command names,
and then trying to configure in-tree (which breaks all existing
VPATH builds, since automake refuses to do a VPATH build if it
detects an in-tree configure). The third line (executing "-n")
is fixed by updating to the latest gnulib; the rest of the problem
is fixed by copying the same filtering in our cfg.mk as what
gnulib just added, so that we avoid any $(shell) invocations which
in turn depend on variables that are only populated by a working
Makefile. With that in place, we are back to the much nicer:
$ make
There seems to be no Makefile in this directory.
You must run ./configure before running 'make'.
make: *** [abort-due-to-no-makefile] Error 1
Additionally, although harder to see - there was a trailing space in
the message warning us that autogen would run an in-tree configure.
* .gnulib: Update to latest, in part for maint.mk improvements.
* cfg.mk (_update_required): Don't check for update in
unconfigured directory.
* autogen.sh (no_git): Drop trailing space.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
Pushing under the gnulib maintenance rule.
* .gnulib e8e0eb6...d55899f (35):
> maintainer-makefile: delete obsolete code
> maintainer-makefile: avoid spurious error messages
> rename: avoid unused-but-set-variable compiler warning
> maint: add ChangeLog entry missing in previous commit
> rename: mark a label as potentially unused
> gnulib-common.m4: Fix typo in _GL_UNUSED_LABEL.
> acl: apply pure attribute to two functions
> gnulib-common.m4: add _GL_UNUSED_LABEL
> dup2, fcntl, fcntl-h: port to AIX 7.1
> printf, config.rpath: Port to FreeBSD 10.
> ftoastr: work around compiler bug in IBM xlc 12.1
> valgrind-tests: fixed misleading help message
> isfinite, isinf, isnan tests: fix for little-endian PowerPC
> exclude-tests: port to AIX 7.1
> pthread_sigmask, timer-time: use gl_THREADLIB only if needed
> gnulib-tool: wget translations using --no-verbose rather than --quiet
> gnulib-tool: adjust translation wget to avoid a https redirection
> getlogin_r-tests: check return value rather than errno
> getlogin_r-tests: fix various issues in recent change
> fchdir: port 'open' and 'close' redefinitions to AIX 7.1
> update from texinfo
> xalloc: don't potentially generate invalid code for xmemdup calls
> getlogin_r-tests: avoid false failure under sudo/ssh etc.
> getlogin-tests: avoid false failure under cron
> mbrtowc.m4: fix a comment typo
> mbrlen, mbrtowc: fix bug with empty input
> doc: document mbrtowc and mbrlen problem with empty input
> doc: document exec* = spawn+exit bug with non-Cygwin Windows platforms
> autoupdate
> getlogin-tests: avoid false failure under sudo/ssh etc.
> mbsstr, quotearg, xstrtol: pacify IRIX 6.5 cc
> update from texinfo
> autoupdate
> autoupdate
> autoupdate
.gnulib | 2 +-
autogen.sh | 2 +-
cfg.mk | 4 ++++
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/.gnulib b/.gnulib
index e8e0eb6..d55899f 160000
--- a/.gnulib
+++ b/.gnulib
@@ -1 +1 @@
-Subproject commit e8e0eb6bfb728685ec8d5afd924e41b18e9d928d
+Subproject commit d55899fd2c5794ac85ecb14d5e2f646a89e4b4dd
diff --git a/autogen.sh b/autogen.sh
index 5aa1990..1965f64 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -35,7 +35,7 @@ if test -z "$NOCONFIGURE" ; then
echo "Running ./configure with $EXTRA_ARGS $@"
else
if test -z "$*" && test ! -f "$THEDIR/config.status"; then
- echo "I am going to run ./configure with no arguments - if you wish "
+ echo "I am going to run ./configure with no arguments - if you wish"
echo "to pass any to it, please specify them on the $0 command line."
fi
fi
diff --git a/cfg.mk b/cfg.mk
index 4601b35..b5f1fa2 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -939,6 +939,7 @@ sc_require_locale_h:
# We don't use this feature of maint.mk.
prev_version_file = /dev/null
+ifneq ($(_gl-Makefile),)
ifeq (0,$(MAKELEVEL))
_curr_status = .git-module-status
# The sed filter accommodates those who check out on a commit from which
@@ -971,6 +972,7 @@ ifeq (0,$(MAKELEVEL))
maint.mk Makefile: _autogen
endif
endif
+endif
# It is necessary to call autogen any time gnulib changes. Autogen
# reruns configure, then we regenerate all Makefiles at once.
@@ -980,7 +982,9 @@ _autogen:
./config.status
# regenerate HACKING as part of the syntax-check
+ifneq ($(_gl-Makefile),)
syntax-check: $(top_srcdir)/HACKING bracket-spacing-check
+endif
bracket-spacing-check:
$(AM_V_GEN)files=`$(VC_LIST) | grep '\.c$$'`; \
--
1.9.3
10 years, 5 months
[libvirt] [PATCH V7] 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>
---
V6 here
https://www.redhat.com/archives/libvir-list/2014-May/msg00017.html
In V7:
There were no comments on V6, but during testing I noticed that
'virsh migrate --suspend ...' was not being honored. Fixed that
in this version so that the domain is paused on the destination
once migration completes.
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 | 581 ++++++++++++++++++++++++++++++++++++++++++++
src/libxl/libxl_migration.h | 79 ++++++
7 files changed, 905 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 df7d510..35467ac 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;
@@ -4155,6 +4164,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;
@@ -4333,6 +4343,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, flags) < 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,
@@ -4423,6 +4653,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..e3699c5
--- /dev/null
+++ b/src/libxl/libxl_migration.c
@@ -0,0 +1,581 @@
+/*
+ * 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;
+ unsigned int flags;
+
+ /* 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;
+ bool paused = args->flags & VIR_MIGRATE_PAUSED;
+ 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, paused, 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,
+ unsigned int flags)
+{
+ 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->flags = flags;
+ 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..aab96f5
--- /dev/null
+++ b/src/libxl/libxl_migration.h
@@ -0,0 +1,79 @@
+/*
+ * 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,
+ unsigned int flags);
+
+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, 5 months
[libvirt] [PATCH] cfg.mk: Introduce rule for setlocale()
by Michal Privoznik
In the past we had some issues where setlocale() was called without
corresponding include of locale.h. While on some systems this may
work, on others the compilation failed. We should have a syntax-check
rule for that to prevent this from happening again.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
cfg.mk | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/cfg.mk b/cfg.mk
index 9e8fcec..36395c6 100644
--- a/cfg.mk
+++ b/cfg.mk
@@ -929,6 +929,15 @@ sc_prohibit_mixed_case_abbreviations:
halt='Use PCI, USB, SCSI, not Pci, Usb, Scsi' \
$(_sc_search_regexp)
+# Require #include <locale.h> in all files that call setlocale()
+sc_require_locale_h:
+ @for i in $$($(VC_LIST_EXCEPT) | grep '\.[chx]$$'); do \
+ if test -z "$$(grep setlocale $$i)" ; then continue; fi; \
+ if test -z "$$(grep 'include <locale.h>' $$i)" ; then \
+ echo '$(ME): missing locale.h include in' $$i 1>&2; exit 1; \
+ fi; \
+ done;
+
# We don't use this feature of maint.mk.
prev_version_file = /dev/null
--
2.0.0
10 years, 5 months
[libvirt] Parse commandline for -device option
by Hong-Hua.Yin@freescale.com
Hi Maintainers,
Currently libvirt could only parse commandline for several legacy devices.
For example,
-pcidevice: qemuParseCommandLinePCI()
-usbdevice: qemuParseCommandLineUSB()
It also provides test cases for host device assignment.
DO_TEST("hostdev-usb-address");
DO_TEST("hostdev-pci-address");
But for other hostdev with -device option, it failed to convert into <hostdev> tag.
-device vfio-pci,host=06:12.5,id=hostdev0,bus=pci.0,addr=0x3
$ virsh domxml-from-native qemu-argv kvm.args >kvm.xml
<qemu:commandline>
<qemu:arg value='-device'/>
<qemu:arg value='vfio-pci,host=06:12.5,id=hostdev0,bus=pci.0,addr=0x3'/>
</qemu:commandline>
Expected XML file should like below:
<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x06' slot='0x12' function='0x5'/>
</source>
</hostdev>
Maybe it is not very critical.
Is it complicated to add support to -device option in function qemuParseCommandLine()?
Do you have any thought or plan about it?
Best Regards,
Olivia
10 years, 5 months
[libvirt] Problem connecting to hypervisor.
by Vikas Kokare
I am trying to establish a connection (using virsh command) to a couple of
hypervisor hosts, both on SLES 11.3 environments. The host from where i am
making both the connections is a SLES 10.4 instance.
*kvmh911351246:~ # virsh -c qemu+ssh://9.113.51.247:22/system
<http://9.113.51.247:22/system>libvir: XML-RPC error : authentication
requirederror: failed to connect to the hypervisor*
The SSH authentication to hypervisor host 9.113.51.247 has already been
established.
*kvmh911351246:~ # ssh root(a)9.113.51.247 <root(a)9.113.51.247>Last login: Tue
Jun 3 11:31:56 2014 from scm-kvmh2-rhel6 SLES11-51-247:~ #*
Hence the cause of the authentication failure is not clear.
The second connection to another SLES 11.3 host looks like
*virsh # connect qemu+ssh://9.121.58.19:22/system
<http://9.121.58.19:22/system> bash: socat: command not foundlibvir: Remote
error : socket closed unexpectedlyerror: Failed to connect to the
hypervisor*
where the cause of the error is entirely different.
The libvirt packages available on these environments are
*9.113.51.247 (SLES 11.3)*
*libvirt-cim-0.5.12-0.7.16libvirt-1.0.5.1-0.7.10libvirt-python-1.0.5.1-0.7.10libvirt-client-32bit-1.0.5.1-0.7.10
libvirt-lock-sanlock-1.0.5.1-0.7.10libvirt-client-1.0.5.1-0.7.10*
*9.121.58.19 (SLES 11.3)*
*libvirt-cim-0.5.12-0.7.16libvirt-client-1.0.5.1-0.7.10libvirt-python-1.0.5.1-0.7.10
libvirt-1.0.5.1-0.7.10*
*9.113.51.246 ( SLES 10.4)*
*libvirt-python-0.3.3-18.22.1libvirt-devel-0.3.3-18.22.1libvirt-0.3.3-18.22.1*
How can these connection failures be debugged? Is there a way to know more
information about them?
10 years, 5 months
[libvirt] [PATCH] virnuma: Check for numa_bitmask_isbitset presence
by Michal Privoznik
On some systems, libnuma can be present but it's so ancient that
it misses some symbols that virNumaGetDistances() needs. To be
more precise: numa_bitmask_isbitset() and numa_nodes_ptr are the
symbols in question. Fortunately, they were both introduced in
the same release so it's sufficient for us to check for only one
of them. And the winner is numa_bitmask_isbitset().
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Notes:
While this is a build breaker, it's not that critical. Come on -
who runs libvirt from git on stable enterprise systems? I'm
sending it to know if the check for numa_bitmask_isbitset() is in
the right place or should be moved to a different file.
m4/virt-numactl.m4 | 4 ++
src/util/virnuma.c | 135 +++++++++++++++++++++++++++--------------------------
2 files changed, 73 insertions(+), 66 deletions(-)
diff --git a/m4/virt-numactl.m4 b/m4/virt-numactl.m4
index 1dcb029..fa66d24 100644
--- a/m4/virt-numactl.m4
+++ b/m4/virt-numactl.m4
@@ -19,6 +19,10 @@ dnl
AC_DEFUN([LIBVIRT_CHECK_NUMACTL],[
LIBVIRT_CHECK_LIB([NUMACTL], [numa], [numa_available], [numa.h])
+ AC_CHECK_LIB([numa], [numa_bitmask_isbitset], [have_numa_bitmask_isbitset=yes])
+ if test "$have_numa_bitmask_isbitset" = "yes"; then
+ AC_DEFINE_UNQUOTED([HAVE_NUMA_BITMASK_ISBITSET], 1, [whether numa_bitmask_isbitset is available])
+ fi
])
AC_DEFUN([LIBVIRT_RESULT_NUMACTL],[
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index 042844b..f979f49 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -217,61 +217,6 @@ virNumaGetMaxNode(void)
/**
- * virNumaGetDistances:
- * @node: identifier of the requested NUMA node
- * @distances: array of distances to sibling nodes
- * @ndistances: size of @distances
- *
- * Get array of distances to sibling nodes from @node. If a
- * distances[x] equals to zero, the node x is not enabled or
- * doesn't exist. As a special case, if @node itself refers to
- * disabled or nonexistent NUMA node, then @distances and
- * @ndistances are set to NULL and zero respectively.
- *
- * The distances are a bit of magic. For a local node the value
- * is 10, for remote it's typically 20 meaning that time penalty
- * for accessing a remote node is two time bigger than when
- * accessing a local node.
- *
- * Returns 0 on success, -1 otherwise.
- */
-int
-virNumaGetDistances(int node,
- int **distances,
- int *ndistances)
-{
- int ret = -1;
- int max_node;
- size_t i;
-
- if (!numa_bitmask_isbitset(numa_nodes_ptr, node)) {
- VIR_DEBUG("Node %d does not exist", node);
- *distances = NULL;
- *ndistances = 0;
- return 0;
- }
-
- if ((max_node = virNumaGetMaxNode()) < 0)
- goto cleanup;
-
- if (VIR_ALLOC_N(*distances, max_node) < 0)
- goto cleanup;
-
- *ndistances = max_node + 1;
-
- for (i = 0; i<= max_node; i++) {
- if (!numa_bitmask_isbitset(numa_nodes_ptr, i))
- continue;
-
- (*distances)[i] = numa_distance(node, i);
- }
-
- ret = 0;
- cleanup:
- return ret;
-}
-
-/**
* virNumaGetNodeMemory:
* @node: identifier of the requested NUMA node
* @memsize: returns the total size of memory in the NUMA node
@@ -443,17 +388,6 @@ virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED,
_("NUMA isn't available on this host"));
return -1;
}
-
-int
-virNumaGetDistances(int node ATTRIBUTE_UNUSED,
- int **distances,
- int *ndistances)
-{
- *distances = NULL;
- *ndistances = 0;
- VIR_DEBUG("NUMA isn't available on this host");
- return 0;
-}
#endif
@@ -469,3 +403,72 @@ virNumaGetMaxCPUs(void)
{
return NUMA_MAX_N_CPUS;
}
+
+
+#ifdef HAVE_NUMA_BITMASK_ISBITSET
+/**
+ * virNumaGetDistances:
+ * @node: identifier of the requested NUMA node
+ * @distances: array of distances to sibling nodes
+ * @ndistances: size of @distances
+ *
+ * Get array of distances to sibling nodes from @node. If a
+ * distances[x] equals to zero, the node x is not enabled or
+ * doesn't exist. As a special case, if @node itself refers to
+ * disabled or nonexistent NUMA node, then @distances and
+ * @ndistances are set to NULL and zero respectively.
+ *
+ * The distances are a bit of magic. For a local node the value
+ * is 10, for remote it's typically 20 meaning that time penalty
+ * for accessing a remote node is two time bigger than when
+ * accessing a local node.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int
+virNumaGetDistances(int node,
+ int **distances,
+ int *ndistances)
+{
+ int ret = -1;
+ int max_node;
+ size_t i;
+
+ if (!numa_bitmask_isbitset(numa_nodes_ptr, node)) {
+ VIR_DEBUG("Node %d does not exist", node);
+ *distances = NULL;
+ *ndistances = 0;
+ return 0;
+ }
+
+ if ((max_node = virNumaGetMaxNode()) < 0)
+ goto cleanup;
+
+ if (VIR_ALLOC_N(*distances, max_node) < 0)
+ goto cleanup;
+
+ *ndistances = max_node + 1;
+
+ for (i = 0; i<= max_node; i++) {
+ if (!numa_bitmask_isbitset(numa_nodes_ptr, i))
+ continue;
+
+ (*distances)[i] = numa_distance(node, i);
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+#else
+int
+virNumaGetDistances(int node ATTRIBUTE_UNUSED,
+ int **distances,
+ int *ndistances)
+{
+ *distances = NULL;
+ *ndistances = 0;
+ VIR_DEBUG("NUMA isn't available on this host");
+ return 0;
+}
+#endif
--
2.0.0
10 years, 5 months
[libvirt] [RFC] Atomic Operations
by Tucker DiNapoli
I'm working on job control which involves a lot of locking and unlocking,
often for operations that could be done atomically. I use the existing
atomic integer operations in viratomic.h where possible, but there are a
lot of parameters involved in jobs (such as time, thread id's, progress
information, etc) which don't fit in an integer.
I have several ideas of ways to update the existing integer atomic
operations to support more types. The easiest way (at least regarding code)
would be to use an existing atomic operations library. My suggestion would
be the libatomic_ops library, which is licensed under an MIT style license
and could be added to the source tree as a git submodule (similar to the
way gnulib is) or a specific version could be used and the library source
itself added to the git repository. The library can be found at
https://github.com/ivmai/libatomic_ops/ .
The other way of augmenting atomic operations would be to extend the
existing viratomic.h file to support additional types. Personally I have
experience working with GCC atomic operations and could implement that
myself, but I wouldn't be able to implement the windows versions.
Again I think the easiest and most maintainable way of supporting atomic
operations is via an external library, but I am not sure of the feasibility
of adding another dependency to libvirt. In general atomic operations are
an optimization, but they can help make multithreaded programming easier
and I think libvirt would be enhanced by having more comprehensive support
for atomic operations.
Tucker DiNapoli
10 years, 5 months
[libvirt] [libvirt-sandbox] virt-sandbox-service: fixed /lib/ into /usr/lib for searching unit files
by Cédric Bosdonnat
---
bin/virt-sandbox-service | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service
index 2dcbfb8..9ed37e0 100755
--- a/bin/virt-sandbox-service
+++ b/bin/virt-sandbox-service
@@ -1071,7 +1071,7 @@ class CheckUnit(argparse.Action):
src = "/etc/systemd/system/" + unit
if os.path.exists(src):
return src
- src = "/lib/systemd/system/" + unit
+ src = "/usr/lib/systemd/system/" + unit
if os.path.exists(src):
return src
return None
--
1.8.4.5
10 years, 5 months
[libvirt] [PATCH] virnuma: Implement virNumaGetDistances stub for non-NUMA
by Michal Privoznik
In case the libvirt is built without numactl support, we're
missing the virNumaGetDistances() stub so the linking fails:
CCLD libvirt_lxc
libvirt_lxc-nodeinfo.o: In function `virNodeCapsGetSiblingInfo':
/home/zippy/tmp/libvirt.git/src/nodeinfo.c:1763: undefined reference to `virNumaGetDistances'
collect2: error: ld returned 1 exit status
make[3]: *** [libvirt_lxc] Error 1
The issue was introduced in 77c830d8c4.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
Notes:
Pushing under build-breaker and trivial rules.
src/util/virnuma.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/util/virnuma.c b/src/util/virnuma.c
index e8ceec8..042844b 100644
--- a/src/util/virnuma.c
+++ b/src/util/virnuma.c
@@ -443,6 +443,17 @@ virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED,
_("NUMA isn't available on this host"));
return -1;
}
+
+int
+virNumaGetDistances(int node ATTRIBUTE_UNUSED,
+ int **distances,
+ int *ndistances)
+{
+ *distances = NULL;
+ *ndistances = 0;
+ VIR_DEBUG("NUMA isn't available on this host");
+ return 0;
+}
#endif
--
2.0.0
10 years, 5 months