diff options
author | Venky Shankar <vshankar@redhat.com> | 2014-07-09 18:36:18 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-07-14 06:42:50 -0700 |
commit | 23ae9f3ad79d2d83447096d8b3627491b2e74bb8 (patch) | |
tree | a53444a3f662f0caefc9ad5773b98443c2366597 | |
parent | 210a59e48a52515615e440e2a6e1b650063c370b (diff) |
test: utility to create files with a specific gfid
python test utility that uses setxattr() interface to
create files with a predefined gfid (which is also used
by geo-replication). this utility aids in writing test
cases for gfid-access translator.
Change-Id: Ib11248844a094cc02dae74d969f2e9212f94ede4
BUG: 1111490
Signed-off-by: Venky Shankar <vshankar@redhat.com>
Reviewed-on: http://review.gluster.org/8275
Reviewed-by: Aravinda VK <avishwan@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rwxr-xr-x | tests/utils/gfid-access.py | 91 | ||||
-rw-r--r-- | tests/utils/libcxattr.py | 94 |
2 files changed, 185 insertions, 0 deletions
diff --git a/tests/utils/gfid-access.py b/tests/utils/gfid-access.py new file mode 100755 index 00000000000..25fe35bf50b --- /dev/null +++ b/tests/utils/gfid-access.py @@ -0,0 +1,91 @@ +# +# Copyright (c) 2011-2014 Red Hat, Inc. <http://www.redhat.com> +# This file is part of GlusterFS. + +# This file is licensed to you under your choice of the GNU Lesser +# General Public License, version 3 or any later version (LGPLv3 or +# later), or the GNU General Public License, version 2 (GPLv2), in all +# cases as published by the Free Software Foundation. +# + +import os +import sys +import stat +import time +import struct +import random +import libcxattr + +from errno import EEXIST + +Xattr = libcxattr.Xattr() + +def umask(): + return os.umask(0) + +def _fmt_mknod(l): + return "!II%dsI%dsIII" % (37, l+1) + +def _fmt_mkdir(l): + return "!II%dsI%dsII" % (37, l+1) + +def _fmt_symlink(l1, l2): + return "!II%dsI%ds%ds" % (37, l1+1, l2+1) + +def entry_pack_reg(gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(_fmt_mknod(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), 0, umask()) + +def entry_pack_dir(gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(_fmt_mkdir(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), umask()) + +def entry_pack_symlink(gf, bn, lnk, mo, uid, gid): + blen = len(bn) + llen = len(lnk) + return struct.pack(_fmt_symlink(blen, llen), + uid, gid, gf, mo, bn, lnk) + +if __name__ == '__main__': + if len(sys.argv) < 6: + print("USAGE: %s <mount> <pargfid|ROOT> <filename> <GFID> <file type>" % (sys.argv[0])) + sys.exit(-1) # nothing to do + mtpt = sys.argv[1] + pargfid = sys.argv[2] + fname = sys.argv[3] + randomgfid = sys.argv[4] + ftype = sys.argv[5] + + os.chdir(mtpt) + if pargfid == 'ROOT': + pargfid = '.gfid/00000000-0000-0000-0000-000000000001' + else: + pargfid = '.gfid/' + pargfid + + blob = None + + # entry op: use non-zero uid/gid (to catch gfid-access xlator bugs) + if ftype == 'file': + mode = stat.S_IFREG | 644 + blob = entry_pack_reg(randomgfid, fname, mode, 10, 10) + elif ftype =='dir': + mode = stat.S_IFDIR | 755 + blob = entry_pack_dir(randomgfid, fname, mode, 10, 10) + else: # not yet... + sys.exit(-1) + + if blob == None: + sys.exit(-1) + try: + Xattr.lsetxattr(pargfid, 'glusterfs.gfid.newfile', blob) + except OSError: + ex = sys.exc_info()[1] + if not ex.errno in [EEXIST]: + raise + sys.exit(-1) + print "File creation OK" + sys.exit(0) diff --git a/tests/utils/libcxattr.py b/tests/utils/libcxattr.py new file mode 100644 index 00000000000..74d120fa196 --- /dev/null +++ b/tests/utils/libcxattr.py @@ -0,0 +1,94 @@ +# +# Copyright (c) 2011-2014 Red Hat, Inc. <http://www.redhat.com> +# This file is part of GlusterFS. + +# This file is licensed to you under your choice of the GNU Lesser +# General Public License, version 3 or any later version (LGPLv3 or +# later), or the GNU General Public License, version 2 (GPLv2), in all +# cases as published by the Free Software Foundation. +# + +import os +from ctypes import CDLL, c_int, create_string_buffer +from ctypes.util import find_library + + +class Xattr(object): + + """singleton that wraps the extended attribues system + interface for python using ctypes + + Just implement it to the degree we need it, in particular + - we need just the l*xattr variants, ie. we never want symlinks to be + followed + - don't need size discovery for getxattr, as we always know the exact + sizes we expect + """ + + libc = CDLL(find_library("libc")) + + @classmethod + def geterrno(cls): + return c_int.in_dll(cls.libc, 'errno').value + + @classmethod + def raise_oserr(cls): + errn = cls.geterrno() + raise OSError(errn, os.strerror(errn)) + + @classmethod + def _query_xattr(cls, path, siz, syscall, *a): + if siz: + buf = create_string_buffer('\0' * siz) + else: + buf = None + ret = getattr(cls.libc, syscall)(*((path,) + a + (buf, siz))) + if ret == -1: + cls.raise_oserr() + if siz: + return buf.raw[:ret] + else: + return ret + + @classmethod + def lgetxattr(cls, path, attr, siz=0): + return cls._query_xattr(path, siz, 'lgetxattr', attr) + + @classmethod + def lgetxattr_buf(cls, path, attr): + """lgetxattr variant with size discovery""" + size = cls.lgetxattr(path, attr) + if size == -1: + cls.raise_oserr() + if size == 0: + return '' + return cls.lgetxattr(path, attr, size) + + @classmethod + def llistxattr(cls, path, siz=0): + ret = cls._query_xattr(path, siz, 'llistxattr') + if isinstance(ret, str): + ret = ret.split('\0') + return ret + + @classmethod + def lsetxattr(cls, path, attr, val): + ret = cls.libc.lsetxattr(path, attr, val, len(val), 0) + if ret == -1: + cls.raise_oserr() + + @classmethod + def lremovexattr(cls, path, attr): + ret = cls.libc.lremovexattr(path, attr) + if ret == -1: + cls.raise_oserr() + + @classmethod + def llistxattr_buf(cls, path): + """listxattr variant with size discovery""" + size = cls.llistxattr(path) + if size == -1: + cls.raise_oserr() + if size == 0: + return [] + return cls.llistxattr(path, size) |