#!/usr/bin/env python3
"""
Graid System Analysis Tool
This script analyzes various logs and configuration files to assess the health
and configuration of a Graid storage system and related components.
Usage:
python3 graid_analysis_script.py [--log-dir LOG_DIRECTORY] [--output OUTPUT_FILE] [--html] [--color] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
Example:
python3 graid_analysis_script.py --log-dir /path/to/logs --output report.txt --html --color --log-level INFO
"""
import os
import re
import datetime
import sys
import argparse
import json
import gzip
import logging
from pathlib import Path
from collections import defaultdict
# ANSI color codes for terminal output
class Colors:
RESET = "\033[0m"
BOLD = "\033[1m"
RED = "\033[31m"
GREEN = "\033[32m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
MAGENTA = "\033[35m"
CYAN = "\033[36m"
# Severity colors
CRITICAL = RED + BOLD
HIGH = RED
MEDIUM = YELLOW
LOW = BLUE
OK = GREEN
# Whether to use colors in output
USE_COLORS = False
# Collection of all issues found during analysis
ALL_ISSUES = []
# Parse command-line arguments
def parse_args():
parser = argparse.ArgumentParser(description='Graid System Analysis Tool')
parser.add_argument('--log-dir', type=str, default='.',
help='Directory containing the log files (default: current directory)')
parser.add_argument('--output', type=str, default='graid_analysis_report.txt',
help='Output file for the analysis report (default: graid_analysis_report.txt)')
parser.add_argument('--html', action='store_true',
help='Generate an HTML report in addition to text report')
parser.add_argument('--color', action='store_true',
help='Use color in terminal output (text report will still be plain text)')
parser.add_argument('--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default='INFO', help='Set the logging level (default: INFO)')
return parser.parse_args()
args = parse_args()
# Set color usage based on command line argument
USE_COLORS = args.color
# Define base paths based on command-line arguments
BASE_DIR = Path(args.log_dir)
REPORT_FILE = Path(args.output)
# Set up logging
def setup_logging(log_level):
"""Configure logging with appropriate level and format"""
numeric_level = getattr(logging, log_level.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError(f'Invalid log level: {log_level}')
# Configure the root logger
logging.basicConfig(
level=numeric_level,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
return logging.getLogger('graid_analysis')
# Initialize logger
logger = setup_logging(args.log_level)
def add_issue(component, description, severity="MEDIUM", raw_data=None):
"""
Add an issue to the global issues list
:param component: Component with the issue (e.g., "Graid", "NVMe", "NVIDIA")
:param description: Description of the issue
:param severity: Severity level ("CRITICAL", "HIGH", "MEDIUM", "LOW")
:param raw_data: Raw data related to the issue
"""
issue = {
"component": component,
"description": description,
"severity": severity,
"timestamp": datetime.datetime.now().isoformat(),
}
if raw_data:
issue["raw_data"] = raw_data
ALL_ISSUES.append(issue)
return issue
def colorize(text, color_code):
"""Apply color to text if colors are enabled"""
if USE_COLORS:
return f"{color_code}{text}{Colors.RESET}"
return text
def generate_executive_summary():
"""
Generate an executive summary of all issues found during analysis
"""
summary = []
# Group issues by severity
issues_by_severity = defaultdict(list)
for issue in ALL_ISSUES:
issues_by_severity[issue["severity"]].append(issue)
# Add summary header
summary.append(colorize("EXECUTIVE SUMMARY", Colors.BOLD))
summary.append(colorize("="*80, Colors.BOLD))
# Add issue counts
total_issues = len(ALL_ISSUES)
if total_issues == 0:
summary.append(colorize(
"No issues found. The system appears to be in good health.", Colors.GREEN))
return "\n".join(summary)
summary.append(
f"Total issues found: {colorize(str(total_issues), Colors.BOLD)}")
# Add counts by severity
for severity in ["CRITICAL", "HIGH", "MEDIUM", "LOW"]:
count = len(issues_by_severity[severity])
if count > 0:
color = getattr(Colors, severity)
summary.append(f"{colorize(severity, color)} issues: {count}")
# List all critical issues
if issues_by_severity["CRITICAL"]:
summary.append(
"\n" + colorize("CRITICAL ISSUES REQUIRING IMMEDIATE ATTENTION:", Colors.CRITICAL))
for issue in issues_by_severity["CRITICAL"]:
summary.append(f"- {issue['component']}: {issue['description']}")
# List high severity issues
if issues_by_severity["HIGH"]:
summary.append("\n" + colorize("HIGH SEVERITY ISSUES:", Colors.HIGH))
for issue in issues_by_severity["HIGH"]:
summary.append(f"- {issue['component']}: {issue['description']}")
# Summarize medium and low severity issues
if issues_by_severity["MEDIUM"]:
summary.append(
f"\n{colorize('MEDIUM SEVERITY ISSUES:', Colors.MEDIUM)} {len(issues_by_severity['MEDIUM'])} found")
if issues_by_severity["LOW"]:
summary.append(
f"{colorize('LOW SEVERITY ISSUES:', Colors.LOW)} {len(issues_by_severity['LOW'])} found")
return "\n".join(summary)
def generate_html_report(all_results):
"""
Generate an HTML version of the report
:param all_results: List of all results from the analysis
:return: HTML content as a string
"""
html_output = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Graid System Analysis Report - {datetime.datetime.now().strftime('%Y-%m-%d')}</title>
<style>
body {{
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
color: #333;
max-width: 1200px;
margin: 0 auto;
}}
h1, h2, h3, h4 {{
color: #0066cc;
}}
h1 {{
border-bottom: 2px solid #0066cc;
padding-bottom: 10px;
}}
.section {{
margin-bottom: 30px;
border: 1px solid #ddd;
border-radius: 5px;
padding: 15px;
background-color: #f9f9f9;
}}
.section-title {{
background-color: #0066cc;
color: white;
padding: 10px;
margin: -15px -15px 15px -15px;
border-radius: 5px 5px 0 0;
}}
.executive-summary {{
background-color: #f0f7ff;
border-left: 5px solid #0066cc;
}}
.issue {{
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
}}
.critical {{
background-color: #ffebee;
border-left: 5px solid #d32f2f;
}}
.high {{
background-color: #fff8e1;
border-left: 5px solid #ff8f00;
}}
.medium {{
background-color: #e8f5e9;
border-left: 5px solid #388e3c;
}}
.low {{
background-color: #e3f2fd;
border-left: 5px solid #1976d2;
}}
table {{
border-collapse: collapse;
width: 100%;
margin-bottom: 15px;
}}
th, td {{
text-align: left;
padding: 12px;