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