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
---
libvirt.spec.in | 3 +
src/Makefile.am | 25 ++++++++++-
src/locking/libvirt_sanlock.aug | 31 ++++++++++++++
src/locking/lock_driver_sanlock.c | 77 ++++++++++++++++++++++++++++++++-
src/locking/sanlock.conf | 6 +++
src/locking/test_libvirt_sanlock.aug | 7 +++
6 files changed, 144 insertions(+), 5 deletions(-)
create mode 100644 src/locking/libvirt_sanlock.aug
create mode 100644 src/locking/sanlock.conf
create mode 100644 src/locking/test_libvirt_sanlock.aug
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 11b8591..9b22983 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1028,7 +1028,10 @@ fi
%if %{with_sanlock}
%files lock-sanlock
%defattr(-, root, root)
+%config(noreplace) %{_sysconfdir}/libvirt/qemu-sanlock.conf
%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
%files client -f %{name}.lang
diff --git a/src/Makefile.am b/src/Makefile.am
index 52fc63c..9208883 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1035,6 +1035,10 @@ if WITH_LXC
$(srcdir)/lxc/test_libvirtd_lxc.aug; \
fi
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:
@@ -1182,9 +1186,26 @@ lockdriver_LTLIBRARIES = sanlock.la
sanlock_la_SOURCES = $(LOCK_DRIVER_SANLOCK_SOURCES)
sanlock_la_CFLAGS = $(AM_CLFAGS)
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
-EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES)
+EXTRA_DIST += $(LOCK_DRIVER_SANLOCK_SOURCES) locking/sanlock.conf
endif
noinst_LTLIBRARIES += libvirt-net-rpc.la libvirt-net-rpc-server.la
libvirt-net-rpc-client.la
diff --git a/src/locking/libvirt_sanlock.aug b/src/locking/libvirt_sanlock.aug
new file mode 100644
index 0000000..baa639a
--- /dev/null
+++ b/src/locking/libvirt_sanlock.aug
@@ -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
diff --git a/src/locking/lock_driver_sanlock.c b/src/locking/lock_driver_sanlock.c
index 3eab23e..7ad54e8 100644
--- a/src/locking/lock_driver_sanlock.c
+++ b/src/locking/lock_driver_sanlock.c
@@ -45,9 +45,19 @@
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
+
+typedef struct _virLockManagerSanlockDriver virLockManagerSanlockDriver;
+typedef virLockManagerSanlockDriver *virLockManagerSanlockDriverPtr;
+
typedef struct _virLockManagerSanlockPrivate virLockManagerSanlockPrivate;
typedef virLockManagerSanlockPrivate *virLockManagerSanlockPrivatePtr;
+struct _virLockManagerSanlockDriver {
+ bool requireLeaseForDisks;
+};
+
+static virLockManagerSanlockDriver *driver = NULL;
+
struct _virLockManagerSanlockPrivate {
char vm_name[SANLK_NAME_LEN];
char vm_uuid[VIR_UUID_BUFLEN];
@@ -62,22 +72,76 @@ struct _virLockManagerSanlockPrivate {
/*
* sanlock plugin for the libvirt virLockManager API
*/
+static int virLockManagerSanlockLoadConfig(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)) { \
+ 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 ATTRIBUTE_UNUSED,
- const char *configFile ATTRIBUTE_UNUSED,
+
+static int virLockManagerSanlockInit(unsigned int version,
+ const char *configFile,
unsigned int flags)
{
+ VIR_DEBUG("version=%u configFile=%s flags=%u", version,
NULLSTR(configFile), flags);
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;
}
static int virLockManagerSanlockDeinit(void)
{
+ if (!driver)
+ return 0;
+
virLockError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Unloading sanlock plugin is forbidden"));
return -1;
}
+
static int virLockManagerSanlockNew(virLockManagerPtr lock,
unsigned int type,
size_t nparams,
@@ -90,6 +154,12 @@ static int virLockManagerSanlockNew(virLockManagerPtr lock,
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) {
virLockError(VIR_ERR_INTERNAL_ERROR,
_("Unsupported object type %d"), type);
@@ -245,7 +315,8 @@ static int virLockManagerSanlockAcquire(virLockManagerPtr lock,
VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY, -1);
if (priv->res_count == 0 &&
- priv->hasRWDisks) {
+ priv->hasRWDisks &&
+ driver->requireLeaseForDisks) {
virLockError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Read/write, exclusive access, disks were present, but no
leases specified"));
return -1;
diff --git a/src/locking/sanlock.conf b/src/locking/sanlock.conf
new file mode 100644
index 0000000..818b529
--- /dev/null
+++ b/src/locking/sanlock.conf
@@ -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
diff --git a/src/locking/test_libvirt_sanlock.aug b/src/locking/test_libvirt_sanlock.aug
new file mode 100644
index 0000000..2f1f57a
--- /dev/null
+++ b/src/locking/test_libvirt_sanlock.aug
@@ -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" }
--
1.7.4.4