From 70b02de104e537214c1fb843430df670cb7f4445 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Fri, 6 Feb 2026 19:08:56 -0500 Subject: [PATCH] Fix ticket ASCII art alignment, Ceph classification, and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix all 9 box sections to produce exactly 80-char lines - Add Ceph/OSD keyword detection to _get_issue_type() - Make _get_impact_level() recognize HEALTH_WARN/HEALTH_ERR/DOWN - Remove unused make_box() method - Fix wrong Gitea URL (10.10.10.110 → 10.10.10.63) in README Co-Authored-By: Claude Opus 4.6 --- README.md | 2 +- hwmonDaemon.py | 66 ++++++++++++++++++++++++-------------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 5408175..cca1516 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ sudo systemctl start hwmon.timer ### One liner (run as root) ```bash -curl -o /etc/systemd/system/hwmon.service http://10.10.10.110:3000/LotusGuild/hwmonDaemon/raw/branch/main/hwmon.service && curl -o /etc/systemd/system/hwmon.timer http://10.10.10.110:3000/LotusGuild/hwmonDaemon/raw/branch/main/hwmon.timer && systemctl daemon-reload && systemctl enable hwmon.timer && systemctl start hwmon.timer +curl -o /etc/systemd/system/hwmon.service http://10.10.10.63:3000/LotusGuild/hwmonDaemon/raw/branch/main/hwmon.service && curl -o /etc/systemd/system/hwmon.timer http://10.10.10.63:3000/LotusGuild/hwmonDaemon/raw/branch/main/hwmon.timer && systemctl daemon-reload && systemctl enable hwmon.timer && systemctl start hwmon.timer ``` ## Manual Execution diff --git a/hwmonDaemon.py b/hwmonDaemon.py index 174f85a..c56c187 100644 --- a/hwmonDaemon.py +++ b/hwmonDaemon.py @@ -1081,12 +1081,6 @@ class SystemHealthMonitor: return drive_details - def make_box(self, title: str, content: str, content_width: int = 70) -> str: - """Create a formatted box with title and content.""" - return f""" -┏━ {title} {'━' * (content_width - len(title) - 3)}┓ -{content} -┗{'━' * content_width}┛""" def _get_issue_type(self, issue: str) -> str: """Determine issue type from issue description.""" @@ -1094,8 +1088,10 @@ class SystemHealthMonitor: return "SMART Health Issue" elif "Drive" in issue: return "Storage Issue" + elif any(kw in issue for kw in ["Ceph", "OSD", "ceph"]): + return "Ceph Cluster Issue" elif "ECC" in issue: - return "Memory Issue" + return "Memory Issue" elif "CPU" in issue: return "Performance Issue" elif "Network" in issue: @@ -1104,9 +1100,10 @@ class SystemHealthMonitor: def _get_impact_level(self, issue: str) -> str: """Determine impact level from issue description.""" - if "CRITICAL" in issue or "UNHEALTHY" in issue: + issue_upper = issue.upper() + if "CRITICAL" in issue_upper or "UNHEALTHY" in issue_upper or "HEALTH_ERR" in issue_upper: return "🔴 Critical - Immediate Action Required" - elif "WARNING" in issue: + elif "WARNING" in issue_upper or "HEALTH_WARN" in issue_upper or "DOWN" in issue_upper: return "🟡 Warning - Action Needed Soon" return "🟢 Low - Monitor Only" @@ -1116,17 +1113,18 @@ class SystemHealthMonitor: timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") priority = "⚠ HIGH" if "CRITICAL" in issue else "● MEDIUM" - # Standard box width for all sections (80 chars total) + # Box width: all lines are exactly 80 chars + # border lines: ┏ + 78 ━ + ┓ = 80 + # content lines: prefix + field_width + ┃ = 80 box_width = 78 - field_width = 62 # Width for value fields after label banner = f""" ┏{'━' * box_width}┓ ┃{' HARDWARE MONITORING ALERT TICKET '.center(box_width)}┃ ┣{'━' * box_width}┫ -┃ Host : {hostname:<{box_width - 15}}┃ -┃ Generated : {timestamp:<{box_width - 15}}┃ -┃ Priority : {priority:<{box_width - 15}}┃ +┃ Host : {hostname:<{box_width - 14}}┃ +┃ Generated : {timestamp:<{box_width - 14}}┃ +┃ Priority : {priority:<{box_width - 14}}┃ ┗{'━' * box_width}┛""" issue_type = self._get_issue_type(issue) @@ -1134,8 +1132,8 @@ class SystemHealthMonitor: executive_summary = f""" ┏━ EXECUTIVE SUMMARY {'━' * (box_width - 20)}┓ -┃ Issue Type │ {issue_type:<{field_width}}┃ -┃ Impact Level │ {impact_level:<{field_width}}┃ +┃ Issue Type │ {issue_type:<60}┃ +┃ Impact Level │ {impact_level:<60}┃ ┗{'━' * box_width}┛""" description = banner + executive_summary @@ -1179,12 +1177,12 @@ class SystemHealthMonitor: description += f""" ┏━ DRIVE SPECIFICATIONS {'━' * (box_width - 23)}┓ -┃ Device Path │ {device_safe:<{field_width}}┃ -┃ Model │ {model_safe:<{field_width}}┃ -┃ Serial │ {serial_safe:<{field_width}}┃ -┃ Capacity │ {capacity_safe:<{field_width}}┃ -┃ Type │ {type_safe:<{field_width}}┃ -┃ Firmware │ {firmware_safe:<{field_width}}┃ +┃ Device Path │ {device_safe:<61}┃ +┃ Model │ {model_safe:<61}┃ +┃ Serial │ {serial_safe:<61}┃ +┃ Capacity │ {capacity_safe:<61}┃ +┃ Type │ {type_safe:<61}┃ +┃ Firmware │ {firmware_safe:<61}┃ ┗{'━' * box_width}┛ """ @@ -1202,9 +1200,9 @@ class SystemHealthMonitor: description += f""" ┏━ DRIVE TIMELINE {'━' * (box_width - 17)}┓ -┃ Power-On Hours │ {power_on_safe:<{field_width - 4}}┃ -┃ Last SMART Test │ {last_test_safe:<{field_width - 4}}┃ -┃ Drive Age │ {age_safe:<{field_width - 4}}┃ +┃ Power-On Hours │ {power_on_safe:<56}┃ +┃ Last SMART Test │ {last_test_safe:<56}┃ +┃ Drive Age │ {age_safe:<56}┃ ┗{'━' * box_width}┛ """ @@ -1215,8 +1213,8 @@ class SystemHealthMonitor: description += f""" ┏━ SMART STATUS {'━' * (box_width - 15)}┓ -┃ Status │ {smart_status_safe:<{field_width}}┃ -┃ Temperature │ {temp_safe:<{field_width}}┃ +┃ Status │ {smart_status_safe:<62}┃ +┃ Temperature │ {temp_safe:<62}┃ ┗{'━' * box_width}┛ """ @@ -1225,7 +1223,7 @@ class SystemHealthMonitor: for attr, value in drive_info['smart_attributes'].items(): attr_safe = str(attr).replace('_', ' ') if attr else 'Unknown' value_safe = str(value) if value is not None else 'N/A' - description += f"┃ {attr_safe:<27} │ {value_safe:<{field_width - 14}}┃\n" + description += f"┃ {attr_safe:<27} │ {value_safe:<46}┃\n" description += f"┗{'━' * box_width}┛\n" if drive_info.get('partitions'): @@ -1247,11 +1245,11 @@ class SystemHealthMonitor: description += f""" ┏━ PARTITION: {mountpoint_display} {'━' * (box_width - 14 - len(mountpoint_display))}┓ -┃ Filesystem │ {fstype_safe:<{field_width}}┃ -┃ Usage Meter │ {usage_meter} {usage_pct_str:>5}┃ -┃ Total Space │ {total_space_safe:<{field_width}}┃ -┃ Used Space │ {used_space_safe:<{field_width}}┃ -┃ Free Space │ {free_space_safe:<{field_width}}┃ +┃ Filesystem │ {fstype_safe:<61}┃ +┃ Usage Meter │ {usage_meter} {usage_pct_str:>10}┃ +┃ Total Space │ {total_space_safe:<61}┃ +┃ Used Space │ {used_space_safe:<61}┃ +┃ Free Space │ {free_space_safe:<61}┃ ┗{'━' * box_width}┛ """ @@ -1260,7 +1258,7 @@ class SystemHealthMonitor: description += f"\n┏━ FIRMWARE ALERTS {'━' * (box_width - 18)}┓\n" for issue_item in firmware_info['known_issues']: issue_safe = str(issue_item) if issue_item else 'Unknown issue' - description += f"┃ ⚠ {issue_safe:<{box_width - 5}}┃\n" + description += f"┃ ⚠ {issue_safe:<{box_width - 4}}┃\n" description += f"┗{'━' * box_width}┛\n" except Exception as e: description += f"\nError generating drive details: {str(e)}\n"