#define VIR_FROM_THIS VIR_FROM_LOCKING
#define VIR_LOCK_MANAGER_SANLOCK_AUTO_DISK_LOCKSPACE "__LIBVIRT__DISKS__"
+#define VIR_LOCK_MANAGER_SANLOCK_KILLPATH LIBEXECDIR "/libvirt_sanlock_helper"
/*
* temporary fix for the case where the sanlock devel package is
static virLockManagerSanlockDriver *driver = NULL;
struct _virLockManagerSanlockPrivate {
+ const char *vm_uri;
char vm_name[SANLK_NAME_LEN];
- char vm_uuid[VIR_UUID_BUFLEN];
+ unsigned char vm_uuid[VIR_UUID_BUFLEN];
unsigned int vm_id;
unsigned int vm_pid;
unsigned int flags;
priv->vm_pid = param->value.ui;
} else if (STREQ(param->key, "id")) {
priv->vm_id = param->value.ui;
+ } else if (STREQ(param->key, "uri")) {
+ priv->vm_uri = param->value.cstr;
}
}
return 0;
}
+static int
+virLockManagerSanlockRegisterKillscript(int sock,
+ const char *vmuri,
+ const char *uuidstr,
+ virDomainLockFailureAction action)
+{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *path;
+ char *args = NULL;
+ int ret = -1;
+ int rv;
+
+ if (action > VIR_DOMAIN_LOCK_FAILURE_IGNORE) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Failure action %s is not supported by sanlock"),
+ virDomainLockFailureTypeToString(action));
+ goto cleanup;
+ }
+
+ virBufferEscape(&buf, '\\', "\\ ", "%s", vmuri);
+ virBufferAddLit(&buf, " ");
+ virBufferEscape(&buf, '\\', "\\ ", "%s", uuidstr);
+ virBufferAddLit(&buf, " ");
+ virBufferEscape(&buf, '\\', "\\ ", "%s",
+ virDomainLockFailureTypeToString(action));
+
+ if (virBufferError(&buf)) {
+ virBufferFreeAndReset(&buf);
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Unfortunately, sanlock_killpath() does not use const for either
+ * path or args even though it will just copy them into its own
+ * buffers.
+ */
+ path = (char *) VIR_LOCK_MANAGER_SANLOCK_KILLPATH;
+ args = virBufferContentAndReset(&buf);
+
+ VIR_DEBUG("Register sanlock killpath: %s %s", path, args);
+
+ /* sanlock_killpath() would just crop the strings */
+ if (strlen(path) >= SANLK_HELPER_PATH_LEN) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Sanlock helper path is longer than %d: '%s'"),
+ SANLK_HELPER_PATH_LEN - 1, path);
+ goto cleanup;
+ }
+ if (strlen(args) >= SANLK_HELPER_ARGS_LEN) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Sanlock helper arguments are longer than %d:"
+ " '%s'"),
+ SANLK_HELPER_ARGS_LEN - 1, args);
+ goto cleanup;
+ }
+
+ if ((rv = sanlock_killpath(sock, 0, path, args)) < 0) {
+ if (rv <= -200) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to register lock failure action:"
+ " error %d"), rv);
+ } else {
+ virReportSystemError(-rv, "%s",
+ _("Failed to register lock failure"
+ " action"));
+ }
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(args);
+ return ret;
+}
+
static int virLockManagerSanlockAcquire(virLockManagerPtr lock,
const char *state,
unsigned int flags,
- virDomainLockFailureAction action ATTRIBUTE_UNUSED,
+ virDomainLockFailureAction action,
int *fd)
{
virLockManagerSanlockPrivatePtr priv = lock->privateData;
res_count = priv->res_count;
}
- VIR_DEBUG("Register sanlock %d", flags);
/* We only initialize 'sock' if we are in the real
* child process and we need it to be inherited
*
* If sock==-1, then sanlock auto-open/closes a
* temporary sock
*/
- if (priv->vm_pid == getpid() &&
- (sock = sanlock_register()) < 0) {
- if (sock <= -200)
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Failed to open socket to sanlock daemon: error %d"),
- sock);
- else
- virReportSystemError(-sock, "%s",
- _("Failed to open socket to sanlock daemon"));
- goto error;
+ if (priv->vm_pid == getpid()) {
+ VIR_DEBUG("Register sanlock %d", flags);
+ if ((sock = sanlock_register()) < 0) {
+ if (sock <= -200)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to open socket to sanlock daemon: error %d"),
+ sock);
+ else
+ virReportSystemError(-sock, "%s",
+ _("Failed to open socket to sanlock daemon"));
+ goto error;
+ }
+
+ if (action != VIR_DOMAIN_LOCK_FAILURE_DEFAULT) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(priv->vm_uuid, uuidstr);
+ if (virLockManagerSanlockRegisterKillscript(sock, priv->vm_uri,
+ uuidstr, action) < 0)
+ goto error;
+ }
}
if (!(flags & VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY)) {
--- /dev/null
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <locale.h>
+
+#include "configmake.h"
+#include "internal.h"
+#include "conf.h"
+#include "memory.h"
+#include "domain_conf.h"
+
+
+static int
+getArgs(int argc,
+ char **argv,
+ const char **uri,
+ const char **uuid,
+ virDomainLockFailureAction *action)
+{
+ int act;
+
+ if (argc != 4) {
+ fprintf(stderr, _("%s uri uuid action\n"), argv[0]);
+ return -1;
+ }
+
+ *uri = argv[1];
+ *uuid = argv[2];
+
+ act = virDomainLockFailureTypeFromString(argv[3]);
+ if (act < 0) {
+ fprintf(stderr, _("invalid failure action: '%s'\n"), argv[3]);
+ return -1;
+ }
+ *action = act;
+
+ return 0;
+}
+
+
+static int
+authCallback(virConnectCredentialPtr cred ATTRIBUTE_UNUSED,
+ unsigned int ncred ATTRIBUTE_UNUSED,
+ void *cbdata ATTRIBUTE_UNUSED)
+{
+ return -1;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ const char *uri;
+ const char *uuid;
+ virDomainLockFailureAction action;
+ char *xml = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ int ret = EXIT_FAILURE;
+
+ int authTypes[] = {
+ VIR_CRED_AUTHNAME,
+ VIR_CRED_ECHOPROMPT,
+ VIR_CRED_PASSPHRASE,
+ VIR_CRED_NOECHOPROMPT,
+ };
+ virConnectAuth auth = {
+ .credtype = authTypes,
+ .ncredtype = ARRAY_CARDINALITY(authTypes),
+ .cb = authCallback,
+ };
+
+ if (setlocale(LC_ALL, "") == NULL ||
+ bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
+ textdomain(PACKAGE) == NULL) {
+ fprintf(stderr, _("%s: initialization failed\n"), argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (getArgs(argc, argv, &uri, &uuid, &action) < 0)
+ goto cleanup;
+
+ if (!(conn = virConnectOpenAuth(uri, &auth, 0)) ||
+ !(dom = virDomainLookupByUUIDString(conn, uuid)))
+ goto cleanup;
+
+ switch (action) {
+ case VIR_DOMAIN_LOCK_FAILURE_POWEROFF:
+ if (virDomainDestroy(dom) == 0 ||
+ virDomainIsActive(dom) == 0)
+ ret = EXIT_SUCCESS;
+ break;
+
+ case VIR_DOMAIN_LOCK_FAILURE_RESTART:
+ if (virDomainIsPersistent(dom)) {
+ if ((virDomainDestroy(dom) == 0 ||
+ virDomainIsActive(dom) == 0) &&
+ virDomainCreate(dom) == 0)
+ ret = EXIT_SUCCESS;
+ } else {
+ xml = virDomainGetXMLDesc(dom,
+ VIR_DOMAIN_XML_SECURE |
+ VIR_DOMAIN_XML_INACTIVE);
+
+ if (!xml ||
+ (virDomainDestroy(dom) < 0 &&
+ virDomainIsActive(dom) != 0))
+ goto cleanup;
+ virDomainFree(dom);
+ if ((dom = virDomainCreateXML(conn, xml, 0)))
+ ret = EXIT_SUCCESS;
+ }
+ break;
+
+ case VIR_DOMAIN_LOCK_FAILURE_PAUSE:
+ if (virDomainSuspend(dom) == 0)
+ ret = EXIT_SUCCESS;
+ break;
+
+ case VIR_DOMAIN_LOCK_FAILURE_IGNORE:
+ ret = EXIT_SUCCESS;
+ break;
+
+ default:
+ fprintf(stderr, _("unsupported failure action: '%s'\n"),
+ virDomainLockFailureTypeToString(action));
+ break;
+ }
+
+cleanup:
+ if (dom)
+ virDomainFree(dom);
+ if (conn)
+ virConnectClose(conn);
+ VIR_FREE(xml);
+
+ return ret;
+}