提交 eb8268a4 编写于 作者: D Daniel P. Berrange

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: NDaniel P. Berrange <berrange@redhat.com>
上级 f234dc93
......@@ -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
......
......@@ -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
......
......@@ -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.
......
......@@ -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
......
(* /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
/*
* 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,
};
#
# 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
module Test_libvirt_lockd =
::CONFIG::
test Libvirt_lockd.lns get conf =
{ "auto_disk_leases" = "0" }
{ "require_lease_for_disks" = "1" }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册