summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c18
-rw-r--r--cli/src/cli-cmd-volume.c2
-rw-r--r--doc/gluster.83
-rw-r--r--geo-replication/syncdaemon/gsyncd.py29
-rw-r--r--geo-replication/syncdaemon/master.py3
-rw-r--r--geo-replication/syncdaemon/monitor.py10
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-geo-rep.c8
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" [<VOLNAME>] [<SLAVE-URL>] {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 <MASTER_VOL> to <SLAVE_HOST> ho
\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> {pause|resume} [force] \fR
Pause/resume the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>.
.TP
-\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> delete \fR
+\fB\ volume geo-replication <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> delete [reset-sync-time]\fR
Delete the geo-replication session from <MASTER_VOL> to <SLAVE_HOST> host machine having <SLAVE_VOL>.
+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 <MASTER_VOL> <SLAVE_HOST>::<SLAVE_VOL> config [[!]<options> [<value>]] \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);