summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2011-07-06 17:30:08 +0100
committerDaniel P. Berrange <berrange@redhat.com>2012-12-13 15:26:57 +0000
commiteb8268a4f6ad66306a0038207b745c44dc281a3a (patch)
tree75e0d18698e9fea87c13a4bf838d3481d9a12674
parentf234dc9366189108dc22c314334d322702d799b5 (diff)
downloadlibvirt-eb8268a4f6ad66306a0038207b745c44dc281a3a.tar.gz
Add a virtlockd client as a lock driver impl
This adds a 'lockd' lock driver which is just a client which talks to the lockd daemon to perform all locking. This will be the default lock driver for any hypervisor which needs one. * src/Makefile.am: Add lockd.so plugin * src/locking/lock_driver_lockd.c: Lockd driver impl Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
-rw-r--r--.gitignore1
-rw-r--r--po/POTFILES.in1
-rw-r--r--run.in2
-rw-r--r--src/Makefile.am54
-rw-r--r--src/locking/libvirt_lockd.aug32
-rw-r--r--src/locking/lock_driver_lockd.c659
-rw-r--r--src/locking/lockd.conf18
-rw-r--r--src/locking/test_libvirt_lockd.aug.in6
8 files changed, 767 insertions, 6 deletions
diff --git a/.gitignore b/.gitignore
index 8a68ab03aa..32ae8a7bb3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -110,6 +110,7 @@
/src/libvirt_lxc
/src/locking/lock_daemon_dispatch_stubs.h
/src/locking/lock_protocol.[ch]
+/src/locking/qemu-lockd.conf
/src/locking/qemu-sanlock.conf
/src/locking/test_libvirt_sanlock.aug
/src/lxc/lxc_controller_dispatch.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6df9869792..f0cfd7fc5c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -51,6 +51,7 @@ src/libvirt-qemu.c
src/locking/lock_daemon.c
src/locking/lock_daemon_config.c
src/locking/lock_daemon_dispatch.c
+src/locking/lock_driver_lockd.c
src/locking/lock_driver_sanlock.c
src/locking/lock_manager.c
src/locking/sanlock_helper.c
diff --git a/run.in b/run.in
index f7d30ca41c..845eef5494 100644
--- a/run.in
+++ b/run.in
@@ -53,6 +53,8 @@ fi
export LD_LIBRARY_PATH
export LIBVIRT_DRIVER_DIR="$b/src/.libs"
+export LIBVIRT_LOCK_MANAGER_PLUGIN_DIR="$b/src/.libs"
+export VIRTLOCKD_PATH="$b/src/virtlockd"
export LIBVIRTD_PATH="$b/daemon/libvirtd"
# For Python.
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b1cad01dc..a5c666e76b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -164,6 +164,10 @@ LOCK_DAEMON_GENERATED = \
BUILT_SOURCES += $(LOCK_DAEMON_GENERATED)
MAINTAINERCLEANFILES += $(LOCK_DAEMON_GENERATED)
+LOCK_DRIVER_LOCKD_SOURCES = \
+ locking/lock_driver_lockd.c \
+ $(NULL)
+
LOCK_DAEMON_SOURCES = \
locking/lock_daemon.h \
locking/lock_daemon.c \
@@ -1300,9 +1304,14 @@ EXTRA_DIST += \
check-local: check-augeas
-.PHONY: check-augeas check-augeas-qemu check-augeas-lxc check-augeas-sanlock
+.PHONY: check-augeas \
+ check-augeas-qemu \
+ check-augeas-lxc \
+ check-augeas-sanlock \
+ check-augeas-lockd \
+ $(NULL)
-check-augeas: check-augeas-qemu check-augeas-lxc check-augeas-sanlock
+check-augeas: check-augeas-qemu check-augeas-lxc check-augeas-sanlock check-augeas-lockd
AUG_GENTEST = $(PERL) $(top_srcdir)/build-aux/augeas-gentest.pl
EXTRA_DIST += $(top_srcdir)/build-aux/augeas-gentest.pl
@@ -1346,6 +1355,15 @@ else
check-augeas-sanlock:
endif
+test_libvirt_lockd.aug: locking/test_libvirt_lockd.aug.in \
+ locking/qemu-lockd.conf $(AUG_GENTEST)
+ $(AM_V_GEN)$(AUG_GENTEST) locking/qemu-lockd.conf $< $@
+
+check-augeas-lockd: test_libvirt_lockd.aug
+ $(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
+ '$(AUGPARSE)' -I $(srcdir)/locking test_libvirt_lockd.aug; \
+ fi
+
#
# Build our version script. This is composed of three parts:
#
@@ -1539,7 +1557,32 @@ libvirt_qemu_la_CFLAGS = $(AM_CFLAGS)
libvirt_qemu_la_LIBADD = libvirt.la $(CYGWIN_EXTRA_LIBADD)
EXTRA_DIST += $(LIBVIRT_QEMU_SYMBOL_FILE)
+lockdriverdir = $(libdir)/libvirt/lock-driver
+lockdriver_LTLIBRARIES =
+
if WITH_LIBVIRTD
+lockdriver_LTLIBRARIES += lockd.la
+lockd_la_SOURCES = \
+ $(LOCK_DRIVER_LOCKD_SOURCES) \
+ $(LOCK_PROTOCOL_GENERATED) \
+ $(NULL)
+lockd_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS)
+lockd_la_LDFLAGS = -module -avoid-version
+lockd_la_LIBADD = ../gnulib/lib/libgnu.la libvirt-net-rpc.la libvirt-net-rpc-client.la
+if WITH_DTRACE_PROBES
+lockd_la_LIBADD += libvirt_probes.lo
+endif
+if WITH_QEMU
+nodist_conf_DATA = locking/qemu-lockd.conf
+BUILT_SOURCES += locking/qemu-lockd.conf
+DISTCLEANFILES += locking/qemu-lockd.conf
+endif
+
+locking/%-lockd.conf: $(srcdir)/locking/lockd.conf
+ $(AM_V_GEN)$(MKDIR_P) locking ; \
+ cp $< $@
+
+
sbin_PROGRAMS = virtlockd
virtlockd_SOURCES = \
@@ -1567,7 +1610,8 @@ virtlockd_LDADD += libvirt_probes.lo
endif
else
-EXTRA_DIST += $(LOCK_DAEMON_SOURCES)
+EXTRA_DIST += $(LOCK_DAEMON_SOURCES) \
+ $(LOCK_DRIVER_LOCKD_SOURCES)
endif
EXTRA_DIST += locking/virtlockd.sysconf
@@ -1661,9 +1705,7 @@ virtlockd.socket: locking/virtlockd.socket.in $(top_builddir)/config.status
if HAVE_SANLOCK
-lockdriverdir = $(libdir)/libvirt/lock-driver
-lockdriver_LTLIBRARIES = sanlock.la
-
+lockdriver_LTLIBRARIES += sanlock.la
sanlock_la_SOURCES = $(LOCK_DRIVER_SANLOCK_SOURCES)
sanlock_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS)
sanlock_la_LDFLAGS = -module -avoid-version
diff --git a/src/locking/libvirt_lockd.aug b/src/locking/libvirt_lockd.aug
new file mode 100644
index 0000000000..4649644562
--- /dev/null
+++ b/src/locking/libvirt_lockd.aug
@@ -0,0 +1,32 @@
+(* /etc/libvirt/qemu-lockd.conf *)
+
+module Libvirt_lockd =
+ autoload xfm
+
+ let eol = del /[ \t]*\n/ "\n"
+ let value_sep = del /[ \t]*=[ \t]*/ " = "
+ let indent = del /[ \t]*/ ""
+
+ let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
+ let bool_val = store /0|1/
+ let int_val = store /[0-9]+/
+
+ let str_entry (kw:string) = [ key kw . value_sep . str_val ]
+ let bool_entry (kw:string) = [ key kw . value_sep . bool_val ]
+ let int_entry (kw:string) = [ key kw . value_sep . int_val ]
+
+
+ (* Each enty in the config is one of the following three ... *)
+ let entry = bool_entry "auto_disk_leases"
+ | bool_entry "require_lease_for_disks"
+ let comment = [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ]
+ let empty = [ label "#empty" . eol ]
+
+ let record = indent . entry . eol
+
+ let lns = ( record | comment | empty ) *
+
+ let filter = incl "/etc/libvirt/qemu-lockd.conf"
+ . Util.stdexcl
+
+ let xfm = transform lns filter
diff --git a/src/locking/lock_driver_lockd.c b/src/locking/lock_driver_lockd.c
new file mode 100644
index 0000000000..5a7fbaf5c0
--- /dev/null
+++ b/src/locking/lock_driver_lockd.c
@@ -0,0 +1,659 @@
+/*
+ * lock_driver_lockd.c: A lock driver which locks nothing
+ *
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ *
+ * 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/>.
+ *
+ */
+
+#include <config.h>
+
+#include "lock_driver.h"
+#include "conf.h"
+#include "memory.h"
+#include "logging.h"
+#include "uuid.h"
+#include "util.h"
+#include "virfile.h"
+#include "virterror_internal.h"
+#include "rpc/virnetclient.h"
+#include "lock_protocol.h"
+#include "configmake.h"
+
+#define VIR_FROM_THIS VIR_FROM_LOCKING
+
+#define virLockError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+typedef struct _virLockManagerLockDaemonPrivate virLockManagerLockDaemonPrivate;
+typedef virLockManagerLockDaemonPrivate *virLockManagerLockDaemonPrivatePtr;
+
+typedef struct _virLockManagerLockDaemonResource virLockManagerLockDaemonResource;
+typedef virLockManagerLockDaemonResource *virLockManagerLockDaemonResourcePtr;
+
+typedef struct _virLockManagerLockDaemonDriver virLockManagerLockDaemonDriver;
+typedef virLockManagerLockDaemonDriver *virLockManagerLockDaemonDriverPtr;
+
+struct _virLockManagerLockDaemonResource {
+ char *lockspace;
+ char *name;
+ unsigned int flags;
+};
+
+struct _virLockManagerLockDaemonPrivate {
+ unsigned char uuid[VIR_UUID_BUFLEN];
+ char *name;
+ int id;
+ pid_t pid;
+
+ size_t nresources;
+ virLockManagerLockDaemonResourcePtr resources;
+
+ bool hasRWDisks;
+};
+
+
+struct _virLockManagerLockDaemonDriver {
+ bool autoDiskLease;
+ bool requireLeaseForDisks;
+};
+
+static virLockManagerLockDaemonDriverPtr driver = NULL;
+
+#define VIRTLOCKD_PATH SBINDIR "/virtlockd"
+
+static const char *
+virLockManagerLockDaemonFindDaemon(void)
+{
+ const char *customDaemon = getenv("VIRTLOCKD_PATH");
+
+ if (customDaemon)
+ return customDaemon;
+
+ if (virFileIsExecutable(VIRTLOCKD_PATH))
+ return VIRTLOCKD_PATH;
+
+ return NULL;
+}
+
+static int virLockManagerLockDaemonLoadConfig(const char *configFile)
+{
+ virConfPtr conf;
+ virConfValuePtr p;
+
+ if (access(configFile, R_OK) == -1) {
+ if (errno != ENOENT) {
+ virReportSystemError(errno,
+ _("Unable to access config file %s"),
+ configFile);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (!(conf = virConfReadFile(configFile, 0)))
+ return -1;
+
+#define CHECK_TYPE(name,typ) if (p && p->type != (typ)) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ "%s: %s: expected type " #typ, \
+ configFile, (name)); \
+ virConfFree(conf); \
+ return -1; \
+ }
+
+ p = virConfGetValue(conf, "auto_disk_leases");
+ CHECK_TYPE("auto_disk_leases", VIR_CONF_LONG);
+ if (p) driver->autoDiskLease = p->l;
+
+ p = virConfGetValue(conf, "require_lease_for_disks");
+ CHECK_TYPE("require_lease_for_disks", VIR_CONF_LONG);
+ if (p)
+ driver->requireLeaseForDisks = p->l;
+ else
+ driver->requireLeaseForDisks = !driver->autoDiskLease;
+
+ virConfFree(conf);
+ return 0;
+}
+
+
+static char *virLockManagerLockDaemonPath(bool privileged)
+{
+ char *path;
+ if (privileged) {
+ if (!(path = strdup(LOCALSTATEDIR "/run/libvirt/virtlockd-sock"))) {
+ virReportOOMError();
+ return NULL;
+ }
+ } else {
+ char *rundir = NULL;
+
+ if (!(rundir = virGetUserRuntimeDirectory()))
+ return NULL;
+
+ if (virAsprintf(&path, "%s/virtlockd-sock", rundir) < 0) {
+ VIR_FREE(rundir);
+ virReportOOMError();
+ return NULL;
+ }
+
+ }
+ return path;
+}
+
+
+static int
+virLockManagerLockDaemonConnectionRegister(virLockManagerPtr lock,
+ virNetClientPtr client,
+ virNetClientProgramPtr program,
+ int *counter)
+{
+ virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
+ virLockSpaceProtocolRegisterArgs args;
+ int rv = -1;
+
+ memset(&args, 0, sizeof(args));
+
+ args.flags = 0;
+ memcpy(args.owner.uuid, priv->uuid, VIR_UUID_BUFLEN);
+ args.owner.name = priv->name;
+ args.owner.id = priv->id;
+ args.owner.pid = priv->pid;
+
+ if (virNetClientProgramCall(program,
+ client,
+ (*counter)++,
+ VIR_LOCK_SPACE_PROTOCOL_PROC_REGISTER,
+ 0, NULL, NULL, NULL,
+ (xdrproc_t)xdr_virLockSpaceProtocolRegisterArgs, (char*)&args,
+ (xdrproc_t)xdr_void, NULL) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ return rv;
+}
+
+
+static int
+virLockManagerLockDaemonConnectionRestrict(virLockManagerPtr lock ATTRIBUTE_UNUSED,
+ virNetClientPtr client,
+ virNetClientProgramPtr program,
+ int *counter)
+{
+ virLockSpaceProtocolRestrictArgs args;
+ int rv = -1;
+
+ memset(&args, 0, sizeof(args));
+
+ args.flags = 0;
+
+ if (virNetClientProgramCall(program,
+ client,
+ (*counter)++,
+ VIR_LOCK_SPACE_PROTOCOL_PROC_RESTRICT,
+ 0, NULL, NULL, NULL,
+ (xdrproc_t)xdr_virLockSpaceProtocolRestrictArgs, (char*)&args,
+ (xdrproc_t)xdr_void, NULL) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ return rv;
+}
+
+
+static virNetClientPtr virLockManagerLockDaemonConnectionNew(bool privileged,
+ virNetClientProgramPtr *prog)
+{
+ virNetClientPtr client = NULL;
+ char *lockdpath;
+ const char *daemonPath = NULL;
+
+ *prog = NULL;
+
+ if (!(lockdpath = virLockManagerLockDaemonPath(privileged)))
+ goto error;
+
+ if (!privileged)
+ daemonPath = virLockManagerLockDaemonFindDaemon();
+
+ if (!(client = virNetClientNewUNIX(lockdpath,
+ daemonPath != NULL,
+ daemonPath)))
+ goto error;
+
+ if (!(*prog = virNetClientProgramNew(VIR_LOCK_SPACE_PROTOCOL_PROGRAM,
+ VIR_LOCK_SPACE_PROTOCOL_PROGRAM_VERSION,
+ NULL,
+ 0,
+ NULL)))
+ goto error;
+
+ if (virNetClientAddProgram(client, *prog) < 0)
+ goto error;
+
+ VIR_FREE(lockdpath);
+
+ return client;
+
+error:
+ VIR_FREE(lockdpath);
+ virNetClientClose(client);
+ virObjectUnref(client);
+ virObjectUnref(*prog);
+ return NULL;
+}
+
+
+static virNetClientPtr
+virLockManagerLockDaemonConnect(virLockManagerPtr lock,
+ virNetClientProgramPtr *program,
+ int *counter)
+{
+ virNetClientPtr client;
+
+ if (!(client = virLockManagerLockDaemonConnectionNew(getuid() == 0, program)))
+ return NULL;
+
+ if (virLockManagerLockDaemonConnectionRegister(lock,
+ client,
+ *program,
+ counter) < 0)
+ goto error;
+
+ return client;
+
+error:
+ virNetClientClose(client);
+ virObjectUnref(client);
+ return NULL;
+}
+
+
+static int virLockManagerLockDaemonDeinit(void);
+
+static int virLockManagerLockDaemonInit(unsigned int version,
+ const char *configFile,
+ unsigned int flags)
+{
+ VIR_DEBUG("version=%u configFile=%s flags=%x", version, NULLSTR(configFile), flags);
+
+ virCheckFlags(0, -1);
+
+ if (driver)
+ return 0;
+
+ if (VIR_ALLOC(driver) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ driver->requireLeaseForDisks = true;
+ driver->autoDiskLease = true;
+
+ if (virLockManagerLockDaemonLoadConfig(configFile) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ virLockManagerLockDaemonDeinit();
+ return -1;
+}
+
+static int virLockManagerLockDaemonDeinit(void)
+{
+ if (!driver)
+ return 0;
+
+ VIR_FREE(driver);
+
+ return 0;
+}
+
+static void virLockManagerLockDaemonFree(virLockManagerPtr lock)
+{
+ virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
+ size_t i;
+
+ if (!priv)
+ return;
+
+ lock->privateData = NULL;
+
+ for (i = 0 ; i < priv->nresources ; i++) {
+ VIR_FREE(priv->resources[i].lockspace);
+ VIR_FREE(priv->resources[i].name);
+ }
+ VIR_FREE(priv->resources);
+
+ VIR_FREE(priv->name);
+
+ VIR_FREE(priv);
+}
+
+
+static int virLockManagerLockDaemonNew(virLockManagerPtr lock,
+ unsigned int type,
+ size_t nparams,
+ virLockManagerParamPtr params,
+ unsigned int flags)
+{
+ virLockManagerLockDaemonPrivatePtr priv;
+ size_t i;
+
+ virCheckFlags(VIR_LOCK_MANAGER_USES_STATE, -1);
+
+ if (VIR_ALLOC(priv) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ lock->privateData = priv;
+
+ switch (type) {
+ case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
+ for (i = 0 ; i < nparams ; i++) {
+ if (STREQ(params[i].key, "uuid")) {
+ memcpy(priv->uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
+ } else if (STREQ(params[i].key, "name")) {
+ if (!(priv->name = strdup(params[i].value.str))) {
+ virReportOOMError();
+ return -1;
+ }
+ } else if (STREQ(params[i].key, "id")) {
+ priv->id = params[i].value.i;
+ } else if (STREQ(params[i].key, "pid")) {
+ priv->pid = params[i].value.i;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected parameter %s for object"),
+ params[i].key);
+ }
+ }
+ if (priv->id == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing ID parameter for domain object"));
+ return -1;
+ }
+ if (priv->pid == 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing PID parameter for domain object"));
+ return -1;
+ }
+ if (!priv->name) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing name parameter for domain object"));
+ return -1;
+ }
+ if (!virUUIDIsValid(priv->uuid)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing UUID parameter for domain object"));
+ return -1;
+ }
+ break;
+
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown lock manager object type %d"),
+ type);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock,
+ unsigned int type,
+ const char *name,
+ size_t nparams,
+ virLockManagerParamPtr params,
+ unsigned int flags)
+{
+ virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
+ char *newName;
+ char *newLockspace = NULL;
+
+ virCheckFlags(VIR_LOCK_MANAGER_RESOURCE_READONLY |
+ VIR_LOCK_MANAGER_RESOURCE_SHARED, -1);
+
+ if (flags & VIR_LOCK_MANAGER_RESOURCE_READONLY)
+ return 0;
+
+ switch (type) {
+ case VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK:
+ if (params || nparams) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unexpected parameters for disk resource"));
+ return -1;
+ }
+ if (!driver->autoDiskLease) {
+ if (!(flags & (VIR_LOCK_MANAGER_RESOURCE_SHARED |
+ VIR_LOCK_MANAGER_RESOURCE_READONLY)))
+ priv->hasRWDisks = true;
+ return 0;
+ }
+ if (!(newLockspace = strdup(""))) {
+ virReportOOMError();
+ return -1;
+ }
+ break;
+ case VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE: {
+ size_t i;
+ char *path = NULL;
+ char *lockspace = NULL;
+ for (i = 0 ; i < nparams ; i++) {
+ if (STREQ(params[i].key, "offset")) {
+ if (params[i].value.ul != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Offset must be zero for this lock manager"));
+ return -1;
+ }
+ } else if (STREQ(params[i].key, "lockspace")) {
+ lockspace = params[i].value.str;
+ } else if (STREQ(params[i].key, "path")) {
+ path = params[i].value.str;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected parameter %s for lease resource"),
+ params[i].key);
+ return -1;
+ }
+ }
+ if (!path || !lockspace) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Missing path or lockspace for lease resource"));
+ return -1;
+ }
+ if (virAsprintf(&newLockspace, "%s/%s",
+ path, lockspace) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ } break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown lock manager object type %d"),
+ type);
+ return -1;
+ }
+
+ if (!(newName = strdup(name)))
+ goto no_memory;
+
+ if (VIR_EXPAND_N(priv->resources, priv->nresources, 1) < 0)
+ goto no_memory;
+
+ priv->resources[priv->nresources-1].lockspace = newLockspace;
+ priv->resources[priv->nresources-1].name = newName;
+
+ if (flags & VIR_LOCK_MANAGER_RESOURCE_SHARED)
+ priv->resources[priv->nresources-1].flags |=
+ VIR_LOCK_SPACE_PROTOCOL_ACQUIRE_RESOURCE_SHARED;
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+ VIR_FREE(newName);
+ return -1;
+}
+
+
+static int virLockManagerLockDaemonAcquire(virLockManagerPtr lock,
+ const char *state ATTRIBUTE_UNUSED,
+ unsigned int flags,
+ virDomainLockFailureAction action ATTRIBUTE_UNUSED,
+ int *fd)
+{
+ virNetClientPtr client = NULL;
+ virNetClientProgramPtr program = NULL;
+ int counter = 0;
+ int rv = -1;
+ virLockManagerLockDaemonPrivatePtr priv = lock->privateData;
+
+ virCheckFlags(VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY |
+ VIR_LOCK_MANAGER_ACQUIRE_RESTRICT, -1);
+
+ if (priv->nresources == 0 &&
+ priv->hasRWDisks &&
+ driver->requireLeaseForDisks) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Read/write, exclusive access, disks were present, but no leases specified"));
+ return -1;
+ }
+
+ if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
+ goto cleanup;
+
+ if (fd &&
+ (*fd = virNetClientDupFD(client, false)) < 0)
+ goto cleanup;
+
+ if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) {
+ size_t i;
+ for (i = 0 ; i < priv->nresources ; i++) {
+ virLockSpaceProtocolAcquireResourceArgs args;
+
+ memset(&args, 0, sizeof(args));
+
+ if (priv->resources[i].lockspace)
+ args.path = priv->resources[i].lockspace;
+ args.name = priv->resources[i].name;
+ args.flags = priv->resources[i].flags;
+
+ if (virNetClientProgramCall(program,
+ client,
+ counter++,
+ VIR_LOCK_SPACE_PROTOCOL_PROC_ACQUIRE_RESOURCE,
+ 0, NULL, NULL, NULL,
+ (xdrproc_t)xdr_virLockSpaceProtocolAcquireResourceArgs, &args,
+ (xdrproc_t)xdr_void, NULL) < 0)
+ goto cleanup;
+ }
+ }
+
+ if ((flags & VIR_LOCK_MANAGER_ACQUIRE_RESTRICT) &&
+ virLockManagerLockDaemonConnectionRestrict(lock, client, program, &counter) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ if (rv != 0 && fd)
+ VIR_FORCE_CLOSE(*fd);
+ virNetClientClose(client);
+ virObjectUnref(client);
+ virObjectUnref(program);
+
+ return rv;
+}
+
+static int virLockManagerLockDaemonRelease(virLockManagerPtr lock,
+ char **state,
+ unsigned int flags)
+{
+ virNetClientPtr client = NULL;
+ virNetClientProgramPtr program = NULL;
+ int counter = 0;
+ virLockSpaceProtocolReleaseResourceArgs args;
+ int rv = -1;
+
+ memset(&args, 0, sizeof(args));
+
+ if (state)
+ *state = NULL;
+
+ if (!(client = virLockManagerLockDaemonConnect(lock, &program, &counter)))
+ goto cleanup;
+
+ args.flags = flags;
+
+ if (virNetClientProgramCall(program,
+ client,
+ counter++,
+ VIR_LOCK_SPACE_PROTOCOL_PROC_RELEASE_RESOURCE,
+ 0, NULL, NULL, NULL,
+ (xdrproc_t)xdr_virLockSpaceProtocolReleaseResourceArgs, &args,
+ (xdrproc_t)xdr_void, NULL) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ virNetClientClose(client);
+ virObjectUnref(client);
+ virObjectUnref(program);
+
+ return rv;
+}
+
+
+static int virLockManagerLockDaemonInquire(virLockManagerPtr lock ATTRIBUTE_UNUSED,
+ char **state,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ if (state)
+ *state = NULL;
+
+ return 0;
+}
+
+virLockDriver virLockDriverImpl =
+{
+ .version = VIR_LOCK_MANAGER_VERSION,
+ .flags = 0,
+
+ .drvInit = virLockManagerLockDaemonInit,
+ .drvDeinit = virLockManagerLockDaemonDeinit,
+
+ .drvNew = virLockManagerLockDaemonNew,
+ .drvFree = virLockManagerLockDaemonFree,
+
+ .drvAddResource = virLockManagerLockDaemonAddResource,
+
+ .drvAcquire = virLockManagerLockDaemonAcquire,
+ .drvRelease = virLockManagerLockDaemonRelease,
+
+ .drvInquire = virLockManagerLockDaemonInquire,
+};
diff --git a/src/locking/lockd.conf b/src/locking/lockd.conf
new file mode 100644
index 0000000000..0b885c534f
--- /dev/null
+++ b/src/locking/lockd.conf
@@ -0,0 +1,18 @@
+
+#
+# The default lockd behaviour is to acquire locks directly
+# against each configured disk file / block device. If the
+# application wishes to instead manually manage leases in
+# the guest XML, then this parameter can be disabled
+#
+#auto_disk_leases = 0
+
+#
+# Flag to determine whether we allow starting of guests
+# which do not have any <lease> elements defined in their
+# configuration.
+#
+# If 'auto_disk_leases' is disabled, this setting defaults
+# to enabled, otherwise it defaults to disabled.
+#
+#require_lease_for_disks = 1
diff --git a/src/locking/test_libvirt_lockd.aug.in b/src/locking/test_libvirt_lockd.aug.in
new file mode 100644
index 0000000000..5be0d99b94
--- /dev/null
+++ b/src/locking/test_libvirt_lockd.aug.in
@@ -0,0 +1,6 @@
+module Test_libvirt_lockd =
+ ::CONFIG::
+
+ test Libvirt_lockd.lns get conf =
+{ "auto_disk_leases" = "0" }
+{ "require_lease_for_disks" = "1" }