[PATCH] [wip] python: add the get_hosts status support
by Federico Simoncelli
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
python/sanlock.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 133 insertions(+), 2 deletions(-)
diff --git a/python/sanlock.c b/python/sanlock.c
index 64a95d7..e1fe1a9 100644
--- a/python/sanlock.c
+++ b/python/sanlock.c
@@ -694,7 +694,7 @@ py_rem_lockspace(PyObject *self __unused, PyObject *args, PyObject *keywds)
/* get_lockspaces */
PyDoc_STRVAR(pydoc_get_lockspaces, "\
-get_lockspaces() -> dict\n\
+get_lockspaces() -> list\n\
Return the list of lockspaces currently managed by sanlock. The reported\n\
flag indicates whether the lockspace is acquired (0) or in transition.\n\
The possible transition values are LSFLAG_ADD if the lockspace is in the\n\
@@ -714,7 +714,7 @@ py_get_lockspaces(PyObject *self __unused, PyObject *args, PyObject *keywds)
Py_END_ALLOW_THREADS
if (rv < 0) {
- __set_exception(rv, "Sanlock get lockspace failure");
+ __set_exception(rv, "Sanlock get lockspaces failure");
goto exit_fail;
}
@@ -784,6 +784,108 @@ exit_fail:
return NULL;
}
+/* get_hosts */
+PyDoc_STRVAR(pydoc_get_hosts, "\
+get_hosts(lockspace, host_id=0) -> list\n\
+Return the list of hosts currently alive in a lockspace. When the host_id\n\
+is specified then only the requested host status is returned. The reported\n\
+flag indicates whether the host is free (HOST_FREE), alive (HOST_LIVE),\n\
+failing (HOST_FAIL) or dead (HOST_DEAD).\n\
+The other returned information are: the generation, the last timestamp and\n\
+the io_timeout.\n");
+
+static PyObject *
+py_get_hosts(PyObject *self __unused, PyObject *args, PyObject *keywds)
+{
+ int rv, i, hss_count = 0;
+ uint64_t host_id = 0;
+ const char *lockspace = NULL;
+ struct sanlk_host *hss = NULL;
+ PyObject *ls_list = NULL, *ls_entry = NULL, *ls_value = NULL;
+
+ static char *kwlist[] = {"lockspace", "host_id", NULL};
+
+ /* parse python tuple */
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|k", kwlist,
+ &lockspace, &host_id)) {
+ return NULL;
+ }
+
+ /* get all the lockspaces (gil disabled) */
+ Py_BEGIN_ALLOW_THREADS
+ rv = sanlock_get_hosts(lockspace, host_id, &hss, &hss_count, 0);
+ Py_END_ALLOW_THREADS
+
+ if (rv < 0) {
+ __set_exception(rv, "Sanlock get hosts failure");
+ goto exit_fail;
+ }
+
+ /* prepare the dictionary holding the information */
+ if ((ls_list = PyList_New(0)) == NULL)
+ goto exit_fail;
+
+ for (i = 0; i < hss_count; i++) {
+ if ((ls_entry = PyDict_New()) == NULL)
+ goto exit_fail;
+
+ /* fill the dictionary information: host_id */
+ if ((ls_value = PyInt_FromLong(hss[i].host_id)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "host_id", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: generation */
+ if ((ls_value = PyInt_FromLong(hss[i].generation)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "generation", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: timestamp */
+ if ((ls_value = PyInt_FromLong(hss[i].timestamp)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "timestamp", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: io_timeout */
+ if ((ls_value = PyInt_FromLong(hss[i].io_timeout)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "io_timeout", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: flags */
+ if ((ls_value = PyInt_FromLong(hss[i].flags)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "flags", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ if (PyList_Append(ls_list, ls_entry) != 0)
+ goto exit_fail;
+
+ Py_DECREF(ls_entry);
+ }
+
+ /* success */
+ free(hss);
+ return ls_list;
+
+ /* failure */
+exit_fail:
+ if (hss) free(hss);
+ Py_XDECREF(ls_entry);
+ Py_XDECREF(ls_list);
+ return NULL;
+}
/* acquire */
PyDoc_STRVAR(pydoc_acquire, "\
@@ -1089,6 +1191,8 @@ sanlock_methods[] = {
METH_VARARGS|METH_KEYWORDS, pydoc_rem_lockspace},
{"get_lockspaces", (PyCFunction) py_get_lockspaces,
METH_VARARGS|METH_KEYWORDS, pydoc_get_lockspaces},
+ {"get_hosts", (PyCFunction) py_get_hosts,
+ METH_VARARGS|METH_KEYWORDS, pydoc_get_hosts},
{"acquire", (PyCFunction) py_acquire,
METH_VARARGS|METH_KEYWORDS, pydoc_acquire},
{"release", (PyCFunction) py_release,
@@ -1155,6 +1259,7 @@ initsanlock(void)
Py_INCREF(py_exception);
}
+ /* lockspaces list flags */
if ((sk_constant = PyInt_FromLong(SANLK_LSF_ADD)) != NULL) {
if (PyModule_AddObject(py_module, "LSFLAG_ADD", sk_constant)) {
Py_DECREF(sk_constant);
@@ -1167,6 +1272,7 @@ initsanlock(void)
}
}
+ /* resource request flags */
if ((sk_constant = PyInt_FromLong(SANLK_REQ_FORCE)) != NULL) {
if (PyModule_AddObject(py_module, "REQ_FORCE", sk_constant)) {
Py_DECREF(sk_constant);
@@ -1178,4 +1284,29 @@ initsanlock(void)
Py_DECREF(sk_constant);
}
}
+
+ /* hosts list flags */
+ if ((sk_constant = PyInt_FromLong(SANLK_HOST_FREE)) != NULL) {
+ if (PyModule_AddObject(py_module, "HOST_FREE", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
+
+ if ((sk_constant = PyInt_FromLong(SANLK_HOST_LIVE)) != NULL) {
+ if (PyModule_AddObject(py_module, "HOST_LIVE", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
+
+ if ((sk_constant = PyInt_FromLong(SANLK_HOST_FAIL)) != NULL) {
+ if (PyModule_AddObject(py_module, "HOST_FAIL", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
+
+ if ((sk_constant = PyInt_FromLong(SANLK_HOST_DEAD)) != NULL) {
+ if (PyModule_AddObject(py_module, "HOST_DEAD", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
}
--
1.7.1
10 years, 10 months
[PATCH] [wip] python: add the get_hosts status support
by Federico Simoncelli
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
python/sanlock.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 101 insertions(+), 2 deletions(-)
diff --git a/python/sanlock.c b/python/sanlock.c
index 64a95d7..233c3c9 100644
--- a/python/sanlock.c
+++ b/python/sanlock.c
@@ -694,7 +694,7 @@ py_rem_lockspace(PyObject *self __unused, PyObject *args, PyObject *keywds)
/* get_lockspaces */
PyDoc_STRVAR(pydoc_get_lockspaces, "\
-get_lockspaces() -> dict\n\
+get_lockspaces() -> list\n\
Return the list of lockspaces currently managed by sanlock. The reported\n\
flag indicates whether the lockspace is acquired (0) or in transition.\n\
The possible transition values are LSFLAG_ADD if the lockspace is in the\n\
@@ -714,7 +714,7 @@ py_get_lockspaces(PyObject *self __unused, PyObject *args, PyObject *keywds)
Py_END_ALLOW_THREADS
if (rv < 0) {
- __set_exception(rv, "Sanlock get lockspace failure");
+ __set_exception(rv, "Sanlock get lockspaces failure");
goto exit_fail;
}
@@ -784,6 +784,103 @@ exit_fail:
return NULL;
}
+/* get_hosts */
+PyDoc_STRVAR(pydoc_get_hosts, "\
+get_hosts() -> dict\n\
+\n");
+
+static PyObject *
+py_get_hosts(PyObject *self __unused, PyObject *args, PyObject *keywds)
+{
+ int rv, i, hss_count = 0;
+ uint64_t host_id = 0;
+ const char *lockspace = NULL;
+ struct sanlk_host *hss = NULL;
+ PyObject *ls_list = NULL, *ls_entry = NULL, *ls_value = NULL;
+
+ static char *kwlist[] = {"lockspace", "host_id", NULL};
+
+ /* parse python tuple */
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|k", kwlist,
+ &lockspace, &host_id)) {
+ return NULL;
+ }
+
+ /* get all the lockspaces (gil disabled) */
+ Py_BEGIN_ALLOW_THREADS
+ rv = sanlock_get_hosts(lockspace, host_id, &hss, &hss_count, 0);
+ Py_END_ALLOW_THREADS
+
+ if (rv < 0) {
+ __set_exception(rv, "Sanlock get hosts failure");
+ goto exit_fail;
+ }
+
+ /* prepare the dictionary holding the information */
+ if ((ls_list = PyList_New(0)) == NULL)
+ goto exit_fail;
+
+ for (i = 0; i < hss_count; i++) {
+ if ((ls_entry = PyDict_New()) == NULL)
+ goto exit_fail;
+
+ /* fill the dictionary information: host_id */
+ if ((ls_value = PyInt_FromLong(hss[i].host_id)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "host_id", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: generation */
+ if ((ls_value = PyInt_FromLong(hss[i].generation)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "generation", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: timestamp */
+ if ((ls_value = PyInt_FromLong(hss[i].timestamp)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "timestamp", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: io_timeout */
+ if ((ls_value = PyInt_FromLong(hss[i].io_timeout)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "io_timeout", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ /* fill the dictionary information: flags */
+ if ((ls_value = PyInt_FromLong(hss[i].flags)) == NULL)
+ goto exit_fail;
+ rv = PyDict_SetItemString(ls_entry, "flags", ls_value);
+ Py_DECREF(ls_value);
+ if (rv != 0)
+ goto exit_fail;
+
+ if (PyList_Append(ls_list, ls_entry) != 0)
+ goto exit_fail;
+
+ Py_DECREF(ls_entry);
+ }
+
+ /* success */
+ free(hss);
+ return ls_list;
+
+ /* failure */
+exit_fail:
+ if (hss) free(hss);
+ Py_XDECREF(ls_entry);
+ Py_XDECREF(ls_list);
+ return NULL;
+}
/* acquire */
PyDoc_STRVAR(pydoc_acquire, "\
@@ -1089,6 +1186,8 @@ sanlock_methods[] = {
METH_VARARGS|METH_KEYWORDS, pydoc_rem_lockspace},
{"get_lockspaces", (PyCFunction) py_get_lockspaces,
METH_VARARGS|METH_KEYWORDS, pydoc_get_lockspaces},
+ {"get_hosts", (PyCFunction) py_get_hosts,
+ METH_VARARGS|METH_KEYWORDS, pydoc_get_hosts},
{"acquire", (PyCFunction) py_acquire,
METH_VARARGS|METH_KEYWORDS, pydoc_acquire},
{"release", (PyCFunction) py_release,
--
1.7.1
10 years, 10 months
[PATCHv2] python: add the support for request
by Federico Simoncelli
Signed-off-by: Federico Simoncelli <fsimonce(a)redhat.com>
---
python/sanlock.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/python/sanlock.c b/python/sanlock.c
index e1e0397..64a95d7 100644
--- a/python/sanlock.c
+++ b/python/sanlock.c
@@ -907,6 +907,64 @@ exit_fail:
return NULL;
}
+/* request */
+PyDoc_STRVAR(pydoc_request, "\
+request(lockspace, resource, disks [, action=REQ_RELEASE, version=0])\n\
+Request the owner of a resource to do something specified by action.\n\
+The possible values for action are: REQ_RELEASE to request a graceful\n\
+release of the resource and REQ_SIGKILL to sigkill the owner of the\n\
+resource (forcible release).\n\
+The disks must be in the format: [(path, offset), ... ]");
+static PyObject *
+py_request(PyObject *self __unused, PyObject *args, PyObject *keywds)
+{
+ int rv, action = SANLK_REQ_GRACEFUL, version = 0;
+ const char *lockspace, *resource;
+ struct sanlk_resource *res;
+ PyObject *disks;
+
+ static char *kwlist[] = {"lockspace", "resource", "disks", "action",
+ "version", NULL};
+
+ /* parse python tuple */
+ if (!PyArg_ParseTupleAndKeywords(args, keywds, "ssO!|ii", kwlist,
+ &lockspace, &resource, &PyList_Type, &disks, &action, &version)) {
+ return NULL;
+ }
+
+ /* parse and check sanlock resource */
+ if (__parse_resource(disks, &res) < 0) {
+ return NULL;
+ }
+
+ /* prepare sanlock names */
+ strncpy(res->lockspace_name, lockspace, SANLK_NAME_LEN);
+ strncpy(res->name, resource, SANLK_NAME_LEN);
+
+ /* prepare the resource version */
+ if (version) {
+ res->flags |= SANLK_RES_LVER;
+ res->lver = version;
+ }
+
+ /* request sanlock resource (gil disabled) */
+ Py_BEGIN_ALLOW_THREADS
+ rv = sanlock_request(0, action, res);
+ Py_END_ALLOW_THREADS
+
+ if (rv != 0) {
+ __set_exception(rv, "Sanlock request not submitted");
+ goto exit_fail;
+ }
+
+ free(res);
+ Py_RETURN_NONE;
+
+exit_fail:
+ free(res);
+ return NULL;
+}
+
/* killpath */
PyDoc_STRVAR(pydoc_killpath, "\
killpath(path, args [, slkfd=fd])\n\
@@ -1035,6 +1093,8 @@ sanlock_methods[] = {
METH_VARARGS|METH_KEYWORDS, pydoc_acquire},
{"release", (PyCFunction) py_release,
METH_VARARGS|METH_KEYWORDS, pydoc_release},
+ {"request", (PyCFunction) py_request,
+ METH_VARARGS|METH_KEYWORDS, pydoc_request},
{"killpath", (PyCFunction) py_killpath,
METH_VARARGS|METH_KEYWORDS, pydoc_killpath},
{NULL, NULL, 0, NULL}
@@ -1106,4 +1166,16 @@ initsanlock(void)
Py_DECREF(sk_constant);
}
}
+
+ if ((sk_constant = PyInt_FromLong(SANLK_REQ_FORCE)) != NULL) {
+ if (PyModule_AddObject(py_module, "REQ_FORCE", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
+
+ if ((sk_constant = PyInt_FromLong(SANLK_REQ_GRACEFUL)) != NULL) {
+ if (PyModule_AddObject(py_module, "REQ_GRACEFUL", sk_constant)) {
+ Py_DECREF(sk_constant);
+ }
+ }
}
--
1.7.1
10 years, 10 months
src/sanlock.8
by David Teigland
src/sanlock.8 | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
New commits:
commit ac7c1ccf914551d19b2ffffadc6887e821a56b67
Author: David Teigland <teigland(a)redhat.com>
Date: Fri May 3 09:35:10 2013 -0500
sanlock: update request types in man page
Forgot to include in the previous commit.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/sanlock.8 b/src/sanlock.8
index a23e54a..edcaf35 100644
--- a/src/sanlock.8
+++ b/src/sanlock.8
@@ -515,15 +515,14 @@ set in A's bitmap for request_finish_seconds.)
\fIforce_mode\fP determines the action the resource lease owner should
take:
-\fB1\fP (KILL_PID): kill the process holding the resource lease. When the
+\fB1\fP (FORCE): kill the process holding the resource lease. When the
process has exited, the resource lease will be released, and can then be
acquired by anyone. The kill signal is SIGKILL (or SIGTERM if SIGKILL
is restricted.)
-\fB2\fP (SIGUSR1): send SIGUSR1 to the process holding the resource lease.
-
-\fB3\fP (KILLPATH): run the program configured by sanlock_killpath
-against the process holding the resource lease.
+\fB2\fP (GRACEFUL): run the program configured by sanlock_killpath
+against the process holding the resource lease. If no killpath is
+defined, then FORCE is used.
.SS Graceful recovery
10 years, 10 months
fence_sanlock/fence_sanlock.8 fence_sanlock/fence_sanlockd.8 fence_sanlock/fence_sanlockd.c src/cmd.c src/helper.c src/resource.c src/sanlock_internal.h src/sanlock_resource.h
by David Teigland
fence_sanlock/fence_sanlock.8 | 85 ++++++++++++++++++++++++++++++++++++++---
fence_sanlock/fence_sanlockd.8 | 4 +
fence_sanlock/fence_sanlockd.c | 68 ++++++++++++++++++++++++++++++++
src/cmd.c | 2
src/helper.c | 2
src/resource.c | 29 +++++--------
src/sanlock_internal.h | 4 +
src/sanlock_resource.h | 20 ++++++---
8 files changed, 182 insertions(+), 32 deletions(-)
New commits:
commit 4c058f277ad2dbd852cd3087f48edf4562de0bb3
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Apr 10 16:01:27 2013 -0500
sanlock/fence_sanlock: request modes FORCE and GRACEFUL
FORCE is new name for KILL_PID.
GRACEFUL is killpath (or SIGTERM of no killpath is set)
SIGUSR1 is removed; a killpath prog should send the signal
fence_sanlock is converted to use killpath to send SIGUSR1.
The killpath program is "fence_sanlockd -1" (-1 is new).
Change sanlock helper to use execvp so we don't need to
know the fence_sanlockd path.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/fence_sanlock/fence_sanlock.8 b/fence_sanlock/fence_sanlock.8
index d9e41be..66f0912 100644
--- a/fence_sanlock/fence_sanlock.8
+++ b/fence_sanlock/fence_sanlock.8
@@ -1,4 +1,4 @@
-.TH FENCE_SANLOCK 8 2012-09-26
+.TH FENCE_SANLOCK 8 2013-05-02
.SH NAME
fence_sanlock \- fence agent using watchdog and shared storage leases
@@ -166,7 +166,11 @@ See \-i
.SH FILES
-Example cluster.conf configuration for fence_sanlock:
+Example cluster.conf configuration for fence_sanlock.
+.br
+(For cman based clusters in which fenced runs agents.)
+.br
+Also see cluster.conf(5), fenced(8), fence_node(8).
.nf
<clusternode name="node01" nodeid="1">
@@ -194,10 +198,81 @@ Example cluster.conf configuration for fence_sanlock:
<fencedevice name="wd" agent="fence_sanlock" path="/dev/fence/leases"/>
.fi
+.PP
+
+Example dlm.conf configuration for fence_sanlock.
+.br
+(For non-cman based clusters in which dlm_controld runs agents.)
+.br
+Also see dlm.conf(5), dlm_controld(8).
+
+.nf
+device wd /usr/sbin/fence_sanlock path=/dev/fence/leases
+connect wd node=1 host_id=1
+connect wd node=2 host_id=2
+unfence wd
+.fi
+
+.SH TEST
+
+To test fence_sanlock directly, without clustering:
+
+.nf
+1. Initialize storage
+
+node1: create 1G lv on shared storage /dev/fence/leases
+node1: fence_sanlock -o sanlock_init -p /dev/fence/leases
+
+2. Start services
+
+node1: service fence_sanlockd start
+node2: service fence_sanlockd start
+
+3. Enable fencing
+
+node1: fence_sanlock -o on -p /dev/fence/leases -i 1
+node2: fence_sanlock -o on -p /dev/fence/leases -i 2
+
+This "unfence" step may take a couple minutes.
+
+4. Verify hosts and leases
+
+node1: sanlock status
+s fence:1:/dev/fence/leases:0
+r fence:h1:/dev/fence/leases:1048576:1 p 2465
+
+node2: sanlock status
+s fence:2:/dev/fence/leases:0
+r fence:h2:/dev/fence/leases:2097152:1 p 2366
+
+node1: sanlock host_status
+lockspace fence
+1 timestamp 717
+2 timestamp 678
+
+node2: sanlock host_status
+lockspace fence
+1 timestamp 738
+2 timestamp 678
+
+5. Fence node2
+
+node1: fence_sanlock -o off -p /dev/fence/leases -i 2
+
+This may take a few minutes to return.
+
+When node2 is not dead before fencing, sanlock on node1 will log errors
+about failing to acquire the lease while node2 is still alive. This is
+expected.
+
+6. Success
+
+node1 fence_sanlock should exit 0 after node2 is reset by its watchdog.
+.fi
+
+
.SH SEE ALSO
.BR fence_sanlockd (8),
.BR sanlock (8),
-.BR wdmd (8),
-.BR fence_node (8),
-.BR fenced (8)
+.BR wdmd (8)
diff --git a/fence_sanlock/fence_sanlockd.8 b/fence_sanlock/fence_sanlockd.8
index 33ce051..33f2dc7 100644
--- a/fence_sanlock/fence_sanlockd.8
+++ b/fence_sanlock/fence_sanlockd.8
@@ -30,6 +30,10 @@ for full description.
.B \-s
Send options (p,i) to waiting fence_sanlockd -w.
+.B \-1
+ Send SIGUSR1 to running fence_sanlockd.
+
+
.SH SEE ALSO
.BR fence_sanlock (8),
.BR sanlock (8),
diff --git a/fence_sanlock/fence_sanlockd.c b/fence_sanlock/fence_sanlockd.c
index aa45736..b52bd7c 100644
--- a/fence_sanlock/fence_sanlockd.c
+++ b/fence_sanlock/fence_sanlockd.c
@@ -149,6 +149,36 @@ static int client_add(int fd, void (*workfn)(int ci), void (*deadfn)(int ci))
goto again;
}
+static int read_lockfile(int *pid)
+{
+ char buf[16];
+ int fd, rv;
+
+ sprintf(lockfile_path, "%s/%s.pid", DAEMON_RUN_DIR, prog_name);
+
+ fd = open(lockfile_path, O_RDONLY);
+ if (fd < 0) {
+ log_error("lockfile open error %s: %s",
+ lockfile_path, strerror(errno));
+ return -1;
+ }
+
+ memset(buf, 0, sizeof(buf));
+
+ rv = read(fd, buf, sizeof(buf));
+ if (rv < 0) {
+ log_error("lockfile read error %s: %s",
+ lockfile_path, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ *pid = atoi(buf);
+
+ close(fd);
+ return 0;
+}
+
static int lockfile(void)
{
char buf[16];
@@ -352,6 +382,26 @@ static int send_options(void)
return rv;
}
+static int send_signal(int sig)
+{
+ int rv, pid;
+
+ openlog("fence_sanlockd-1", LOG_CONS | LOG_PID, LOG_DAEMON);
+
+ rv = read_lockfile(&pid);
+ if (rv < 0)
+ return rv;
+
+ rv = kill(pid, sig);
+ if (rv < 0) {
+ log_error("kill sig %d pid %d error %d", sig, pid, errno);
+ } else {
+ syslog(LOG_INFO, "sent signal %d to pid %d", sig, pid);
+ }
+
+ return rv;
+}
+
/*
* A running fence_sanlock agent has a pid file we can read.
* We use this to check what host_id it's fencing, so we can
@@ -464,6 +514,7 @@ static void print_usage(void)
printf(" -i <host_id> Local sanlock host_id (1-%d)\n", MAX_HOSTS);
printf(" -w Wait for fence_sanlockd -s to send options (p,i)\n");
printf(" -s Send options (p,i) to waiting fence_sanlockd -w\n");
+ printf(" -1 Send SIGUSR1 to running fence_sanlockd\n");
printf(" -h Print this help, then exit\n");
printf(" -V Print program version information, then exit\n");
}
@@ -476,6 +527,7 @@ int main(int argc, char *argv[])
int poll_timeout;
int sleep_seconds;
int send_opts = 0, wait_opts = 0;
+ int send_sigusr1 = 0;
int cont = 1;
int optchar;
int sock, con, rv, i;
@@ -483,7 +535,7 @@ int main(int argc, char *argv[])
int victim_host_id;
while (cont) {
- optchar = getopt(argc, argv, "Dp:i:hVws");
+ optchar = getopt(argc, argv, "Dp:i:hVws1");
switch (optchar) {
case 'D':
@@ -506,6 +558,9 @@ int main(int argc, char *argv[])
case 's':
send_opts = 1;
break;
+ case '1':
+ send_sigusr1 = 1;
+ break;
case 'h':
print_usage();
exit(0);
@@ -522,6 +577,11 @@ int main(int argc, char *argv[])
};
}
+ if (send_sigusr1) {
+ rv = send_signal(SIGUSR1);
+ return rv;
+ }
+
if (wait_opts && send_opts) {
fprintf(stderr, "-w and -s options cannot be used together\n");
exit(1);
@@ -584,6 +644,12 @@ int main(int argc, char *argv[])
goto out_refcount;
}
+ rv = sanlock_killpath(sock, 0, "fence_sanlockd", (char *)"-1");
+ if (rv < 0) {
+ log_error("killpath error %d", sock);
+ goto out_refcount;
+ }
+
rv = sanlock_restrict(sock, SANLK_RESTRICT_SIGKILL);
if (rv < 0) {
log_error("restrict error %d", sock);
diff --git a/src/cmd.c b/src/cmd.c
index 19416be..8ad72b7 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -310,6 +310,8 @@ static void cmd_acquire(struct task *task, struct cmd_args *ca)
token->io_timeout = spi.io_timeout;
if (cl->restricted & SANLK_RESTRICT_SIGKILL)
token->flags |= T_RESTRICT_SIGKILL;
+ if (cl->restricted & SANLK_RESTRICT_SIGTERM)
+ token->flags |= T_RESTRICT_SIGTERM;
/* save a record of what this token_id is for later debugging */
log_level(spi.space_id, token->token_id, NULL, LOG_WARNING,
diff --git a/src/helper.c b/src/helper.c
index 2fce221..27898d5 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -103,7 +103,7 @@ static void run_path(struct helper_msg *hm)
av[av_count++] = strdup(arg);
}
- execv(av[0], av);
+ execvp(av[0], av);
}
static int read_hm(int fd, struct helper_msg *hm)
diff --git a/src/resource.c b/src/resource.c
index 2a60a16..226a6ce 100644
--- a/src/resource.c
+++ b/src/resource.c
@@ -564,6 +564,8 @@ static struct resource *new_resource(struct token *token)
r->pid = token->pid;
if (token->flags & T_RESTRICT_SIGKILL)
r->flags |= R_RESTRICT_SIGKILL;
+ if (token->flags & T_RESTRICT_SIGTERM)
+ r->flags |= R_RESTRICT_SIGTERM;
}
return r;
@@ -856,27 +858,20 @@ static void do_request(struct token *tt, int pid, uint32_t force_mode)
memset(&hm, 0, sizeof(hm));
- if (force_mode == SANLK_REQ_KILL_PID) {
+ if (force_mode == SANLK_REQ_FORCE) {
hm.type = HELPER_MSG_KILLPID;
hm.pid = pid;
hm.sig = (flags & R_RESTRICT_SIGKILL) ? SIGTERM : SIGKILL;
- } else if (force_mode == SANLK_REQ_SIGUSR1) {
- hm.type = HELPER_MSG_KILLPID;
- hm.pid = pid;
- hm.sig = SIGUSR1;
- } else if (force_mode == SANLK_REQ_KILLPATH) {
- if (!killpath[0]) {
- log_error("do_request %d force_mode %d no killpath",
- pid, force_mode);
- return;
+ } else if (force_mode == SANLK_REQ_GRACEFUL) {
+ if (killpath[0]) {
+ hm.type = HELPER_MSG_RUNPATH;
+ memcpy(hm.path, killpath, SANLK_HELPER_PATH_LEN);
+ memcpy(hm.args, killargs, SANLK_HELPER_ARGS_LEN);
+ } else {
+ hm.type = HELPER_MSG_KILLPID;
+ hm.pid = pid;
+ hm.sig = (flags & R_RESTRICT_SIGTERM) ? SIGKILL : SIGTERM;
}
- /* there's no thread locking for the clients array so
- we can't go searching for killpath/killargs for this
- pid from here, so we copy the info into struct
- resource so we can use it here. */
- hm.type = HELPER_MSG_RUNPATH;
- memcpy(hm.path, killpath, SANLK_HELPER_PATH_LEN);
- memcpy(hm.args, killargs, SANLK_HELPER_ARGS_LEN);
} else {
log_error("do_request %d unknown force_mode %d",
pid, force_mode);
diff --git a/src/sanlock_internal.h b/src/sanlock_internal.h
index 34ce260..f0153c6 100644
--- a/src/sanlock_internal.h
+++ b/src/sanlock_internal.h
@@ -68,7 +68,8 @@ struct sync_disk {
*/
#define T_RESTRICT_SIGKILL 0x00000001 /* inherited from client->restricted */
-#define T_LS_DEAD 0x00000002 /* don't bother trying to release if ls is dead */
+#define T_RESTRICT_SIGTERM 0x00000002 /* inherited from client->restricted */
+#define T_LS_DEAD 0x00000004 /* don't bother trying to release if ls is dead */
struct token {
/* values copied from acquire res arg */
@@ -99,6 +100,7 @@ struct token {
#define R_THREAD_EXAMINE 0x00000002
#define R_THREAD_RELEASE 0x00000004
#define R_RESTRICT_SIGKILL 0x00000008 /* inherited from token */
+#define R_RESTRICT_SIGTERM 0x00000010 /* inherited from token */
struct resource {
struct list_head list;
diff --git a/src/sanlock_resource.h b/src/sanlock_resource.h
index f68fc3e..3148b25 100644
--- a/src/sanlock_resource.h
+++ b/src/sanlock_resource.h
@@ -33,15 +33,21 @@
/*
* request force_mode
- * SANLK_REQ_KILL_PID: send SIGKILL to pid holding the resource, or
- * SIGTERM if SIGKILL is restricted
- * SANLK_REQ_SIGUSR1: send SIGUSR1 to pid holding the resource
- * SANLK_REQ_KILLPATH: run configured killpath against the pid
+ *
+ * SANLK_REQ_FORCE (SANLK_REQ_KILL_PID deprecated)
+ * Send SIGKILL to the pid holding the resource
+ * (or SIGTERM if SIGKILL is restricted.)
+ *
+ * SANLK_REQ_GRACEFUL
+ * Run killpath against the pid if it is defined, otherwise
+ * send SIGTERM to the pid (or SIGKILL if SIGTERM is restricted).
*/
-#define SANLK_REQ_KILL_PID 0x00000001
-#define SANLK_REQ_SIGUSR1 0x00000002
-#define SANLK_REQ_KILLPATH 0x00000003
+#define SANLK_REQ_FORCE 0x00000001
+#define SANLK_REQ_GRACEFUL 0x00000002
+
+/* old name deprecated */
+#define SANLK_REQ_KILL_PID SANLK_REQ_FORCE
int sanlock_register(void);
10 years, 10 months