To facilitate use of the locking plugins from hypervisor drivers,
introduce a higher level API for locking virDomainObjPtr instances.
In includes APIs targetted to VM startup, and hotplug/unplug
* src/Makefile.am: Add domain lock API
* src/locking/domain_lock.c, src/locking/domain_lock.h: High
level API for domain locking
---
src/Makefile.am | 3 +-
src/libvirt_private.syms | 11 ++
src/locking/README | 7 +
src/locking/domain_lock.c | 284 +++++++++++++++++++++++++++++++++++++++++++++
src/locking/domain_lock.h | 56 +++++++++
5 files changed, 360 insertions(+), 1 deletions(-)
create mode 100644 src/locking/domain_lock.c
create mode 100644 src/locking/domain_lock.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 96e2edf..1e5a72e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -96,7 +96,8 @@ DRIVER_SOURCES = \
libvirt.c libvirt_internal.h \
locking/lock_manager.c locking/lock_manager.h \
locking/lock_driver.h \
- locking/lock_driver_nop.h locking/lock_driver_nop.c
+ locking/lock_driver_nop.h locking/lock_driver_nop.c \
+ locking/domain_lock.h locking/domain_lock.c
# XML configuration format handling sources
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d27d294..779fada 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -409,6 +409,17 @@ virDomainEventWatchdogNewFromDom;
virDomainEventWatchdogNewFromObj;
+# domain_lock.h
+virDomainLockProcessStart;
+virDomainLockProcessInquire;
+virDomainLockProcessPause;
+virDomainLockProcessResume;
+virDomainLockDiskAttach;
+virDomainLockDiskDetach;
+virDomainLockLeaseAttach;
+virDomainLockLeaseDetach;
+
+
# domain_nwfilter.h
virDomainConfNWFilterInstantiate;
virDomainConfNWFilterRegister;
diff --git a/src/locking/README b/src/locking/README
index 4fa4f89..da2a8f8 100644
--- a/src/locking/README
+++ b/src/locking/README
@@ -1,3 +1,10 @@
+ Using the Lock Manager APIs
+ ===========================
+
+This file describes how to use the lock manager APIs.
+All the guest lifecycle sequences here have higher
+level wrappers provided by the 'domain_lock.h' API,
+which simplify thue usage
At libvirtd startup:
diff --git a/src/locking/domain_lock.c b/src/locking/domain_lock.c
new file mode 100644
index 0000000..85352e2
--- /dev/null
+++ b/src/locking/domain_lock.c
@@ -0,0 +1,284 @@
+/*
+ * domain_lock.c: Locking for domain lifecycle operations
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#include <intprops.h>
+
+#include "domain_lock.h"
+#include "memory.h"
+#include "uuid.h"
+#include "virterror_internal.h"
+#include "logging.h"
+
+#define VIR_FROM_THIS VIR_FROM_LOCKING
+
+
+static int virDomainLockManagerAddLease(virLockManagerPtr lock,
+ virDomainLeaseDefPtr lease)
+{
+ unsigned int leaseFlags = 0;
+ virLockManagerParam lparams[] = {
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
+ .key = "path",
+ .value = { .str = lease->path },
+ },
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_ULONG,
+ .key = "offset",
+ .value = { .ul = lease->offset },
+ },
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
+ .key = "lockspace",
+ .value = { .str = lease->lockspace },
+ },
+ };
+ size_t nparams = ARRAY_CARDINALITY(lparams);
+ if (!lease->lockspace)
+ nparams--;
+
+ VIR_DEBUG("Add lease %s", lease->path);
+ if (virLockManagerAddResource(lock,
+ VIR_LOCK_MANAGER_RESOURCE_TYPE_LEASE,
+ lease->key,
+ nparams,
+ lparams,
+ leaseFlags) < 0) {
+ VIR_DEBUG("Failed to add lease %s", lease->path);
+ return -1;
+ }
+ return 0;
+}
+
+
+static int virDomainLockManagerAddDisk(virLockManagerPtr lock,
+ virDomainDiskDefPtr disk)
+{
+ unsigned int diskFlags = 0;
+ if (!disk->src)
+ return 0;
+
+ if (!(disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK ||
+ disk->type == VIR_DOMAIN_DISK_TYPE_FILE ||
+ disk->type == VIR_DOMAIN_DISK_TYPE_DIR))
+ return 0;
+
+ if (disk->readonly)
+ diskFlags |= VIR_LOCK_MANAGER_RESOURCE_READONLY;
+ if (disk->shared)
+ diskFlags |= VIR_LOCK_MANAGER_RESOURCE_SHARED;
+
+ VIR_DEBUG("Add disk %s", disk->src);
+ if (virLockManagerAddResource(lock,
+ VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
+ disk->src,
+ 0,
+ NULL,
+ diskFlags) < 0) {
+ VIR_DEBUG("Failed add disk %s", disk->src);
+ return -1;
+ }
+ return 0;
+}
+
+static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ bool withResources)
+{
+ virLockManagerPtr lock;
+ int i;
+ virLockManagerParam params[] = {
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
+ .key = "uuid",
+ },
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
+ .key = "name",
+ .value = { .str = dom->def->name },
+ },
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
+ .key = "id",
+ .value = { .i = dom->def->id },
+ },
+ { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
+ .key = "pid",
+ .value = { .i = dom->pid },
+ },
+ };
+ VIR_DEBUG("plugin=%p dom=%p withResources=%d",
+ plugin, dom, withResources);
+
+ memcpy(params[0].value.uuid, dom->def->uuid, VIR_UUID_BUFLEN);
+
+ if (!(lock = virLockManagerNew(plugin,
+ VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN,
+ ARRAY_CARDINALITY(params),
+ params,
+ 0)))
+ goto error;
+
+ if (withResources) {
+ VIR_DEBUG("Adding leases");
+ for (i = 0 ; i < dom->def->nleases ; i++)
+ if (virDomainLockManagerAddLease(lock, dom->def->leases[i]) < 0)
+ goto error;
+
+ VIR_DEBUG("Adding disks");
+ for (i = 0 ; i < dom->def->ndisks ; i++)
+ if (virDomainLockManagerAddDisk(lock, dom->def->disks[i]) < 0)
+ goto error;
+ }
+
+ return lock;
+
+error:
+ virLockManagerFree(lock);
+ return NULL;
+}
+
+
+int virDomainLockProcessStart(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ bool paused)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, true);
+ int ret;
+ if (paused)
+ ret = virLockManagerAcquire(lock, NULL, VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY);
+ else
+ ret = virLockManagerAcquire(lock, NULL, 0);
+
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+int virDomainLockProcessPause(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ char **state)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, true);
+ int ret = virLockManagerRelease(lock, state, 0);
+
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+int virDomainLockProcessResume(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ const char *state)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, true);
+ int ret = virLockManagerAcquire(lock, state, 0);
+
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+int virDomainLockProcessInquire(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ char **state)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, true);
+ int ret = virLockManagerInquire(lock, state, 0);
+
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+
+int virDomainLockDiskAttach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainDiskDefPtr disk)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, false);
+ int ret = -1;
+
+ if (virDomainLockManagerAddDisk(lock, disk) < 0)
+ goto cleanup;
+
+ if (virLockManagerAcquire(lock, NULL, 0) < 0)
+ goto cleanup;
+
+cleanup:
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+int virDomainLockDiskDetach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainDiskDefPtr disk)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, false);
+ int ret = -1;
+
+ if (virDomainLockManagerAddDisk(lock, disk) < 0)
+ goto cleanup;
+
+ if (virLockManagerRelease(lock, NULL, 0) < 0)
+ goto cleanup;
+
+cleanup:
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+
+int virDomainLockLeaseAttach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainLeaseDefPtr lease)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, false);
+ int ret = -1;
+
+ if (virDomainLockManagerAddLease(lock, lease) < 0)
+ goto cleanup;
+
+ if (virLockManagerAcquire(lock, NULL, 0) < 0)
+ goto cleanup;
+
+cleanup:
+ virLockManagerFree(lock);
+
+ return ret;
+}
+
+int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainLeaseDefPtr lease)
+{
+ virLockManagerPtr lock = virDomainLockManagerNew(plugin, dom, false);
+ int ret = -1;
+
+ if (virDomainLockManagerAddLease(lock, lease) < 0)
+ goto cleanup;
+
+ if (virLockManagerRelease(lock, NULL, 0) < 0)
+ goto cleanup;
+
+cleanup:
+ virLockManagerFree(lock);
+
+ return ret;
+}
diff --git a/src/locking/domain_lock.h b/src/locking/domain_lock.h
new file mode 100644
index 0000000..40fadd4
--- /dev/null
+++ b/src/locking/domain_lock.h
@@ -0,0 +1,56 @@
+/*
+ * domain_lock.c: Locking for domain lifecycle operations
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __VIR_DOMAIN_LOCK_H__
+# define __VIR_DOMAIN_LOCK_H__
+
+# include "internal.h"
+# include "domain_conf.h"
+# include "lock_manager.h"
+
+int virDomainLockProcessStart(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ bool paused);
+int virDomainLockProcessPause(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ char **state);
+int virDomainLockProcessResume(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ const char *state);
+int virDomainLockProcessInquire(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ char **state);
+
+int virDomainLockDiskAttach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainDiskDefPtr disk);
+int virDomainLockDiskDetach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainDiskDefPtr disk);
+
+int virDomainLockLeaseAttach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainLeaseDefPtr lease);
+int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
+ virDomainObjPtr dom,
+ virDomainLeaseDefPtr lease);
+
+#endif /* __VIR_DOMAIN_LOCK_H__ */
--
1.7.4.4