Provide integration with libvirt's lock manager in the libxl driver.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
DISTCLEANFILES += locking/qemu-lockd.conf
endif WITH_QEMU
+if WITH_LIBXL
+nodist_conf_DATA += locking/libxl-lockd.conf
+BUILT_SOURCES += locking/libxl-lockd.conf
+DISTCLEANFILES += locking/libxl-lockd.conf
+endif WITH_LIBXL
+
locking/%-lockd.conf: $(srcdir)/locking/lockd.conf
$(AM_V_GEN)$(MKDIR_P) locking ; \
cp $< $@
BUILT_SOURCES += locking/qemu-sanlock.conf
DISTCLEANFILES += locking/qemu-sanlock.conf
endif WITH_QEMU
+
+if WITH_LIBXL
+nodist_conf_DATA += locking/libxl-sanlock.conf
+BUILT_SOURCES += locking/libxl-sanlock.conf
+DISTCLEANFILES += locking/libxl-sanlock.conf
+endif WITH_LIBXL
else ! WITH_SANLOCK
EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES)
endif ! WITH_SANLOCK
(* Config entry grouped by function - same order as example config *)
let autoballoon_entry = bool_entry "autoballoon"
+ let lock_entry = str_entry "lock_manager"
(* Each entry in the config is one of the following ... *)
let entry = autoballoon_entry
+ | lock_entry
let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
let empty = [ label "#empty" . eol ]
# autoballoon setting.
#
#autoballoon = 1
+
+
+# In order to prevent accidentally starting two domains that
+# share one writable disk, libvirt offers two approaches for
+# locking files: sanlock and virtlockd. sanlock is an external
+# project which libvirt integrates with via the libvirt-lock-sanlock
+# package. virtlockd is a libvirt implementation that is enabled with
+# "lockd". Accepted values are "sanlock" and "lockd".
+#
+#lock_manager = "lockd"
VIR_FREE(cfg->libDir);
VIR_FREE(cfg->saveDir);
VIR_FREE(cfg->autoDumpDir);
+ VIR_FREE(cfg->lockManagerName);
}
const char *filename)
{
virConfPtr conf = NULL;
+ virConfValuePtr p;
int ret = -1;
/* Check the file is readable before opening it, otherwise
if (libxlGetAutoballoonConf(cfg, conf) < 0)
goto cleanup;
+ if ((p = virConfGetValue(conf, "lock_manager"))) {
+ if (p->type != VIR_CONF_STRING) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s",
+ _("Unexpected type for 'lock_manager' setting"));
+ goto cleanup;
+ }
+
+ if (VIR_STRDUP(cfg->lockManagerName, p->str) < 0)
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
# include "virobject.h"
# include "virchrdev.h"
# include "virhostdev.h"
+# include "locking/lock_manager.h"
# define LIBXL_DRIVER_NAME "xenlight"
# define LIBXL_VNC_PORT_MIN 5900
* memory for new domains from domain0. */
bool autoballoon;
+ char *lockManagerName;
+
/* Once created, caps are immutable */
virCapsPtr caps;
/* Immutable pointer, lockless APIs*/
virSysinfoDefPtr hostsysinfo;
+
+ /* Immutable pointer. lockless access */
+ virLockManagerPluginPtr lockManager;
};
# define LIBXL_SAVE_MAGIC "libvirt-xml\n \0 \r"
#include "virlog.h"
#include "virstring.h"
#include "virtime.h"
+#include "locking/domain_lock.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
{
libxlDomainObjPrivatePtr priv = data;
+ VIR_FREE(priv->lockState);
virObjectUnref(priv);
}
+static int
+libxlDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
+{
+ libxlDomainObjPrivatePtr priv = data;
+
+ priv->lockState = virXPathString("string(./lockstate)", ctxt);
+
+ return 0;
+}
+
+static int
+libxlDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
+{
+ libxlDomainObjPrivatePtr priv = data;
+
+ if (priv->lockState)
+ virBufferAsprintf(buf, "<lockstate>%s</lockstate>\n", priv->lockState);
+
+ return 0;
+}
+
virDomainXMLPrivateDataCallbacks libxlDomainXMLPrivateDataCallbacks = {
.alloc = libxlDomainObjPrivateAlloc,
.free = libxlDomainObjPrivateFree,
+ .parse = libxlDomainObjPrivateXMLParse,
+ .format = libxlDomainObjPrivateXMLFormat,
};
virHostdevReAttachDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
vm->def, VIR_HOSTDEV_SP_PCI, NULL);
+ VIR_FREE(priv->lockState);
+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
+ VIR_WARN("Unable to release lease on %s", vm->def->name);
+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
+
vm->def->id = -1;
if (priv->deathW) {
vm->def, VIR_HOSTDEV_SP_PCI) < 0)
goto cleanup;
+ if (virDomainLockProcessStart(driver->lockManager,
+ "xen:///system",
+ vm,
+ true,
+ NULL) < 0)
+ goto cleanup;
+
+ if (virDomainLockProcessResume(driver->lockManager,
+ "xen:///system",
+ vm,
+ priv->lockState) < 0)
+ goto cleanup;
+ VIR_FREE(priv->lockState);
+
/* Unlock virDomainObj while creating the domain */
virObjectUnlock(vm);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight failed to restore domain '%s'"),
d_config.c_info.name);
- goto cleanup;
+ goto release_dom;
}
/*
if (libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW))
goto cleanup_dom;
+
if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL)
goto cleanup_dom;
goto cleanup;
cleanup_dom:
+ ret = -1;
if (priv->deathW) {
libxl_evdisable_domain_death(cfg->ctx, priv->deathW);
priv->deathW = NULL;
vm->def->id = -1;
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
+ release_dom:
+ virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState);
+
cleanup:
libxl_domain_config_dispose(&d_config);
VIR_FREE(dom_xml);
virChrdevsPtr devs;
libxl_evgen_domain_death *deathW;
unsigned short migrationPort;
+ char *lockState;
struct libxlDomainJobObj job;
};
#include "viratomic.h"
#include "virhostdev.h"
#include "network/bridge_driver.h"
+#include "locking/domain_lock.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
virObjectUnref(libxl_driver->domains);
virObjectUnref(libxl_driver->reservedVNCPorts);
virObjectUnref(libxl_driver->migrationPorts);
+ virLockManagerPluginUnref(libxl_driver->lockManager);
virObjectEventStateFree(libxl_driver->domainEventState);
virSysinfoDefFree(libxl_driver->hostsysinfo);
goto error;
}
+ if (!(libxl_driver->lockManager =
+ virLockManagerPluginNew(cfg->lockManagerName ?
+ cfg->lockManagerName : "nop",
+ "libxl",
+ cfg->configBaseDir,
+ 0)))
+ goto error;
+
/* read the host sysinfo */
libxl_driver->hostsysinfo = virSysinfoRead();
if (libxlMakeDisk(l_disk, &x_disk) < 0)
goto cleanup;
+ if (virDomainLockDiskAttach(libxl_driver->lockManager,
+ "xen:///system",
+ vm, l_disk) < 0)
+ goto cleanup;
+
if ((ret = libxl_device_disk_add(cfg->ctx, vm->def->id,
&x_disk, NULL)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("libxenlight failed to attach disk '%s'"),
l_disk->dst);
+ if (virDomainLockDiskDetach(libxl_driver->lockManager,
+ vm, l_disk) < 0) {
+ VIR_WARN("Unable to release lock on %s",
+ virDomainDiskGetSource(l_disk));
+ }
goto cleanup;
}
goto cleanup;
}
+ if (virDomainLockDiskDetach(libxl_driver->lockManager,
+ vm, l_disk) < 0)
+ VIR_WARN("Unable to release lock on %s",
+ virDomainDiskGetSource(l_disk));
+
virDomainDiskRemove(vm->def, idx);
virDomainDiskDefFree(l_disk);
#include "libxl_driver.h"
#include "libxl_conf.h"
#include "libxl_migration.h"
+#include "locking/domain_lock.h"
#define VIR_FROM_THIS VIR_FROM_LIBXL
const char *dname ATTRIBUTE_UNUSED,
unsigned int flags)
{
+ libxlDomainObjPrivatePtr priv = vm->privateData;
char *hostname = NULL;
unsigned short port = 0;
char portstr[100];
sockfd = virNetSocketDupFD(sock, true);
virObjectUnref(sock);
+ if (virDomainLockProcessPause(driver->lockManager, vm, &priv->lockState) < 0)
+ VIR_WARN("Unable to release lease on %s", vm->def->name);
+ VIR_DEBUG("Preserving lock state '%s'", NULLSTR(priv->lockState));
+
/* suspend vm and send saved data to dst through socket fd */
virObjectUnlock(vm);
ret = libxlDoMigrateSend(driver, vm, flags, sockfd);
test Libvirtd_libxl.lns get conf =
{ "autoballoon" = "1" }
+{ "lock_manager" = "lockd" }