b7d4d7
From 03de45e5fb1c8aa5369848ed9e52abd1365e1d21 Mon Sep 17 00:00:00 2001
b7d4d7
From: Shwetha K Acharya <sacharya@redhat.com>
b7d4d7
Date: Wed, 31 Jul 2019 11:34:19 +0530
b7d4d7
Subject: [PATCH 493/511] geo-rep: Note section is required for ignore_deletes
b7d4d7
b7d4d7
There exists a window of 15 sec, where the deletes are picked up
b7d4d7
by history crawl when the ignore_deletes is set to true.
b7d4d7
And it eventually deletes the file/s from slave which is/are not
b7d4d7
supposed to be deleted. Though it is working as per design, a
b7d4d7
note regarding this is needed.
b7d4d7
b7d4d7
Added a warning message indicating the same.
b7d4d7
Also logged info when the worker restarts after ignore-deletes
b7d4d7
option set.
b7d4d7
b7d4d7
>fixes: bz#1708603
b7d4d7
>Change-Id: I103be882fac18b4cef935efa355f5037a396f7c1
b7d4d7
>Signed-off-by: Shwetha K Acharya <sacharya@redhat.com>
b7d4d7
Upstream patch: https://review.gluster.org/c/glusterfs/+/22702
b7d4d7
b7d4d7
BUG: 1224906
b7d4d7
Change-Id: I103be882fac18b4cef935efa355f5037a396f7c1
b7d4d7
Signed-off-by: srijan-sivakumar <ssivakum@redhat.com>
b7d4d7
Reviewed-on: https://code.engineering.redhat.com/gerrit/220757
b7d4d7
Tested-by: RHGS Build Bot <nigelb@redhat.com>
b7d4d7
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
b7d4d7
---
b7d4d7
 cli/src/cli-cmd-parser.c             | 45 ++++++++++++++++++++------
b7d4d7
 cli/src/cli-cmd-volume.c             | 20 ++++++++----
b7d4d7
 cli/src/cli.h                        |  3 +-
b7d4d7
 geo-replication/syncdaemon/gsyncd.py |  2 +-
b7d4d7
 geo-replication/syncdaemon/master.py |  6 ++++
b7d4d7
 tests/00-geo-rep/bug-1708603.t       | 63 ++++++++++++++++++++++++++++++++++++
b7d4d7
 6 files changed, 120 insertions(+), 19 deletions(-)
b7d4d7
 create mode 100644 tests/00-geo-rep/bug-1708603.t
b7d4d7
b7d4d7
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
b7d4d7
index 5fd05f4..34f17c9 100644
b7d4d7
--- a/cli/src/cli-cmd-parser.c
b7d4d7
+++ b/cli/src/cli-cmd-parser.c
b7d4d7
@@ -2901,7 +2901,8 @@ out:
b7d4d7
 }
b7d4d7
 
b7d4d7
 int32_t
b7d4d7
-cli_cmd_gsync_set_parse(const char **words, int wordcount, dict_t **options)
b7d4d7
+cli_cmd_gsync_set_parse(struct cli_state *state, const char **words,
b7d4d7
+                        int wordcount, dict_t **options, char **errstr)
b7d4d7
 {
b7d4d7
     int32_t ret = -1;
b7d4d7
     dict_t *dict = NULL;
b7d4d7
@@ -2918,6 +2919,8 @@ cli_cmd_gsync_set_parse(const char **words, int wordcount, dict_t **options)
b7d4d7
     char *save_ptr = NULL;
b7d4d7
     char *slave_temp = NULL;
b7d4d7
     char *token = NULL;
b7d4d7
+    gf_answer_t answer = GF_ANSWER_NO;
b7d4d7
+    const char *question = NULL;
b7d4d7
 
b7d4d7
     GF_ASSERT(words);
b7d4d7
     GF_ASSERT(options);
b7d4d7
@@ -2990,8 +2993,10 @@ cli_cmd_gsync_set_parse(const char **words, int wordcount, dict_t **options)
b7d4d7
 
b7d4d7
     if (masteri && gsyncd_url_check(words[masteri]))
b7d4d7
         goto out;
b7d4d7
-    if (slavei && !glob && !gsyncd_url_check(words[slavei]))
b7d4d7
+    if (slavei && !glob && !gsyncd_url_check(words[slavei])) {
b7d4d7
+        gf_asprintf(errstr, "Invalid slave url: %s", words[slavei]);
b7d4d7
         goto out;
b7d4d7
+    }
b7d4d7
 
b7d4d7
     w = str_getunamb(words[cmdi], opwords);
b7d4d7
     if (!w)
b7d4d7
@@ -3101,16 +3106,36 @@ cli_cmd_gsync_set_parse(const char **words, int wordcount, dict_t **options)
b7d4d7
     }
b7d4d7
     if (!ret)
b7d4d7
         ret = dict_set_int32(dict, "type", type);
b7d4d7
-    if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG)
b7d4d7
+    if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG) {
b7d4d7
+        if (!strcmp((char *)words[wordcount - 2], "ignore-deletes") &&
b7d4d7
+            !strcmp((char *)words[wordcount - 1], "true")) {
b7d4d7
+            question =
b7d4d7
+                "There exists ~15 seconds delay for the option to take"
b7d4d7
+                " effect from stime of the corresponding brick. Please"
b7d4d7
+                " check the log for the time, the option is effective."
b7d4d7
+                " Proceed";
b7d4d7
+
b7d4d7
+            answer = cli_cmd_get_confirmation(state, question);
b7d4d7
+
b7d4d7
+            if (GF_ANSWER_NO == answer) {
b7d4d7
+                gf_log("cli", GF_LOG_INFO,
b7d4d7
+                       "Operation "
b7d4d7
+                       "cancelled, exiting");
b7d4d7
+                *errstr = gf_strdup("Aborted by user.");
b7d4d7
+                ret = -1;
b7d4d7
+                goto out;
b7d4d7
+            }
b7d4d7
+        }
b7d4d7
+
b7d4d7
         ret = config_parse(words, wordcount, dict, cmdi, glob);
b7d4d7
+    }
b7d4d7
 
b7d4d7
 out:
b7d4d7
     if (slave_temp)
b7d4d7
         GF_FREE(slave_temp);
b7d4d7
-    if (ret) {
b7d4d7
-        if (dict)
b7d4d7
-            dict_unref(dict);
b7d4d7
-    } else
b7d4d7
+    if (ret && dict)
b7d4d7
+        dict_unref(dict);
b7d4d7
+    else
b7d4d7
         *options = dict;
b7d4d7
 
b7d4d7
     return ret;
b7d4d7
@@ -5659,9 +5684,9 @@ cli_cmd_bitrot_parse(const char **words, int wordcount, dict_t **options)
b7d4d7
     int32_t ret = -1;
b7d4d7
     char *w = NULL;
b7d4d7
     char *volname = NULL;
b7d4d7
-    char *opwords[] = {
b7d4d7
-        "enable",       "disable", "scrub-throttle", "scrub-frequency", "scrub",
b7d4d7
-        "signing-time", "signer-threads", NULL};
b7d4d7
+    char *opwords[] = {"enable",          "disable", "scrub-throttle",
b7d4d7
+                       "scrub-frequency", "scrub",   "signing-time",
b7d4d7
+                       "signer-threads",  NULL};
b7d4d7
     char *scrub_throt_values[] = {"lazy", "normal", "aggressive", NULL};
b7d4d7
     char *scrub_freq_values[] = {"hourly",  "daily",  "weekly", "biweekly",
b7d4d7
                                  "monthly", "minute", NULL};
b7d4d7
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
b7d4d7
index 72504ca..6f5bf8b 100644
b7d4d7
--- a/cli/src/cli-cmd-volume.c
b7d4d7
+++ b/cli/src/cli-cmd-volume.c
b7d4d7
@@ -2457,6 +2457,7 @@ cli_cmd_volume_gsync_set_cbk(struct cli_state *state, struct cli_cmd_word *word,
b7d4d7
     rpc_clnt_procedure_t *proc = NULL;
b7d4d7
     call_frame_t *frame = NULL;
b7d4d7
     cli_local_t *local = NULL;
b7d4d7
+    char *errstr = NULL;
b7d4d7
 #if (USE_EVENTS)
b7d4d7
     int ret1 = -1;
b7d4d7
     int cmd_type = -1;
b7d4d7
@@ -2468,16 +2469,21 @@ cli_cmd_volume_gsync_set_cbk(struct cli_state *state, struct cli_cmd_word *word,
b7d4d7
 
b7d4d7
     proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GSYNC_SET];
b7d4d7
 
b7d4d7
-    frame = create_frame(THIS, THIS->ctx->pool);
b7d4d7
-    if (frame == NULL) {
b7d4d7
-        ret = -1;
b7d4d7
+    ret = cli_cmd_gsync_set_parse(state, words, wordcount, &options, &errstr);
b7d4d7
+    if (ret) {
b7d4d7
+        if (errstr) {
b7d4d7
+            cli_err("%s", errstr);
b7d4d7
+            GF_FREE(errstr);
b7d4d7
+        } else {
b7d4d7
+            cli_usage_out(word->pattern);
b7d4d7
+        }
b7d4d7
+        parse_err = 1;
b7d4d7
         goto out;
b7d4d7
     }
b7d4d7
 
b7d4d7
-    ret = cli_cmd_gsync_set_parse(words, wordcount, &options);
b7d4d7
-    if (ret) {
b7d4d7
-        cli_usage_out(word->pattern);
b7d4d7
-        parse_err = 1;
b7d4d7
+    frame = create_frame(THIS, THIS->ctx->pool);
b7d4d7
+    if (frame == NULL) {
b7d4d7
+        ret = -1;
b7d4d7
         goto out;
b7d4d7
     }
b7d4d7
 
b7d4d7
diff --git a/cli/src/cli.h b/cli/src/cli.h
b7d4d7
index c30ae9c..7b4f446 100644
b7d4d7
--- a/cli/src/cli.h
b7d4d7
+++ b/cli/src/cli.h
b7d4d7
@@ -269,7 +269,8 @@ int32_t
b7d4d7
 cli_cmd_volume_reset_parse(const char **words, int wordcount, dict_t **opt);
b7d4d7
 
b7d4d7
 int32_t
b7d4d7
-cli_cmd_gsync_set_parse(const char **words, int wordcount, dict_t **opt);
b7d4d7
+cli_cmd_gsync_set_parse(struct cli_state *state, const char **words,
b7d4d7
+                        int wordcount, dict_t **opt, char **errstr);
b7d4d7
 
b7d4d7
 int32_t
b7d4d7
 cli_cmd_quota_parse(const char **words, int wordcount, dict_t **opt);
b7d4d7
diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py
b7d4d7
index 8940384..215c62d 100644
b7d4d7
--- a/geo-replication/syncdaemon/gsyncd.py
b7d4d7
+++ b/geo-replication/syncdaemon/gsyncd.py
b7d4d7
@@ -315,7 +315,7 @@ def main():
b7d4d7
 
b7d4d7
     # Log message for loaded config file
b7d4d7
     if config_file is not None:
b7d4d7
-        logging.info(lf("Using session config file", path=config_file))
b7d4d7
+        logging.debug(lf("Using session config file", path=config_file))
b7d4d7
 
b7d4d7
     set_term_handler()
b7d4d7
     excont = FreeObject(exval=0)
b7d4d7
diff --git a/geo-replication/syncdaemon/master.py b/geo-replication/syncdaemon/master.py
b7d4d7
index 08e98f8..98637e7 100644
b7d4d7
--- a/geo-replication/syncdaemon/master.py
b7d4d7
+++ b/geo-replication/syncdaemon/master.py
b7d4d7
@@ -1549,6 +1549,12 @@ class GMasterChangeloghistoryMixin(GMasterChangelogMixin):
b7d4d7
         data_stime = self.get_data_stime()
b7d4d7
 
b7d4d7
         end_time = int(time.time())
b7d4d7
+
b7d4d7
+        #as start of historical crawl marks Geo-rep worker restart
b7d4d7
+        if gconf.get("ignore-deletes"):
b7d4d7
+            logging.info(lf('ignore-deletes config option is set',
b7d4d7
+                         stime=data_stime))
b7d4d7
+
b7d4d7
         logging.info(lf('starting history crawl',
b7d4d7
                         turns=self.history_turns,
b7d4d7
                         stime=data_stime,
b7d4d7
diff --git a/tests/00-geo-rep/bug-1708603.t b/tests/00-geo-rep/bug-1708603.t
b7d4d7
new file mode 100644
b7d4d7
index 0000000..26913f1
b7d4d7
--- /dev/null
b7d4d7
+++ b/tests/00-geo-rep/bug-1708603.t
b7d4d7
@@ -0,0 +1,63 @@
b7d4d7
+#!/bin/bash
b7d4d7
+
b7d4d7
+. $(dirname $0)/../include.rc
b7d4d7
+. $(dirname $0)/../volume.rc
b7d4d7
+. $(dirname $0)/../geo-rep.rc
b7d4d7
+. $(dirname $0)/../env.rc
b7d4d7
+
b7d4d7
+SCRIPT_TIMEOUT=300
b7d4d7
+
b7d4d7
+##Cleanup and start glusterd
b7d4d7
+cleanup;
b7d4d7
+TEST glusterd;
b7d4d7
+TEST pidof glusterd
b7d4d7
+
b7d4d7
+
b7d4d7
+##Variables
b7d4d7
+GEOREP_CLI="gluster volume geo-replication"
b7d4d7
+master=$GMV0
b7d4d7
+SH0="127.0.0.1"
b7d4d7
+slave=${SH0}::${GSV0}
b7d4d7
+num_active=2
b7d4d7
+num_passive=2
b7d4d7
+master_mnt=$M0
b7d4d7
+slave_mnt=$M1
b7d4d7
+
b7d4d7
+############################################################
b7d4d7
+#SETUP VOLUMES AND GEO-REPLICATION
b7d4d7
+############################################################
b7d4d7
+
b7d4d7
+##create_and_start_master_volume
b7d4d7
+TEST $CLI volume create $GMV0 replica 2 $H0:$B0/${GMV0}{1,2,3,4};
b7d4d7
+TEST $CLI volume start $GMV0
b7d4d7
+
b7d4d7
+##create_and_start_slave_volume
b7d4d7
+TEST $CLI volume create $GSV0 replica 2 $H0:$B0/${GSV0}{1,2,3,4};
b7d4d7
+TEST $CLI volume start $GSV0
b7d4d7
+
b7d4d7
+##Mount master
b7d4d7
+TEST glusterfs -s $H0 --volfile-id $GMV0 $M0
b7d4d7
+
b7d4d7
+##Mount slave
b7d4d7
+TEST glusterfs -s $H0 --volfile-id $GSV0 $M1
b7d4d7
+
b7d4d7
+#Create geo-rep session
b7d4d7
+TEST create_georep_session $master $slave
b7d4d7
+
b7d4d7
+echo n | $GEOREP_CLI $master $slave config ignore-deletes true >/dev/null 2>&1
b7d4d7
+EXPECT "false" echo $($GEOREP_CLI $master $slave config ignore-deletes)
b7d4d7
+echo y | $GEOREP_CLI $master $slave config ignore-deletes true
b7d4d7
+EXPECT "true" echo $($GEOREP_CLI $master $slave config ignore-deletes)
b7d4d7
+
b7d4d7
+#Stop Geo-rep
b7d4d7
+TEST $GEOREP_CLI $master $slave stop
b7d4d7
+
b7d4d7
+#Delete Geo-rep
b7d4d7
+TEST $GEOREP_CLI $master $slave delete
b7d4d7
+
b7d4d7
+#Cleanup authorized keys
b7d4d7
+sed -i '/^command=.*SSH_ORIGINAL_COMMAND#.*/d' ~/.ssh/authorized_keys
b7d4d7
+sed -i '/^command=.*gsyncd.*/d' ~/.ssh/authorized_keys
b7d4d7
+
b7d4d7
+cleanup;
b7d4d7
+#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=000000
b7d4d7
-- 
b7d4d7
1.8.3.1
b7d4d7