From 301e4e8366759c45aaff03a7953ab5248b5f61de Mon Sep 17 00:00:00 2001 From: Milind Changire Date: Fri, 22 Apr 2016 16:56:47 +0530 Subject: georep: add reset-sync-time option for session delete Set the stime xattr at all the brick roots to (0,0) if the argument reset-sync-time has been provided on the command-line. To avoid testing against directory specific stime, the remote stime is assumed to be minus_infinity, if the root directory stime is set to (0,0), before the directory scan begins. This triggers a full volume resync to slave in the case of a geo-rep session recreation with the same master-slave volume pair. Command synopsis: gluster volume geo-replication :: delete \ [reset-sync-time] Update gluster cli man page to include new sub-command reset-sync-time. Change-Id: Ie4ce03b9425ed9bb81eda8681058c0fc6f990948 BUG: 1357772 Signed-off-by: Milind Changire Reviewed-on: http://review.gluster.org/14051 Reviewed-by: Kotresh HR Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Aravinda VK (cherry picked from commit 70fd68d94f768c098b3178c151fa92c5079a8cfd) Reviewed-on: http://review.gluster.org/14952 --- cli/src/cli-cmd-parser.c | 18 ++++++++++++++++- cli/src/cli-cmd-volume.c | 2 +- doc/gluster.8 | 3 ++- geo-replication/syncdaemon/gsyncd.py | 29 +++++++++++++++++++++++++--- geo-replication/syncdaemon/master.py | 3 +++ geo-replication/syncdaemon/monitor.py | 10 ++++++++++ xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 8 ++++++++ 7 files changed, 67 insertions(+), 6 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 7aed82c32f8..f1a60117d84 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2570,7 +2570,7 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) * volume geo-replication [$m [$s]] status [detail] * volume geo-replication [$m] $s config [[!]$opt [$val]] * volume geo-replication $m $s start|stop [force] - * volume geo-replication $m $s delete + * volume geo-replication $m $s delete [reset-sync-time] * volume geo-replication $m $s pause [force] * volume geo-replication $m $s resume [force] */ @@ -2698,6 +2698,22 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) cmdi++; } + if (type == GF_GSYNC_OPTION_TYPE_DELETE && + !strcmp ((char *)words[wordcount-1], "reset-sync-time")) { + if (strcmp ((char *)words[wordcount-2], "delete")) { + ret = -1; + goto out; + } + if (!slavei || !masteri) { + ret = -1; + goto out; + } + ret = dict_set_uint32 (dict, "reset-sync-time", _gf_true); + if (ret) + goto out; + cmdi++; + } + if (type != GF_GSYNC_OPTION_TYPE_CONFIG && (cmdi < wordcount - 1 || glob)) goto out; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 0c1b2d2274e..52d80fffb70 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -2640,7 +2640,7 @@ struct cli_cmd volume_cmds[] = { #if (SYNCDAEMON_COMPILE) {"volume "GEOREP" [] [] {create [[ssh-port n] [[no-verify]|[push-pem]]] [force]" - "|start [force]|stop [force]|pause [force]|resume [force]|config|status [detail]|delete} [options...]", + "|start [force]|stop [force]|pause [force]|resume [force]|config|status [detail]|delete [reset-sync-time]} [options...]", cli_cmd_volume_gsync_set_cbk, "Geo-sync operations", cli_cmd_check_gsync_exists_cbk}, diff --git a/doc/gluster.8 b/doc/gluster.8 index 78e822a99ad..23a0fcd061b 100644 --- a/doc/gluster.8 +++ b/doc/gluster.8 @@ -144,8 +144,9 @@ Query status of the geo-replication session from to ho \fB\ volume geo-replication :: {pause|resume} [force] \fR Pause/resume the geo-replication session from to host machine having . .TP -\fB\ volume geo-replication :: delete \fR +\fB\ volume geo-replication :: delete [reset-sync-time]\fR Delete the geo-replication session from to host machine having . +Optionally you can also reset the sync time in case you need to resync the entire volume on session recreate. .TP \fB\ volume geo-replication :: config [[!] []] \fR View (when no option provided) or set configuration for this geo-replication session. diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py index da5de0f40f8..f41756a0b93 100644 --- a/geo-replication/syncdaemon/gsyncd.py +++ b/geo-replication/syncdaemon/gsyncd.py @@ -27,7 +27,7 @@ from ipaddr import IPAddress, IPNetwork from gconf import gconf from syncdutils import FreeObject, norm, grabpidfile, finalize -from syncdutils import log_raise_exception, privileged +from syncdutils import log_raise_exception, privileged, boolify from syncdutils import GsyncdError, select, set_term_handler from configinterface import GConffile, upgrade_config_file import resource @@ -37,6 +37,8 @@ from subprocess import PIPE import subprocess from changelogagent import agent, Changelog from gsyncdstatus import set_monitor_status, GeorepStatus +from libcxattr import Xattr +import struct ParseError = XET.ParseError if hasattr(XET, 'ParseError') else SyntaxError @@ -253,9 +255,9 @@ def main_i(): action='callback', callback=store_abs) op.add_option('-l', '--log-file', metavar='LOGF', type=str, action='callback', callback=store_abs) - op.add_option('--iprefix', metavar='LOGD', type=str, + op.add_option('--iprefix', metavar='LOGD', type=str, action='callback', callback=store_abs) - op.add_option('--changelog-log-file', metavar='LOGF', type=str, + op.add_option('--changelog-log-file', metavar='LOGF', type=str, action='callback', callback=store_abs) op.add_option('--log-file-mbr', metavar='LOGF', type=str, action='callback', callback=store_abs) @@ -355,6 +357,9 @@ def main_i(): action='callback', callback=store_local) op.add_option('--delete', dest='delete', action='callback', callback=store_local_curry(True)) + op.add_option('--path-list', dest='path_list', action='callback', + type=str, callback=store_local) + op.add_option('--reset-sync-time', default=False, action='store_true') op.add_option('--status-get', dest='status_get', action='callback', callback=store_local_curry(True)) op.add_option('--debug', dest="go_daemon", action='callback', @@ -572,6 +577,10 @@ def main_i(): delete = rconf.get('delete') if delete: logging.info('geo-replication delete') + # remove the stime xattr from all the brick paths so that + # a re-create of a session will start sync all over again + stime_xattr_name = getattr(gconf, 'master.stime_xattr_name', None) + # Delete pid file, status file, socket file cleanup_paths = [] if getattr(gconf, 'pid_file', None): @@ -604,6 +613,20 @@ def main_i(): # To delete temp files for f in glob.glob(path + "*"): _unlink(f) + + reset_sync_time = boolify(gconf.reset_sync_time) + if reset_sync_time and stime_xattr_name: + path_list = rconf.get('path_list') + paths = [] + for p in path_list.split('--path='): + stripped_path = p.strip() + if stripped_path != "": + # set stime to (0,0) to trigger full volume content resync + # to slave on session recreation + # look at master.py::Xcrawl hint: zero_zero + Xattr.lsetxattr(stripped_path, stime_xattr_name, + struct.pack("!II", 0, 0)) + return if restricted and gconf.allow_network: diff --git a/geo-replication/syncdaemon/master.py b/geo-replication/syncdaemon/master.py index be68a7fd7b4..80c4d9d8b95 100644 --- a/geo-replication/syncdaemon/master.py +++ b/geo-replication/syncdaemon/master.py @@ -1377,6 +1377,9 @@ class GMasterXsyncMixin(GMasterChangelogMixin): "correct xtime for %s (%d)" % (path, xtr)) xtr = self.minus_infinity xtr = max(xtr, xtr_root) + zero_zero = (0, 0) + if xtr_root == zero_zero: + xtr = self.minus_infinity if not self.need_sync(path, xtl, xtr): if path == '.': self.sync_done([(path, xtl)], True) diff --git a/geo-replication/syncdaemon/monitor.py b/geo-replication/syncdaemon/monitor.py index 050218b6d1b..a26de0c9cf5 100644 --- a/geo-replication/syncdaemon/monitor.py +++ b/geo-replication/syncdaemon/monitor.py @@ -165,6 +165,7 @@ class Volinfo(object): else: return 0 + class Monitor(object): """class which spawns and manages gsyncd workers""" @@ -428,6 +429,15 @@ def distribute(*resources): suuid = svol.uuid slave_host = slave.remote_addr.split('@')[-1] slave_vol = si.volume + + # save this xattr for the session delete command + old_stime_xattr_name = getattr(gconf, "master.stime_xattr_name", None) + new_stime_xattr_name = "trusted.glusterfs." + mvol.uuid + "." + \ + svol.uuid + ".stime" + if not old_stime_xattr_name or \ + old_stime_xattr_name != new_stime_xattr_name: + gconf.configinterface.set("master.stime_xattr_name", + new_stime_xattr_name) else: raise GsyncdError("unknown slave type " + slave.url) logging.info('slave bricks: ' + repr(sbricks)) diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c index 56b5d6b25a4..594ea124c10 100644 --- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c @@ -4985,6 +4985,7 @@ glusterd_gsync_delete (glusterd_volinfo_t *volinfo, char *slave, char geo_rep_dir[PATH_MAX] = ""; char *conf_path = NULL; xlator_t *this = NULL; + uint32_t reset_sync_time = _gf_false; this = THIS; GF_ASSERT (this); @@ -5021,6 +5022,13 @@ glusterd_gsync_delete (glusterd_volinfo_t *volinfo, char *slave, runner_argprintf (&runner, "%s", conf_path); runner_argprintf (&runner, "--iprefix=%s", DATADIR); + runner_argprintf (&runner, "--path-list=%s", path_list); + + ret = dict_get_uint32 (dict, "reset-sync-time", &reset_sync_time); + if (!ret && reset_sync_time) { + runner_add_args (&runner, "--reset-sync-time", NULL); + } + if (volinfo) { master = volinfo->volname; runner_argprintf (&runner, ":%s", master); -- cgit