14f8ab
From 87e6ea2cd63898c5d243b0f0c719f4f6347fb829 Mon Sep 17 00:00:00 2001
14f8ab
From: Milind Changire <mchangir@redhat.com>
14f8ab
Date: Thu, 5 Jan 2017 19:53:19 +0530
14f8ab
Subject: [PATCH 347/349] tools/glusterfind: handle offline bricks
14f8ab
14f8ab
Problem:
14f8ab
glusterfind is unable to copy remote output file to local node when a
14f8ab
remove-brick is in progress on the remote node. After copying remote
14f8ab
files, in the --full output listing path, a "sort -u" command is run on
14f8ab
the collected files. However, "sort" exits with an error code if it
14f8ab
finds any file missing.
14f8ab
14f8ab
Solution:
14f8ab
Maintain a map of (pid, output file) when the node commands are started
14f8ab
and remove the mapping for the pid for which the command returns an
14f8ab
error. Use the list of files present in the map for the "sort" command.
14f8ab
14f8ab
Backport of:
14f8ab
> Patch: https://review.gluster.org/16332
14f8ab
> Change-Id: Ie6e019037379f4cb163f24b1c65eb382efc2fb3b
14f8ab
> fixes: bz#1410439
14f8ab
> Signed-off-by: Milind Changire <mchangir@redhat.com>
14f8ab
> Signed-off-by: Shwetha K Acharya <sacharya@redhat.com>
14f8ab
14f8ab
BUG: 1789447
14f8ab
Change-Id: Ie6e019037379f4cb163f24b1c65eb382efc2fb3b
14f8ab
Signed-off-by: Kotresh HR <khiremat@redhat.com>
14f8ab
Reviewed-on: https://code.engineering.redhat.com/gerrit/189214
14f8ab
Tested-by: RHGS Build Bot <nigelb@redhat.com>
14f8ab
Reviewed-by: Sunny Kumar <sunkumar@redhat.com>
14f8ab
---
14f8ab
 tools/glusterfind/src/gfind_py2py3.py | 25 ++++++++++++++
14f8ab
 tools/glusterfind/src/main.py         | 61 +++++++++++++++++++++--------------
14f8ab
 2 files changed, 61 insertions(+), 25 deletions(-)
14f8ab
14f8ab
diff --git a/tools/glusterfind/src/gfind_py2py3.py b/tools/glusterfind/src/gfind_py2py3.py
14f8ab
index 1d41ec5..87324fb 100644
14f8ab
--- a/tools/glusterfind/src/gfind_py2py3.py
14f8ab
+++ b/tools/glusterfind/src/gfind_py2py3.py
14f8ab
@@ -40,6 +40,19 @@ if sys.version_info >= (3,):
14f8ab
     def gfind_history_changelog_done(libgfc, clfile):
14f8ab
         return libgfc.gf_history_changelog_done(clfile.encode())
14f8ab
 
14f8ab
+    def gfind_write_row(f, row, field_separator, p_rep, row_2_rep):
14f8ab
+        f.write(u"{0}{1}{2}{3}{4}\n".format(row,
14f8ab
+                                            field_separator,
14f8ab
+                                            p_rep,
14f8ab
+                                            field_separator,
14f8ab
+                                            row_2_rep))
14f8ab
+
14f8ab
+    def gfind_write(f, row, field_separator, p_rep):
14f8ab
+        f.write(u"{0}{1}{2}\n".format(row,
14f8ab
+                                      field_separator,
14f8ab
+                                      p_rep))
14f8ab
+
14f8ab
+
14f8ab
 else:
14f8ab
 
14f8ab
     # Raw conversion of bytearray to string
14f8ab
@@ -61,3 +74,15 @@ else:
14f8ab
 
14f8ab
     def gfind_history_changelog_done(libgfc, clfile):
14f8ab
         return libgfc.gf_history_changelog_done(clfile)
14f8ab
+
14f8ab
+    def gfind_write_row(f, row, field_separator, p_rep, row_2_rep):
14f8ab
+        f.write(u"{0}{1}{2}{3}{4}\n".format(row,
14f8ab
+                                            field_separator,
14f8ab
+                                            p_rep,
14f8ab
+                                            field_separator,
14f8ab
+                                            row_2_rep).encode())
14f8ab
+
14f8ab
+    def gfind_write(f, row, field_separator, p_rep):
14f8ab
+        f.write(u"{0}{1}{2}\n".format(row,
14f8ab
+                                      field_separator,
14f8ab
+                                      p_rep).encode())
14f8ab
diff --git a/tools/glusterfind/src/main.py b/tools/glusterfind/src/main.py
14f8ab
index cc5a86f..fefe4a3 100644
14f8ab
--- a/tools/glusterfind/src/main.py
14f8ab
+++ b/tools/glusterfind/src/main.py
14f8ab
@@ -16,6 +16,7 @@ from multiprocessing import Process
14f8ab
 import os
14f8ab
 import xml.etree.cElementTree as etree
14f8ab
 from argparse import ArgumentParser, RawDescriptionHelpFormatter, Action
14f8ab
+from gfind_py2py3 import gfind_write_row, gfind_write
14f8ab
 import logging
14f8ab
 import shutil
14f8ab
 import tempfile
14f8ab
@@ -35,9 +36,9 @@ GlusterFS Incremental API
14f8ab
 ParseError = etree.ParseError if hasattr(etree, 'ParseError') else SyntaxError
14f8ab
 
14f8ab
 logger = logging.getLogger()
14f8ab
-node_outfiles = []
14f8ab
 vol_statusStr = ""
14f8ab
 gtmpfilename = None
14f8ab
+g_pid_nodefile_map = {}
14f8ab
 
14f8ab
 
14f8ab
 class StoreAbsPath(Action):
14f8ab
@@ -111,7 +112,7 @@ def node_cmd(host, host_uuid, task, cmd, args, opts):
14f8ab
 
14f8ab
 
14f8ab
 def run_cmd_nodes(task, args, **kwargs):
14f8ab
-    global node_outfiles
14f8ab
+    global g_pid_nodefile_map
14f8ab
     nodes = get_nodes(args.volume)
14f8ab
     pool = []
14f8ab
     for num, node in enumerate(nodes):
14f8ab
@@ -142,7 +143,6 @@ def run_cmd_nodes(task, args, **kwargs):
14f8ab
                 if tag == "":
14f8ab
                     tag = '""' if not is_host_local(host_uuid) else ""
14f8ab
 
14f8ab
-            node_outfiles.append(node_outfile)
14f8ab
             # remote file will be copied into this directory
14f8ab
             mkdirp(os.path.dirname(node_outfile),
14f8ab
                    exit_on_err=True, logger=logger)
14f8ab
@@ -180,7 +180,6 @@ def run_cmd_nodes(task, args, **kwargs):
14f8ab
                 if tag == "":
14f8ab
                     tag = '""' if not is_host_local(host_uuid) else ""
14f8ab
 
14f8ab
-            node_outfiles.append(node_outfile)
14f8ab
             # remote file will be copied into this directory
14f8ab
             mkdirp(os.path.dirname(node_outfile),
14f8ab
                    exit_on_err=True, logger=logger)
14f8ab
@@ -264,6 +263,7 @@ def run_cmd_nodes(task, args, **kwargs):
14f8ab
                         args=(host, host_uuid, task, cmd, args, opts))
14f8ab
             p.start()
14f8ab
             pool.append(p)
14f8ab
+            g_pid_nodefile_map[p.pid] = node_outfile
14f8ab
 
14f8ab
     for num, p in enumerate(pool):
14f8ab
         p.join()
14f8ab
@@ -271,8 +271,11 @@ def run_cmd_nodes(task, args, **kwargs):
14f8ab
             logger.warn("Command %s failed in %s" % (task, nodes[num][1]))
14f8ab
             if task in ["create", "delete"]:
14f8ab
                 fail("Command %s failed in %s" % (task, nodes[num][1]))
14f8ab
-            elif task == "pre" and args.disable_partial:
14f8ab
-                sys.exit(1)
14f8ab
+            elif task == "pre" or task == "query":
14f8ab
+                if args.disable_partial:
14f8ab
+                    sys.exit(1)
14f8ab
+                else:
14f8ab
+                    del g_pid_nodefile_map[p.pid]
14f8ab
 
14f8ab
 
14f8ab
 @cache_output
14f8ab
@@ -512,16 +515,10 @@ def write_output(outfile, outfilemerger, field_separator):
14f8ab
                     continue
14f8ab
 
14f8ab
                 if row_2_rep and row_2_rep != "":
14f8ab
-                    f.write(u"{0}{1}{2}{3}{4}\n".format(row[0],
14f8ab
-                                                        field_separator,
14f8ab
-                                                        p_rep,
14f8ab
-                                                        field_separator,
14f8ab
-                                                        row_2_rep).encode())
14f8ab
-                else:
14f8ab
-                    f.write(u"{0}{1}{2}\n".format(row[0],
14f8ab
-                                                  field_separator,
14f8ab
-                                                  p_rep).encode())
14f8ab
+                    gfind_write_row(f, row[0], field_separator, p_rep, field_separator, row_2_rep)
14f8ab
 
14f8ab
+                else:
14f8ab
+                    gfind_write(f, row[0], field_separator, p_rep)
14f8ab
 
14f8ab
 def mode_create(session_dir, args):
14f8ab
     logger.debug("Init is called - Session: %s, Volume: %s"
14f8ab
@@ -571,6 +568,7 @@ def mode_create(session_dir, args):
14f8ab
 
14f8ab
 def mode_query(session_dir, args):
14f8ab
     global gtmpfilename
14f8ab
+    global g_pid_nodefile_map
14f8ab
 
14f8ab
     # Verify volume status
14f8ab
     cmd = ["gluster", 'volume', 'info', args.volume, "--xml"]
14f8ab
@@ -634,14 +632,20 @@ def mode_query(session_dir, args):
14f8ab
 
14f8ab
     # Merger
14f8ab
     if args.full:
14f8ab
-        cmd = ["sort", "-u"] + node_outfiles + ["-o", args.outfile]
14f8ab
-        execute(cmd,
14f8ab
-                exit_msg="Failed to merge output files "
14f8ab
-                "collected from nodes", logger=logger)
14f8ab
+        if len(g_pid_nodefile_map) > 0:
14f8ab
+            cmd = ["sort", "-u"] + g_pid_nodefile_map.values() + \
14f8ab
+                  ["-o", args.outfile]
14f8ab
+            execute(cmd,
14f8ab
+                    exit_msg="Failed to merge output files "
14f8ab
+                    "collected from nodes", logger=logger)
14f8ab
+        else:
14f8ab
+            fail("Failed to collect any output files from peers. "
14f8ab
+                 "Looks like all bricks are offline.", logger=logger)
14f8ab
     else:
14f8ab
         # Read each Changelogs db and generate finaldb
14f8ab
         create_file(args.outfile, exit_on_err=True, logger=logger)
14f8ab
-        outfilemerger = OutputMerger(args.outfile + ".db", node_outfiles)
14f8ab
+        outfilemerger = OutputMerger(args.outfile + ".db",
14f8ab
+                                     g_pid_nodefile_map.values())
14f8ab
         write_output(args.outfile, outfilemerger, args.field_separator)
14f8ab
 
14f8ab
     try:
14f8ab
@@ -656,6 +660,7 @@ def mode_query(session_dir, args):
14f8ab
 
14f8ab
 def mode_pre(session_dir, args):
14f8ab
     global gtmpfilename
14f8ab
+    global g_pid_nodefile_map
14f8ab
 
14f8ab
     """
14f8ab
     Read from Session file and write to session.pre file
14f8ab
@@ -696,14 +701,20 @@ def mode_pre(session_dir, args):
14f8ab
 
14f8ab
     # Merger
14f8ab
     if args.full:
14f8ab
-        cmd = ["sort", "-u"] + node_outfiles + ["-o", args.outfile]
14f8ab
-        execute(cmd,
14f8ab
-                exit_msg="Failed to merge output files "
14f8ab
-                "collected from nodes", logger=logger)
14f8ab
+        if len(g_pid_nodefile_map) > 0:
14f8ab
+            cmd = ["sort", "-u"] + g_pid_nodefile_map.values() + \
14f8ab
+                  ["-o", args.outfile]
14f8ab
+            execute(cmd,
14f8ab
+                    exit_msg="Failed to merge output files "
14f8ab
+                    "collected from nodes", logger=logger)
14f8ab
+        else:
14f8ab
+            fail("Failed to collect any output files from peers. "
14f8ab
+                 "Looks like all bricks are offline.", logger=logger)
14f8ab
     else:
14f8ab
         # Read each Changelogs db and generate finaldb
14f8ab
         create_file(args.outfile, exit_on_err=True, logger=logger)
14f8ab
-        outfilemerger = OutputMerger(args.outfile + ".db", node_outfiles)
14f8ab
+        outfilemerger = OutputMerger(args.outfile + ".db",
14f8ab
+                                     g_pid_nodefile_map.values())
14f8ab
         write_output(args.outfile, outfilemerger, args.field_separator)
14f8ab
 
14f8ab
     try:
14f8ab
-- 
14f8ab
1.8.3.1
14f8ab