9f5ccc
From 4a2441e76f4240568093080769ede07bb7fb2016 Mon Sep 17 00:00:00 2001
9f5ccc
From: Kotresh HR <khiremat@redhat.com>
9f5ccc
Date: Sun, 20 Oct 2019 01:01:39 +0530
9f5ccc
Subject: [PATCH 311/313] geo-rep: Fix Permission denied traceback on non root
9f5ccc
 setup
9f5ccc
9f5ccc
Problem:
9f5ccc
While syncing rename of directory in hybrid crawl, geo-rep
9f5ccc
crashes as below.
9f5ccc
9f5ccc
Traceback (most recent call last):
9f5ccc
  File "/usr/local/libexec/glusterfs/python/syncdaemon/repce.py", line 118, in worker
9f5ccc
    res = getattr(self.obj, rmeth)(*in_data[2:])
9f5ccc
  File "/usr/local/libexec/glusterfs/python/syncdaemon/resource.py", line 588, in entry_ops
9f5ccc
    src_entry = get_slv_dir_path(slv_host, slv_volume, gfid)
9f5ccc
  File "/usr/local/libexec/glusterfs/python/syncdaemon/syncdutils.py", line 687, in get_slv_dir_path
9f5ccc
    [ENOENT], [ESTALE])
9f5ccc
  File "/usr/local/libexec/glusterfs/python/syncdaemon/syncdutils.py", line 546, in errno_wrap
9f5ccc
    return call(*arg)
9f5ccc
PermissionError: [Errno 13] Permission denied: '/bricks/brick1/b1/.glusterfs/8e/c0/8ec0fcd4-d50f-4a6e-b473-a7943ab66640'
9f5ccc
9f5ccc
Cause:
9f5ccc
Conversion of gfid to path for a directory uses readlink on backend
9f5ccc
.glusterfs gfid path. But this fails for non root user with
9f5ccc
permission denied.
9f5ccc
9f5ccc
Fix:
9f5ccc
Use gfid2path interface to get the path from gfid
9f5ccc
9f5ccc
Backport of:
9f5ccc
 > Patch: https://review.gluster.org/23570
9f5ccc
 > Change-Id: I9d40c713a1b32cea95144cbc0f384ada82972222
9f5ccc
 > fixes: bz#1763439
9f5ccc
 > Signed-off-by: Kotresh HR <khiremat@redhat.com>
9f5ccc
9f5ccc
Change-Id: I9d40c713a1b32cea95144cbc0f384ada82972222
9f5ccc
BUG: 1763412
9f5ccc
Signed-off-by: Kotresh HR <khiremat@redhat.com>
9f5ccc
Reviewed-on: https://code.engineering.redhat.com/gerrit/183665
9f5ccc
Tested-by: RHGS Build Bot <nigelb@redhat.com>
9f5ccc
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
9f5ccc
---
9f5ccc
 geo-replication/syncdaemon/gsyncd.py               |  3 +-
9f5ccc
 geo-replication/syncdaemon/syncdutils.py           | 35 ++++++++++++++++------
9f5ccc
 tests/00-geo-rep/00-georep-verify-non-root-setup.t | 30 +++++++++++++++----
9f5ccc
 3 files changed, 52 insertions(+), 16 deletions(-)
9f5ccc
9f5ccc
diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
9f5ccc
index 7b48d82..8940384 100644
9f5ccc
--- a/geo-replication/syncdaemon/gsyncd.py
9f5ccc
+++ b/geo-replication/syncdaemon/gsyncd.py
9f5ccc
@@ -231,7 +231,8 @@ def main():
9f5ccc
     # Set default path for config file in that case
9f5ccc
     # If an subcmd accepts config file then it also accepts
9f5ccc
     # master and Slave arguments.
9f5ccc
-    if config_file is None and hasattr(args, "config_file"):
9f5ccc
+    if config_file is None and hasattr(args, "config_file") \
9f5ccc
+        and args.subcmd != "slave":
9f5ccc
         config_file = "%s/geo-replication/%s_%s_%s/gsyncd.conf" % (
9f5ccc
             GLUSTERD_WORKDIR,
9f5ccc
             args.master,
9f5ccc
diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py
9f5ccc
index aadaebd..b08098e 100644
9f5ccc
--- a/geo-replication/syncdaemon/syncdutils.py
9f5ccc
+++ b/geo-replication/syncdaemon/syncdutils.py
9f5ccc
@@ -57,6 +57,7 @@ from hashlib import sha256 as sha256
9f5ccc
 
9f5ccc
 # auxiliary gfid based access prefix
9f5ccc
 _CL_AUX_GFID_PFX = ".gfid/"
9f5ccc
+ROOT_GFID = "00000000-0000-0000-0000-000000000001"
9f5ccc
 GF_OP_RETRIES = 10
9f5ccc
 
9f5ccc
 GX_GFID_CANONICAL_LEN = 37  # canonical gfid len + '\0'
9f5ccc
@@ -670,6 +671,7 @@ def get_slv_dir_path(slv_host, slv_volume, gfid):
9f5ccc
     global slv_bricks
9f5ccc
 
9f5ccc
     dir_path = ENOENT
9f5ccc
+    pfx = gauxpfx()
9f5ccc
 
9f5ccc
     if not slv_bricks:
9f5ccc
         slv_info = Volinfo(slv_volume, slv_host, master=False)
9f5ccc
@@ -683,15 +685,30 @@ def get_slv_dir_path(slv_host, slv_volume, gfid):
9f5ccc
                                gfid[2:4],
9f5ccc
                                gfid], [ENOENT], [ESTALE])
9f5ccc
         if dir_path != ENOENT:
9f5ccc
-            realpath = errno_wrap(os.readlink, [dir_path],
9f5ccc
-                                  [ENOENT], [ESTALE])
9f5ccc
-            if not isinstance(realpath, int):
9f5ccc
-                realpath_parts = realpath.split('/')
9f5ccc
-                pargfid = realpath_parts[-2]
9f5ccc
-                basename = realpath_parts[-1]
9f5ccc
-                pfx = gauxpfx()
9f5ccc
-                dir_entry = os.path.join(pfx, pargfid, basename)
9f5ccc
-                return dir_entry
9f5ccc
+            try:
9f5ccc
+                realpath = errno_wrap(os.readlink, [dir_path],
9f5ccc
+                                      [ENOENT], [ESTALE])
9f5ccc
+                if not isinstance(realpath, int):
9f5ccc
+                    realpath_parts = realpath.split('/')
9f5ccc
+                    pargfid = realpath_parts[-2]
9f5ccc
+                    basename = realpath_parts[-1]
9f5ccc
+                    dir_entry = os.path.join(pfx, pargfid, basename)
9f5ccc
+                    return dir_entry
9f5ccc
+            except OSError:
9f5ccc
+                # .gfid/GFID
9f5ccc
+                gfidpath = unescape_space_newline(os.path.join(pfx, gfid))
9f5ccc
+                realpath = errno_wrap(Xattr.lgetxattr_buf,
9f5ccc
+                      [gfidpath, 'glusterfs.gfid2path'], [ENOENT], [ESTALE])
9f5ccc
+                if not isinstance(realpath, int):
9f5ccc
+                    basename = os.path.basename(realpath).rstrip('\x00')
9f5ccc
+                    dirpath = os.path.dirname(realpath)
9f5ccc
+                    if dirpath is "/":
9f5ccc
+                        pargfid = ROOT_GFID
9f5ccc
+                    else:
9f5ccc
+                        dirpath = dirpath.strip("/")
9f5ccc
+                        pargfid = get_gfid_from_mnt(dirpath)
9f5ccc
+                    dir_entry = os.path.join(pfx, pargfid, basename)
9f5ccc
+                    return dir_entry
9f5ccc
 
9f5ccc
     return None
9f5ccc
 
9f5ccc
diff --git a/tests/00-geo-rep/00-georep-verify-non-root-setup.t b/tests/00-geo-rep/00-georep-verify-non-root-setup.t
9f5ccc
index e753c1f..c9fd8b2 100644
9f5ccc
--- a/tests/00-geo-rep/00-georep-verify-non-root-setup.t
9f5ccc
+++ b/tests/00-geo-rep/00-georep-verify-non-root-setup.t
9f5ccc
@@ -118,8 +118,8 @@ clean_lock_files
9f5ccc
 TEST /usr/sbin/groupadd $grp
9f5ccc
 
9f5ccc
 clean_lock_files
9f5ccc
-##Create non-root user and assign it to newly created group
9f5ccc
-
9f5ccc
+##Del if exists and create non-root user and assign it to newly created group
9f5ccc
+userdel -r -f $usr
9f5ccc
 TEST /usr/sbin/useradd -G $grp $usr
9f5ccc
 
9f5ccc
 ##Modify password for non-root user to have control over distributing ssh-key
9f5ccc
@@ -140,8 +140,6 @@ TEST killall_gluster;
9f5ccc
 TEST glusterd;
9f5ccc
 TEST pidof glusterd;
9f5ccc
 
9f5ccc
-
9f5ccc
-
9f5ccc
 ##Create, start and mount meta_volume
9f5ccc
 TEST $CLI volume create $META_VOL replica 3 $H0:$B0/${META_VOL}{1,2,3};
9f5ccc
 TEST $CLI volume start $META_VOL
9f5ccc
@@ -225,6 +223,26 @@ TEST $GEOREP_CLI  $master $slave_url resume
9f5ccc
 #Validate failure of volume stop when geo-rep is running
9f5ccc
 TEST ! $CLI volume stop $GMV0
9f5ccc
 
9f5ccc
+#Hybrid directory rename test BZ#1763439
9f5ccc
+TEST $GEOREP_CLI $master $slave_url config change_detector xsync
9f5ccc
+mkdir ${master_mnt}/dir1
9f5ccc
+mkdir ${master_mnt}/dir1/dir2
9f5ccc
+mkdir ${master_mnt}/dir1/dir3
9f5ccc
+mkdir ${master_mnt}/hybrid_d1
9f5ccc
+
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/hybrid_d1
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/dir2
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/dir3
9f5ccc
+
9f5ccc
+mv ${master_mnt}/hybrid_d1 ${master_mnt}/hybrid_rn_d1
9f5ccc
+mv ${master_mnt}/dir1/dir2 ${master_mnt}/rn_dir2
9f5ccc
+mv ${master_mnt}/dir1/dir3 ${master_mnt}/dir1/rn_dir3
9f5ccc
+
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/hybrid_rn_d1
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/rn_dir2
9f5ccc
+EXPECT_WITHIN $GEO_REP_TIMEOUT 0 directory_ok ${slave_mnt}/dir1/rn_dir3
9f5ccc
+
9f5ccc
 #Stop Geo-rep
9f5ccc
 TEST $GEOREP_CLI $master $slave_url stop
9f5ccc
 
9f5ccc
@@ -232,8 +250,8 @@ TEST $GEOREP_CLI $master $slave_url stop
9f5ccc
 TEST $GEOREP_CLI $master $slave_url delete
9f5ccc
 
9f5ccc
 #Cleanup authorized_keys
9f5ccc
-sed -i '/^command=.*SSH_ORIGINAL_COMMAND#.*/d' ~/.ssh/authorized_keys
9f5ccc
-sed -i '/^command=.*gsyncd.*/d' ~/.ssh/authorized_keys
9f5ccc
+sed -i '/^command=.*SSH_ORIGINAL_COMMAND#.*/d' /home/$usr/.ssh/authorized_keys
9f5ccc
+sed -i '/^command=.*gsyncd.*/d' /home/$usr/.ssh/authorized_keys
9f5ccc
 
9f5ccc
 #clear mountbroker
9f5ccc
 gluster-mountbroker remove --user $usr
9f5ccc
-- 
9f5ccc
1.8.3.1
9f5ccc