From: Kotresh HR Date: Wed, 4 Mar 2020 12:54:30 +0000 (+0530) Subject: libcephfs/pybind: Add setattrx, fsetattrx X-Git-Tag: v16.1.0~2070^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a5b140b33814730d85509291917047e36808d4dd;p=ceph.git libcephfs/pybind: Add setattrx, fsetattrx Fixes: https://tracker.ceph.com/issues/44171 Signed-off-by: Kotresh HR --- diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx index f88b960413ae..c1244bbe53fa 100644 --- a/src/pybind/cephfs/cephfs.pyx +++ b/src/pybind/cephfs/cephfs.pyx @@ -45,6 +45,15 @@ FALLOC_FL_KEEP_SIZE = 0x01 FALLOC_FL_PUNCH_HOLE = 0x02 FALLOC_FL_NO_HIDE_STALE = 0x04 +CEPH_SETATTR_MODE = 0x1 +CEPH_SETATTR_UID = 0x2 +CEPH_SETATTR_GID = 0x4 +CEPH_SETATTR_MTIME = 0x8 +CEPH_SETATTR_ATIME = 0x10 +CEPH_SETATTR_SIZE = 0x20 +CEPH_SETATTR_CTIME = 0x40 +CEPH_SETATTR_BTIME = 0x200 + cdef extern from "Python.h": # These are in cpython/string.pxd, but use "object" types instead of # PyObject*, which invokes assumptions in cpython that we need to @@ -166,6 +175,8 @@ cdef extern from "cephfs/libcephfs.h" nogil: int ceph_statx(ceph_mount_info *cmount, const char *path, statx *stx, unsigned want, unsigned flags) int ceph_statfs(ceph_mount_info *cmount, const char *path, statvfs *stbuf) + int ceph_setattrx(ceph_mount_info *cmount, const char *relpath, statx *stx, int mask, int flags) + int ceph_fsetattrx(ceph_mount_info *cmount, int fd, statx *stx, int mask) int ceph_mds_command(ceph_mount_info *cmount, const char *mds_spec, const char **cmd, size_t cmdlen, const char *inbuf, size_t inbuflen, char **outbuf, size_t *outbuflen, char **outs, size_t *outslen) @@ -1960,6 +1971,101 @@ cdef class LibCephFS(object): return dict_result + def setattrx(self, path, dict_stx, mask, flags): + """ + Set a file's attributes. + + :param path: the path to the file/directory to set the attributes of. + :param mask: a mask of all the CEPH_SETATTR_* values that have been set in the statx struct. + :param stx: a dict of statx structure that must include attribute values to set on the file. + :param flags: mask of AT_* flags (only AT_ATTR_NOFOLLOW is respected for now) + """ + + self.require_state("mounted") + path = cstr(path, 'path') + if not isinstance(dict_stx, dict): + raise TypeError('dict_stx must be a dict') + if not isinstance(mask, int): + raise TypeError('mask must be a int') + if not isinstance(flags, int): + raise TypeError('flags must be a int') + + cdef statx stx + + if (mask & CEPH_SETATTR_MODE): + stx.stx_mode = dict_stx["mode"] + if (mask & CEPH_SETATTR_UID): + stx.stx_uid = dict_stx["uid"] + if (mask & CEPH_SETATTR_GID): + stx.stx_gid = dict_stx["gid"] + if (mask & CEPH_SETATTR_MTIME): + stx.stx_mtime = to_timespec(dict_stx["mtime"].timestamp()) + if (mask & CEPH_SETATTR_ATIME): + stx.stx_atime = to_timespec(dict_stx["atime"].timestamp()) + if (mask & CEPH_SETATTR_CTIME): + stx.stx_ctime = to_timespec(dict_stx["ctime"].timestamp()) + if (mask & CEPH_SETATTR_SIZE): + stx.stx_size = dict_stx["size"] + if (mask & CEPH_SETATTR_BTIME): + stx.stx_btime = to_timespec(dict_stx["btime"].timestamp()) + + cdef: + char* _path = path + int _mask = mask + int _flags = flags + dict_result = dict() + + with nogil: + ret = ceph_setattrx(self.cluster, _path, &stx, _mask, _flags) + if ret < 0: + raise make_ex(ret, "error in setattrx: %s" % path) + + def fsetattrx(self, fd, dict_stx, mask): + """ + Set a file's attributes. + + :param path: the path to the file/directory to set the attributes of. + :param mask: a mask of all the CEPH_SETATTR_* values that have been set in the statx struct. + :param stx: a dict of statx structure that must include attribute values to set on the file. + """ + + self.require_state("mounted") + if not isinstance(fd, int): + raise TypeError('fd must be a int') + if not isinstance(dict_stx, dict): + raise TypeError('dict_stx must be a dict') + if not isinstance(mask, int): + raise TypeError('mask must be a int') + + cdef statx stx + + if (mask & CEPH_SETATTR_MODE): + stx.stx_mode = dict_stx["mode"] + if (mask & CEPH_SETATTR_UID): + stx.stx_uid = dict_stx["uid"] + if (mask & CEPH_SETATTR_GID): + stx.stx_gid = dict_stx["gid"] + if (mask & CEPH_SETATTR_MTIME): + stx.stx_mtime = to_timespec(dict_stx["mtime"].timestamp()) + if (mask & CEPH_SETATTR_ATIME): + stx.stx_atime = to_timespec(dict_stx["atime"].timestamp()) + if (mask & CEPH_SETATTR_CTIME): + stx.stx_ctime = to_timespec(dict_stx["ctime"].timestamp()) + if (mask & CEPH_SETATTR_SIZE): + stx.stx_size = dict_stx["size"] + if (mask & CEPH_SETATTR_BTIME): + stx.stx_btime = to_timespec(dict_stx["btime"].timestamp()) + + cdef: + int _fd = fd + int _mask = mask + dict_result = dict() + + with nogil: + ret = ceph_fsetattrx(self.cluster, _fd, &stx, _mask) + if ret < 0: + raise make_ex(ret, "error in fsetattrx") + def symlink(self, existing, newname): """ Creates a symbolic link. diff --git a/src/test/pybind/test_cephfs.py b/src/test/pybind/test_cephfs.py index ee12c6404768..c7eeb6c7985d 100644 --- a/src/test/pybind/test_cephfs.py +++ b/src/test/pybind/test_cephfs.py @@ -570,10 +570,15 @@ def test_lazyio(): def test_replication(): fd = cephfs.open(b'/file-rep', 'w', 0o755) assert_raises(TypeError, cephfs.get_file_replication, "fd") + l_dict = cephfs.get_layout(fd) + assert('pool_name' in l_dict.keys()) cnt = cephfs.get_file_replication(fd) - assert_equal(cnt, 3) + get_rep_cnt_cmd = "ceph osd pool get " + l_dict["pool_name"] + " size" + s=os.popen(get_rep_cnt_cmd).read().strip('\n') + size=int(s.split(" ")[-1]) + assert_equal(cnt, size) cnt = cephfs.get_path_replication(b'/file-rep') - assert_equal(cnt, 3) + assert_equal(cnt, size) cephfs.close(fd) cephfs.unlink(b'/file-rep') @@ -640,3 +645,79 @@ def test_preadv_pwritev(): assert_equal([b"asdf", b"zxcvb"], list(buf)) cephfs.close(fd) cephfs.unlink(b'file-1') + +@with_setup(setup_test) +def test_setattrx(): + fd = cephfs.open(b'file-setattrx', 'w', 0o655) + cephfs.write(fd, b"1111", 0) + cephfs.close(fd) + st = cephfs.statx(b'file-setattrx', libcephfs.CEPH_STATX_MODE, 0) + mode = st["mode"] | stat.S_IXUSR + assert_raises(TypeError, cephfs.setattrx, b'file-setattrx', "dict", 0, 0) + + time.sleep(1) + statx_dict = dict() + statx_dict["mode"] = mode + statx_dict["uid"] = 9999 + statx_dict["gid"] = 9999 + dt = datetime.now() + statx_dict["mtime"] = dt + statx_dict["atime"] = dt + statx_dict["ctime"] = dt + statx_dict["size"] = 10 + statx_dict["btime"] = dt + cephfs.setattrx(b'file-setattrx', statx_dict, libcephfs.CEPH_SETATTR_MODE | libcephfs.CEPH_SETATTR_UID | + libcephfs.CEPH_SETATTR_GID | libcephfs.CEPH_SETATTR_MTIME | + libcephfs.CEPH_SETATTR_ATIME | libcephfs.CEPH_SETATTR_CTIME | + libcephfs.CEPH_SETATTR_SIZE | libcephfs.CEPH_SETATTR_BTIME, 0) + st1 = cephfs.statx(b'file-setattrx', libcephfs.CEPH_STATX_MODE | libcephfs.CEPH_STATX_UID | + libcephfs.CEPH_STATX_GID | libcephfs.CEPH_STATX_MTIME | + libcephfs.CEPH_STATX_ATIME | libcephfs.CEPH_STATX_CTIME | + libcephfs.CEPH_STATX_SIZE | libcephfs.CEPH_STATX_BTIME, 0) + assert_equal(mode, st1["mode"]) + assert_equal(9999, st1["uid"]) + assert_equal(9999, st1["gid"]) + assert_equal(int(dt.timestamp()), int(st1["mtime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["atime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["ctime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["btime"].timestamp())) + assert_equal(10, st1["size"]) + cephfs.unlink(b'file-setattrx') + +@with_setup(setup_test) +def test_fsetattrx(): + fd = cephfs.open(b'file-fsetattrx', 'w', 0o655) + cephfs.write(fd, b"1111", 0) + st = cephfs.statx(b'file-fsetattrx', libcephfs.CEPH_STATX_MODE, 0) + mode = st["mode"] | stat.S_IXUSR + assert_raises(TypeError, cephfs.fsetattrx, fd, "dict", 0, 0) + + time.sleep(1) + statx_dict = dict() + statx_dict["mode"] = mode + statx_dict["uid"] = 9999 + statx_dict["gid"] = 9999 + dt = datetime.now() + statx_dict["mtime"] = dt + statx_dict["atime"] = dt + statx_dict["ctime"] = dt + statx_dict["size"] = 10 + statx_dict["btime"] = dt + cephfs.fsetattrx(fd, statx_dict, libcephfs.CEPH_SETATTR_MODE | libcephfs.CEPH_SETATTR_UID | + libcephfs.CEPH_SETATTR_GID | libcephfs.CEPH_SETATTR_MTIME | + libcephfs.CEPH_SETATTR_ATIME | libcephfs.CEPH_SETATTR_CTIME | + libcephfs.CEPH_SETATTR_SIZE | libcephfs.CEPH_SETATTR_BTIME) + st1 = cephfs.statx(b'file-fsetattrx', libcephfs.CEPH_STATX_MODE | libcephfs.CEPH_STATX_UID | + libcephfs.CEPH_STATX_GID | libcephfs.CEPH_STATX_MTIME | + libcephfs.CEPH_STATX_ATIME | libcephfs.CEPH_STATX_CTIME | + libcephfs.CEPH_STATX_SIZE | libcephfs.CEPH_STATX_BTIME, 0) + assert_equal(mode, st1["mode"]) + assert_equal(9999, st1["uid"]) + assert_equal(9999, st1["gid"]) + assert_equal(int(dt.timestamp()), int(st1["mtime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["atime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["ctime"].timestamp())) + assert_equal(int(dt.timestamp()), int(st1["btime"].timestamp())) + assert_equal(10, st1["size"]) + cephfs.close(fd) + cephfs.unlink(b'file-fsetattrx')