Add: function analyze

Add argument -a --analyze
Add conf parameter 'analyze'
Add analizys for scripts: 'df-m', 'df-i'

Change-Id: I0697777da6be773103b337c001df8aaeb4290db1
(cherry picked from commit abdb347e6b9c5a23a43421228aeb77edc997f0b9)
This commit is contained in:
Oleksandr Liemieshko 2016-11-03 20:19:28 -07:00 committed by Dmitry Sutyagin
parent 41d9d89207
commit 78a462dacd
5 changed files with 137 additions and 2 deletions

View File

@ -4,7 +4,7 @@
%global pypi_name timmy
Name: python-%{pypi_name}
Version: 1.23.7
Version: 1.24.0
Release: 1%{?dist}~mos0
Summary: Log collector tool for OpenStack Fuel

123
timmy/analyze.py Normal file
View File

@ -0,0 +1,123 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from timmy.env import project_name
import logging
import sys
logger = logging.getLogger(project_name)
def analyze(node_manager):
col_msg = 'Column "%s" not found in output of "%s" from node "%s"'
green = 0
unknown = 1
yellow = 2
red = 3
def parse_df_m(data, script, node):
column_use = "Use%"
full = 100
near_full = 80
health = green
details = []
if column_use not in data[0]:
logger.warning(col_msg % (column_use, script, node.repr))
health = unknown
index = data[0].split().index(column_use)
for line in data[2:]:
value = int(line.split()[index][:-1])
if value >= full:
health = red
details.append(line)
elif value >= near_full:
health = yellow if health < yellow else health
details.append(line)
return health, details
def parse_df_i(data, script, node):
column_use = "IUse%"
full = 100
near_full = 80
health = green
details = []
if column_use not in data[0]:
logger.warning(col_msg % (column_use, script, node.repr))
health = unknown
index = data[0].split().index(column_use)
for line in data[2:]:
if "%" in line.split()[index]:
value = int(line.split()[index][:-1])
if value >= full:
health = red
details.append(line)
elif value >= near_full:
health = yellow if health < yellow else health
details.append(line)
return health, details
fn_mapping = {"df-m": parse_df_m,
"df-i": parse_df_i}
results = {}
for node in node_manager.nodes.values():
for script, output_file in node.mapscr.items():
if script in fn_mapping:
with open(output_file, "r") as f:
data = [l.rstrip() for l in f.readlines()]
health, details = fn_mapping[script](data, script, node)
if node.repr not in results:
results[node.repr] = []
results[node.repr].append({"script": script,
"output_file": output_file,
"health": health,
"details": details})
node_manager.analyze_results = results
def analyze_print_results(node_manager):
code_colors = {3: ["RED", "\033[91m"],
2: ["YELLOW", "\033[93m"],
0: ["GREEN", "\033[92m"],
1: ["BLUE", "\033[94m"]}
color_end = "\033[0m"
print("Nodes health analysis:")
for node, result in node_manager.analyze_results.items():
node_health = max([x["health"] for x in result])
node_color = code_colors[node_health][1]
health_repr = code_colors[node_health][0]
print(" %s%s: %s%s" % (node_color, node, health_repr, color_end))
if node_health == 0:
continue
for r in result:
if r['health'] == 0:
continue
color = code_colors[r["health"]][1]
sys.stdout.write(color)
for key, value in r.items():
if key == "health":
value = code_colors[value][0]
if key == "details" and len(value) > 0:
if len(value) > 1:
print(" details:")
for d in value:
print(" - %s" % d)
else:
print(" details: %s" % value[0])
elif key != "details":
print(" %s: %s" % (key, value))
sys.stdout.write(color_end)

View File

@ -15,6 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from timmy.analyze import analyze, analyze_print_results
from timmy.env import project_name, version
from timmy.nodes import Node
from timmy.tools import signal_wrapper
@ -171,6 +172,9 @@ def parser_init(add_help=False):
parser.add_argument('-m', '--module', metavar='INVENTORY MODULE',
default='fuel',
help='Use module to get node data')
parser.add_argument('-a', '--analyze', action='store_true',
help=('Analyze collected outputs to determine node or'
'service health and print results'))
parser.add_argument('-v', '--verbose', action='count', default=0,
help=('This works for -vvvv, -vvv, -vv, -v, -v -v,'
'etc, If no -v then logging.WARNING is '
@ -286,6 +290,8 @@ def main(argv=None):
# this is mainly to see the path in logs instad of ""
conf['archive_dir'] = os.getcwd()
conf['archive_name'] = os.path.split(args.dest_file)[1]
if args.analyze:
conf['analyze'] = True
logger.info('Using rqdir: %s, rqfile: %s' %
(conf['rqdir'], conf['rqfile']))
nm = pretty_run(args.quiet, 'Initializing node data',
@ -315,6 +321,9 @@ def main(argv=None):
if nm.has(Node.ckey, Node.skey):
pretty_run(args.quiet, 'Executing commands and scripts',
nm.run_commands, args=(args.maxthreads,))
if conf['analyze']:
pretty_run(args.quiet, 'Analyzing outputs', analyze,
args=[nm])
if nm.has('scripts_all_pairs'):
pretty_run(args.quiet, 'Executing paired scripts',
nm.run_scripts_all_pairs, args=(args.maxthreads,))
@ -350,6 +359,8 @@ def main(argv=None):
for line in output_dict[node.ip]['output']:
name = output_dict[node.ip]['name'].rjust(maxlength)
print("%s: %s" % (name, line))
if conf['analyze']:
analyze_print_results(nm)
if nm.has(Node.ckey, Node.skey, Node.fkey, Node.flkey) and not args.quiet:
print('Outputs and/or files available in "%s".' % nm.conf['outdir'])
if all([not args.no_archive, nm.has(*Node.conf_archive_general),

View File

@ -72,6 +72,7 @@ def init_default_conf():
conf['do_print_results'] = False
'''Clean - erase previous results in outdir and archive_dir dir, if any.'''
conf['clean'] = True
conf['analyze'] = False
return conf

View File

@ -16,7 +16,7 @@
# under the License.
project_name = 'timmy'
version = '1.23.7'
version = '1.24.0'
if __name__ == '__main__':
import sys