diff --git a/gecko b/gecko index a031271..0378b64 100755 --- a/gecko +++ b/gecko @@ -83,8 +83,9 @@ def run_triage(): gecko.grab_science_image() gecko.compress_report() - if gecko.email_alerts: - gecko.send_report() + if gecko.email_alerts: + gecko.send_report() + gecko.cleanup_reports_dir() print("\nTriage workflow complete!") else: diff --git a/triage_package/triage.ini b/triage_package/triage.ini index a321c66..1ac7a87 100644 --- a/triage_package/triage.ini +++ b/triage_package/triage.ini @@ -38,6 +38,7 @@ report_path = time_pattern = ^(\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?) email_alerts = recipient_email = +machine_name = #sender_email = #sender_password = diff --git a/triage_package/triage_tool.py b/triage_package/triage_tool.py index c27a4da..cbcee2c 100755 --- a/triage_package/triage_tool.py +++ b/triage_package/triage_tool.py @@ -19,19 +19,18 @@ import os import sys import subprocess -import tarfile +import zipfile import shutil import configparser -import smtplib -from pathlib import Path +from pathlib import Path #pylint: disable=W0611 from email.message import EmailMessage import re from datetime import datetime, timezone, timedelta import glob import threading #pylint: disable=W0611 import socket #pylint: disable=W0611 -import psutil -from vncdotool import api #pylint: disable=W0611 +import psutil #pylint: disable=E0401 +from vncdotool import api #pylint: disable=E0401,W0611 class Triagetools(object): """Triage tool for bug catching and error reporting""" @@ -45,7 +44,7 @@ def __init__(self, config: str, message:str = "", init = False): self.cutoff = datetime.now().replace(tzinfo=None) - timedelta(hours=24) self.message = message self.time_pattern = r"^(\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?)" - self.tar_filename = "" + self.zip_filename = "" # Create a ConfigParser object self.config = configparser.ConfigParser() @@ -109,7 +108,7 @@ def load_config(self, config): self.email_alerts = self.config.getboolean("Report", "email_alerts") if self.email_alerts: self.target_email = self.config["Report"]["recipient_email"] - #self.sender_email = self.config["Report"]["sender_email"] + self.machine_name = self.config["Report"]["machine_name"] #self.sender_password = self.config["Report"]["sender_password"] self.r_path = self.config["Report"]["report_path"] self.log_dir = self.config["Logs"]["logs_dir"] @@ -239,7 +238,7 @@ def find_displays(self): return sorted(displays, key=lambda d: int(d[1:])) def gather_logs(self): - ''' Gathers Logs from all paths to dump into tar comp. ''' + ''' Gathers Logs from all paths to dump into zip comp. ''' #Iterate through log paths in config file for subdir, dirs, files in os.walk(self.log_dir): # pylint: disable = W0612 for file in files: @@ -293,26 +292,26 @@ def comb_logs(self): print(f"An unexpected error occurred: {e}") def compress_report(self): - '''Compresses report file into a tar.gz format to be emailed''' - #Tar file and add it to message - #with tarfile.open(f"{self.reports_path}/gecko_{self.utc_date}.tar.gz", "w:gz") as tar: - # tar.add(f"{self.reports_path}", arcname=os.path.basename(f"{self.reports_path}")) + """Compresses report files into a .zip format to be emailed""" filename = f"{self.reports_path}/gecko_{self.utc_date}" - filename = filename.replace(" ", "_").replace('+','') - self.tar_filename = filename.replace(':', '').replace('.', '_') + ".tar.gz" - with tarfile.open(self.tar_filename, "w:gz") as tar: - for root, dirs, files in os.walk(self.reports_path): + filename = filename.replace(" ", "_").replace("+", "") + self.zip_filename = filename.replace(":", "").replace(".", "_") + ".zip" + + with zipfile.ZipFile(self.zip_filename, "w", compression=zipfile.ZIP_DEFLATED) as zipf: + for root, dirs, files in os.walk(self.reports_path): # pylint: disable = W0612 for file in files: - # Only include files containing utc_time - if self.utc_time in file or ".log" in file: + # Only include files containing utc_time OR log files + if self.utc_time in file or file.endswith(".log"): full_path = os.path.join(root, file) - # Keep relative structure inside tar + # Keep relative structure inside zip arcname = os.path.relpath(full_path, self.reports_path) - tar.add(full_path, arcname=arcname) + zipf.write(full_path, arcname=arcname) + + print(f"Created ZIP file: {self.zip_filename}") def grab_science_image(self): '''Grabs most recent science image(s) to include in triage''' @@ -354,11 +353,19 @@ def send_report(self): # Create email msg = EmailMessage() msg['Subject'] = f'Gecko Report {self.utc_date}' - msg['From'] = self.sender_email # replace with actual sender + msg['From'] = self.machine_name # replace with actual sender msg['To'] = self.target_email # can be comma-separated string or list + zip_path = os.path.join(self.reports_path, self.zip_filename) # Email body - msg.set_content("Please see attached report images.") + body = ( + f"{self.message}\n\n" + "To view logs and images:\n" + " 1. Download the attached .zip file\n" + " 2. Extract it\n\n" + f"Compressed report location:\n{zip_path}" + ) + msg.set_content(body) #.txt file first with open(self.report_name, 'rb') as f: @@ -369,17 +376,17 @@ def send_report(self): filename=os.path.basename(self.report_name) ) - #tar.gz file next - with open(self.tar_filename, 'rb') as f: - msg.add_attachment( - f.read(), - maintype='application', - subtype='gzip', - filename=os.path.basename(self.tar_filename) - ) + #.zip file next + #with open(self.zip_filename, 'rb') as f: + # msg.add_attachment( + # f.read(), + # maintype='application', + # subtype='gzip', + # filename=os.path.basename(self.zip_filename) + # ) # Attach PNG images recursively from the reports_path - image_files = glob.glob(os.path.join(self.reports_path, '**', f'*{self.utc_time}.png'), recursive=True) + #image_files = glob.glob(os.path.join(self.reports_path, '**', f'*{self.utc_time}.png'), recursive=True) #for file in image_files: # with open(file, 'rb') as fp: # img_data = fp.read() @@ -396,14 +403,14 @@ def send_report(self): # smtp.send_message(msg) #print(f"Report sent to {self.target_email}") - for file in image_files: - with open(file, "rb") as fp: - msg.add_attachment( - fp.read(), - maintype="image", - subtype="png", - filename=os.path.basename(file) - ) + #for file in image_files: + # with open(file, "rb") as fp: + # msg.add_attachment( + # fp.read(), + # maintype="image", + # subtype="png", + # filename=os.path.basename(file) + # ) # Send using local sendmail instead of SMTP try: @@ -416,3 +423,11 @@ def send_report(self): except Exception as e: #pylint: disable=W0718 print("Failed to send report:", e) + + def cleanup_reports_dir(self): + """Clean up and rid of all files that are not a .zip file""" + for root, dirs, files in os.walk(self.reports_path): # pylint: disable = W0612 + for filename in files: + full_path = os.path.join(self.reports_path, filename) + if not full_path.endswith(".zip"): + os.remove(full_path)