summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenky Shankar <vshankar@redhat.com>2014-07-09 18:36:18 +0530
committerVijay Bellur <vbellur@redhat.com>2014-07-14 06:42:50 -0700
commit23ae9f3ad79d2d83447096d8b3627491b2e74bb8 (patch)
treea53444a3f662f0caefc9ad5773b98443c2366597
parent210a59e48a52515615e440e2a6e1b650063c370b (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-xtests/utils/gfid-access.py91
-rw-r--r--tests/utils/libcxattr.py94
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)