Support loading a configuration file for sanlock plugin

Introduce a configuration file with a single parameter
'require_lease_for_disks', which is used to decide whether
it is allowed to start a guest which has read/write disks,
but without any leases.

* libvirt.spec.in: Add sanlock config file and augeas
  lens
* src/Makefile.am: Install sanlock config file and
  augeas lens
* src/locking/libvirt_sanlock.aug: Augeas master lens
* src/locking/test_libvirt_sanlock.aug: Augeas test file
* src/locking/sanlock.conf: Example sanlock config
* src/locking/lock_driver_sanlock.c: Wire up loading
  of configuration file
This commit is contained in:
Daniel P. Berrange 2011-06-14 09:20:49 +01:00
parent 5df29ebc25
commit 58eb4f2cbb
6 changed files with 144 additions and 5 deletions

View File

@ -1031,7 +1031,10 @@ fi
%if %{with_sanlock} %if %{with_sanlock}
%files lock-sanlock %files lock-sanlock
%defattr(-, root, root) %defattr(-, root, root)
%config(noreplace) %{_sysconfdir}/libvirt/qemu-sanlock.conf
%attr(0755, root, root) %{_libdir}/libvirt/lock-driver/sanlock.so %attr(0755, root, root) %{_libdir}/libvirt/lock-driver/sanlock.so
%{_datadir}/augeas/lenses/libvirt_sanlock.aug
%{_datadir}/augeas/lenses/tests/test_libvirt_sanlock.aug
%endif %endif
%files client -f %{name}.lang %files client -f %{name}.lang

View File

@ -1035,6 +1035,10 @@ if WITH_LXC
$(srcdir)/lxc/test_libvirtd_lxc.aug; \ $(srcdir)/lxc/test_libvirtd_lxc.aug; \
fi fi
endif endif
$(AM_V_GEN)if test -x '$(AUGPARSE)'; then \
'$(AUGPARSE)' -I $(srcdir)/locking \
$(srcdir)/locking/test_libvirt_sanlock.aug; \
fi
# #
# Build our version script. This is composed of three parts: # Build our version script. This is composed of three parts:
@ -1189,9 +1193,26 @@ lockdriver_LTLIBRARIES = sanlock.la
sanlock_la_SOURCES = $(LOCK_DRIVER_SANLOCK_SOURCES) sanlock_la_SOURCES = $(LOCK_DRIVER_SANLOCK_SOURCES)
sanlock_la_CFLAGS = $(AM_CLFAGS) sanlock_la_CFLAGS = $(AM_CLFAGS)
sanlock_la_LDFLAGS = -module -avoid-version sanlock_la_LDFLAGS = -module -avoid-version
sanlock_la_LIBADD = -lsanlock sanlock_la_LIBADD = -lsanlock \
../gnulib/lib/libgnu.la
augeas_DATA += locking/libvirt_sanlock.aug
augeastest_DATA += locking/test_libvirt_sanlock.aug
EXTRA_DIST += locking/sanlock.conf \
locking/libvirt_sanlock.aug \
locking/test_libvirt_sanlock.aug
$(builddir)/locking/%-sanlock.conf: $(srcdir)/locking/sanlock.conf
$(AM_V_GEN)mkdir locking ; \
cp $< $@
if WITH_QEMU
conf_DATA += locking/qemu-sanlock.conf
BUILT_SOURCES += locking/qemu-sanlock.conf
endif
else else
EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES) EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES) locking/sanlock.conf
endif endif
noinst_LTLIBRARIES += libvirt-net-rpc.la libvirt-net-rpc-server.la libvirt-net-rpc-client.la noinst_LTLIBRARIES += libvirt-net-rpc.la libvirt-net-rpc-server.la libvirt-net-rpc-client.la

View File

@ -0,0 +1,31 @@
(* /etc/libvirt/qemu-sanlock.conf *)
module Libvirt_sanlock =
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 "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-sanlock.conf"
. Util.stdexcl
let xfm = transform lns filter

View File

@ -45,9 +45,19 @@
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__) __FUNCTION__, __LINE__, __VA_ARGS__)
typedef struct _virLockManagerSanlockDriver virLockManagerSanlockDriver;
typedef virLockManagerSanlockDriver *virLockManagerSanlockDriverPtr;
typedef struct _virLockManagerSanlockPrivate virLockManagerSanlockPrivate; typedef struct _virLockManagerSanlockPrivate virLockManagerSanlockPrivate;
typedef virLockManagerSanlockPrivate *virLockManagerSanlockPrivatePtr; typedef virLockManagerSanlockPrivate *virLockManagerSanlockPrivatePtr;
struct _virLockManagerSanlockDriver {
bool requireLeaseForDisks;
};
static virLockManagerSanlockDriver *driver = NULL;
struct _virLockManagerSanlockPrivate { struct _virLockManagerSanlockPrivate {
char vm_name[SANLK_NAME_LEN]; char vm_name[SANLK_NAME_LEN];
char vm_uuid[VIR_UUID_BUFLEN]; char vm_uuid[VIR_UUID_BUFLEN];
@ -62,22 +72,76 @@ struct _virLockManagerSanlockPrivate {
/* /*
* sanlock plugin for the libvirt virLockManager API * sanlock plugin for the libvirt virLockManager API
*/ */
static int virLockManagerSanlockLoadConfig(const char *configFile)
{
virConfPtr conf;
virConfValuePtr p;
static int virLockManagerSanlockInit(unsigned int version ATTRIBUTE_UNUSED, if (access(configFile, R_OK) == -1) {
const char *configFile ATTRIBUTE_UNUSED, 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)) { \
virLockError(VIR_ERR_INTERNAL_ERROR, \
"%s: %s: expected type " #typ, \
configFile, (name)); \
virConfFree(conf); \
return -1; \
}
p = virConfGetValue(conf, "require_lease_for_disks");
CHECK_TYPE("require_lease_for_disks", VIR_CONF_LONG);
if (p)
driver->requireLeaseForDisks = p->l;
virConfFree(conf);
return 0;
}
static int virLockManagerSanlockInit(unsigned int version,
const char *configFile,
unsigned int flags) unsigned int flags)
{ {
VIR_DEBUG("version=%u configFile=%s flags=%u", version, NULLSTR(configFile), flags);
virCheckFlags(0, -1); virCheckFlags(0, -1);
if (driver)
return 0;
if (VIR_ALLOC(driver) < 0) {
virReportOOMError();
return -1;
}
driver->requireLeaseForDisks = true;
if (virLockManagerSanlockLoadConfig(configFile) < 0)
return -1;
return 0; return 0;
} }
static int virLockManagerSanlockDeinit(void) static int virLockManagerSanlockDeinit(void)
{ {
if (!driver)
return 0;
virLockError(VIR_ERR_INTERNAL_ERROR, "%s", virLockError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unloading sanlock plugin is forbidden")); _("Unloading sanlock plugin is forbidden"));
return -1; return -1;
} }
static int virLockManagerSanlockNew(virLockManagerPtr lock, static int virLockManagerSanlockNew(virLockManagerPtr lock,
unsigned int type, unsigned int type,
size_t nparams, size_t nparams,
@ -90,6 +154,12 @@ static int virLockManagerSanlockNew(virLockManagerPtr lock,
virCheckFlags(0, -1); virCheckFlags(0, -1);
if (!driver) {
virLockError(VIR_ERR_INTERNAL_ERROR,
_("Sanlock plugin is not initialized"));
return -1;
}
if (type != VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN) { if (type != VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN) {
virLockError(VIR_ERR_INTERNAL_ERROR, virLockError(VIR_ERR_INTERNAL_ERROR,
_("Unsupported object type %d"), type); _("Unsupported object type %d"), type);
@ -246,7 +316,8 @@ static int virLockManagerSanlockAcquire(virLockManagerPtr lock,
VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1); VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1);
if (priv->res_count == 0 && if (priv->res_count == 0 &&
priv->hasRWDisks) { priv->hasRWDisks &&
driver->requireLeaseForDisks) {
virLockError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virLockError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Read/write, exclusive access, disks were present, but no leases specified")); _("Read/write, exclusive access, disks were present, but no leases specified"));
return -1; return -1;

6
src/locking/sanlock.conf Normal file
View File

@ -0,0 +1,6 @@
#
# Flag to determine whether we allow starting of guests
# which do not have any <lease> elements defined in their
# configuration.
#
#require_lease_for_disks = 1

View File

@ -0,0 +1,7 @@
module Test_libvirt_sanlock =
let conf = "require_lease_for_disks = 1
"
test Libvirt_sanlock.lns get conf =
{ "require_lease_for_disks" = "1" }