From c268302dd4dcd22a503e21f30d5bbfb2df3013f6 Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Tue, 18 Mar 2014 16:53:10 -0400 Subject: changing gluster dir to glusterfs making this change to avoid package conflicts with gluster-swift and glusterfs-api rpm. Eventually we will remove the python code from glusterfs-api rpm and create a new rpm package from libgfapi-python. Change-Id: I1b20cd747e500aed17fba89f96e62423325b5230 Signed-off-by: Thiago da Silva --- gluster/__init__.py | 47 --- gluster/gfapi.py | 538 ------------------------------- glusterfs/__init__.py | 47 +++ glusterfs/gfapi.py | 538 +++++++++++++++++++++++++++++++ setup.py | 2 +- test/functional/libgfapi-python-tests.py | 2 +- test/unit/gluster/test_gfapi.py | 216 ++++++------- tox.ini | 2 +- 8 files changed, 696 insertions(+), 696 deletions(-) delete mode 100644 gluster/__init__.py delete mode 100644 gluster/gfapi.py create mode 100644 glusterfs/__init__.py create mode 100644 glusterfs/gfapi.py diff --git a/gluster/__init__.py b/gluster/__init__.py deleted file mode 100644 index 900183b..0000000 --- a/gluster/__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/gluster/gfapi.py b/gluster/gfapi.py deleted file mode 100644 index 8eeb3d6..0000000 --- a/gluster/gfapi.py +++ /dev/null @@ -1,538 +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 -import os -import stat -import errno - -from contextlib import contextmanager - -# Disclaimer: many of the helper functions (e.g., exists, isdir) where copied -# from the python source code - -# Looks like ctypes is having trouble with dependencies, so just force them to -# load with RTLD_GLOBAL until I figure that out. -api = ctypes.CDLL(find_library("gfapi"), ctypes.RTLD_GLOBAL, use_errno=True) - -# 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 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), - ] - -api.glfs_creat.restype = ctypes.c_void_p -api.glfs_open.restype = ctypes.c_void_p -api.glfs_lstat.restype = ctypes.c_int -api.glfs_lstat.argtypes = [ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat)] -api.glfs_opendir.restype = ctypes.c_void_p -api.glfs_readdir_r.restype = ctypes.c_int -api.glfs_readdir_r.argtypes = [ctypes.c_void_p, ctypes.POINTER(Dirent), - ctypes.POINTER(ctypes.POINTER(Dirent))] -api.glfs_stat.restype = ctypes.c_int -api.glfs_stat.argtypes = [ctypes.c_void_p, ctypes.c_char_p, - ctypes.POINTER(Stat)] -api.glfs_fstat.restype = ctypes.c_int -api.glfs_fstat.argtypes = [ctypes.c_void_p, ctypes.POINTER(Stat)] - - -class File(object): - - def __init__(self, fd): - self.fd = fd - - 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.glfs_discard(self.fd, offset, len) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - def fallocate(self, mode, offset, len): - ret = api.glfs_fallocate(self.fd, mode, offset, len) - 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 fstat(self): - """ - Returns Stat object for this file. - """ - s = 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 read(self, buflen, flags=0): - rbuf = ctypes.create_string_buffer(buflen) - ret = api.glfs_read(self.fd, rbuf, buflen, flags) - 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): - # 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)) - 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(Dirent)() - - def __del__(self): - self._api.glfs_closedir(self.fd) - self._api = None - - def next(self): - entry = 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): - - # Housekeeping functions. - - 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 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 - - @contextmanager - def creat(self, path, flags, mode): - fd = api.glfs_creat(self.fs, path, flags, mode) - if not fd: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - - fileobj = None - try: - fileobj = File(fd) - yield fileobj - finally: - fileobj.close() - - 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 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, 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 = 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): - """ - 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): - ret = api.glfs_mkdir(self.fs, path, mode) - if ret < 0: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - return ret - - @contextmanager - def open(self, path, flags): - fd = api.glfs_open(self.fs, path, flags) - if not fd: - err = ctypes.get_errno() - raise OSError(err, os.strerror(err)) - - fileobj = None - try: - fileobj = File(fd) - yield fileobj - finally: - fileobj.close() - - 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 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 = 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 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 new file mode 100644 index 0000000..900183b --- /dev/null +++ b/glusterfs/__init__.py @@ -0,0 +1,47 @@ +# 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/gfapi.py b/glusterfs/gfapi.py new file mode 100644 index 0000000..8eeb3d6 --- /dev/null +++ b/glusterfs/gfapi.py @@ -0,0 +1,538 @@ +# 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 +import os +import stat +import errno + +from contextlib import contextmanager + +# Disclaimer: many of the helper functions (e.g., exists, isdir) where copied +# from the python source code + +# Looks like ctypes is having trouble with dependencies, so just force them to +# load with RTLD_GLOBAL until I figure that out. +api = ctypes.CDLL(find_library("gfapi"), ctypes.RTLD_GLOBAL, use_errno=True) + +# 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 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), + ] + +api.glfs_creat.restype = ctypes.c_void_p +api.glfs_open.restype = ctypes.c_void_p +api.glfs_lstat.restype = ctypes.c_int +api.glfs_lstat.argtypes = [ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat)] +api.glfs_opendir.restype = ctypes.c_void_p +api.glfs_readdir_r.restype = ctypes.c_int +api.glfs_readdir_r.argtypes = [ctypes.c_void_p, ctypes.POINTER(Dirent), + ctypes.POINTER(ctypes.POINTER(Dirent))] +api.glfs_stat.restype = ctypes.c_int +api.glfs_stat.argtypes = [ctypes.c_void_p, ctypes.c_char_p, + ctypes.POINTER(Stat)] +api.glfs_fstat.restype = ctypes.c_int +api.glfs_fstat.argtypes = [ctypes.c_void_p, ctypes.POINTER(Stat)] + + +class File(object): + + def __init__(self, fd): + self.fd = fd + + 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.glfs_discard(self.fd, offset, len) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + def fallocate(self, mode, offset, len): + ret = api.glfs_fallocate(self.fd, mode, offset, len) + 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 fstat(self): + """ + Returns Stat object for this file. + """ + s = 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 read(self, buflen, flags=0): + rbuf = ctypes.create_string_buffer(buflen) + ret = api.glfs_read(self.fd, rbuf, buflen, flags) + 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): + # 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)) + 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(Dirent)() + + def __del__(self): + self._api.glfs_closedir(self.fd) + self._api = None + + def next(self): + entry = 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): + + # Housekeeping functions. + + 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 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 + + @contextmanager + def creat(self, path, flags, mode): + fd = api.glfs_creat(self.fs, path, flags, mode) + if not fd: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + + fileobj = None + try: + fileobj = File(fd) + yield fileobj + finally: + fileobj.close() + + 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 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, 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 = 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): + """ + 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): + ret = api.glfs_mkdir(self.fs, path, mode) + if ret < 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + return ret + + @contextmanager + def open(self, path, flags): + fd = api.glfs_open(self.fs, path, flags) + if not fd: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + + fileobj = None + try: + fileobj = File(fd) + yield fileobj + finally: + fileobj.close() + + 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 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 = 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 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 fc396d0..e95068a 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ from setuptools import setup, find_packages -from gluster import __canonical_version__ as version +from glusterfs import __canonical_version__ as version name = 'gfapi' diff --git a/test/functional/libgfapi-python-tests.py b/test/functional/libgfapi-python-tests.py index 212f34b..cdb556c 100644 --- a/test/functional/libgfapi-python-tests.py +++ b/test/functional/libgfapi-python-tests.py @@ -18,7 +18,7 @@ import os import types import loremipsum -from gluster import gfapi +from glusterfs import gfapi class BinFileOpsTest(unittest.TestCase): diff --git a/test/unit/gluster/test_gfapi.py b/test/unit/gluster/test_gfapi.py index f82778d..8fcf938 100644 --- a/test/unit/gluster/test_gfapi.py +++ b/test/unit/gluster/test_gfapi.py @@ -14,12 +14,12 @@ # limitations under the License. import unittest -import gluster +import glusterfs import os import stat import errno -from gluster import gfapi +from glusterfs import gfapi from nose import SkipTest from mock import Mock, patch from contextlib import nested @@ -56,17 +56,17 @@ class TestFile(unittest.TestCase): cls.fd = None def setUp(self): - self._saved_glfs_close = gluster.gfapi.api.glfs_close - gluster.gfapi.api.glfs_close = _mock_glfs_close + self._saved_glfs_close = glusterfs.gfapi.api.glfs_close + glusterfs.gfapi.api.glfs_close = _mock_glfs_close def tearDown(self): - gluster.gfapi.api.glfs_close = self._saved_glfs_close + glusterfs.gfapi.api.glfs_close = self._saved_glfs_close def test_fchown_success(self): mock_glfs_fchown = Mock() mock_glfs_fchown.return_value = 0 - with patch("gluster.gfapi.api.glfs_fchown", mock_glfs_fchown): + with patch("glusterfs.gfapi.api.glfs_fchown", mock_glfs_fchown): ret = self.fd.fchown(9, 11) self.assertEquals(ret, 0) @@ -74,14 +74,14 @@ class TestFile(unittest.TestCase): mock_glfs_fchown = Mock() mock_glfs_fchown.return_value = -1 - with patch("gluster.gfapi.api.glfs_fchown", mock_glfs_fchown): + with patch("glusterfs.gfapi.api.glfs_fchown", mock_glfs_fchown): self.assertRaises(OSError, self.fd.fchown, 9, 11) def test_fdatasync_success(self): mock_glfs_fdatasync = Mock() mock_glfs_fdatasync.return_value = 4 - with patch("gluster.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): + with patch("glusterfs.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): ret = self.fd.fdatasync() self.assertEquals(ret, 4) @@ -89,14 +89,14 @@ class TestFile(unittest.TestCase): mock_glfs_fdatasync = Mock() mock_glfs_fdatasync.return_value = -1 - with patch("gluster.gfapi.api.glfs_fdatasync", mock_glfs_fdatasync): + with patch("glusterfs.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("gluster.gfapi.api.glfs_fstat", mock_glfs_fstat): + with patch("glusterfs.gfapi.api.glfs_fstat", mock_glfs_fstat): s = self.fd.fstat() self.assertTrue(isinstance(s, gfapi.Stat)) @@ -104,14 +104,14 @@ class TestFile(unittest.TestCase): mock_glfs_fstat = Mock() mock_glfs_fstat.return_value = -1 - with patch("gluster.gfapi.api.glfs_fstat", mock_glfs_fstat): + with patch("glusterfs.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("gluster.gfapi.api.glfs_fsync", mock_glfs_fsync): + with patch("glusterfs.gfapi.api.glfs_fsync", mock_glfs_fsync): ret = self.fd.fsync() self.assertEquals(ret, 4) @@ -119,7 +119,7 @@ class TestFile(unittest.TestCase): mock_glfs_fsync = Mock() mock_glfs_fsync.return_value = -1 - with patch("gluster.gfapi.api.glfs_fsync", mock_glfs_fsync): + with patch("glusterfs.gfapi.api.glfs_fsync", mock_glfs_fsync): self.assertRaises(OSError, self.fd.fsync) def test_read_success(self): @@ -127,7 +127,7 @@ class TestFile(unittest.TestCase): rbuf.value = "hello" return 5 - with patch("gluster.gfapi.api.glfs_read", _mock_glfs_read): + with patch("glusterfs.gfapi.api.glfs_read", _mock_glfs_read): b = self.fd.read(5) self.assertEqual(b.value, "hello") @@ -135,14 +135,14 @@ class TestFile(unittest.TestCase): mock_glfs_read = Mock() mock_glfs_read.return_value = -1 - with patch("gluster.gfapi.api.glfs_read", mock_glfs_read): + with patch("glusterfs.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("gluster.gfapi.api.glfs_read", mock_glfs_read): + with patch("glusterfs.gfapi.api.glfs_read", mock_glfs_read): b = self.fd.read(5) self.assertEqual(b, 0) @@ -150,7 +150,7 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = 5 - with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): + with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): ret = self.fd.write("hello") self.assertEqual(ret, 5) @@ -158,7 +158,7 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = 3 - with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): + with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): b = bytearray(3) ret = self.fd.write(b) self.assertEqual(ret, 3) @@ -167,7 +167,7 @@ class TestFile(unittest.TestCase): mock_glfs_write = Mock() mock_glfs_write.return_value = -1 - with patch("gluster.gfapi.api.glfs_write", mock_glfs_write): + with patch("glusterfs.gfapi.api.glfs_write", mock_glfs_write): self.assertRaises(OSError, self.fd.write, "hello") def test_fallocate_success(self): @@ -175,7 +175,7 @@ class TestFile(unittest.TestCase): mock_glfs_fallocate = Mock() mock_glfs_fallocate.return_value = 0 - with patch("gluster.gfapi.api.glfs_fallocate", mock_glfs_fallocate): + with patch("glusterfs.gfapi.api.glfs_fallocate", mock_glfs_fallocate): ret = self.fd.fallocate(0, 0, 1024) self.assertEqual(ret, 0) @@ -184,7 +184,7 @@ class TestFile(unittest.TestCase): mock_glfs_fallocate = Mock() mock_glfs_fallocate.return_value = -1 - with patch("gluster.gfapi.api.glfs_fallocate", mock_glfs_fallocate): + with patch("glusterfs.gfapi.api.glfs_fallocate", mock_glfs_fallocate): self.assertRaises(OSError, self.fd.fallocate, 0, 0, 1024) def test_discard_success(self): @@ -192,7 +192,7 @@ class TestFile(unittest.TestCase): mock_glfs_discard = Mock() mock_glfs_discard.return_value = 0 - with patch("gluster.gfapi.api.glfs_discard", mock_glfs_discard): + with patch("glusterfs.gfapi.api.glfs_discard", mock_glfs_discard): ret = self.fd.discard(1024, 1024) self.assertEqual(ret, 0) @@ -201,18 +201,18 @@ class TestFile(unittest.TestCase): mock_glfs_discard = Mock() mock_glfs_discard.return_value = -1 - with patch("gluster.gfapi.api.glfs_discard", mock_glfs_discard): + with patch("glusterfs.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 = gluster.gfapi.api.glfs_closedir - gluster.gfapi.api.glfs_closedir = _mock_glfs_closedir + self._saved_glfs_closedir = glusterfs.gfapi.api.glfs_closedir + glusterfs.gfapi.api.glfs_closedir = _mock_glfs_closedir def tearDown(self): - gluster.gfapi.api.glfs_closedir = self._saved_glfs_closedir + glusterfs.gfapi.api.glfs_closedir = self._saved_glfs_closedir def test_next_success(self): raise SkipTest("need to solve issue with dependency on libgfapi.so") @@ -221,7 +221,7 @@ class TestDir(unittest.TestCase): cursor.contents = "bla" return 0 - with patch("gluster.gfapi.api.glfs_readdir_r", mock_glfs_readdir_r): + with patch("glusterfs.gfapi.api.glfs_readdir_r", mock_glfs_readdir_r): fd = gfapi.Dir(2) ent = fd.next() self.assertTrue(isinstance(ent, gfapi.Dirent)) @@ -231,39 +231,39 @@ class TestVolume(unittest.TestCase): @classmethod def setUpClass(cls): - cls._saved_glfs_new = gluster.gfapi.api.glfs_new - gluster.gfapi.api.glfs_new = _mock_glfs_new + cls._saved_glfs_new = glusterfs.gfapi.api.glfs_new + glusterfs.gfapi.api.glfs_new = _mock_glfs_new cls._saved_glfs_set_volfile_server = \ - gluster.gfapi.api.glfs_set_volfile_server - gluster.gfapi.api.glfs_set_volfile_server = \ + glusterfs.gfapi.api.glfs_set_volfile_server + glusterfs.gfapi.api.glfs_set_volfile_server = \ _mock_glfs_set_volfile_server - cls._saved_glfs_fini = gluster.gfapi.api.glfs_fini - gluster.gfapi.api.glfs_fini = _mock_glfs_fini + cls._saved_glfs_fini = glusterfs.gfapi.api.glfs_fini + glusterfs.gfapi.api.glfs_fini = _mock_glfs_fini - cls._saved_glfs_close = gluster.gfapi.api.glfs_close - gluster.gfapi.api.glfs_close = _mock_glfs_close + cls._saved_glfs_close = glusterfs.gfapi.api.glfs_close + glusterfs.gfapi.api.glfs_close = _mock_glfs_close - cls._saved_glfs_closedir = gluster.gfapi.api.glfs_closedir - gluster.gfapi.api.glfs_closedir = _mock_glfs_closedir + cls._saved_glfs_closedir = glusterfs.gfapi.api.glfs_closedir + glusterfs.gfapi.api.glfs_closedir = _mock_glfs_closedir cls.vol = gfapi.Volume("mockhost", "test") @classmethod def tearDownClass(cls): cls.vol = None - gluster.gfapi.api.glfs_new = cls._saved_glfs_new - gluster.gfapi.api.glfs_set_volfile_server = \ + glusterfs.gfapi.api.glfs_new = cls._saved_glfs_new + glusterfs.gfapi.api.glfs_set_volfile_server = \ cls._saved_glfs_set_volfile_server - 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 + 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 def test_chown_success(self): mock_glfs_chown = Mock() mock_glfs_chown.return_value = 0 - with patch("gluster.gfapi.api.glfs_chown", mock_glfs_chown): + with patch("glusterfs.gfapi.api.glfs_chown", mock_glfs_chown): ret = self.vol.chown("file.txt", 9, 11) self.assertEquals(ret, 0) @@ -271,14 +271,14 @@ class TestVolume(unittest.TestCase): mock_glfs_chown = Mock() mock_glfs_chown.return_value = -1 - with patch("gluster.gfapi.api.glfs_chown", mock_glfs_chown): + with patch("glusterfs.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("gluster.gfapi.api.glfs_creat", mock_glfs_creat): + with patch("glusterfs.gfapi.api.glfs_creat", mock_glfs_creat): with self.vol.creat("file.txt", os.O_WRONLY, 0644) as fd: self.assertTrue(isinstance(fd, gfapi.File)) self.assertEqual(mock_glfs_creat.call_count, 1) @@ -294,14 +294,14 @@ class TestVolume(unittest.TestCase): with self.vol.creat("file.txt", os.O_WRONLY, 0644) as fd: self.assertEqual(fd, None) - with patch("gluster.gfapi.api.glfs_creat", mock_glfs_creat): + with patch("glusterfs.gfapi.api.glfs_creat", mock_glfs_creat): self.assertRaises(OSError, assert_creat) def test_exists_true(self): mock_glfs_stat = Mock() mock_glfs_stat.return_value = 0 - with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.exists("file.txt") self.assertTrue(ret) @@ -309,7 +309,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.exists("file.txt") self.assertFalse(ret) @@ -319,7 +319,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFDIR mock_glfs_stat.return_value = s - with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): + with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isdir("dir") self.assertTrue(ret) @@ -329,7 +329,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_stat.return_value = s - with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): + with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isdir("file") self.assertFalse(ret) @@ -337,7 +337,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.isdir("dirdoesnotexist") self.assertFalse(ret) @@ -347,7 +347,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_stat.return_value = s - with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): + with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isfile("file") self.assertTrue(ret) @@ -357,7 +357,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFDIR mock_glfs_stat.return_value = s - with patch("gluster.gfapi.Volume.stat", mock_glfs_stat): + with patch("glusterfs.gfapi.Volume.stat", mock_glfs_stat): ret = self.vol.isfile("dir") self.assertFalse(ret) @@ -365,7 +365,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): ret = self.vol.isfile("filedoesnotexist") self.assertFalse(ret) @@ -375,7 +375,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFLNK mock_glfs_lstat.return_value = s - with patch("gluster.gfapi.Volume.lstat", mock_glfs_lstat): + with patch("glusterfs.gfapi.Volume.lstat", mock_glfs_lstat): ret = self.vol.islink("solnk") self.assertTrue(ret) @@ -385,7 +385,7 @@ class TestVolume(unittest.TestCase): s.st_mode = stat.S_IFREG mock_glfs_lstat.return_value = s - with patch("gluster.gfapi.Volume.lstat", mock_glfs_lstat): + with patch("glusterfs.gfapi.Volume.lstat", mock_glfs_lstat): ret = self.vol.islink("file") self.assertFalse(ret) @@ -393,7 +393,7 @@ class TestVolume(unittest.TestCase): mock_glfs_lstat = Mock() mock_glfs_lstat.return_value = -1 - with patch("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("glusterfs.gfapi.api.glfs_lstat", mock_glfs_lstat): ret = self.vol.islink("linkdoesnotexist") self.assertFalse(ret) @@ -402,7 +402,7 @@ class TestVolume(unittest.TestCase): buf.value = "fake_xattr" return 10 - with patch("gluster.gfapi.api.glfs_getxattr", mock_glfs_getxattr): + with patch("glusterfs.gfapi.api.glfs_getxattr", mock_glfs_getxattr): buf = self.vol.getxattr("file.txt", "key1", 32) self.assertEquals("fake_xattr", buf) @@ -410,7 +410,7 @@ class TestVolume(unittest.TestCase): mock_glfs_getxattr = Mock() mock_glfs_getxattr.return_value = -1 - with patch("gluster.gfapi.api.glfs_getxattr", mock_glfs_getxattr): + with patch("glusterfs.gfapi.api.glfs_getxattr", mock_glfs_getxattr): self.assertRaises(IOError, self.vol.getxattr, "file.txt", "key1", 32) @@ -430,8 +430,8 @@ class TestVolume(unittest.TestCase): mock_Dir_next = Mock() mock_Dir_next.side_effect = [dirent1, dirent2, dirent3, None] - with nested(patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir), - patch("gluster.gfapi.Dir.next", mock_Dir_next)): + with nested(patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir), + patch("glusterfs.gfapi.Dir.next", mock_Dir_next)): d = self.vol.listdir("testdir") self.assertEqual(len(d), 2) self.assertEqual(d[0], 'mockfile') @@ -440,7 +440,7 @@ class TestVolume(unittest.TestCase): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = None - with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir): self.assertRaises(OSError, self.vol.listdir, "test.txt") def test_listxattr_success(self): @@ -448,7 +448,7 @@ class TestVolume(unittest.TestCase): buf.raw = "key1\0key2\0" return 10 - with patch("gluster.gfapi.api.glfs_listxattr", mock_glfs_listxattr): + with patch("glusterfs.gfapi.api.glfs_listxattr", mock_glfs_listxattr): xattrs = self.vol.listxattr("file.txt") self.assertTrue("key1" in xattrs) self.assertTrue("key2" in xattrs) @@ -457,14 +457,14 @@ class TestVolume(unittest.TestCase): mock_glfs_listxattr = Mock() mock_glfs_listxattr.return_value = -1 - with patch("gluster.gfapi.api.glfs_listxattr", mock_glfs_listxattr): + with patch("glusterfs.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("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("glusterfs.gfapi.api.glfs_lstat", mock_glfs_lstat): s = self.vol.lstat("file.txt") self.assertTrue(isinstance(s, gfapi.Stat)) @@ -472,14 +472,14 @@ class TestVolume(unittest.TestCase): mock_glfs_lstat = Mock() mock_glfs_lstat.return_value = -1 - with patch("gluster.gfapi.api.glfs_lstat", mock_glfs_lstat): + with patch("glusterfs.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("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): s = self.vol.stat("file.txt") self.assertTrue(isinstance(s, gfapi.Stat)) @@ -487,7 +487,7 @@ class TestVolume(unittest.TestCase): mock_glfs_stat = Mock() mock_glfs_stat.return_value = -1 - with patch("gluster.gfapi.api.glfs_stat", mock_glfs_stat): + with patch("glusterfs.gfapi.api.glfs_stat", mock_glfs_stat): self.assertRaises(OSError, self.vol.stat, "file.txt") def test_makedirs_success(self): @@ -497,8 +497,8 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.side_effect = (False, True, False) - with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("gluster.gfapi.Volume.exists", mock_exists)): + with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("glusterfs.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) @@ -511,8 +511,8 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.side_effect = [False, True, False] - with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("gluster.gfapi.Volume.exists", mock_exists)): + with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("glusterfs.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) @@ -526,15 +526,15 @@ class TestVolume(unittest.TestCase): mock_exists = Mock() mock_exists.return_value = False - with nested(patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir), - patch("gluster.gfapi.Volume.exists", mock_exists)): + with nested(patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir), + patch("glusterfs.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("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir): + with patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir): ret = self.vol.mkdir("testdir", 0775) self.assertEquals(ret, 0) @@ -542,14 +542,14 @@ class TestVolume(unittest.TestCase): mock_glfs_mkdir = Mock() mock_glfs_mkdir.return_value = -1 - with patch("gluster.gfapi.api.glfs_mkdir", mock_glfs_mkdir): + with patch("glusterfs.gfapi.api.glfs_mkdir", mock_glfs_mkdir): self.assertRaises(OSError, self.vol.mkdir, "testdir", 0775) def test_open_success(self): mock_glfs_open = Mock() mock_glfs_open.return_value = 2 - with patch("gluster.gfapi.api.glfs_open", mock_glfs_open): + with patch("glusterfs.gfapi.api.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) @@ -564,14 +564,14 @@ class TestVolume(unittest.TestCase): with self.vol.open("file.txt", os.O_WRONLY) as fd: self.assertEqual(fd, None) - with patch("gluster.gfapi.api.glfs_open", mock_glfs_open): + with patch("glusterfs.gfapi.api.glfs_open", mock_glfs_open): self.assertRaises(OSError, assert_open) def test_opendir_success(self): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = 2 - with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("glusterfs.gfapi.api.glfs_opendir", mock_glfs_opendir): d = self.vol.opendir("testdir") self.assertTrue(isinstance(d, gfapi.Dir)) @@ -579,14 +579,14 @@ class TestVolume(unittest.TestCase): mock_glfs_opendir = Mock() mock_glfs_opendir.return_value = None - with patch("gluster.gfapi.api.glfs_opendir", mock_glfs_opendir): + with patch("glusterfs.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("gluster.gfapi.api.glfs_rename", mock_glfs_rename): + with patch("glusterfs.gfapi.api.glfs_rename", mock_glfs_rename): ret = self.vol.rename("file.txt", "newfile.txt") self.assertEquals(ret, 0) @@ -594,7 +594,7 @@ class TestVolume(unittest.TestCase): mock_glfs_rename = Mock() mock_glfs_rename.return_value = -1 - with patch("gluster.gfapi.api.glfs_rename", mock_glfs_rename): + with patch("glusterfs.gfapi.api.glfs_rename", mock_glfs_rename): self.assertRaises(OSError, self.vol.rename, "file.txt", "newfile.txt") @@ -602,7 +602,7 @@ class TestVolume(unittest.TestCase): mock_glfs_rmdir = Mock() mock_glfs_rmdir.return_value = 0 - with patch("gluster.gfapi.api.glfs_rmdir", mock_glfs_rmdir): + with patch("glusterfs.gfapi.api.glfs_rmdir", mock_glfs_rmdir): ret = self.vol.rmdir("testdir") self.assertEquals(ret, 0) @@ -610,14 +610,14 @@ class TestVolume(unittest.TestCase): mock_glfs_rmdir = Mock() mock_glfs_rmdir.return_value = -1 - with patch("gluster.gfapi.api.glfs_rmdir", mock_glfs_rmdir): + with patch("glusterfs.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("gluster.gfapi.api.glfs_unlink", mock_glfs_unlink): + with patch("glusterfs.gfapi.api.glfs_unlink", mock_glfs_unlink): ret = self.vol.unlink("file.txt") self.assertEquals(ret, 0) @@ -625,14 +625,14 @@ class TestVolume(unittest.TestCase): mock_glfs_unlink = Mock() mock_glfs_unlink.return_value = -1 - with patch("gluster.gfapi.api.glfs_unlink", mock_glfs_unlink): + with patch("glusterfs.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("gluster.gfapi.api.glfs_removexattr", + with patch("glusterfs.gfapi.api.glfs_removexattr", mock_glfs_removexattr): ret = self.vol.removexattr("file.txt", "key1") self.assertEquals(ret, 0) @@ -641,7 +641,7 @@ class TestVolume(unittest.TestCase): mock_glfs_removexattr = Mock() mock_glfs_removexattr.return_value = -1 - with patch("gluster.gfapi.api.glfs_removexattr", + with patch("glusterfs.gfapi.api.glfs_removexattr", mock_glfs_removexattr): self.assertRaises(IOError, self.vol.removexattr, "file.txt", "key1") @@ -664,11 +664,11 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - 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)): + 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)): self.vol.rmtree("dir1") mock_rmdir.assert_any_call("dir1/dir2") mock_unlink.assert_called_once_with("dir1/file") @@ -681,15 +681,15 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), - patch("gluster.gfapi.Volume.islink", mock_islink)): + with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), + patch("glusterfs.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("gluster.gfapi.Volume.islink", mock_islink): + with patch("glusterfs.gfapi.Volume.islink", mock_islink): self.assertRaises(OSError, self.vol.rmtree, "dir1") def test_rmtree_ignore_unlink_rmdir_exception(self): @@ -710,11 +710,11 @@ class TestVolume(unittest.TestCase): mock_islink = Mock() mock_islink.return_value = False - 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)): + 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)): self.vol.rmtree("dir1", True) mock_rmdir.assert_any_call("dir1/dir2") mock_unlink.assert_called_once_with("dir1/file") @@ -724,7 +724,7 @@ class TestVolume(unittest.TestCase): mock_glfs_setxattr = Mock() mock_glfs_setxattr.return_value = 0 - with patch("gluster.gfapi.api.glfs_setxattr", mock_glfs_setxattr): + with patch("glusterfs.gfapi.api.glfs_setxattr", mock_glfs_setxattr): ret = self.vol.setxattr("file.txt", "key1", "hello", 5) self.assertEquals(ret, 0) @@ -732,7 +732,7 @@ class TestVolume(unittest.TestCase): mock_glfs_setxattr = Mock() mock_glfs_setxattr.return_value = -1 - with patch("gluster.gfapi.api.glfs_setxattr", mock_glfs_setxattr): + with patch("glusterfs.gfapi.api.glfs_setxattr", mock_glfs_setxattr): self.assertRaises(IOError, self.vol.setxattr, "file.txt", "key1", "hello", 5) @@ -740,7 +740,7 @@ class TestVolume(unittest.TestCase): mock_glfs_symlink = Mock() mock_glfs_symlink.return_value = 0 - with patch("gluster.gfapi.api.glfs_symlink", mock_glfs_symlink): + with patch("glusterfs.gfapi.api.glfs_symlink", mock_glfs_symlink): ret = self.vol.symlink("file.txt", "filelink") self.assertEquals(ret, 0) @@ -748,7 +748,7 @@ class TestVolume(unittest.TestCase): mock_glfs_symlink = Mock() mock_glfs_symlink.return_value = -1 - with patch("gluster.gfapi.api.glfs_symlink", mock_glfs_symlink): + with patch("glusterfs.gfapi.api.glfs_symlink", mock_glfs_symlink): self.assertRaises(OSError, self.vol.symlink, "file.txt", "filelink") @@ -761,8 +761,8 @@ class TestVolume(unittest.TestCase): mock_isdir = Mock() mock_isdir.side_effect = [True, False] - with nested(patch("gluster.gfapi.Volume.listdir", mock_listdir), - patch("gluster.gfapi.Volume.isdir", mock_isdir)): + with nested(patch("glusterfs.gfapi.Volume.listdir", mock_listdir), + patch("glusterfs.gfapi.Volume.isdir", mock_isdir)): for (path, dirs, files) in self.vol.walk("dir1"): self.assertEqual(dirs, ['dir2']) self.assertEqual(files, ['file']) @@ -775,7 +775,7 @@ class TestVolume(unittest.TestCase): def mock_onerror(err): self.assertTrue(isinstance(err, OSError)) - with patch("gluster.gfapi.Volume.listdir", mock_listdir): + with patch("glusterfs.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 1c09aea..2e71767 100644 --- a/tox.ini +++ b/tox.ini @@ -30,7 +30,7 @@ deps = changedir = {toxinidir} commands = flake8 - flake8 gluster test + flake8 glusterfs test [testenv:cover] setenv = NOSE_WITH_COVERAGE=1 -- cgit