Add Synology monthly drive health report parser
Add parser for Synology monthly drive health reports with support for both
Dutch and English notifications. Reports are classified as informational
and excluded from schedule learning and reporting logic.
Features:
- Recognizes Dutch ("Maandelijks schijfintegriteitsrapport", "Gezond") and
English ("Monthly Drive Health Report", "Healthy") variants
- Extracts hostname from subject or body ("Van/From NAS-HOSTNAME")
- Automatic status detection: Healthy/Gezond/No problem detected → Success,
otherwise → Warning
- Backup type: "Health Report", Job name: "Monthly Drive Health"
- Added registry entry (order 237) for /parsers page visibility
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b6a85d1c8e
commit
f539d62daf
@ -113,6 +113,32 @@ PARSER_DEFINITIONS = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "synology_drive_health",
|
||||||
|
"backup_software": "Synology",
|
||||||
|
"backup_types": ["Health Report"],
|
||||||
|
"order": 237,
|
||||||
|
"enabled": True,
|
||||||
|
"match": {
|
||||||
|
"subject_contains_any": ["schijfintegriteitsrapport", "Drive Health Report"],
|
||||||
|
"body_contains_any": ["health of the drives", "integriteitsrapport van de schijven"],
|
||||||
|
},
|
||||||
|
"description": "Parses Synology monthly drive health reports (informational; excluded from reporting and missing logic).",
|
||||||
|
"example": {
|
||||||
|
"subject": "[NAS-HOSTNAME] Monthly Drive Health Report on NAS-HOSTNAME - Healthy",
|
||||||
|
"from_address": "nas@example.local",
|
||||||
|
"body_snippet": "The following is your monthly report regarding the health of the drives on NAS-HOSTNAME. No problem detected with the drives in DSM.",
|
||||||
|
"parsed_result": {
|
||||||
|
"backup_software": "Synology",
|
||||||
|
"backup_type": "Health Report",
|
||||||
|
"job_name": "Monthly Drive Health",
|
||||||
|
"overall_status": "Success",
|
||||||
|
"objects": [
|
||||||
|
{"name": "NAS-HOSTNAME", "status": "Success"}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "veeam_replication_job",
|
"name": "veeam_replication_job",
|
||||||
"backup_software": "Veeam",
|
"backup_software": "Veeam",
|
||||||
|
|||||||
@ -73,6 +73,75 @@ def _parse_synology_dsm_update_cancelled(subject: str, text: str) -> Tuple[bool,
|
|||||||
|
|
||||||
return True, result, objects
|
return True, result, objects
|
||||||
|
|
||||||
|
|
||||||
|
# --- Synology Drive Health Report (informational, excluded from reporting) ---
|
||||||
|
|
||||||
|
DRIVE_HEALTH_PATTERNS = [
|
||||||
|
"schijfintegriteitsrapport",
|
||||||
|
"Drive Health Report",
|
||||||
|
"Monthly Drive Health",
|
||||||
|
"health of the drives",
|
||||||
|
"integriteitsrapport van de schijven",
|
||||||
|
]
|
||||||
|
|
||||||
|
_DRIVE_HEALTH_SUBJECT_RE = re.compile(
|
||||||
|
r"\b(?:schijfintegriteitsrapport\s+over|Drive\s+Health\s+Report\s+on)\s+(?P<host>[A-Za-z0-9._-]+)",
|
||||||
|
re.I,
|
||||||
|
)
|
||||||
|
|
||||||
|
_DRIVE_HEALTH_FROM_RE = re.compile(r"\b(?:Van|From)\s+(?P<host>[A-Za-z0-9._-]+)\b", re.I)
|
||||||
|
|
||||||
|
_DRIVE_HEALTH_STATUS_HEALTHY_RE = re.compile(
|
||||||
|
r"\b(?:Gezond|Healthy|geen\s+problemen\s+gedetecteerd|No\s+problem\s+detected)\b",
|
||||||
|
re.I,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_synology_drive_health(subject: str, text: str) -> bool:
|
||||||
|
haystack = f"{subject}\n{text}".lower()
|
||||||
|
return any(p.lower() in haystack for p in DRIVE_HEALTH_PATTERNS)
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_synology_drive_health(subject: str, text: str) -> Tuple[bool, Dict, List[Dict]]:
|
||||||
|
haystack = f"{subject}\n{text}"
|
||||||
|
host = ""
|
||||||
|
|
||||||
|
# Try to extract hostname from subject first
|
||||||
|
m = _DRIVE_HEALTH_SUBJECT_RE.search(subject or "")
|
||||||
|
if m:
|
||||||
|
host = (m.group("host") or "").strip()
|
||||||
|
|
||||||
|
# Fallback: extract from body "Van/From NAS-NAME"
|
||||||
|
if not host:
|
||||||
|
m = _DRIVE_HEALTH_FROM_RE.search(text or "")
|
||||||
|
if m:
|
||||||
|
host = (m.group("host") or "").strip()
|
||||||
|
|
||||||
|
# Determine status based on health indicators
|
||||||
|
overall_status = "Success"
|
||||||
|
overall_message = "Healthy"
|
||||||
|
|
||||||
|
if not _DRIVE_HEALTH_STATUS_HEALTHY_RE.search(haystack):
|
||||||
|
# If we don't find healthy indicators, mark as Warning
|
||||||
|
overall_status = "Warning"
|
||||||
|
overall_message = "Drive health issue detected"
|
||||||
|
|
||||||
|
# Informational job: show in Run Checks, but do not participate in schedules / reporting.
|
||||||
|
result: Dict = {
|
||||||
|
"backup_software": "Synology",
|
||||||
|
"backup_type": "Health Report",
|
||||||
|
"job_name": "Monthly Drive Health",
|
||||||
|
"overall_status": overall_status,
|
||||||
|
"overall_message": overall_message + (f" ({host})" if host else ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
objects: List[Dict] = []
|
||||||
|
if host:
|
||||||
|
objects.append({"name": host, "status": overall_status})
|
||||||
|
|
||||||
|
return True, result, objects
|
||||||
|
|
||||||
|
|
||||||
_BR_RE = re.compile(r"<\s*br\s*/?\s*>", re.I)
|
_BR_RE = re.compile(r"<\s*br\s*/?\s*>", re.I)
|
||||||
_TAG_RE = re.compile(r"<[^>]+>")
|
_TAG_RE = re.compile(r"<[^>]+>")
|
||||||
_WS_RE = re.compile(r"[\t\r\f\v ]+")
|
_WS_RE = re.compile(r"[\t\r\f\v ]+")
|
||||||
@ -509,6 +578,12 @@ def try_parse_synology(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
|||||||
if ok:
|
if ok:
|
||||||
return True, result, objects
|
return True, result, objects
|
||||||
|
|
||||||
|
# Drive Health Report (informational; no schedule; excluded from reporting)
|
||||||
|
if _is_synology_drive_health(subject, text):
|
||||||
|
ok, result, objects = _parse_synology_drive_health(subject, text)
|
||||||
|
if ok:
|
||||||
|
return True, result, objects
|
||||||
|
|
||||||
# DSM Account Protection (informational; no schedule)
|
# DSM Account Protection (informational; no schedule)
|
||||||
if _is_synology_account_protection(subject, text):
|
if _is_synology_account_protection(subject, text):
|
||||||
ok, result, objects = _parse_account_protection(subject, text)
|
ok, result, objects = _parse_account_protection(subject, text)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ This file documents all changes made to this project via Claude Code.
|
|||||||
## [2026-02-09]
|
## [2026-02-09]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Added parser for Synology monthly drive health reports (backup software: Synology, backup type: Health Report, job name: Monthly Drive Health, informational only, no schedule learning) with support for both Dutch and English notifications ("schijfintegriteitsrapport"/"Drive Health Report") and automatic status detection (Healthy/Gezond → Success, problems → Warning)
|
||||||
- Added "Cleanup orphaned jobs" maintenance option in Settings → Maintenance to delete jobs without valid customer links and their associated emails/runs permanently from database (useful when customers are removed)
|
- Added "Cleanup orphaned jobs" maintenance option in Settings → Maintenance to delete jobs without valid customer links and their associated emails/runs permanently from database (useful when customers are removed)
|
||||||
- Added "Preview orphaned jobs" button to show detailed list of jobs to be deleted with run/email counts before confirming deletion (verification step for safety)
|
- Added "Preview orphaned jobs" button to show detailed list of jobs to be deleted with run/email counts before confirming deletion (verification step for safety)
|
||||||
- Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing)
|
- Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user