mirror of https://gitee.com/openkylin/libvirt.git
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>
This commit is contained in:
parent
f234dc9366
commit
eb8268a4f6
|
@ -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
|
||||
|
|
2
run.in
2
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
};
|
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
module Test_libvirt_lockd =
|
||||
::CONFIG::
|
||||
|
||||
test Libvirt_lockd.lns get conf =
|
||||
{ "auto_disk_leases" = "0" }
|
||||
{ "require_lease_for_disks" = "1" }
|
Loading…
Reference in New Issue