diff options
author | Christian Hopps <chopps@labn.net> | 2021-06-30 00:03:31 +0200 |
---|---|---|
committer | Christian Hopps <chopps@labn.net> | 2021-06-30 17:46:10 +0200 |
commit | 5417cc2de3b7a2f06f066f978ffbfdfd4f3bba98 (patch) | |
tree | 67d9411df4a4e0d378a9818c90499e91ad63e00d /tools | |
parent | vtysh: add CLI timestamp '-t' flag (diff) | |
download | frr-5417cc2de3b7a2f06f066f978ffbfdfd4f3bba98.tar.xz frr-5417cc2de3b7a2f06f066f978ffbfdfd4f3bba98.zip |
tests: collect support bundle data in parallel, fix bugs
Speedup (large topo): OLD: ~6 minutes NEW: ~1 second.
(when paired with common_config.py changes)
- Collect each "proc" support in parallel
- For each "proc" only call vtysh once with all commands
Bug fixes:
- output was broken, a dump of python "repr" format of str.
Signed-off-by: Christian Hopps <chopps@labn.net>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/generate_support_bundle.py | 186 |
1 files changed, 79 insertions, 107 deletions
diff --git a/tools/generate_support_bundle.py b/tools/generate_support_bundle.py index 38fdbd46d..56b2872d1 100755 --- a/tools/generate_support_bundle.py +++ b/tools/generate_support_bundle.py @@ -1,117 +1,89 @@ #!/usr/bin/env python3 +# +# Copyright (c) 2021, LabN Consulting, L.L.C. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; see the file COPYING; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# ######################################################## ### Python Script to generate the FRR support bundle ### ######################################################## +import argparse +import logging import os import subprocess -import datetime - -ETC_DIR = "/etc/frr/" -LOG_DIR = "/var/log/frr/" -SUCCESS = 1 -FAIL = 0 - -inputFile = ETC_DIR + "support_bundle_commands.conf" - -# Create the output file name -def createOutputFile(procName): - fileName = procName + "_support_bundle.log" - oldFile = LOG_DIR + fileName - cpFileCmd = "cp " + oldFile + " " + oldFile + ".prev" - rmFileCmd = "rm -rf " + oldFile - print("Making backup of " + oldFile) - os.system(cpFileCmd) - print("Removing " + oldFile) - os.system(rmFileCmd) - return fileName - - -# Open the output file for this process -def openOutputFile(fileName): - crt_file_cmd = LOG_DIR + fileName - print(crt_file_cmd) - try: - outputFile = open(crt_file_cmd, "w") - return outputFile - except IOError: - return () - - -# Close the output file for this process -def closeOutputFile(f): - try: - f.close() - return SUCCESS - except IOError: - return FAIL - - -# Execute the command over vtysh and store in the -# output file -def executeCommand(cmd, outputFile): - cmd_exec_str = 'vtysh -c "' + cmd + '" ' +import tempfile + +def open_with_backup(path): + if os.path.exists(path): + print("Making backup of " + path) + subprocess.check_call("mv {0} {0}.prev".format(path)) + return open(path, "w") + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-c", "--config", default="/etc/frr/support_bundle_commands.conf", help="input config") + parser.add_argument("-l", "--log-dir", default="/var/log/frr", help="directory for logfiles") + args = parser.parse_args() + + collecting = False # file format has sentinels (seem superfluous) + proc_cmds = {} + proc = None + temp = None + + # Collect all the commands for each daemon try: - cmd_output = subprocess.check_output(cmd_exec_str, shell=True) - try: - dateTime = datetime.datetime.now() - outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n") - outputFile.write(str(cmd_output)) - outputFile.write( - "########################################################\n" - ) - outputFile.write("\n") - except Exception as e: - print("Writing to output file Failed: ", e) - except subprocess.CalledProcessError as e: - dateTime = datetime.datetime.now() - outputFile.write(">>[" + str(dateTime) + "]" + cmd + "\n") - outputFile.write(e.output) - outputFile.write("########################################################\n") - outputFile.write("\n") - print("Error:" + e.output) - - -# Process the support bundle configuration file -# and call appropriate functions -def processConfFile(): - - lines = list() - outputFile = None - - try: - with open(inputFile, "r") as supportBundleConfFile: - for l in supportBundleConfFile: - lines.append(l.rstrip()) - except IOError: - print("conf file {} not present".format(inputFile)) - return - - for line in lines: - if len(line) == 0 or line[0] == "#": - continue - - cmd_line = line.split(":") - if cmd_line[0] == "PROC_NAME": - outputFileName = createOutputFile(cmd_line[1]) - if outputFileName: - print(outputFileName, "created for", cmd_line[1]) - elif cmd_line[0] == "CMD_LIST_START": - outputFile = openOutputFile(outputFileName) - if outputFile: - print(outputFileName, "opened") - else: - print(outputFileName, "open failed") - return FAIL - elif cmd_line[0] == "CMD_LIST_END": - if closeOutputFile(outputFile): - print(outputFileName, "closed") + for line in open(args.config): + line = line.rstrip() + if len(line) == 0 or line[0] == "#": + continue + + cmd_line = line.split(":") + if cmd_line[0] == "PROC_NAME": + proc = cmd_line[1] + temp = tempfile.NamedTemporaryFile("w+") + collecting = False + elif cmd_line[0] == "CMD_LIST_START": + collecting = True + elif cmd_line[0] == "CMD_LIST_END": + collecting = False + temp.flush() + proc_cmds[proc] = open(temp.name) + temp.close() + elif collecting: + temp.write(line + "\n") else: - print(outputFileName, "close failed") - else: - print("Execute:", cmd_line[0]) - executeCommand(cmd_line[0], outputFile) - + print("Ignoring unexpected input " + line.rstrip()) + except IOError as error: + logging.fatal("Cannot read config file: %s: %s", args.config, str(error)) + return -# Main Function -processConfFile() + # Spawn a vtysh to fetch each set of commands + procs = [] + for proc in proc_cmds: + ofn = os.path.join(args.log_dir, proc + "_support_bundle.log") + p = subprocess.Popen( + ["/usr/bin/env", "vtysh", "-t"], + stdin=proc_cmds[proc], + stdout=open_with_backup(ofn), + stderr=subprocess.STDOUT, + ) + procs.append(p) + + for p in procs: + p.wait() + +if __name__ == "__main__": + main() |