]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
libcephfs/pybind: Add setattrx, fsetattrx
authorKotresh HR <khiremat@redhat.com>
Wed, 4 Mar 2020 12:54:30 +0000 (18:24 +0530)
committerKotresh HR <khiremat@redhat.com>
Thu, 21 May 2020 11:32:10 +0000 (17:02 +0530)
Fixes: https://tracker.ceph.com/issues/44171
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/pybind/cephfs/cephfs.pyx
src/test/pybind/test_cephfs.py

index f88b960413aeb8ec048fb78036b0f2435937583b..c1244bbe53fafb803c95aa14ca0c3dbe8206bde9 100644 (file)
@@ -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.
index ee12c6404768bb2e530d4620e5442dfc62319b55..c7eeb6c7985d163b5d8dbfe00e1fd9f72138334a 100644 (file)
@@ -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')