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