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