Signed-off-by: Federico Simoncelli fsimonce@redhat.com --- python/example.py | 12 +++++ python/sanlock.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 2 deletions(-)
diff --git a/python/example.py b/python/example.py index 875ddc8..f3cd414 100644 --- a/python/example.py +++ b/python/example.py @@ -1,4 +1,5 @@ import os +import time import signal import tempfile import sanlock @@ -37,6 +38,17 @@ def main(): print "Acquiring '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME) sanlock.acquire(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, slkfd=fd, version=0) + while True: + print "Trying to get lockspace '%s' hosts" % LOCKSPACE_NAME + try: + hosts_list = sanlock.get_hosts(LOCKSPACE_NAME) + except sanlock.SanlockException as e: + if e.errno != os.errno.EAGAIN: + raise + else: + print "Lockspace '%s' hosts: " % LOCKSPACE_NAME, hosts_list + break + time.sleep(5) print "Releasing '%s' on '%s'" % (RESOURCE_NAME, LOCKSPACE_NAME) sanlock.release(LOCKSPACE_NAME, RESOURCE_NAME, SNLK_DISKS, slkfd=fd) except Exception as e: diff --git a/python/sanlock.c b/python/sanlock.c index 6ad3469..c1067ae 100644 --- a/python/sanlock.c +++ b/python/sanlock.c @@ -134,6 +134,75 @@ exit_fail: return -1; }
+static PyObject * +__hosts_to_list(struct sanlk_host *hss, int hss_count) +{ + int i, rv; + PyObject *ls_list = NULL, *ls_entry = NULL, *ls_value = NULL; + + /* 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); + } + + return ls_list; + + /* failure */ +exit_fail: + Py_XDECREF(ls_entry); + Py_XDECREF(ls_list); + return NULL; +} + /* register */ PyDoc_STRVAR(pydoc_register, "\ register() -> int\n\ @@ -694,7 +763,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 +783,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 +853,51 @@ 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), dead (HOST_DEAD) or unknown (HOST_UNKNOWN).\n\ +The unknown state is the default when sanlock just joined the lockspace\n\ +and didn't collect enough information to determine the real status of other\n\ +hosts. The dictionary returned also contains: the generation, the last\n\ +timestamp and the io_timeout.\n"); + +static PyObject * +py_get_hosts(PyObject *self __unused, PyObject *args, PyObject *keywds) +{ + int rv, hss_count = 0; + uint64_t host_id = 0; + const char *lockspace = NULL; + struct sanlk_host *hss = NULL; + PyObject *ls_list = 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; + } + + ls_list = __hosts_to_list(hss, hss_count); + +exit_fail: + if (hss) free(hss); + return ls_list; +}
/* acquire */ PyDoc_STRVAR(pydoc_acquire, "\ @@ -1101,6 +1215,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, @@ -1182,5 +1298,12 @@ initsanlock(void) PYSNLK_INIT_ADD_CONSTANT(SANLK_REQ_FORCE, "REQ_FORCE"); PYSNLK_INIT_ADD_CONSTANT(SANLK_REQ_GRACEFUL, "REQ_GRACEFUL");
+ /* hosts list flags */ + PYSNLK_INIT_ADD_CONSTANT(SANLK_HOST_FREE, "HOST_FREE"); + PYSNLK_INIT_ADD_CONSTANT(SANLK_HOST_LIVE, "HOST_LIVE"); + PYSNLK_INIT_ADD_CONSTANT(SANLK_HOST_FAIL, "HOST_FAIL"); + PYSNLK_INIT_ADD_CONSTANT(SANLK_HOST_DEAD, "HOST_DEAD"); + PYSNLK_INIT_ADD_CONSTANT(SANLK_HOST_UNKNOWN, "HOST_UNKNOWN"); + #undef PYSNLK_INIT_ADD_CONSTANT }