From 77d79754d914ce7d15d02d5fc9d9785609094850 Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Thu, 7 Jun 2018 06:32:36 -0400 Subject: [PATCH 305/305] geo-rep: Fix geo-rep for older versions of unshare Geo-rep mounts are private to worker. It uses mount namespace using unshare command to achieve the same. Well, the unshare command has to support '--propagation' option. So geo-rep breaks on the systems with older unshare version. The patch makes it fall back to lazy umount behaviour if the unshare does not support propagation option. Backpor of: > Patch: https://review.gluster.org/20221 > fixes: bz#1589782 > Change-Id: Ia614f068aede288d63ac62fea4461b1865066054 > Signed-off-by: Kotresh HR BUG: 1569312 Change-Id: Ia614f068aede288d63ac62fea4461b1865066054 Signed-off-by: Kotresh HR Reviewed-on: https://code.engineering.redhat.com/gerrit/142613 Tested-by: RHGS Build Bot Reviewed-by: Aravinda Vishwanathapura Krishna Murthy Reviewed-by: Atin Mukherjee --- geo-replication/syncdaemon/gsyncd.py | 1 + geo-replication/syncdaemon/monitor.py | 15 +++++++++++---- geo-replication/syncdaemon/resource.py | 21 ++++++++++++++++++--- geo-replication/syncdaemon/syncdutils.py | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py index b0ed0ae..fff193b 100644 --- a/geo-replication/syncdaemon/gsyncd.py +++ b/geo-replication/syncdaemon/gsyncd.py @@ -775,6 +775,7 @@ def main_i(): elif remote: # master gconf.label = gconf.local_path + gconf.worker = True else: gconf.label = 'slave' startup(go_daemon=go_daemon, log_file=log_file, label=gconf.label) diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py index 55f8330..9245572 100644 --- a/geo-replication/syncdaemon/monitor.py +++ b/geo-replication/syncdaemon/monitor.py @@ -29,7 +29,7 @@ from syncdutils import gf_event, EVENT_GEOREP_FAULTY from syncdutils import Volinfo, Popen from gsyncdstatus import GeorepStatus, set_monitor_status - +from syncdutils import unshare_propagation_supported ParseError = XET.ParseError if hasattr(XET, 'ParseError') else SyntaxError @@ -247,9 +247,16 @@ class Monitor(object): if access_mount: os.execv(sys.executable, args_to_worker) else: - unshare_cmd = ['unshare', '-m', '--propagation', 'private'] - cmd = unshare_cmd + args_to_worker - os.execvp("unshare", cmd) + if unshare_propagation_supported(): + logging.debug("Worker would mount volume privately") + unshare_cmd = ['unshare', '-m', '--propagation', + 'private'] + cmd = unshare_cmd + args_to_worker + os.execvp("unshare", cmd) + else: + logging.debug("Mount is not private. It would be lazy" + " umounted") + os.execv(sys.executable, args_to_worker) cpids.add(cpid) agents.add(apid) diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py index c4b5b53..00e62b7 100644 --- a/geo-replication/syncdaemon/resource.py +++ b/geo-replication/syncdaemon/resource.py @@ -40,6 +40,7 @@ from gsyncdstatus import GeorepStatus from syncdutils import get_master_and_slave_data_from_args from syncdutils import lf, Popen, sup, Volinfo from syncdutils import Xattr, matching_disk_gfid, get_gfid_from_mnt +from syncdutils import unshare_propagation_supported UrlRX = re.compile('\A(\w+)://([^ *?[]*)\Z') HostRX = re.compile('[a-zA-Z\d](?:[a-zA-Z\d.-]*[a-zA-Z\d])?', re.I) @@ -1302,15 +1303,29 @@ class GLUSTER(AbstractUrl, SlaveLocal, SlaveRemote): assert(mntdata[-1] == '\0') mntpt = mntdata[:-1] assert(mntpt) - if mounted and gconf.label == 'slave' \ + + umount_master = False + umount_slave = False + master_access_mount = getattr(gconf, 'access_mount', + False) + worker = getattr(gconf, 'worker', None) + + if worker \ + and not unshare_propagation_supported() \ + and not boolify(master_access_mount): + umount_master = True + if gconf.label == 'slave' \ and not boolify(gconf.slave_access_mount): + umount_slave = True + + if mounted and (umount_master or umount_slave): po = self.umount_l(mntpt) po.terminate_geterr(fail_on_err=False) if po.returncode != 0: po.errlog() rv = po.returncode - if gconf.label == 'slave' \ - and not boolify(gconf.slave_access_mount): + logging.debug("Lazy umount done: %s" % mntpt) + if umount_master or umount_slave: self.cleanup_mntpt(mntpt) except: logging.exception('mount cleanup failure:') diff --git a/geo-replication/syncdaemon/syncdutils.py b/geo-replication/syncdaemon/syncdutils.py index a493c37..6dafb0a 100644 --- a/geo-replication/syncdaemon/syncdutils.py +++ b/geo-replication/syncdaemon/syncdutils.py @@ -76,6 +76,7 @@ CHANGELOG_AGENT_SERVER_VERSION = 1.0 CHANGELOG_AGENT_CLIENT_VERSION = 1.0 NodeID = None rsync_version = None +unshare_mnt_propagation = None SPACE_ESCAPE_CHAR = "%20" NEWLINE_ESCAPE_CHAR = "%0A" PERCENTAGE_ESCAPE_CHAR = "%25" @@ -637,6 +638,23 @@ def get_master_and_slave_data_from_args(args): return (master_name, slave_data) +def unshare_propagation_supported(): + global unshare_mnt_propagation + if unshare_mnt_propagation is not None: + return unshare_mnt_propagation + + unshare_mnt_propagation = False + p = subprocess.Popen(["unshare", "--help"], + stderr=subprocess.PIPE, + stdout=subprocess.PIPE) + out, err = p.communicate() + if p.returncode == 0: + if "propagation" in out: + unshare_mnt_propagation = True + + return unshare_mnt_propagation + + def get_rsync_version(rsync_cmd): global rsync_version if rsync_version is not None: -- 1.8.3.1