Fix description template strings not rendering (missing f-string prefix)
Lint / Notify on failure (push) Has been cancelled
Lint / Python (flake8) (push) Has been cancelled
Security / Python Security (bandit) (push) Has been cancelled
Test / Python Tests (pytest) (push) Has been cancelled

All multi-line ASCII art blocks in _generate_ticket_description were
regular strings, not f-strings — so {hostname}, {'━' * box_width},
{cluster_health}, etc. were sent as literal template text instead of
rendered values. Added f prefix to all affected triple-quoted strings:
banner, executive_summary, DRIVE SPECIFICATIONS, DRIVE TIMELINE,
SMART STATUS, PARTITION, CEPH CLUSTER STATUS, CPU STATUS,
NETWORK STATUS, CONTAINER STORAGE.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 08:11:09 -04:00
parent 78691e6235
commit c0c96bf003
+10 -10
View File
@@ -1330,7 +1330,7 @@ class SystemHealthMonitor:
# content lines: prefix + field_width + ┃ = 80 # content lines: prefix + field_width + ┃ = 80
box_width = 78 box_width = 78
banner = """ banner = f"""
{'' * box_width} {'' * box_width}
{' HARDWARE MONITORING ALERT TICKET '.center(box_width)} {' HARDWARE MONITORING ALERT TICKET '.center(box_width)}
{'' * box_width} {'' * box_width}
@@ -1342,7 +1342,7 @@ class SystemHealthMonitor:
issue_type = self._get_issue_type(issue) issue_type = self._get_issue_type(issue)
impact_level = self._get_impact_level(issue) impact_level = self._get_impact_level(issue)
executive_summary = """ executive_summary = f"""
┏━ EXECUTIVE SUMMARY {'' * (box_width - 20)} ┏━ EXECUTIVE SUMMARY {'' * (box_width - 20)}
┃ Issue Type │ {issue_type:<60} ┃ Issue Type │ {issue_type:<60}
┃ Impact Level │ {impact_level:<60} ┃ Impact Level │ {impact_level:<60}
@@ -1407,7 +1407,7 @@ class SystemHealthMonitor:
type_safe = drive_details.get('type') or 'N/A' type_safe = drive_details.get('type') or 'N/A'
firmware_safe = drive_details.get('firmware') or 'N/A' firmware_safe = drive_details.get('firmware') or 'N/A'
description += """ description += f"""
┏━ DRIVE SPECIFICATIONS {'' * (box_width - 23)} ┏━ DRIVE SPECIFICATIONS {'' * (box_width - 23)}
┃ Device Path │ {device_safe:<61} ┃ Device Path │ {device_safe:<61}
┃ Model │ {model_safe:<61} ┃ Model │ {model_safe:<61}
@@ -1422,7 +1422,7 @@ class SystemHealthMonitor:
last_test_safe = last_test_date or 'N/A' last_test_safe = last_test_date or 'N/A'
age_safe = age or 'N/A' age_safe = age or 'N/A'
description += """ description += f"""
┏━ DRIVE TIMELINE {'' * (box_width - 17)} ┏━ DRIVE TIMELINE {'' * (box_width - 17)}
┃ Power-On Hours │ {power_on_safe:<56} ┃ Power-On Hours │ {power_on_safe:<56}
┃ Last SMART Test │ {last_test_safe:<56} ┃ Last SMART Test │ {last_test_safe:<56}
@@ -1435,7 +1435,7 @@ class SystemHealthMonitor:
temp_value = drive_info.get('temperature') temp_value = drive_info.get('temperature')
temp_safe = f"{temp_value}°C" if temp_value is not None else 'N/A' temp_safe = f"{temp_value}°C" if temp_value is not None else 'N/A'
description += """ description += f"""
┏━ SMART STATUS {'' * (box_width - 15)} ┏━ SMART STATUS {'' * (box_width - 15)}
┃ Status │ {smart_status_safe:<62} ┃ Status │ {smart_status_safe:<62}
┃ Temperature │ {temp_safe:<62} ┃ Temperature │ {temp_safe:<62}
@@ -1467,7 +1467,7 @@ class SystemHealthMonitor:
# Truncate mountpoint if too long for header # Truncate mountpoint if too long for header
mountpoint_display = mountpoint_safe[:50] if len(mountpoint_safe) > 50 else mountpoint_safe mountpoint_display = mountpoint_safe[:50] if len(mountpoint_safe) > 50 else mountpoint_safe
description += """ description += f"""
┏━ PARTITION: {mountpoint_display} {'' * (box_width - 14 - len(mountpoint_display))} ┏━ PARTITION: {mountpoint_display} {'' * (box_width - 14 - len(mountpoint_display))}
┃ Filesystem │ {fstype_safe:<61} ┃ Filesystem │ {fstype_safe:<61}
┃ Usage Meter │ {usage_meter} {usage_pct_str:>10} ┃ Usage Meter │ {usage_meter} {usage_pct_str:>10}
@@ -1520,7 +1520,7 @@ class SystemHealthMonitor:
cpu_status = cpu_health.get('status', 'N/A') cpu_status = cpu_health.get('status', 'N/A')
cpu_usage_str = f"{cpu_usage}%" if isinstance(cpu_usage, (int, float)) else cpu_usage cpu_usage_str = f"{cpu_usage}%" if isinstance(cpu_usage, (int, float)) else cpu_usage
description += """ description += f"""
┏━ CPU STATUS {'' * (box_width - 13)} ┏━ CPU STATUS {'' * (box_width - 13)}
┃ Usage │ {cpu_usage_str:<61} ┃ Usage │ {cpu_usage_str:<61}
┃ Threshold │ {str(cpu_threshold) + '%':<61} ┃ Threshold │ {str(cpu_threshold) + '%':<61}
@@ -1553,7 +1553,7 @@ class SystemHealthMonitor:
if len(issues_str) > 61: if len(issues_str) > 61:
issues_str = issues_str[:58] + '...' issues_str = issues_str[:58] + '...'
description += """ description += f"""
┏━ NETWORK STATUS {'' * (box_width - 17)} ┏━ NETWORK STATUS {'' * (box_width - 17)}
┃ Management │ {mgmt_status:<61} ┃ Management │ {mgmt_status:<61}
┃ Ceph Network │ {ceph_status:<61} ┃ Ceph Network │ {ceph_status:<61}
@@ -1585,7 +1585,7 @@ class SystemHealthMonitor:
usage_meter = '' * blocks + '' * (50 - blocks) usage_meter = '' * blocks + '' * (50 - blocks)
usage_pct_str = f"{usage_pct:.1f}%" usage_pct_str = f"{usage_pct:.1f}%"
description += """ description += f"""
┏━ CONTAINER STORAGE {'' * (box_width - 20)} ┏━ CONTAINER STORAGE {'' * (box_width - 20)}
┃ VMID │ {vmid:<61} ┃ VMID │ {vmid:<61}
┃ Mountpoint │ {mountpoint:<61} ┃ Mountpoint │ {mountpoint:<61}
@@ -1613,7 +1613,7 @@ class SystemHealthMonitor:
osd_up = sum(1 for o in osd_list if o.get('status') == 'up') osd_up = sum(1 for o in osd_list if o.get('status') == 'up')
osd_summary = f"{osd_up}/{osd_total} up" if osd_total > 0 else 'N/A' osd_summary = f"{osd_up}/{osd_total} up" if osd_total > 0 else 'N/A'
description += """ description += f"""
┏━ CEPH CLUSTER STATUS {'' * (box_width - 22)} ┏━ CEPH CLUSTER STATUS {'' * (box_width - 22)}
┃ Health │ {cluster_health:<61} ┃ Health │ {cluster_health:<61}
┃ Usage │ {usage_pct_str:<61} ┃ Usage │ {usage_pct_str:<61}