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 + * . + * + */ + +#include + +#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 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" }