From da1650ef882f7de4158118db71f7a2fdd196bc0a Mon Sep 17 00:00:00 2001 From: Alpha Date: Sat, 29 Aug 2015 23:47:43 -0400 Subject: Provide use_errno to all gfapi foreign function prototypes Updated tests to include OSError messages Added error reasons to LibgfapiException exceptions BUG 1196161: https://bugzilla.redhat.com/show_bug.cgi?id=1196161 Change-Id: Iddf40751696874ffcaa50cd9d5ecc06c4993baf2 Signed-off-by: Prashanth Pai --- gluster/api.py | 304 ++++++++++++++++--------------- gluster/gfapi.py | 27 ++- test/functional/libgfapi-python-tests.py | 24 ++- 3 files changed, 193 insertions(+), 162 deletions(-) diff --git a/gluster/api.py b/gluster/api.py index 0ec5413..c7270bb 100755 --- a/gluster/api.py +++ b/gluster/api.py @@ -257,216 +257,222 @@ class Dirent (ctypes.Structure): # } # +def gfapi_prototype(method_name, restype, *argtypes): + """ + Create a named foreign function belonging to gfapi + + :param method_name: Name of the foreign function + :param restype: resulting type + :param argtypes: arguments that represent argument types + :returns: foreign function of gfapi library + """ + # use_errno=True ensures that errno is exposed by ctypes.get_errno() + return ctypes.CFUNCTYPE(restype, *argtypes, use_errno=True)( + (method_name, client) + ) + # Define function prototypes for the wrapper functions. -glfs_init = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_init', client)) +glfs_init = gfapi_prototype('glfs_init', ctypes.c_int, ctypes.c_void_p) -glfs_statvfs = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_void_p)(('glfs_statvfs', client)) +glfs_statvfs = gfapi_prototype('glfs_statvfs', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_void_p) -glfs_new = ctypes.CFUNCTYPE( - ctypes.c_void_p, ctypes.c_char_p)(('glfs_new', client)) +glfs_new = gfapi_prototype('glfs_new', ctypes.c_void_p, ctypes.c_char_p) -glfs_set_volfile_server = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_int)(('glfs_set_volfile_server', client)) # noqa +glfs_set_volfile_server = gfapi_prototype( + 'glfs_set_volfile_server', ctypes.c_int, + ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int) -glfs_set_logging = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_int)(('glfs_set_logging', client)) +glfs_set_logging = gfapi_prototype('glfs_set_logging', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_int) -glfs_fini = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fini', client)) +glfs_fini = gfapi_prototype('glfs_fini', ctypes.c_int, + ctypes.c_void_p) -glfs_creat = ctypes.CFUNCTYPE(ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_int, - ctypes.c_uint, - use_errno=True)(('glfs_creat', client)) +glfs_creat = gfapi_prototype('glfs_creat', ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_char_p, ctypes.c_int, ctypes.c_uint) -glfs_open = ctypes.CFUNCTYPE(ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_int, - use_errno=True)(('glfs_open', client)) +glfs_open = gfapi_prototype('glfs_open', ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_char_p, ctypes.c_int) + +glfs_close = gfapi_prototype('glfs_close', ctypes.c_int, + ctypes.c_void_p) -glfs_close = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_close', client)) +glfs_lstat = gfapi_prototype('glfs_lstat', ctypes.c_int, + ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat)) -glfs_lstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat))(('glfs_lstat', client)) +glfs_stat = gfapi_prototype('glfs_stat', ctypes.c_int, + ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat)) -glfs_stat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat))(('glfs_stat', client)) +glfs_fstat = gfapi_prototype('glfs_fstat', ctypes.c_int, + ctypes.c_void_p, ctypes.POINTER(Stat)) -glfs_fstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER( - Stat))(('glfs_fstat', client)) +glfs_chmod = gfapi_prototype('glfs_chmod', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_ushort) -glfs_chmod = ctypes.CFUNCTYPE(ctypes.c_int, +glfs_fchmod = gfapi_prototype('glfs_fchmod', ctypes.c_int, ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_ushort)(('glfs_chmod', client)) + ctypes.c_ushort) -glfs_fchmod = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_ushort)(('glfs_fchmod', client)) +glfs_chown = gfapi_prototype('glfs_chown', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_uint, + ctypes.c_uint) -glfs_chown = ctypes.CFUNCTYPE(ctypes.c_int, +glfs_lchown = gfapi_prototype('glfs_lchown', ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_uint, - ctypes.c_uint)(('glfs_chown', client)) + ctypes.c_uint) -glfs_lchown = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_uint, - ctypes.c_uint)(('glfs_lchown', client)) +glfs_fchown = gfapi_prototype('glfs_fchown', ctypes.c_int, + ctypes.c_void_p, ctypes.c_uint, + ctypes.c_uint) -glfs_fchown = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_uint, - ctypes.c_uint)(('glfs_fchown', client)) +glfs_dup = gfapi_prototype('glfs_dup', ctypes.c_void_p, + ctypes.c_void_p) -glfs_dup = ctypes.CFUNCTYPE( - ctypes.c_void_p, ctypes.c_void_p)(('glfs_dup', client)) +glfs_fdatasync = gfapi_prototype('glfs_fdatasync', ctypes.c_int, + ctypes.c_void_p) -glfs_fdatasync = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fdatasync', client)) +glfs_fsync = gfapi_prototype('glfs_fsync', ctypes.c_int, + ctypes.c_void_p) -glfs_fsync = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fsync', client)) +glfs_lseek = gfapi_prototype('glfs_lseek', ctypes.c_ulong, + ctypes.c_void_p, ctypes.c_ulong, + ctypes.c_int) -glfs_lseek = ctypes.CFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, - ctypes.c_int)(('glfs_lseek', client)) +glfs_read = gfapi_prototype('glfs_read', ctypes.c_ssize_t, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int) -glfs_read = ctypes.CFUNCTYPE(ctypes.c_ssize_t, +glfs_write = gfapi_prototype('glfs_write', ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, - ctypes.c_int)(('glfs_read', client)) + ctypes.c_int) -glfs_write = ctypes.CFUNCTYPE(ctypes.c_ssize_t, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_int)(('glfs_write', client)) +glfs_getxattr = gfapi_prototype('glfs_getxattr', ctypes.c_ssize_t, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t) -glfs_getxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, +glfs_listxattr = gfapi_prototype('glfs_listxattr', ctypes.c_ssize_t, ctypes.c_void_p, ctypes.c_char_p, - ctypes.c_char_p, ctypes.c_void_p, - ctypes.c_size_t)(('glfs_getxattr', client)) + ctypes.c_size_t) -glfs_listxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_size_t)(('glfs_listxattr', client)) +glfs_removexattr = gfapi_prototype('glfs_removexattr', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p) -glfs_removexattr = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p)(('glfs_removexattr', client)) # noqa +glfs_setxattr = gfapi_prototype('glfs_setxattr', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int) -glfs_setxattr = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_int)(('glfs_setxattr', client)) +glfs_rename = gfapi_prototype('glfs_rename', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p) -glfs_rename = ctypes.CFUNCTYPE(ctypes.c_int, +glfs_symlink = gfapi_prototype('glfs_symlink', ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.c_char_p)(('glfs_rename', client)) - -glfs_symlink = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p)(('glfs_symlink', client)) + ctypes.c_char_p) -glfs_unlink = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p)(('glfs_unlink', client)) +glfs_unlink = gfapi_prototype('glfs_unlink', ctypes.c_int, + ctypes.c_void_p, ctypes.c_char_p) -glfs_readdir_r = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, - ctypes.POINTER(Dirent), - ctypes.POINTER(ctypes.POINTER(Dirent)))(('glfs_readdir_r', client)) # noqa +glfs_readdir_r = gfapi_prototype('glfs_readdir_r', ctypes.c_int, + ctypes.c_void_p, + ctypes.POINTER(Dirent), + ctypes.POINTER(ctypes.POINTER(Dirent))) -glfs_closedir = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_closedir', client)) +glfs_closedir = gfapi_prototype('glfs_closedir', ctypes.c_int, + ctypes.c_void_p) +glfs_mkdir = gfapi_prototype('glfs_mkdir', ctypes.c_int, + ctypes.c_void_p, ctypes.c_char_p, + ctypes.c_ushort) -glfs_mkdir = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.c_ushort)(('glfs_mkdir', client)) +glfs_opendir = gfapi_prototype('glfs_opendir', ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_char_p) -glfs_opendir = ctypes.CFUNCTYPE(ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_char_p)(('glfs_opendir', client)) +glfs_rmdir = gfapi_prototype('glfs_rmdir', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p) -glfs_rmdir = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p)(('glfs_rmdir', client)) +glfs_setfsuid = gfapi_prototype('glfs_setfsuid', ctypes.c_int, + ctypes.c_uint) -glfs_setfsuid = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_uint)(('glfs_setfsuid', client)) +glfs_setfsgid = gfapi_prototype('glfs_setfsgid', ctypes.c_int, + ctypes.c_uint) -glfs_setfsgid = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_uint)(('glfs_setfsgid', client)) +glfs_ftruncate = gfapi_prototype('glfs_ftruncate', ctypes.c_int, + ctypes.c_void_p, ctypes.c_int) -glfs_ftruncate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, - ctypes.c_int)(('glfs_ftruncate', client)) +glfs_fgetxattr = gfapi_prototype('glfs_fgetxattr', ctypes.c_ssize_t, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t) -glfs_fgetxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_size_t)(('glfs_fgetxattr', client)) +glfs_fremovexattr = gfapi_prototype('glfs_fremovexattr', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p) -glfs_fremovexattr = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p)(('glfs_fremovexattr', - client)) +glfs_fsetxattr = gfapi_prototype('glfs_fsetxattr', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int) -glfs_fsetxattr = ctypes.CFUNCTYPE(ctypes.c_int, +glfs_flistxattr = gfapi_prototype('glfs_flistxattr', ctypes.c_ssize_t, ctypes.c_void_p, - ctypes.c_char_p, ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_int)(('glfs_fsetxattr', client)) + ctypes.c_size_t) -glfs_flistxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t)(('glfs_flistxattr', - client)) +glfs_access = gfapi_prototype('glfs_access', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_int) -glfs_access = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_int)(('glfs_access', client)) +glfs_readlink = gfapi_prototype('glfs_readlink', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_size_t) -glfs_readlink = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_size_t)(('glfs_readlink', client)) +glfs_chdir = gfapi_prototype('glfs_chdir', ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p) -glfs_chdir = ctypes.CFUNCTYPE(ctypes.c_int, +glfs_getcwd = gfapi_prototype('glfs_getcwd', ctypes.c_char_p, ctypes.c_void_p, - ctypes.c_char_p)(('glfs_chdir', client)) - -glfs_getcwd = ctypes.CFUNCTYPE(ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_size_t)(('glfs_getcwd', client)) + ctypes.c_char_p, + ctypes.c_size_t) # TODO: # discard and fallocate fails with "AttributeError: /lib64/libgfapi.so.0: undefined symbol: glfs_discard", # noqa diff --git a/gluster/gfapi.py b/gluster/gfapi.py index 7fee1bb..5af06e6 100755 --- a/gluster/gfapi.py +++ b/gluster/gfapi.py @@ -432,24 +432,27 @@ class Volume(object): self.fs = api.glfs_new(self.volname) if not self.fs: - raise LibgfapiException("glfs_new(%s) failed." % (self.volname)) + err = ctypes.get_errno() + raise LibgfapiException("glfs_new(%s) failed: %s" % + (self.volname, os.strerror(err))) ret = api.glfs_set_volfile_server(self.fs, self.protocol, self.host, self.port) if ret < 0: - # FIXME: For some reason, get_errno() is not able to capture - # proper errno. Until then.. - # https://bugzilla.redhat.com/show_bug.cgi?id=1196161 + err = ctypes.get_errno() raise LibgfapiException("glfs_set_volfile_server(%s, %s, %s, " - "%s) failed." % (self.fs, self.protocol, - self.host, self.port)) + "%s) failed: %s" % (self.fs, self.protocol, + self.host, self.port, + os.strerror(err))) self.set_logging(self.log_file, self.log_level) if self.fs and not self._mounted: ret = api.glfs_init(self.fs) if ret < 0: - raise LibgfapiException("glfs_init(%s) failed." % (self.fs)) + err = ctypes.get_errno() + raise LibgfapiException("glfs_init(%s) failed: %s" % + (self.fs, os.strerror(err))) else: self._mounted = True @@ -463,7 +466,9 @@ class Volume(object): if self.fs: ret = self._api.glfs_fini(self.fs) if ret < 0: - raise LibgfapiException("glfs_fini(%s) failed." % (self.fs)) + err = ctypes.get_errno() + raise LibgfapiException("glfs_fini(%s) failed: %s" % + (self.fs, os.strerror(err))) else: # Succeeded. Protect against multiple umount() calls. self._mounted = False @@ -497,8 +502,10 @@ class Volume(object): if self.fs: ret = api.glfs_set_logging(self.fs, self.log_file, self.log_level) if ret < 0: - raise LibgfapiException("glfs_set_logging(%s, %s) failed." % - (self.log_file, self.log_level)) + err = ctypes.get_errno() + raise LibgfapiException("glfs_set_logging(%s, %s) failed: %s" % + (self.log_file, self.log_level, + os.strerror(err))) self.log_file = log_file self.log_level = log_level diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py index 87dbfe0..7eb4cd2 100644 --- a/test/functional/libgfapi-python-tests.py +++ b/test/functional/libgfapi-python-tests.py @@ -133,7 +133,13 @@ class FileOpsTest(unittest.TestCase): # invalid mode self.assertRaises(ValueError, self.vol.fopen, "file", 'x+') # file does not exist - self.assertRaises(OSError, self.vol.fopen, "file", 'r') + try: + self.vol.fopen("file", "r") + except OSError as err: + if err.errno != errno.ENOENT: + self.fail("Expecting ENOENT") + else: + self.fail("Expecting ENOENT") def test_fopen(self): # Default permission should be 0666 @@ -290,7 +296,13 @@ class FileOpsTest(unittest.TestCase): def test_rename(self): newpath = self.path + ".rename" self.vol.rename(self.path, newpath) - self.assertRaises(OSError, self.vol.lstat, self.path) + try: + self.vol.lstat(self.path) + except OSError as err: + if err.errno != errno.ENOENT: + self.fail("Expecting ENOENT") + else: + self.fail("Expecting ENOENT") def test_stat(self): sb = self.vol.stat(self.path) @@ -299,7 +311,13 @@ class FileOpsTest(unittest.TestCase): def test_unlink(self): self.vol.unlink(self.path) - self.assertRaises(OSError, self.vol.lstat, self.path) + try: + self.vol.lstat(self.path) + except OSError as err: + if err.errno != errno.ENOENT: + self.fail("Expecting ENOENT") + else: + self.fail("Expecting ENOENT") def test_setxattr(self): value = "hello world" -- cgit