diff --git a/pyproject.toml b/pyproject.toml index 4f6c963b4..a3c1f43a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,3 +26,4 @@ dependencies = {file = ["requirements.txt"]} [project.scripts] hotsos = "hotsos.cli:main" +hotsos-view = "hotsos.tools.summary.view:main" diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/summary/__init__.py b/tools/summary/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/summary/diff b/tools/summary/diff new file mode 100755 index 000000000..b60e71778 --- /dev/null +++ b/tools/summary/diff @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Description: diff two hotsos summary outputs. +# +src=${1:-""} +dst=${2:-""} +format={3:-yaml} +if [[ -z $src ]] || [[ -z $dst ]]; then + echo "USAGE: `basename $0` " + exit +fi + +for f in `find $src -maxdepth 1 -name *summary.${format}`; do + diff -y $dst/$f $f| less +done diff --git a/tools/summary/issues-and-bugs b/tools/summary/issues-and-bugs new file mode 100755 index 000000000..b90f93d98 --- /dev/null +++ b/tools/summary/issues-and-bugs @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Description: display only bugs and issues from summary outputs. +# +path=${1:-hotsos-output} +for f in `find $path -maxdepth 1 -name *summary.json`; do + clear + jq -r '"\nHostname: " + .system.hostname, + "Issues:", (.[]|to_entries[]|select(.key=="potential-issues")|.value|to_entries[]|.key, .value), + "Bugs:", (.[]|to_entries[]|select(.key=="known-bugs")|.value|to_entries[]|.key, .value)' $f + read -p "Next? [ENTER]" +done diff --git a/tools/summary/less b/tools/summary/less new file mode 100755 index 000000000..c7e6c82c0 --- /dev/null +++ b/tools/summary/less @@ -0,0 +1,8 @@ +#!/bin/bash +# +# Description: less each hotsos summary in path +# +path=${1:-hotsos-output} +for f in `find $path -maxdepth 1 -name *summary.yaml`; do + less $f +done diff --git a/tools/summary/view.py b/tools/summary/view.py new file mode 100755 index 000000000..dfe08b23a --- /dev/null +++ b/tools/summary/view.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +""" +Create a structured summary of key information from hotsos summary outputs. +""" +import glob +import os +import json +import sys +import subprocess + +from hotsos.core import plugintools + + +if __name__ == "__main__": + if len(sys.argv) > 1: + path = os.path.join(sys.argv[1], '*.json') + else: + path = '*.json' + + for f in glob.glob(path): + with open(f) as fd: + subprocess.call(['clear']) + s = json.loads(fd.read()) + print("host: {} ".format(s['system']['hostname'])) + print("date: {}".format(s['system']['date'])) + _enabled = [] + _services = {} + _has_bugs = {} + _has_potential_issues = {} + for plugin in plugintools.PLUGINS: + if plugin in s: + _enabled.append(plugin) + if 'services' in s[plugin]: + enabled = s[plugin]['services'] + enabled = enabled.get('systemd', {}) + _services[plugin] = enabled.get('enabled') + + if 'known-bugs' in s[plugin]: + _has_bugs.update(s[plugin]['known-bugs']) + + if 'potential-issues' in s[plugin]: + _has_potential_issues.update( + s[plugin]['potential-issues']) + +# print("enabled: {}".format(', '.join(sorted(_enabled)))) + print("services:") + for plugin, svcs in _services.items(): + print(" {}: {}".format(plugin, ', '.join(svcs))) + + if _has_bugs: + print("bugs:") + for btype, content in _has_bugs.items(): + print(" {}: {}\n".format(btype, '\n'.join(content))) + + if _has_potential_issues: + print("issues:") + for btype, content in _has_potential_issues.items(): + print(" {}:".format(btype)) + for msg in content: + print(" {}".format(msg)) + + input("\nNext? [ENTER]") + + print("") diff --git a/tox.ini b/tox.ini index b4e8d7268..ae45a27ee 100644 --- a/tox.ini +++ b/tox.ini @@ -15,7 +15,9 @@ setenv = VIRTUAL_ENV={envdir} TERM=linux HOTSOS_ROOT={toxinidir}/hotsos TESTS_DIR={[testenv]unit_tests} - PYFILES={toxinidir}/setup.py {toxinidir}/hotsos/ {[testenv]unit_tests} + PYFILES={toxinidir}/setup.py {toxinidir}/hotsos/ \ + {[testenv]unit_tests} \ + {toxinidir}/tools non-utc-tz: TZ=EST+5 deps = -r{toxinidir}/requirements.txt @@ -50,7 +52,11 @@ commands = pylint -v --rcfile={toxinidir}/pylintrc {posargs:{env:PYFILES}} [testenv:bashate] allowlist_externals = bashate -commands = bashate --verbose {toxinidir}/build.sh {toxinidir}/tools/test/functest.sh +commands = bashate --verbose {toxinidir}/build.sh \ + {toxinidir}/tools/test/functest.sh \ + {toxinidir}/tools/summary/diff \ + {toxinidir}/tools/summary/less \ + {toxinidir}/tools/summary/issues-and-bugs [testenv:functional] allowlist_externals = bash