From 75bb7da7094e0344fc7be93408ff6d6ead855253 Mon Sep 17 00:00:00 2001 From: Humble Chirammal Date: Tue, 17 Feb 2015 17:26:43 +0530 Subject: Rename module name from glusterfs to gluster The goal is to consolidate all gluster related python packages under single namespace "gluster". From client's perspective, it was: from glusterfs import gfapi Henceforth, it wil be: from gluster import gfapi Change-Id: If2509f570563ae7660892963607c9474313f803c Signed-off-by: Humble Chirammal --- MANIFEST.in | 2 +- gluster/__init__.py | 49 +++ gluster/api.py | 402 +++++++++++++++++++++ gluster/gfapi.py | 578 +++++++++++++++++++++++++++++++ glusterfs/__init__.py | 47 --- glusterfs/api.py | 402 --------------------- glusterfs/gfapi.py | 578 ------------------------------- setup.py | 4 +- test/functional/libgfapi-python-tests.py | 2 +- test/unit/gluster/test_gfapi.py | 238 ++++++------- tox.ini | 6 +- unittests.sh | 2 +- 12 files changed, 1156 insertions(+), 1154 deletions(-) create mode 100644 gluster/__init__.py create mode 100755 gluster/api.py create mode 100755 gluster/gfapi.py delete mode 100644 glusterfs/__init__.py delete mode 100755 glusterfs/api.py delete mode 100755 glusterfs/gfapi.py diff --git a/MANIFEST.in b/MANIFEST.in index 8b15060..51e5afe 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,7 +2,7 @@ include README.md LICENSE include functional_tests.sh unittests.sh include test-requirements.txt include tox.ini -recursive-include glusterfs *.py +recursive-include gluster *.py recursive-include test *.py include test/test.conf graft doc diff --git a/gluster/__init__.py b/gluster/__init__.py new file mode 100644 index 0000000..4562ec8 --- /dev/null +++ b/gluster/__init__.py @@ -0,0 +1,49 @@ +# Copyright (c) 2012-2014 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from pkgutil import extend_path +__path__ = extend_path(__path__, __name__) + + +class PkgInfo(object): + def __init__(self, canonical_version, release, name, final): + self.canonical_version = canonical_version + self.release = release + self.name = name + self.final = final + + def save_config(self, filename): + """ + Creates a file with the package configuration which can be sourced by + a bash script. + """ + with open(filename, 'w') as fd: + fd.write("NAME=%s\n" % self.name) + fd.write("VERSION=%s\n" % self.canonical_version) + fd.write("RELEASE=%s\n" % self.release) + + @property + def pretty_version(self): + if self.final: + return self.canonical_version + else: + return '%s-dev' % (self.canonical_version,) + + +### +### Change the Package version here +### +_pkginfo = PkgInfo('0.0.1', '0', 'python-libgfapi', False) +__version__ = _pkginfo.pretty_version +__canonical_version__ = _pkginfo.canonical_version diff --git a/gluster/api.py b/gluster/api.py new file mode 100755 index 0000000..803a778 --- /dev/null +++ b/gluster/api.py @@ -0,0 +1,402 @@ + +# Copyright (c) 2012-2014 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import ctypes +from ctypes.util import find_library + + +# Looks like ctypes is having trouble with dependencies, so just force them to +# load with RTLD_GLOBAL until I figure that out. +client = ctypes.CDLL(find_library("gfapi"), ctypes.RTLD_GLOBAL, use_errno=True) +# The above statement "may" fail with OSError on some systems if libgfapi.so +# is located in /usr/local/lib/. This happens when glusterfs is installed from +# source. Refer to: http://bugs.python.org/issue18502 + +# Wow, the Linux kernel folks really play nasty games with this structure. If +# you look at the man page for stat(2) and then at this definition you'll note +# two discrepancies. First, we seem to have st_nlink and st_mode reversed. In +# fact that's exactly how they're defined *for 64-bit systems*; for 32-bit +# they're in the man-page order. Even uglier, the man page makes no mention of +# the *nsec fields, but they are very much present and if they're not included +# then we get memory corruption because libgfapi has a structure definition +# that's longer than ours and they overwrite some random bit of memory after +# the space we allocated. Yes, that's all very disgusting, and I'm still not +# sure this will really work on 32-bit because all of the field types are so +# obfuscated behind macros and feature checks. + + +class Stat (ctypes.Structure): + _fields_ = [ + ("st_dev", ctypes.c_ulong), + ("st_ino", ctypes.c_ulong), + ("st_nlink", ctypes.c_ulong), + ("st_mode", ctypes.c_uint), + ("st_uid", ctypes.c_uint), + ("st_gid", ctypes.c_uint), + ("st_rdev", ctypes.c_ulong), + ("st_size", ctypes.c_ulong), + ("st_blksize", ctypes.c_ulong), + ("st_blocks", ctypes.c_ulong), + ("st_atime", ctypes.c_ulong), + ("st_atimensec", ctypes.c_ulong), + ("st_mtime", ctypes.c_ulong), + ("st_mtimensec", ctypes.c_ulong), + ("st_ctime", ctypes.c_ulong), + ("st_ctimensec", ctypes.c_ulong), + ] + + +class Statvfs (ctypes.Structure): + _fields_ = [ + ("f_bsize", ctypes.c_ulong), + ("f_frsize", ctypes.c_ulong), + ("f_blocks", ctypes.c_ulong), + ("f_bfree", ctypes.c_ulong), + ("f_bavail", ctypes.c_ulong), + ("f_files", ctypes.c_ulong), + ("f_ffree", ctypes.c_ulong), + ("f_favail", ctypes.c_ulong), + ("f_fsid", ctypes.c_ulong), + ("f_flag", ctypes.c_ulong), + ("f_namemax", ctypes.c_ulong), + ("__f_spare", ctypes.c_int * 6), + ] + + +class Dirent (ctypes.Structure): + _fields_ = [ + ("d_ino", ctypes.c_ulong), + ("d_off", ctypes.c_ulong), + ("d_reclen", ctypes.c_ushort), + ("d_type", ctypes.c_char), + ("d_name", ctypes.c_char * 256), + ] + + +# Here is the reference card of libgfapi library exported +# apis with its different versions. +# +# GFAPI_3.4.0 { +# glfs_new; +# glfs_set_volfile; +# glfs_set_volfile_server; +# glfs_set_logging; +# glfs_init; +# glfs_fini; +# glfs_open; +# glfs_creat; +# glfs_close; +# glfs_from_glfd; +# glfs_set_xlator_option; +# glfs_read; +# glfs_write; +# glfs_read_async; +# glfs_write_async; +# glfs_readv; +# glfs_writev; +# glfs_readv_async; +# glfs_writev_async; +# glfs_pread; +# glfs_pwrite; +# glfs_pread_async; +# glfs_pwrite_async; +# glfs_preadv; +# glfs_pwritev; +# glfs_preadv_async; +# glfs_pwritev_async; +# glfs_lseek; +# glfs_truncate; +# glfs_ftruncate; +# glfs_ftruncate_async; +# glfs_lstat; +# glfs_stat; +# glfs_fstat; +# glfs_fsync; +# glfs_fsync_async; +# glfs_fdatasync; +# glfs_fdatasync_async; +# glfs_access; +# glfs_symlink; +# glfs_readlink; +# glfs_mknod; +# glfs_mkdir; +# glfs_unlink; +# glfs_rmdir; +# glfs_rename; +# glfs_link; +# glfs_opendir; +# glfs_readdir_r; +# glfs_readdirplus_r; +# glfs_telldir; +# glfs_seekdir; +# glfs_closedir; +# glfs_statvfs; +# glfs_chmod; +# glfs_fchmod; +# glfs_chown; +# glfs_lchown; +# glfs_fchown; +# glfs_utimens; +# glfs_lutimens; +# glfs_futimens; +# glfs_getxattr; +# glfs_lgetxattr; +# glfs_fgetxattr; +# glfs_listxattr; +# glfs_llistxattr; +# glfs_flistxattr; +# glfs_setxattr; +# glfs_lsetxattr; +# glfs_fsetxattr; +# glfs_removexattr; +# glfs_lremovexattr; +# glfs_fremovexattr; +# glfs_getcwd; +# glfs_chdir; +# glfs_fchdir; +# glfs_realpath; +# glfs_posix_lock; +# glfs_dup; +# +# } +# +# GFAPI_3.4.2 { +# glfs_setfsuid; +# glfs_setfsgid; +# glfs_setfsgroups; +# glfs_h_lookupat; +# glfs_h_creat; +# glfs_h_mkdir; +# glfs_h_mknod; +# glfs_h_symlink; +# glfs_h_unlink; +# glfs_h_close; +# glfs_h_truncate; +# glfs_h_stat; +# glfs_h_getattrs; +# glfs_h_setattrs; +# glfs_h_readlink; +# glfs_h_link; +# glfs_h_rename; +# glfs_h_extract_handle; +# glfs_h_create_from_handle; +# glfs_h_opendir; +# glfs_h_open; +# } +# +# GFAPI_3.5.0 { +# +# glfs_get_volumeid; +# glfs_readdir; +# glfs_readdirplus; +# glfs_fallocate; +# glfs_discard; +# glfs_discard_async; +# glfs_zerofill; +# glfs_zerofill_async; +# glfs_caller_specific_init; +# glfs_h_setxattrs; +# +# } +# +# GFAPI_3.5.1 { +# +# glfs_unset_volfile_server; +# glfs_h_getxattrs; +# glfs_h_removexattrs; +# +# } +# +# GFAPI_3.6.0 { +# +# glfs_get_volfile; +# glfs_h_access; +# +# } +# + +# Define function prototypes for the wrapper functions. + +glfs_init = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_init', client)) + +glfs_statvfs = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_void_p)(('glfs_statvfs', client)) + +glfs_new = ctypes.CFUNCTYPE( + ctypes.c_void_p, ctypes.c_char_p)(('glfs_new', client)) + +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_logging = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_int)(('glfs_set_logging', client)) + +glfs_fini = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_fini', client)) + + +glfs_close = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_close', client)) + +glfs_lstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat))(('glfs_lstat', client)) + +glfs_stat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat))(('glfs_stat', client)) + +glfs_fstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER( + Stat))(('glfs_fstat', client)) + +glfs_chmod = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_ushort)(('glfs_chmod', client)) + +glfs_fchmod = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_ushort)(('glfs_fchmod', client)) + +glfs_chown = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_uint, + ctypes.c_uint)(('glfs_chown', client)) + +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 = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_uint, + ctypes.c_uint)(('glfs_fchown', client)) + +glfs_dup = ctypes.CFUNCTYPE( + ctypes.c_void_p, ctypes.c_void_p)(('glfs_dup', client)) + +glfs_fdatasync = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_fdatasync', client)) + +glfs_fsync = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_fsync', client)) + +glfs_lseek = ctypes.CFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, + ctypes.c_int)(('glfs_lseek', client)) + +glfs_read = ctypes.CFUNCTYPE(ctypes.c_size_t, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int)(('glfs_read', client)) + +glfs_write = ctypes.CFUNCTYPE(ctypes.c_size_t, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_size_t, + ctypes.c_int)(('glfs_write', client)) + +glfs_getxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t)(('glfs_getxattr', client)) + +glfs_listxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, + ctypes.c_void_p, + ctypes.c_char_p, + ctypes.c_void_p, + ctypes.c_size_t)(('glfs_listxattr', client)) + +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 = 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 = ctypes.CFUNCTYPE(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)) + +glfs_unlink = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p)(('glfs_unlink', client)) + +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_closedir = ctypes.CFUNCTYPE( + ctypes.c_int, ctypes.c_void_p)(('glfs_closedir', client)) + + +glfs_mkdir = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, + ctypes.c_ushort)(('glfs_mkdir', client)) + +glfs_opendir = ctypes.CFUNCTYPE(ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_char_p)(('glfs_opendir', client)) + +glfs_rmdir = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_void_p, + ctypes.c_char_p)(('glfs_rmdir', client)) + +glfs_setfsuid = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_uint)(('glfs_setfsuid', client)) + +glfs_setfsgid = ctypes.CFUNCTYPE(ctypes.c_int, + ctypes.c_uint)(('glfs_setfsgid', client)) + + +# TODO: creat and open fails on test_create_file_already_exists & test_open_file_not_exist functional testing, # noqa +# when defined via function prototype.. Need to find RCA. For time being, using it from 'api.glfs_' # noqa +#_glfs_creat = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_uint) # noqa + # (('glfs_creat', client)) # noqa +#_glfs_open = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int) # noqa +# (('glfs_open', client)) # noqa +# TODO: # discard and fallocate fails with "AttributeError: /lib64/libgfapi.so.0: undefined symbol: glfs_discard", # noqa +# for time being, using it from api.* # noqa +# glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa +#_glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t) # noqa +# (('glfs_fallocate', client)) # noqa + + +#glfs_creat = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_uint)(('glfs_creat', client)) # noqa +#glfs_open = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int)(('glfs_open', client)) # noqa + +#glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa +#glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t)(('glfs_fallocate', client)) # noqa diff --git a/gluster/gfapi.py b/gluster/gfapi.py new file mode 100755 index 0000000..3f7a068 --- /dev/null +++ b/gluster/gfapi.py @@ -0,0 +1,578 @@ +# Copyright (c) 2012-2014 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import ctypes +import os +import stat +import errno +from gluster import api + + +class File(object): + + def __init__(self, fd, path=None): + self.fd = fd + self.originalpath = path + + def __enter__(self): + if self.fd is None: + # __enter__ should only be called within the context + # of a 'with' statement when opening a file through + # Volume.open() + raise ValueError("I/O operation on closed file") + return self + + def __exit__(self, type, value, tb): + self.close() + + def close(self): + ret = api.glfs_close(self.fd) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def discard(self, offset, len): + ret = api.client.glfs_discard(self.fd, offset, len) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def dup(self): + dupfd = api.glfs_dup(self.fd) + if not dupfd: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return File(dupfd, self.originalpath) + + def fallocate(self, mode, offset, len): + ret = api.client.glfs_fallocate(self.fd, mode, offset, len) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def fchmod(self, mode): + """ + Change this file's mode + + :param mode: new mode + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_fchmod(self.fd, mode) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def fchown(self, uid, gid): + """ + Change this file's owner and group id + + :param uid: new user id for file + :param gid: new group id for file + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_fchown(self.fd, uid, gid) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def fdatasync(self): + """ + Force write of file + + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_fdatasync(self.fd) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def fgetsize(self): + """ + Return the size of a file, reported by fstat() + """ + return self.fstat().st_size + + def fstat(self): + """ + Returns Stat object for this file. + """ + s = api.Stat() + rc = api.glfs_fstat(self.fd, ctypes.byref(s)) + if rc < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return s + + def fsync(self): + ret = api.glfs_fsync(self.fd) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def lseek(self, pos, how): + """ + Set the read/write offset position of this file. + The new position is defined by 'pos' relative to 'how' + + :param pos: sets new offset position according to 'how' + :param how: SEEK_SET, sets offset position 'pos' bytes relative to + beginning of file, SEEK_CUR, the position is set relative + to the current position and SEEK_END sets the position + relative to the end of the file. + :returns: the new offset position + + """ + return api.glfs_lseek(self.fd, pos, how) + + def read(self, buflen=-1): + """ + read file + + :param buflen: length of read buffer. If less than 0, then whole + file is read. Default is -1. + :returns: buffer of size buflen + """ + if buflen < 0: + buflen = self.fgetsize() + rbuf = ctypes.create_string_buffer(buflen) + ret = api.glfs_read(self.fd, rbuf, buflen, 0) + if ret > 0: + return rbuf + elif ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + else: + return ret + + def write(self, data, flags=0): + # creating a ctypes.c_ubyte buffer to handle converting bytearray + # to the required C data type + + if type(data) is bytearray: + buf = (ctypes.c_ubyte * len(data)).from_buffer(data) + else: + buf = data + ret = api.glfs_write(self.fd, buf, len(buf), flags) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + +class Dir(object): + + def __init__(self, fd): + # Add a reference so the module-level variable "api" doesn't + # get yanked out from under us (see comment above File def'n). + self._api = api + self.fd = fd + self.cursor = ctypes.POINTER(api.Dirent)() + + def __del__(self): + self._api.glfs_closedir(self.fd) + self._api = None + + def next(self): + entry = api.Dirent() + entry.d_reclen = 256 + rc = api.glfs_readdir_r(self.fd, ctypes.byref(entry), + ctypes.byref(self.cursor)) + + if (rc < 0) or (not self.cursor) or (not self.cursor.contents): + return rc + + return entry + + +class Volume(object): + + def __init__(self, host, volid, proto="tcp", port=24007): + # Add a reference so the module-level variable "api" doesn't + # get yanked out from under us (see comment above File def'n). + self._api = api + self.fs = api.glfs_new(volid) + api.glfs_set_volfile_server(self.fs, proto, host, port) + + def __del__(self): + self._api.glfs_fini(self.fs) + self._api = None + + def set_logging(self, path, level): + api.glfs_set_logging(self.fs, path, level) + + def mount(self): + return api.glfs_init(self.fs) + + def chmod(self, path, mode): + """ + Change mode of path + + :param path: the item to be modified + :mode: new mode + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_chmod(self.fs, path, mode) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def chown(self, path, uid, gid): + """ + Change owner and group id of path + + :param path: the item to be modified + :param uid: new user id for item + :param gid: new group id for item + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_chown(self.fs, path, uid, gid) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def exists(self, path): + """ + Test whether a path exists. + Returns False for broken symbolic links. + """ + try: + self.stat(path) + except OSError: + return False + return True + + def getatime(self, path): + """ + Returns the last access time as reported by stat + """ + return self.stat(path).st_atime + + def getctime(self, path): + """ + Returns the time when changes were made to the path as reported by stat + This time is updated when changes are made to the file or dir's inode + or the contents of the file + """ + return self.stat(path).st_ctime + + def getmtime(self, path): + """ + Returns the time when changes were made to the content of the path + as reported by stat + """ + return self.stat(path).st_mtime + + def getsize(self, filename): + """ + Return the size of a file, reported by stat() + """ + return self.stat(filename).st_size + + def getxattr(self, path, key, maxlen): + buf = ctypes.create_string_buffer(maxlen) + rc = api.glfs_getxattr(self.fs, path, key, buf, maxlen) + if rc < 0: + err = ctypes.get_errno() + raise IOError(err, os.strerror(err)) + return buf.value[:rc] + + def isdir(self, path): + """ + Test whether a path is an existing directory + """ + try: + s = self.stat(path) + except OSError: + return False + return stat.S_ISDIR(s.st_mode) + + def isfile(self, path): + """ + Test whether a path is a regular file + """ + try: + s = self.stat(path) + except OSError: + return False + return stat.S_ISREG(s.st_mode) + + def islink(self, path): + """ + Test whether a path is a symbolic link + """ + try: + s = self.lstat(path) + except OSError: + return False + return stat.S_ISLNK(s.st_mode) + + def listdir(self, path): + """ + Return list of entries in a given directory 'path'. + "." and ".." are not included, and the list is not sorted. + """ + dir_list = [] + d = self.opendir(path) + while True: + ent = d.next() + if not isinstance(ent, api.Dirent): + break + name = ent.d_name[:ent.d_reclen] + if not name in [".", ".."]: + dir_list.append(name) + return dir_list + + def listxattr(self, path): + buf = ctypes.create_string_buffer(512) + rc = api.glfs_listxattr(self.fs, path, buf, 512) + if rc < 0: + err = ctypes.get_errno() + raise IOError(err, os.strerror(err)) + xattrs = [] + # Parsing character by character is ugly, but it seems like the + # easiest way to deal with the "strings separated by NUL in one + # buffer" format. + i = 0 + while i < rc: + new_xa = buf.raw[i] + i += 1 + while i < rc: + next_char = buf.raw[i] + i += 1 + if next_char == '\0': + xattrs.append(new_xa) + break + new_xa += next_char + xattrs.sort() + return xattrs + + def lstat(self, path): + s = api.Stat() + rc = api.glfs_lstat(self.fs, path, ctypes.byref(s)) + if rc < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return s + + def makedirs(self, name, mode=0777): + """ + Create directories defined in 'name' recursively. + """ + head, tail = os.path.split(name) + if not tail: + head, tail = os.path.split(head) + if head and tail and not self.exists(head): + try: + self.makedirs(head, mode) + except OSError as err: + if err.errno != errno.EEXIST: + raise + if tail == os.curdir: + return + self.mkdir(name, mode) + + def mkdir(self, path, mode=0777): + ret = api.glfs_mkdir(self.fs, path, mode) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def open(self, path, flags, mode=0777): + if (os.O_CREAT & flags) == os.O_CREAT: + #Without direct call to _api the functest fails on creat and open. + + fd = api.client.glfs_creat(self.fs, path, flags, mode) + else: + fd = api.client.glfs_open(self.fs, path, flags) + if not fd: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + + return File(fd, path) + + def opendir(self, path): + fd = api.glfs_opendir(self.fs, path) + if not fd: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return Dir(fd) + + def removexattr(self, path, key): + ret = api.glfs_removexattr(self.fs, path, key) + if ret < 0: + err = ctypes.get_errno() + raise IOError(err, os.strerror(err)) + return ret + + def rename(self, opath, npath): + ret = api.glfs_rename(self.fs, opath, npath) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def rmdir(self, path): + ret = api.glfs_rmdir(self.fs, path) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def rmtree(self, path, ignore_errors=False, onerror=None): + """ + Delete a whole directory tree structure. Raises OSError + if path is a symbolic link. + + :param path: Directory tree to remove + :param ignore_errors: If True, errors are ignored + :param onerror: If set, it is called to handle the error with arguments + (func, path, exc) where func is the function that + raised the error, path is the argument that caused it + to fail; and exc is the exception that was raised. + If ignore_errors is False and onerror is None, an + exception is raised + """ + if ignore_errors: + def onerror(*args): + pass + elif onerror is None: + def onerror(*args): + raise + if self.islink(path): + raise OSError("Cannot call rmtree on a symbolic link") + names = [] + try: + names = self.listdir(path) + except OSError as e: + onerror(self.listdir, path, e) + for name in names: + fullname = os.path.join(path, name) + if self.isdir(fullname): + self.rmtree(fullname, ignore_errors, onerror) + else: + try: + self.unlink(fullname) + except OSError as e: + onerror(self.unlink, fullname, e) + try: + self.rmdir(path) + except OSError as e: + onerror(self.rmdir, path, e) + + def setfsuid(self, uid): + ret = api.glfs_setfsuid(uid) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def setfsgid(self, gid): + ret = api.glfs_setfsgid(gid) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def setxattr(self, path, key, value, vlen): + ret = api.glfs_setxattr(self.fs, path, key, value, vlen, 0) + if ret < 0: + err = ctypes.get_errno() + raise IOError(err, os.strerror(err)) + return ret + + def stat(self, path): + s = api.Stat() + rc = api.glfs_stat(self.fs, path, ctypes.byref(s)) + if rc < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return s + + def statvfs(self, path): + """ + To get status information about the file system that contains the file + named by the path argument. + """ + s = api.Statvfs() + rc = api.glfs_statvfs(self.fs, path, ctypes.byref(s)) + if rc < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return s + + def symlink(self, source, link_name): + """ + Create a symbolic link 'link_name' which points to 'source' + """ + ret = api.glfs_symlink(self.fs, source, link_name) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def unlink(self, path): + """ + Delete the file 'path' + + :param path: file to be deleted + :returns: 0 if success, raises OSError if it fails + """ + ret = api.glfs_unlink(self.fs, path) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def walk(self, top, topdown=True, onerror=None, followlinks=False): + """ + Directory tree generator. Yields a 3-tuple dirpath, dirnames, filenames + + dirpath is the path to the directory, dirnames is a list of the names + of the subdirectories in dirpath. filenames is a list of the names of + the non-directiry files in dirpath + """ + try: + names = self.listdir(top) + except OSError as err: + if onerror is not None: + onerror(err) + return + + dirs, nondirs = [], [] + for name in names: + if self.isdir(os.path.join(top, name)): + dirs.append(name) + else: + nondirs.append(name) + + if topdown: + yield top, dirs, nondirs + for name in dirs: + new_path = os.path.join(top, name) + if followlinks or not self.islink(new_path): + for x in self.walk(new_path, topdown, onerror, followlinks): + yield x + if not topdown: + yield top, dirs, nondirs diff --git a/glusterfs/__init__.py b/glusterfs/__init__.py deleted file mode 100644 index 900183b..0000000 --- a/glusterfs/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2012-2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -class PkgInfo(object): - def __init__(self, canonical_version, release, name, final): - self.canonical_version = canonical_version - self.release = release - self.name = name - self.final = final - - def save_config(self, filename): - """ - Creates a file with the package configuration which can be sourced by - a bash script. - """ - with open(filename, 'w') as fd: - fd.write("NAME=%s\n" % self.name) - fd.write("VERSION=%s\n" % self.canonical_version) - fd.write("RELEASE=%s\n" % self.release) - - @property - def pretty_version(self): - if self.final: - return self.canonical_version - else: - return '%s-dev' % (self.canonical_version,) - - -### -### Change the Package version here -### -_pkginfo = PkgInfo('0.0.1', '0', 'python-libgfapi', False) -__version__ = _pkginfo.pretty_version -__canonical_version__ = _pkginfo.canonical_version diff --git a/glusterfs/api.py b/glusterfs/api.py deleted file mode 100755 index 803a778..0000000 --- a/glusterfs/api.py +++ /dev/null @@ -1,402 +0,0 @@ - -# Copyright (c) 2012-2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import ctypes -from ctypes.util import find_library - - -# Looks like ctypes is having trouble with dependencies, so just force them to -# load with RTLD_GLOBAL until I figure that out. -client = ctypes.CDLL(find_library("gfapi"), ctypes.RTLD_GLOBAL, use_errno=True) -# The above statement "may" fail with OSError on some systems if libgfapi.so -# is located in /usr/local/lib/. This happens when glusterfs is installed from -# source. Refer to: http://bugs.python.org/issue18502 - -# Wow, the Linux kernel folks really play nasty games with this structure. If -# you look at the man page for stat(2) and then at this definition you'll note -# two discrepancies. First, we seem to have st_nlink and st_mode reversed. In -# fact that's exactly how they're defined *for 64-bit systems*; for 32-bit -# they're in the man-page order. Even uglier, the man page makes no mention of -# the *nsec fields, but they are very much present and if they're not included -# then we get memory corruption because libgfapi has a structure definition -# that's longer than ours and they overwrite some random bit of memory after -# the space we allocated. Yes, that's all very disgusting, and I'm still not -# sure this will really work on 32-bit because all of the field types are so -# obfuscated behind macros and feature checks. - - -class Stat (ctypes.Structure): - _fields_ = [ - ("st_dev", ctypes.c_ulong), - ("st_ino", ctypes.c_ulong), - ("st_nlink", ctypes.c_ulong), - ("st_mode", ctypes.c_uint), - ("st_uid", ctypes.c_uint), - ("st_gid", ctypes.c_uint), - ("st_rdev", ctypes.c_ulong), - ("st_size", ctypes.c_ulong), - ("st_blksize", ctypes.c_ulong), - ("st_blocks", ctypes.c_ulong), - ("st_atime", ctypes.c_ulong), - ("st_atimensec", ctypes.c_ulong), - ("st_mtime", ctypes.c_ulong), - ("st_mtimensec", ctypes.c_ulong), - ("st_ctime", ctypes.c_ulong), - ("st_ctimensec", ctypes.c_ulong), - ] - - -class Statvfs (ctypes.Structure): - _fields_ = [ - ("f_bsize", ctypes.c_ulong), - ("f_frsize", ctypes.c_ulong), - ("f_blocks", ctypes.c_ulong), - ("f_bfree", ctypes.c_ulong), - ("f_bavail", ctypes.c_ulong), - ("f_files", ctypes.c_ulong), - ("f_ffree", ctypes.c_ulong), - ("f_favail", ctypes.c_ulong), - ("f_fsid", ctypes.c_ulong), - ("f_flag", ctypes.c_ulong), - ("f_namemax", ctypes.c_ulong), - ("__f_spare", ctypes.c_int * 6), - ] - - -class Dirent (ctypes.Structure): - _fields_ = [ - ("d_ino", ctypes.c_ulong), - ("d_off", ctypes.c_ulong), - ("d_reclen", ctypes.c_ushort), - ("d_type", ctypes.c_char), - ("d_name", ctypes.c_char * 256), - ] - - -# Here is the reference card of libgfapi library exported -# apis with its different versions. -# -# GFAPI_3.4.0 { -# glfs_new; -# glfs_set_volfile; -# glfs_set_volfile_server; -# glfs_set_logging; -# glfs_init; -# glfs_fini; -# glfs_open; -# glfs_creat; -# glfs_close; -# glfs_from_glfd; -# glfs_set_xlator_option; -# glfs_read; -# glfs_write; -# glfs_read_async; -# glfs_write_async; -# glfs_readv; -# glfs_writev; -# glfs_readv_async; -# glfs_writev_async; -# glfs_pread; -# glfs_pwrite; -# glfs_pread_async; -# glfs_pwrite_async; -# glfs_preadv; -# glfs_pwritev; -# glfs_preadv_async; -# glfs_pwritev_async; -# glfs_lseek; -# glfs_truncate; -# glfs_ftruncate; -# glfs_ftruncate_async; -# glfs_lstat; -# glfs_stat; -# glfs_fstat; -# glfs_fsync; -# glfs_fsync_async; -# glfs_fdatasync; -# glfs_fdatasync_async; -# glfs_access; -# glfs_symlink; -# glfs_readlink; -# glfs_mknod; -# glfs_mkdir; -# glfs_unlink; -# glfs_rmdir; -# glfs_rename; -# glfs_link; -# glfs_opendir; -# glfs_readdir_r; -# glfs_readdirplus_r; -# glfs_telldir; -# glfs_seekdir; -# glfs_closedir; -# glfs_statvfs; -# glfs_chmod; -# glfs_fchmod; -# glfs_chown; -# glfs_lchown; -# glfs_fchown; -# glfs_utimens; -# glfs_lutimens; -# glfs_futimens; -# glfs_getxattr; -# glfs_lgetxattr; -# glfs_fgetxattr; -# glfs_listxattr; -# glfs_llistxattr; -# glfs_flistxattr; -# glfs_setxattr; -# glfs_lsetxattr; -# glfs_fsetxattr; -# glfs_removexattr; -# glfs_lremovexattr; -# glfs_fremovexattr; -# glfs_getcwd; -# glfs_chdir; -# glfs_fchdir; -# glfs_realpath; -# glfs_posix_lock; -# glfs_dup; -# -# } -# -# GFAPI_3.4.2 { -# glfs_setfsuid; -# glfs_setfsgid; -# glfs_setfsgroups; -# glfs_h_lookupat; -# glfs_h_creat; -# glfs_h_mkdir; -# glfs_h_mknod; -# glfs_h_symlink; -# glfs_h_unlink; -# glfs_h_close; -# glfs_h_truncate; -# glfs_h_stat; -# glfs_h_getattrs; -# glfs_h_setattrs; -# glfs_h_readlink; -# glfs_h_link; -# glfs_h_rename; -# glfs_h_extract_handle; -# glfs_h_create_from_handle; -# glfs_h_opendir; -# glfs_h_open; -# } -# -# GFAPI_3.5.0 { -# -# glfs_get_volumeid; -# glfs_readdir; -# glfs_readdirplus; -# glfs_fallocate; -# glfs_discard; -# glfs_discard_async; -# glfs_zerofill; -# glfs_zerofill_async; -# glfs_caller_specific_init; -# glfs_h_setxattrs; -# -# } -# -# GFAPI_3.5.1 { -# -# glfs_unset_volfile_server; -# glfs_h_getxattrs; -# glfs_h_removexattrs; -# -# } -# -# GFAPI_3.6.0 { -# -# glfs_get_volfile; -# glfs_h_access; -# -# } -# - -# Define function prototypes for the wrapper functions. - -glfs_init = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_init', client)) - -glfs_statvfs = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_void_p)(('glfs_statvfs', client)) - -glfs_new = ctypes.CFUNCTYPE( - ctypes.c_void_p, ctypes.c_char_p)(('glfs_new', client)) - -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_logging = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_int)(('glfs_set_logging', client)) - -glfs_fini = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fini', client)) - - -glfs_close = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_close', client)) - -glfs_lstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat))(('glfs_lstat', client)) - -glfs_stat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat))(('glfs_stat', client)) - -glfs_fstat = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER( - Stat))(('glfs_fstat', client)) - -glfs_chmod = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_ushort)(('glfs_chmod', client)) - -glfs_fchmod = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_ushort)(('glfs_fchmod', client)) - -glfs_chown = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_uint, - ctypes.c_uint)(('glfs_chown', client)) - -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 = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_uint, - ctypes.c_uint)(('glfs_fchown', client)) - -glfs_dup = ctypes.CFUNCTYPE( - ctypes.c_void_p, ctypes.c_void_p)(('glfs_dup', client)) - -glfs_fdatasync = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fdatasync', client)) - -glfs_fsync = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_fsync', client)) - -glfs_lseek = ctypes.CFUNCTYPE(ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, - ctypes.c_int)(('glfs_lseek', client)) - -glfs_read = ctypes.CFUNCTYPE(ctypes.c_size_t, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_int)(('glfs_read', client)) - -glfs_write = ctypes.CFUNCTYPE(ctypes.c_size_t, - ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_size_t, - ctypes.c_int)(('glfs_write', client)) - -glfs_getxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_size_t)(('glfs_getxattr', client)) - -glfs_listxattr = ctypes.CFUNCTYPE(ctypes.c_size_t, - ctypes.c_void_p, - ctypes.c_char_p, - ctypes.c_void_p, - ctypes.c_size_t)(('glfs_listxattr', client)) - -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 = 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 = ctypes.CFUNCTYPE(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)) - -glfs_unlink = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p)(('glfs_unlink', client)) - -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_closedir = ctypes.CFUNCTYPE( - ctypes.c_int, ctypes.c_void_p)(('glfs_closedir', client)) - - -glfs_mkdir = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_char_p, - ctypes.c_ushort)(('glfs_mkdir', client)) - -glfs_opendir = ctypes.CFUNCTYPE(ctypes.c_void_p, - ctypes.c_void_p, - ctypes.c_char_p)(('glfs_opendir', client)) - -glfs_rmdir = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_void_p, - ctypes.c_char_p)(('glfs_rmdir', client)) - -glfs_setfsuid = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_uint)(('glfs_setfsuid', client)) - -glfs_setfsgid = ctypes.CFUNCTYPE(ctypes.c_int, - ctypes.c_uint)(('glfs_setfsgid', client)) - - -# TODO: creat and open fails on test_create_file_already_exists & test_open_file_not_exist functional testing, # noqa -# when defined via function prototype.. Need to find RCA. For time being, using it from 'api.glfs_' # noqa -#_glfs_creat = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_uint) # noqa - # (('glfs_creat', client)) # noqa -#_glfs_open = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int) # noqa -# (('glfs_open', client)) # noqa -# TODO: # discard and fallocate fails with "AttributeError: /lib64/libgfapi.so.0: undefined symbol: glfs_discard", # noqa -# for time being, using it from api.* # noqa -# glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa -#_glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t) # noqa -# (('glfs_fallocate', client)) # noqa - - -#glfs_creat = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_uint)(('glfs_creat', client)) # noqa -#glfs_open = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int)(('glfs_open', client)) # noqa - -#glfs_discard = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_size_t)(('glfs_discard', client)) # noqa -#glfs_fallocate = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_ulong, ctypes.c_size_t)(('glfs_fallocate', client)) # noqa diff --git a/glusterfs/gfapi.py b/glusterfs/gfapi.py deleted file mode 100755 index 42c4aef..0000000 --- a/glusterfs/gfapi.py +++ /dev/null @@ -1,578 +0,0 @@ -# Copyright (c) 2012-2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import ctypes -import os -import stat -import errno -from glusterfs import api - - -class File(object): - - def __init__(self, fd, path=None): - self.fd = fd - self.originalpath = path - - def __enter__(self): - if self.fd is None: - # __enter__ should only be called within the context - # of a 'with' statement when opening a file through - # Volume.open() - raise ValueError("I/O operation on closed file") - return self - - def __exit__(self, type, value, tb): - self.close() - - def close(self): - ret = api.glfs_close(self.fd) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def discard(self, offset, len): - ret = api.client.glfs_discard(self.fd, offset, len) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def dup(self): - dupfd = api.glfs_dup(self.fd) - if not dupfd: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return File(dupfd, self.originalpath) - - def fallocate(self, mode, offset, len): - ret = api.client.glfs_fallocate(self.fd, mode, offset, len) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def fchmod(self, mode): - """ - Change this file's mode - - :param mode: new mode - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_fchmod(self.fd, mode) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def fchown(self, uid, gid): - """ - Change this file's owner and group id - - :param uid: new user id for file - :param gid: new group id for file - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_fchown(self.fd, uid, gid) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def fdatasync(self): - """ - Force write of file - - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_fdatasync(self.fd) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def fgetsize(self): - """ - Return the size of a file, reported by fstat() - """ - return self.fstat().st_size - - def fstat(self): - """ - Returns Stat object for this file. - """ - s = api.Stat() - rc = api.glfs_fstat(self.fd, ctypes.byref(s)) - if rc < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return s - - def fsync(self): - ret = api.glfs_fsync(self.fd) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def lseek(self, pos, how): - """ - Set the read/write offset position of this file. - The new position is defined by 'pos' relative to 'how' - - :param pos: sets new offset position according to 'how' - :param how: SEEK_SET, sets offset position 'pos' bytes relative to - beginning of file, SEEK_CUR, the position is set relative - to the current position and SEEK_END sets the position - relative to the end of the file. - :returns: the new offset position - - """ - return api.glfs_lseek(self.fd, pos, how) - - def read(self, buflen=-1): - """ - read file - - :param buflen: length of read buffer. If less than 0, then whole - file is read. Default is -1. - :returns: buffer of size buflen - """ - if buflen < 0: - buflen = self.fgetsize() - rbuf = ctypes.create_string_buffer(buflen) - ret = api.glfs_read(self.fd, rbuf, buflen, 0) - if ret > 0: - return rbuf - elif ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - else: - return ret - - def write(self, data, flags=0): - # creating a ctypes.c_ubyte buffer to handle converting bytearray - # to the required C data type - - if type(data) is bytearray: - buf = (ctypes.c_ubyte * len(data)).from_buffer(data) - else: - buf = data - ret = api.glfs_write(self.fd, buf, len(buf), flags) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - -class Dir(object): - - def __init__(self, fd): - # Add a reference so the module-level variable "api" doesn't - # get yanked out from under us (see comment above File def'n). - self._api = api - self.fd = fd - self.cursor = ctypes.POINTER(api.Dirent)() - - def __del__(self): - self._api.glfs_closedir(self.fd) - self._api = None - - def next(self): - entry = api.Dirent() - entry.d_reclen = 256 - rc = api.glfs_readdir_r(self.fd, ctypes.byref(entry), - ctypes.byref(self.cursor)) - - if (rc < 0) or (not self.cursor) or (not self.cursor.contents): - return rc - - return entry - - -class Volume(object): - - def __init__(self, host, volid, proto="tcp", port=24007): - # Add a reference so the module-level variable "api" doesn't - # get yanked out from under us (see comment above File def'n). - self._api = api - self.fs = api.glfs_new(volid) - api.glfs_set_volfile_server(self.fs, proto, host, port) - - def __del__(self): - self._api.glfs_fini(self.fs) - self._api = None - - def set_logging(self, path, level): - api.glfs_set_logging(self.fs, path, level) - - def mount(self): - return api.glfs_init(self.fs) - - def chmod(self, path, mode): - """ - Change mode of path - - :param path: the item to be modified - :mode: new mode - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_chmod(self.fs, path, mode) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def chown(self, path, uid, gid): - """ - Change owner and group id of path - - :param path: the item to be modified - :param uid: new user id for item - :param gid: new group id for item - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_chown(self.fs, path, uid, gid) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def exists(self, path): - """ - Test whether a path exists. - Returns False for broken symbolic links. - """ - try: - self.stat(path) - except OSError: - return False - return True - - def getatime(self, path): - """ - Returns the last access time as reported by stat - """ - return self.stat(path).st_atime - - def getctime(self, path): - """ - Returns the time when changes were made to the path as reported by stat - This time is updated when changes are made to the file or dir's inode - or the contents of the file - """ - return self.stat(path).st_ctime - - def getmtime(self, path): - """ - Returns the time when changes were made to the content of the path - as reported by stat - """ - return self.stat(path).st_mtime - - def getsize(self, filename): - """ - Return the size of a file, reported by stat() - """ - return self.stat(filename).st_size - - def getxattr(self, path, key, maxlen): - buf = ctypes.create_string_buffer(maxlen) - rc = api.glfs_getxattr(self.fs, path, key, buf, maxlen) - if rc < 0: - err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) - return buf.value[:rc] - - def isdir(self, path): - """ - Test whether a path is an existing directory - """ - try: - s = self.stat(path) - except OSError: - return False - return stat.S_ISDIR(s.st_mode) - - def isfile(self, path): - """ - Test whether a path is a regular file - """ - try: - s = self.stat(path) - except OSError: - return False - return stat.S_ISREG(s.st_mode) - - def islink(self, path): - """ - Test whether a path is a symbolic link - """ - try: - s = self.lstat(path) - except OSError: - return False - return stat.S_ISLNK(s.st_mode) - - def listdir(self, path): - """ - Return list of entries in a given directory 'path'. - "." and ".." are not included, and the list is not sorted. - """ - d = self.opendir(path) - dir_list = [] - while True: - ent = d.next() - if not isinstance(ent, api.Dirent): - break - name = ent.d_name[:ent.d_reclen] - if not name in [".", ".."]: - dir_list.append(name) - return dir_list - - def listxattr(self, path): - buf = ctypes.create_string_buffer(512) - rc = api.glfs_listxattr(self.fs, path, buf, 512) - if rc < 0: - err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) - xattrs = [] - # Parsing character by character is ugly, but it seems like the - # easiest way to deal with the "strings separated by NUL in one - # buffer" format. - i = 0 - while i < rc: - new_xa = buf.raw[i] - i += 1 - while i < rc: - next_char = buf.raw[i] - i += 1 - if next_char == '\0': - xattrs.append(new_xa) - break - new_xa += next_char - xattrs.sort() - return xattrs - - def lstat(self, path): - s = api.Stat() - rc = api.glfs_lstat(self.fs, path, ctypes.byref(s)) - if rc < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return s - - def makedirs(self, name, mode=0777): - """ - Create directories defined in 'name' recursively. - """ - head, tail = os.path.split(name) - if not tail: - head, tail = os.path.split(head) - if head and tail and not self.exists(head): - try: - self.makedirs(head, mode) - except OSError as err: - if err.errno != errno.EEXIST: - raise - if tail == os.curdir: - return - self.mkdir(name, mode) - - def mkdir(self, path, mode=0777): - ret = api.glfs_mkdir(self.fs, path, mode) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def open(self, path, flags, mode=0777): - if (os.O_CREAT & flags) == os.O_CREAT: - #Without direct call to _api the functest fails on creat and open. - - fd = api.client.glfs_creat(self.fs, path, flags, mode) - else: - fd = api.client.glfs_open(self.fs, path, flags) - if not fd: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - - return File(fd, path) - - def opendir(self, path): - fd = api.glfs_opendir(self.fs, path) - if not fd: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return Dir(fd) - - def removexattr(self, path, key): - ret = api.glfs_removexattr(self.fs, path, key) - if ret < 0: - err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) - return ret - - def rename(self, opath, npath): - ret = api.glfs_rename(self.fs, opath, npath) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def rmdir(self, path): - ret = api.glfs_rmdir(self.fs, path) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def rmtree(self, path, ignore_errors=False, onerror=None): - """ - Delete a whole directory tree structure. Raises OSError - if path is a symbolic link. - - :param path: Directory tree to remove - :param ignore_errors: If True, errors are ignored - :param onerror: If set, it is called to handle the error with arguments - (func, path, exc) where func is the function that - raised the error, path is the argument that caused it - to fail; and exc is the exception that was raised. - If ignore_errors is False and onerror is None, an - exception is raised - """ - if ignore_errors: - def onerror(*args): - pass - elif onerror is None: - def onerror(*args): - raise - if self.islink(path): - raise OSError("Cannot call rmtree on a symbolic link") - names = [] - try: - names = self.listdir(path) - except OSError as e: - onerror(self.listdir, path, e) - for name in names: - fullname = os.path.join(path, name) - if self.isdir(fullname): - self.rmtree(fullname, ignore_errors, onerror) - else: - try: - self.unlink(fullname) - except OSError as e: - onerror(self.unlink, fullname, e) - try: - self.rmdir(path) - except OSError as e: - onerror(self.rmdir, path, e) - - def setfsuid(self, uid): - ret = api.glfs_setfsuid(uid) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def setfsgid(self, gid): - ret = api.glfs_setfsgid(gid) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def setxattr(self, path, key, value, vlen): - ret = api.glfs_setxattr(self.fs, path, key, value, vlen, 0) - if ret < 0: - err = ctypes.get_errno() - raise IOError(err, os.strerror(err)) - return ret - - def stat(self, path): - s = api.Stat() - rc = api.glfs_stat(self.fs, path, ctypes.byref(s)) - if rc < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return s - - def statvfs(self, path): - """ - To get status information about the file system that contains the file - named by the path argument. - """ - s = api.Statvfs() - rc = api.glfs_statvfs(self.fs, path, ctypes.byref(s)) - if rc < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return s - - def symlink(self, source, link_name): - """ - Create a symbolic link 'link_name' which points to 'source' - """ - ret = api.glfs_symlink(self.fs, source, link_name) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def unlink(self, path): - """ - Delete the file 'path' - - :param path: file to be deleted - :returns: 0 if success, raises OSError if it fails - """ - ret = api.glfs_unlink(self.fs, path) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def walk(self, top, topdown=True, onerror=None, followlinks=False): - """ - Directory tree generator. Yields a 3-tuple dirpath, dirnames, filenames - - dirpath is the path to the directory, dirnames is a list of the names - of the subdirectories in dirpath. filenames is a list of the names of - the non-directiry files in dirpath - """ - try: - names = self.listdir(top) - except OSError as err: - if onerror is not None: - onerror(err) - return - - dirs, nondirs = [], [] - for name in names: - if self.isdir(os.path.join(top, name)): - dirs.append(name) - else: - nondirs.append(name) - - if topdown: - yield top, dirs, nondirs - for name in dirs: - new_path = os.path.join(top, name) - if followlinks or not self.islink(new_path): - for x in self.walk(new_path, topdown, onerror, followlinks): - yield x - if not topdown: - yield top, dirs, nondirs diff --git a/setup.py b/setup.py index 080a7f4..2b06ead 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ from setuptools import setup -from glusterfs import __canonical_version__ as version +from gluster import __canonical_version__ as version name = 'gfapi' @@ -30,7 +30,7 @@ setup( author='Red Hat, Inc.', author_email='gluster-users@gluster.org', url='http://www.gluster.org', - packages=['glusterfs', ], + packages=['gluster', ], test_suite='nose.collector', classifiers=[ 'Development Status :: 5 - Production/Stable' diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py index 4dbdf2d..a49e626 100644 --- a/test/functional/libgfapi-python-tests.py +++ b/test/functional/libgfapi-python-tests.py @@ -18,7 +18,7 @@ import os import types import errno -from glusterfs import gfapi +from gluster import gfapi from test import get_test_config from ConfigParser import NoSectionError, NoOptionError diff --git a/test/unit/gluster/test_gfapi.py b/test/unit/gluster/test_gfapi.py index 8451b51..f03f61a 100644 --- a/test/unit/gluster/test_gfapi.py +++ b/test/unit/gluster/test_gfapi.py @@ -14,13 +14,13 @@ # limitations under the License. import unittest -import glusterfs +import gluster import os import stat import errno -from glusterfs import gfapi -from glusterfs import api +from gluster import gfapi +from gluster import api from nose import SkipTest from mock import Mock, patch from contextlib import nested @@ -57,11 +57,11 @@ class TestFile(unittest.TestCase): cls.fd = None def setUp(self): - self._saved_glfs_close = glusterfs.gfapi.api.glfs_close - glusterfs.gfapi.api.glfs_close = _mock_glfs_close + self._saved_glfs_close = gluster.gfapi.api.glfs_close + gluster.gfapi.api.glfs_close = _mock_glfs_close def tearDown(self): - glusterfs.gfapi.api.glfs_close = self._saved_glfs_close + gluster.gfapi.api.glfs_close = self._saved_glfs_close def test_fchmod_success(self): mock_glfs_fchmod = Mock() @@ -82,7 +82,7 @@ class TestFile(unittest.TestCase): mock_glfs_fchown = Mock() mock_glfs_fchown.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_fchown", mock_glfs_fchown): + with patch("gluster.gfapi.api.glfs_fchown", mock_glfs_fchown): ret = self.fd.fchown(9, 11) self.assertEquals(ret, 0) @@ -90,14 +90,14 @@ class TestFile(unittest.TestCase): mock_glfs_fchown = Mock() mock_glfs_fchown.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_fchown", mock_glfs_fchown): + with patch("gluster.gfapi.api.glfs_fchown", mock_glfs_fchown): self.assertRaises(OSError, self.fd.fchown, 9, 11) def test_dup(self): mock_glfs_dup = Mock() mock_glfs_dup.return_value = 2 - with patch("glusterfs.gfapi.api.glfs_dup", mock_glfs_dup): + with patch("gluster.gfapi.api.glfs_dup", mock_glfs_dup): f = self.fd.dup() self.assertTrue(isinstance(f, gfapi.File)) self.assertEqual(f.originalpath, "fakefile") @@ -107,7 +107,7 @@ class TestFile(unittest.TestCase): mock_glfs_fdatasync = Mock() mock_glfs_fdatasync.return_value = 4 - with patch("glusterfs.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): + with patch("gluster.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): ret = self.fd.fdatasync() self.assertEquals(ret, 4) @@ -115,14 +115,14 @@ class TestFile(unittest.TestCase): mock_glfs_fdatasync = Mock() mock_glfs_fdatasync.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): + with patch("gluster.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): self.assertRaises(OSError, self.fd.fdatasync) def test_fstat_success(self): mock_glfs_fstat = Mock() mock_glfs_fstat.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_fstat", mock_glfs_fstat): + with patch("gluster.gfapi.api.glfs_fstat", mock_glfs_fstat): s = self.fd.fstat() self.assertTrue(isinstance(s, api.Stat)) @@ -130,14 +130,14 @@ class TestFile(unittest.TestCase): mock_glfs_fstat = Mock() mock_glfs_fstat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_fstat", mock_glfs_fstat): + with patch("gluster.gfapi.api.glfs_fstat", mock_glfs_fstat): self.assertRaises(OSError, self.fd.fstat) def test_fsync_success(self): mock_glfs_fsync = Mock() mock_glfs_fsync.return_value = 4 - with patch("glusterfs.gfapi.api.glfs_fsync", mock_glfs_fsync): + with patch("gluster.gfapi.api.glfs_fsync", mock_glfs_fsync): ret = self.fd.fsync() self.assertEquals(ret, 4) @@ -145,14 +145,14 @@ class TestFile(unittest.TestCase): mock_glfs_fsync = Mock() mock_glfs_fsync.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_fsync", mock_glfs_fsync): + with patch("gluster.gfapi.api.glfs_fsync", mock_glfs_fsync): self.assertRaises(OSError, self.fd.fsync) def test_lseek_success(self): mock_glfs_lseek = Mock() mock_glfs_lseek.return_value = 20 - with patch("glusterfs.gfapi.api.glfs_lseek", mock_glfs_lseek): + with patch("gluster.gfapi.api.glfs_lseek", mock_glfs_lseek): o = self.fd.lseek(20, os.SEEK_SET) self.assertEqual(o, 20) @@ -161,7 +161,7 @@ class TestFile(unittest.TestCase): rbuf.value = "hello" return 5 - with patch("glusterfs.gfapi.api.glfs_read", _mock_glfs_read): + with patch("gluster.gfapi.api.glfs_read", _mock_glfs_read): b = self.fd.read(5) self.assertEqual(b.value, "hello") @@ -169,14 +169,14 @@ class TestFile(unittest.TestCase): mock_glfs_read = Mock() mock_glfs_read.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_read", mock_glfs_read): + with patch("gluster.gfapi.api.glfs_read", mock_glfs_read): self.assertRaises(OSError, self.fd.read, 5) def test_read_fail_empty_buffer(self): mock_glfs_read = Mock() mock_glfs_read.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_read", mock_glfs_read): + with patch("gluster.gfapi.api.glfs_read", mock_glfs_read): b = self.fd.read(5) self.assertEqual(b, 0) @@ -196,7 +196,7 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = 5 - with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): + with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): ret = self.fd.write("hello") self.assertEqual(ret, 5) @@ -204,7 +204,7 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = 3 - with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): + with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): b = bytearray(3) ret = self.fd.write(b) self.assertEqual(ret, 3) @@ -213,61 +213,61 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): + with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): self.assertRaises(OSError, self.fd.write, "hello") def test_fallocate_success(self): - raise SkipTest("need to solve issue with dependency on libgfapi.so") + raise SkipTest("need to solve issue with dependency on gluster.so") mock_glfs_fallocate = Mock() mock_glfs_fallocate.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_fallocate", mock_glfs_fallocate): + with patch("gluster.gfapi.api.glfs_fallocate", mock_glfs_fallocate): ret = self.fd.fallocate(0, 0, 1024) self.assertEqual(ret, 0) def test_fallocate_fail_exception(self): - raise SkipTest("need to solve issue with dependency on libgfapi.so") + raise SkipTest("need to solve issue with dependency on gluster.so") mock_glfs_fallocate = Mock() mock_glfs_fallocate.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_fallocate", mock_glfs_fallocate): + with patch("gluster.gfapi.api.glfs_fallocate", mock_glfs_fallocate): self.assertRaises(OSError, self.fd.fallocate, 0, 0, 1024) def test_discard_success(self): - raise SkipTest("need to solve issue with dependency on libgfapi.so") + raise SkipTest("need to solve issue with dependency on gluster.so") mock_glfs_discard = Mock() mock_glfs_discard.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_discard", mock_glfs_discard): + with patch("gluster.gfapi.api.glfs_discard", mock_glfs_discard): ret = self.fd.discard(1024, 1024) self.assertEqual(ret, 0) def test_discard_fail_exception(self): - raise SkipTest("need to solve issue with dependency on libgfapi.so") + raise SkipTest("need to solve issue with dependency on gluster.so") mock_glfs_discard = Mock() mock_glfs_discard.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_discard", mock_glfs_discard): + with patch("gluster.gfapi.api.glfs_discard", mock_glfs_discard): self.assertRaises(OSError, self.fd.discard, 1024, 1024) class TestDir(unittest.TestCase): def setUp(self): - self._saved_glfs_closedir = glusterfs.gfapi.api.glfs_closedir - glusterfs.gfapi.api.glfs_closedir = _mock_glfs_closedir + self._saved_glfs_closedir = gluster.gfapi.api.glfs_closedir + gluster.gfapi.api.glfs_closedir = _mock_glfs_closedir def tearDown(self): - glusterfs.gfapi.api.glfs_closedir = self._saved_glfs_closedir + gluster.gfapi.api.glfs_closedir = self._saved_glfs_closedir def test_next_success(self): - raise SkipTest("need to solve issue with dependency on libgfapi.so") + raise SkipTest("need to solve issue with dependency on gluster.so") def mock_glfs_readdir_r(fd, ent, cursor): cursor.contents = "bla" return 0 - with patch("glusterfs.gfapi.api.glfs_readdir_r", mock_glfs_readdir_r): + with patch("gluster.gfapi.api.glfs_readdir_r", mock_glfs_readdir_r): fd = gfapi.Dir(2) ent = fd.next() self.assertTrue(isinstance(ent, gfapi.Dirent)) @@ -277,33 +277,33 @@ class TestVolume(unittest.TestCase): @classmethod def setUpClass(cls): - cls._saved_glfs_new = glusterfs.gfapi.api.glfs_new - glusterfs.gfapi.api.glfs_new = _mock_glfs_new + cls._saved_glfs_new = gluster.gfapi.api.glfs_new + gluster.gfapi.api.glfs_new = _mock_glfs_new cls._saved_glfs_set_volfile_server = \ - glusterfs.gfapi.api.glfs_set_volfile_server - glusterfs.gfapi.api.glfs_set_volfile_server = \ + gluster.gfapi.api.glfs_set_volfile_server + gluster.gfapi.api.glfs_set_volfile_server = \ _mock_glfs_set_volfile_server - cls._saved_glfs_fini = glusterfs.gfapi.api.glfs_fini - glusterfs.gfapi.api.glfs_fini = _mock_glfs_fini + cls._saved_glfs_fini = gluster.gfapi.api.glfs_fini + gluster.gfapi.api.glfs_fini = _mock_glfs_fini - cls._saved_glfs_close = glusterfs.gfapi.api.glfs_close - glusterfs.gfapi.api.glfs_close = _mock_glfs_close + cls._saved_glfs_close = gluster.gfapi.api.glfs_close + gluster.gfapi.api.glfs_close = _mock_glfs_close - cls._saved_glfs_closedir = glusterfs.gfapi.api.glfs_closedir - glusterfs.gfapi.api.glfs_closedir = _mock_glfs_closedir + cls._saved_glfs_closedir = gluster.gfapi.api.glfs_closedir + gluster.gfapi.api.glfs_closedir = _mock_glfs_closedir cls.vol = gfapi.Volume("mockhost", "test") @classmethod def tearDownClass(cls): cls.vol = None - glusterfs.gfapi.api.glfs_new = cls._saved_glfs_new - glusterfs.gfapi.api.glfs_set_volfile_server = \ + gluster.gfapi.api.glfs_new = cls._saved_glfs_new + gluster.gfapi.api.glfs_set_volfile_server = \ cls._saved_glfs_set_volfile_server - glusterfs.gfapi.api.glfs_fini = cls._saved_glfs_fini - glusterfs.gfapi.api.glfs_close = cls._saved_glfs_close - glusterfs.gfapi.api.glfs_closedir = cls._saved_glfs_closedir + gluster.gfapi.api.glfs_fini = cls._saved_glfs_fini + gluster.gfapi.api.glfs_close = cls._saved_glfs_close + gluster.gfapi.api.glfs_closedir = cls._saved_glfs_closedir def test_chmod_success(self): mock_glfs_chmod = Mock() @@ -324,7 +324,7 @@ class TestVolume(unittest.TestCase): mock_glfs_chown = Mock() mock_glfs_chown.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_chown", mock_glfs_chown): + with patch("gluster.gfapi.api.glfs_chown", mock_glfs_chown): ret = self.vol.chown("file.txt", 9, 11) self.assertEquals(ret, 0) @@ -332,14 +332,14 @@ class TestVolume(unittest.TestCase): mock_glfs_chown = Mock() mock_glfs_chown.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_chown", mock_glfs_chown): + with patch("gluster.gfapi.api.glfs_chown", mock_glfs_chown): self.assertRaises(OSError, self.vol.chown, "file.txt", 9, 11) def test_creat_success(self): mock_glfs_creat = Mock() mock_glfs_creat.return_value = 2 - with patch("glusterfs.api.client.glfs_creat", mock_glfs_creat): + with patch("gluster.api.client.glfs_creat", mock_glfs_creat): with self.vol.open("file.txt", os.O_CREAT, 0644) as fd: self.assertTrue(isinstance(fd, gfapi.File)) self.assertEqual(mock_glfs_creat.call_count, 1) @@ -351,7 +351,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.exists("file.txt") self.assertTrue(ret) @@ -359,7 +359,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.exists("file.txt") self.assertFalse(ret) @@ -369,7 +369,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFDIR mock_glfs_stat.return_value = s - with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): + with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isdir("dir") self.assertTrue(ret) @@ -379,7 +379,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_stat.return_value = s - with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): + with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isdir("file") self.assertFalse(ret) @@ -387,7 +387,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.isdir("dirdoesnotexist") self.assertFalse(ret) @@ -397,7 +397,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_stat.return_value = s - with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): + with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isfile("file") self.assertTrue(ret) @@ -407,7 +407,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFDIR mock_glfs_stat.return_value = s - with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): + with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isfile("dir") self.assertFalse(ret) @@ -415,7 +415,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.isfile("filedoesnotexist") self.assertFalse(ret) @@ -425,7 +425,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFLNK mock_glfs_lstat.return_value = s - with patch("glusterfs.gfapi.Volume.lstat", mock_glfs_lstat): + with patch("gluster.gfapi.Volume.lstat", mock_glfs_lstat): ret = self.vol.islink("solnk") self.assertTrue(ret) @@ -435,7 +435,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_lstat.return_value = s - with patch("glusterfs.gfapi.Volume.lstat", mock_glfs_lstat): + with patch("gluster.gfapi.Volume.lstat", mock_glfs_lstat): ret = self.vol.islink("file") self.assertFalse(ret) @@ -443,7 +443,7 @@ class TestVolume(unittest.TestCase): mock_glfs_lstat = Mock() mock_glfs_lstat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): ret = self.vol.islink("linkdoesnotexist") self.assertFalse(ret) @@ -452,7 +452,7 @@ class TestVolume(unittest.TestCase): buf.value = "fake_xattr" return 10 - with patch("glusterfs.gfapi.api.glfs_getxattr", mock_glfs_getxattr): + with patch("gluster.gfapi.api.glfs_getxattr", mock_glfs_getxattr): buf = self.vol.getxattr("file.txt", "key1", 32) self.assertEquals("fake_xattr", buf) @@ -460,7 +460,7 @@ class TestVolume(unittest.TestCase): mock_glfs_getxattr = Mock() mock_glfs_getxattr.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_getxattr", mock_glfs_getxattr): + with patch("gluster.gfapi.api.glfs_getxattr", mock_glfs_getxattr): self.assertRaises(IOError, self.vol.getxattr, "file.txt", "key1", 32) @@ -480,9 +480,9 @@ class TestVolume(unittest.TestCase): mock_Dir_next = Mock() mock_Dir_next.side_effect = [dirent1, dirent2, dirent3, None] - with nested(patch("glusterfs.gfapi.api.glfs_opendir", + with nested(patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir), - patch("glusterfs.gfapi.Dir.next", mock_Dir_next)): + patch("gluster.gfapi.Dir.next", mock_Dir_next)): d = self.vol.listdir("testdir") self.assertEqual(len(d), 2) self.assertEqual(d[0], 'mockfile') @@ -491,7 +491,7 @@ class TestVolume(unittest.TestCase): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = None - with patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): self.assertRaises(OSError, self.vol.listdir, "test.txt") def test_listxattr_success(self): @@ -499,7 +499,7 @@ class TestVolume(unittest.TestCase): buf.raw = "key1\0key2\0" return 10 - with patch("glusterfs.gfapi.api.glfs_listxattr", mock_glfs_listxattr): + with patch("gluster.gfapi.api.glfs_listxattr", mock_glfs_listxattr): xattrs = self.vol.listxattr("file.txt") self.assertTrue("key1" in xattrs) self.assertTrue("key2" in xattrs) @@ -508,14 +508,14 @@ class TestVolume(unittest.TestCase): mock_glfs_listxattr = Mock() mock_glfs_listxattr.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_listxattr", mock_glfs_listxattr): + with patch("gluster.gfapi.api.glfs_listxattr", mock_glfs_listxattr): self.assertRaises(IOError, self.vol.listxattr, "file.txt") def test_lstat_success(self): mock_glfs_lstat = Mock() mock_glfs_lstat.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): s = self.vol.lstat("file.txt") self.assertTrue(isinstance(s, api.Stat)) @@ -523,14 +523,14 @@ class TestVolume(unittest.TestCase): mock_glfs_lstat = Mock() mock_glfs_lstat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): self.assertRaises(OSError, self.vol.lstat, "file.txt") def test_stat_success(self): mock_glfs_stat = Mock() mock_glfs_stat.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): s = self.vol.stat("file.txt") self.assertTrue(isinstance(s, api.Stat)) @@ -538,14 +538,14 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): self.assertRaises(OSError, self.vol.stat, "file.txt") def test_statvfs_success(self): mock_glfs_statvfs = Mock() mock_glfs_statvfs.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_statvfs", mock_glfs_statvfs): + with patch("gluster.gfapi.api.glfs_statvfs", mock_glfs_statvfs): s = self.vol.statvfs("/") self.assertTrue(isinstance(s, api.Statvfs)) @@ -553,7 +553,7 @@ class TestVolume(unittest.TestCase): mock_glfs_statvfs = Mock() mock_glfs_statvfs.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_statvfs", mock_glfs_statvfs): + with patch("gluster.gfapi.api.glfs_statvfs", mock_glfs_statvfs): self.assertRaises(OSError, self.vol.statvfs, "/") def test_makedirs_success(self): @@ -563,8 +563,8 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.side_effect = (False, True, False) - with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("glusterfs.gfapi.Volume.exists", mock_exists)): + with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("gluster.gfapi.Volume.exists", mock_exists)): self.vol.makedirs("dir1/", 0775) self.assertEqual(mock_glfs_mkdir.call_count, 1) mock_glfs_mkdir.assert_any_call(self.vol.fs, "dir1/", 0775) @@ -577,8 +577,8 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.side_effect = [False, True, False] - with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("glusterfs.gfapi.Volume.exists", mock_exists)): + with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("gluster.gfapi.Volume.exists", mock_exists)): self.vol.makedirs("./dir1/dir2", 0775) self.assertEqual(mock_glfs_mkdir.call_count, 2) mock_glfs_mkdir.assert_any_call(self.vol.fs, "./dir1", 0775) @@ -592,15 +592,15 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.return_value = False - with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("glusterfs.gfapi.Volume.exists", mock_exists)): + with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("gluster.gfapi.Volume.exists", mock_exists)): self.assertRaises(OSError, self.vol.makedirs, "dir1/dir2", 0775) def test_mkdir_success(self): mock_glfs_mkdir = Mock() mock_glfs_mkdir.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir): + with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir): ret = self.vol.mkdir("testdir", 0775) self.assertEquals(ret, 0) @@ -608,14 +608,14 @@ class TestVolume(unittest.TestCase): mock_glfs_mkdir = Mock() mock_glfs_mkdir.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir): + with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir): self.assertRaises(OSError, self.vol.mkdir, "testdir", 0775) def test_open_with_statement_success(self): mock_glfs_open = Mock() mock_glfs_open.return_value = 2 - with patch("glusterfs.api.client.glfs_open", mock_glfs_open): + with patch("gluster.api.client.glfs_open", mock_glfs_open): with self.vol.open("file.txt", os.O_WRONLY) as fd: self.assertTrue(isinstance(fd, gfapi.File)) self.assertEqual(mock_glfs_open.call_count, 1) @@ -630,14 +630,14 @@ class TestVolume(unittest.TestCase): with self.vol.open("file.txt", os.O_WRONLY) as fd: self.assertEqual(fd, None) - with patch("glusterfs.api.client.glfs_open", mock_glfs_open): + with patch("gluster.api.client.glfs_open", mock_glfs_open): self.assertRaises(OSError, assert_open) def test_open_direct_success(self): mock_glfs_open = Mock() mock_glfs_open.return_value = 2 - with patch("glusterfs.api.client.glfs_open", mock_glfs_open): + with patch("gluster.api.client.glfs_open", mock_glfs_open): fd = self.vol.open("file.txt", os.O_WRONLY) self.assertTrue(isinstance(fd, gfapi.File)) self.assertEqual(mock_glfs_open.call_count, 1) @@ -647,14 +647,14 @@ class TestVolume(unittest.TestCase): mock_glfs_open = Mock() mock_glfs_open.return_value = None - with patch("glusterfs.api.client.glfs_open", mock_glfs_open): + with patch("gluster.api.client.glfs_open", mock_glfs_open): self.assertRaises(OSError, self.vol.open, "file.txt", os.O_RDONLY) def test_opendir_success(self): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = 2 - with patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): d = self.vol.opendir("testdir") self.assertTrue(isinstance(d, gfapi.Dir)) @@ -662,14 +662,14 @@ class TestVolume(unittest.TestCase): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = None - with patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): self.assertRaises(OSError, self.vol.opendir, "testdir") def test_rename_success(self): mock_glfs_rename = Mock() mock_glfs_rename.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_rename", mock_glfs_rename): + with patch("gluster.gfapi.api.glfs_rename", mock_glfs_rename): ret = self.vol.rename("file.txt", "newfile.txt") self.assertEquals(ret, 0) @@ -677,7 +677,7 @@ class TestVolume(unittest.TestCase): mock_glfs_rename = Mock() mock_glfs_rename.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_rename", mock_glfs_rename): + with patch("gluster.gfapi.api.glfs_rename", mock_glfs_rename): self.assertRaises(OSError, self.vol.rename, "file.txt", "newfile.txt") @@ -685,7 +685,7 @@ class TestVolume(unittest.TestCase): mock_glfs_rmdir = Mock() mock_glfs_rmdir.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_rmdir", mock_glfs_rmdir): + with patch("gluster.gfapi.api.glfs_rmdir", mock_glfs_rmdir): ret = self.vol.rmdir("testdir") self.assertEquals(ret, 0) @@ -693,14 +693,14 @@ class TestVolume(unittest.TestCase): mock_glfs_rmdir = Mock() mock_glfs_rmdir.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_rmdir", mock_glfs_rmdir): + with patch("gluster.gfapi.api.glfs_rmdir", mock_glfs_rmdir): self.assertRaises(OSError, self.vol.rmdir, "testdir") def test_unlink_success(self): mock_glfs_unlink = Mock() mock_glfs_unlink.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_unlink", mock_glfs_unlink): + with patch("gluster.gfapi.api.glfs_unlink", mock_glfs_unlink): ret = self.vol.unlink("file.txt") self.assertEquals(ret, 0) @@ -708,14 +708,14 @@ class TestVolume(unittest.TestCase): mock_glfs_unlink = Mock() mock_glfs_unlink.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_unlink", mock_glfs_unlink): + with patch("gluster.gfapi.api.glfs_unlink", mock_glfs_unlink): self.assertRaises(OSError, self.vol.unlink, "file.txt") def test_removexattr_success(self): mock_glfs_removexattr = Mock() mock_glfs_removexattr.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_removexattr", + with patch("gluster.gfapi.api.glfs_removexattr", mock_glfs_removexattr): ret = self.vol.removexattr("file.txt", "key1") self.assertEquals(ret, 0) @@ -724,7 +724,7 @@ class TestVolume(unittest.TestCase): mock_glfs_removexattr = Mock() mock_glfs_removexattr.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_removexattr", + with patch("gluster.gfapi.api.glfs_removexattr", mock_glfs_removexattr): self.assertRaises(IOError, self.vol.removexattr, "file.txt", "key1") @@ -747,11 +747,11 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), - patch("glusterfs.gfapi.Volume.isdir", mock_isdir), - patch("glusterfs.gfapi.Volume.islink", mock_islink), - patch("glusterfs.gfapi.Volume.unlink", mock_unlink), - patch("glusterfs.gfapi.Volume.rmdir", mock_rmdir)): + with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), + patch("gluster.gfapi.Volume.isdir", mock_isdir), + patch("gluster.gfapi.Volume.islink", mock_islink), + patch("gluster.gfapi.Volume.unlink", mock_unlink), + patch("gluster.gfapi.Volume.rmdir", mock_rmdir)): self.vol.rmtree("dir1") mock_rmdir.assert_any_call("dir1/dir2") mock_unlink.assert_called_once_with("dir1/file") @@ -764,15 +764,15 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), - patch("glusterfs.gfapi.Volume.islink", mock_islink)): + with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), + patch("gluster.gfapi.Volume.islink", mock_islink)): self.assertRaises(OSError, self.vol.rmtree, "dir1") def test_rmtree_islink_exception(self): mock_islink = Mock() mock_islink.return_value = True - with patch("glusterfs.gfapi.Volume.islink", mock_islink): + with patch("gluster.gfapi.Volume.islink", mock_islink): self.assertRaises(OSError, self.vol.rmtree, "dir1") def test_rmtree_ignore_unlink_rmdir_exception(self): @@ -793,11 +793,11 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), - patch("glusterfs.gfapi.Volume.isdir", mock_isdir), - patch("glusterfs.gfapi.Volume.islink", mock_islink), - patch("glusterfs.gfapi.Volume.unlink", mock_unlink), - patch("glusterfs.gfapi.Volume.rmdir", mock_rmdir)): + with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), + patch("gluster.gfapi.Volume.isdir", mock_isdir), + patch("gluster.gfapi.Volume.islink", mock_islink), + patch("gluster.gfapi.Volume.unlink", mock_unlink), + patch("gluster.gfapi.Volume.rmdir", mock_rmdir)): self.vol.rmtree("dir1", True) mock_rmdir.assert_any_call("dir1/dir2") mock_unlink.assert_called_once_with("dir1/file") @@ -837,7 +837,7 @@ class TestVolume(unittest.TestCase): mock_glfs_setxattr = Mock() mock_glfs_setxattr.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_setxattr", mock_glfs_setxattr): + with patch("gluster.gfapi.api.glfs_setxattr", mock_glfs_setxattr): ret = self.vol.setxattr("file.txt", "key1", "hello", 5) self.assertEquals(ret, 0) @@ -845,7 +845,7 @@ class TestVolume(unittest.TestCase): mock_glfs_setxattr = Mock() mock_glfs_setxattr.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_setxattr", mock_glfs_setxattr): + with patch("gluster.gfapi.api.glfs_setxattr", mock_glfs_setxattr): self.assertRaises(IOError, self.vol.setxattr, "file.txt", "key1", "hello", 5) @@ -853,7 +853,7 @@ class TestVolume(unittest.TestCase): mock_glfs_symlink = Mock() mock_glfs_symlink.return_value = 0 - with patch("glusterfs.gfapi.api.glfs_symlink", mock_glfs_symlink): + with patch("gluster.gfapi.api.glfs_symlink", mock_glfs_symlink): ret = self.vol.symlink("file.txt", "filelink") self.assertEquals(ret, 0) @@ -861,7 +861,7 @@ class TestVolume(unittest.TestCase): mock_glfs_symlink = Mock() mock_glfs_symlink.return_value = -1 - with patch("glusterfs.gfapi.api.glfs_symlink", mock_glfs_symlink): + with patch("gluster.gfapi.api.glfs_symlink", mock_glfs_symlink): self.assertRaises(OSError, self.vol.symlink, "file.txt", "filelink") @@ -874,8 +874,8 @@ class TestVolume(unittest.TestCase): mock_isdir = Mock() mock_isdir.side_effect = [True, False] - with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), - patch("glusterfs.gfapi.Volume.isdir", mock_isdir)): + with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), + patch("gluster.gfapi.Volume.isdir", mock_isdir)): for (path, dirs, files) in self.vol.walk("dir1"): self.assertEqual(dirs, ['dir2']) self.assertEqual(files, ['file']) @@ -888,7 +888,7 @@ class TestVolume(unittest.TestCase): def mock_onerror(err): self.assertTrue(isinstance(err, OSError)) - with patch("glusterfs.gfapi.Volume.listdir", mock_listdir): + with patch("gluster.gfapi.Volume.listdir", mock_listdir): for (path, dirs, files) in self.vol.walk("dir1", onerror=mock_onerror): pass diff --git a/tox.ini b/tox.ini index 78e2818..fa5663d 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ deps = --download-cache={homedir}/.pipcache -r{toxinidir}/test-requirements.txt changedir = {toxinidir}/test/unit -commands = nosetests -v --exe --with-xunit --with-coverage --cover-package glusterfs --cover-erase --cover-xml --cover-html --cover-branches --with-html-output {posargs} +commands = nosetests -v --exe --with-xunit --with-coverage --cover-package gluster --cover-erase --cover-xml --cover-html --cover-branches --with-html-output {posargs} [tox:jenkins] downloadcache = ~/cache/pip @@ -29,8 +29,8 @@ deps = -r{toxinidir}/test-requirements.txt changedir = {toxinidir} commands = - flake8 - flake8 glusterfs test + flake8 setup.py + flake8 gluster test [testenv:cover] setenv = NOSE_WITH_COVERAGE=1 diff --git a/unittests.sh b/unittests.sh index 9da3643..e5a4c8e 100755 --- a/unittests.sh +++ b/unittests.sh @@ -17,7 +17,7 @@ cd $(dirname $0)/test/unit -nosetests -v --exe --with-coverage --cover-package glusterfs --cover-erase --cover-html --cover-branches $@ +nosetests -v --exe --with-coverage --cover-package gluster --cover-erase --cover-html --cover-branches $@ saved_status=$? rm -f .coverage -- cgit