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