diff options
| author | Kotresh HR <khiremat@redhat.com> | 2019-10-20 01:01:39 +0530 | 
|---|---|---|
| committer | Sunny Kumar <sunkumar@redhat.com> | 2019-10-24 15:15:10 +0000 | 
| commit | 1a3ca8ac92d0e64726de2337d4341079598b34b8 (patch) | |
| tree | 580518ee912f5d2a1897eaba5a4ed115b4651443 | |
| parent | 02fb4e2b603deb8467bf7567749de6d55c70a4bc (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#1764183
Signed-off-by: Kotresh HR <khiremat@redhat.com>
| -rw-r--r-- | geo-replication/syncdaemon/gsyncd.py | 3 | ||||
| -rw-r--r-- | geo-replication/syncdaemon/syncdutils.py | 35 | ||||
| -rw-r--r-- | tests/00-geo-rep/00-georep-verify-non-root-setup.t | 30 | 
3 files changed, 52 insertions, 16 deletions
| diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py index d3c79f5692d..83e3d267b95 100644 --- a/geo-replication/syncdaemon/gsyncd.py +++ b/geo-replication/syncdaemon/gsyncd.py @@ -229,7 +229,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 2ee10ac09fb..9cae0095cf9 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 | 
