Merge branch 'v20260209-06-synology-firmware-update-parser' into main

This commit is contained in:
Ivo Oskamp 2026-02-09 17:25:30 +01:00
commit fd3f3765c3
4 changed files with 63 additions and 13 deletions

View File

@ -1 +1 @@
v20260209-05-responsive-navbar-fix v20260209-06-synology-firmware-update-parser

View File

@ -50,13 +50,13 @@ PARSER_DEFINITIONS = [
}, },
"description": "Parses NTFS Auditing file audit report mails (attachment-based HTML reports).", "description": "Parses NTFS Auditing file audit report mails (attachment-based HTML reports).",
"example": { "example": {
"subject": "Bouter btr-dc001.bouter.nl file audits → 6 ↑ 12", "subject": "SERVER-HOSTNAME file audits → 6 ↑ 12",
"from_address": "auditing@bouter.nl", "from_address": "auditing@example.local",
"body_snippet": "(empty body, HTML report in attachment)", "body_snippet": "(empty body, HTML report in attachment)",
"parsed_result": { "parsed_result": {
"backup_software": "NTFS Auditing", "backup_software": "NTFS Auditing",
"backup_type": "Audit", "backup_type": "Audit",
"job_name": "btr-dc001.bouter.nl file audits", "job_name": "SERVER-HOSTNAME file audits",
"objects": [], "objects": [],
}, },
}, },
@ -73,16 +73,42 @@ PARSER_DEFINITIONS = [
}, },
"description": "Parses QNAP Notification Center firmware update notifications (informational; excluded from reporting and missing logic).", "description": "Parses QNAP Notification Center firmware update notifications (informational; excluded from reporting and missing logic).",
"example": { "example": {
"subject": "[Info][Firmware Update] Notification from your device: BETSIES-NAS01", "subject": "[Info][Firmware Update] Notification from your device: NAS-HOSTNAME",
"from_address": "notifications@customer.tld", "from_address": "notifications@customer.tld",
"body_snippet": "NAS Name: BETSIES-NAS01\n...\nMessage: ...", "body_snippet": "NAS Name: NAS-HOSTNAME\n...\nMessage: ...",
"parsed_result": { "parsed_result": {
"backup_software": "QNAP", "backup_software": "QNAP",
"backup_type": "Firmware Update", "backup_type": "Firmware Update",
"job_name": "Firmware Update", "job_name": "Firmware Update",
"overall_status": "Warning", "overall_status": "Warning",
"objects": [ "objects": [
{"name": "BETSIES-NAS01", "status": "Warning", "error_message": None} {"name": "NAS-HOSTNAME", "status": "Warning", "error_message": None}
],
},
},
},
{
"name": "synology_dsm_update",
"backup_software": "Synology",
"backup_types": ["Updates"],
"order": 236,
"enabled": True,
"match": {
"subject_contains_any": ["DSM-update", "DSM update"],
"body_contains_any": ["automatische DSM-update", "automatic DSM update", "Automatic update of DSM"],
},
"description": "Parses Synology DSM automatic update cancelled notifications (informational; excluded from reporting and missing logic).",
"example": {
"subject": "Synology NAS-HOSTNAME - Automatische DSM-update op NAS-HOSTNAME is geannuleerd door het systeem",
"from_address": "backup@example.local",
"body_snippet": "Het systeem heeft de automatische DSM-update op NAS-HOSTNAME geannuleerd...",
"parsed_result": {
"backup_software": "Synology",
"backup_type": "Updates",
"job_name": "Synology Automatic Update",
"overall_status": "Warning",
"objects": [
{"name": "NAS-HOSTNAME", "status": "Warning"}
], ],
}, },
}, },
@ -383,16 +409,16 @@ PARSER_DEFINITIONS = [
}, },
"description": "Parses NAKIVO Backup & Replication reports for VMware backup jobs.", "description": "Parses NAKIVO Backup & Replication reports for VMware backup jobs.",
"example": { "example": {
"subject": '"exchange01.kuiperbv.nl" job: Successful', "subject": '"VM-HOSTNAME" job: Successful',
"from_address": "NAKIVO Backup & Replication <administrator@customer.local>", "from_address": "NAKIVO Backup & Replication <administrator@customer.local>",
"body_snippet": "Job Run Report... Backup job for VMware ... Successful", "body_snippet": "Job Run Report... Backup job for VMware ... Successful",
"parsed_result": { "parsed_result": {
"backup_software": "NAKIVO", "backup_software": "NAKIVO",
"backup_type": "Backup job for VMware", "backup_type": "Backup job for VMware",
"job_name": "exchange01.kuiperbv.nl", "job_name": "VM-HOSTNAME",
"objects": [ "objects": [
{ {
"name": "exchange01.kuiperbv.nl", "name": "VM-HOSTNAME",
"status": "Success", "status": "Success",
"error_message": "", "error_message": "",
} }

View File

@ -18,10 +18,23 @@ DSM_UPDATE_CANCELLED_PATTERNS = [
"Automatische update van DSM is geannuleerd", "Automatische update van DSM is geannuleerd",
"Automatic DSM update was cancelled", "Automatic DSM update was cancelled",
"Automatic update of DSM was cancelled", "Automatic update of DSM was cancelled",
"Automatische DSM-update",
"DSM-update op",
"Packages on",
"out-of-date",
"Package Center",
"new DSM update",
"Auto Update has detected",
"new version of DSM",
"Update & Restore",
"belangrijke DSM-update",
"kritieke oplossingen",
"wordt automatisch geïnstalleerd",
"is beschikbaar op",
] ]
_DSM_UPDATE_CANCELLED_HOST_RE = re.compile( _DSM_UPDATE_CANCELLED_HOST_RE = re.compile(
r"\b(?:geannuleerd\s+op|cancelled\s+on)\s+(?P<host>[A-Za-z0-9._-]+)\b", r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on|Packages\s+on|running\s+on|detected\s+on)\s+(?P<host>[A-Za-z0-9._-]+)\b",
re.I, re.I,
) )
@ -176,12 +189,14 @@ _ABB_SUBJECT_RE = re.compile(r"\bactive\s+backup\s+for\s+business\b", re.I)
# Examples (NL): # Examples (NL):
# "De back-uptaak vSphere-Task-1 op KANTOOR-NEW is voltooid." # "De back-uptaak vSphere-Task-1 op KANTOOR-NEW is voltooid."
# "Virtuele machine back-uptaak vSphere-Task-1 op KANTOOR-NEW is gedeeltelijk voltooid." # "Virtuele machine back-uptaak vSphere-Task-1 op KANTOOR-NEW is gedeeltelijk voltooid."
# "back-uptaak vSphere-Task-1 op KANTOOR-NEW is genegeerd"
# Examples (EN): # Examples (EN):
# "The backup task vSphere-Task-1 on KANTOOR-NEW has completed." # "The backup task vSphere-Task-1 on KANTOOR-NEW has completed."
# "Virtual machine backup task vSphere-Task-1 on KANTOOR-NEW partially completed." # "Virtual machine backup task vSphere-Task-1 on KANTOOR-NEW partially completed."
# "backup task vSphere-Task-1 on KANTOOR-NEW was skipped"
_ABB_COMPLETED_RE = re.compile( _ABB_COMPLETED_RE = re.compile(
r"\b(?:virtuele\s+machine\s+)?(?:de\s+)?back-?up\s*taak\s+(?P<job>.+?)\s+op\s+(?P<host>[A-Za-z0-9._-]+)\s+is\s+(?P<status>voltooid|gedeeltelijk\s+voltooid)\b" r"\b(?:virtuele\s+machine\s+)?(?:de\s+)?back-?up\s*(?:taak|job)\s+(?:van\s+deze\s+taak\s+)?(?P<job>.+?)\s+op\s+(?P<host>[A-Za-z0-9._-]+)\s+is\s+(?P<status>voltooid|gedeeltelijk\s+voltooid|genegeerd)\b"
r"|\b(?:virtual\s+machine\s+)?(?:the\s+)?back-?up\s+task\s+(?P<job_en>.+?)\s+on\s+(?P<host_en>[A-Za-z0-9._-]+)\s+(?:is\s+)?(?P<status_en>completed|finished|has\s+completed|partially\s+completed)\b", r"|\b(?:virtual\s+machine\s+)?(?:the\s+)?back-?up\s+(?:task|job)\s+(?P<job_en>.+?)\s+on\s+(?P<host_en>[A-Za-z0-9._-]+)\s+(?:is\s+|was\s+)?(?P<status_en>completed|finished|has\s+completed|partially\s+completed|skipped|ignored)\b",
re.I, re.I,
) )
@ -233,6 +248,11 @@ def _parse_active_backup_for_business(subject: str, text: str) -> Tuple[bool, Di
overall_status = "Warning" overall_status = "Warning"
overall_message = "Partially completed" overall_message = "Partially completed"
# "genegeerd" / "skipped" / "ignored" should be treated as Warning
if "genegeerd" in status_raw or "skipped" in status_raw or "ignored" in status_raw:
overall_status = "Warning"
overall_message = "Skipped"
# Explicit failure wording overrides everything # Explicit failure wording overrides everything
if _ABB_FAILED_RE.search(haystack): if _ABB_FAILED_RE.search(haystack):
overall_status = "Error" overall_status = "Error"

View File

@ -8,9 +8,13 @@ This file documents all changes made to this project via Claude Code.
- 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)
- Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning)
- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center", "new DSM update", "Auto Update has detected", "Update & Restore", "belangrijke DSM-update", "kritieke oplossingen", "wordt automatisch geïnstalleerd", "is beschikbaar op") and hostname extraction regex to recognize DSM update cancelled, out-of-date packages, new update available, and automatic installation announcements under same Updates job type while maintaining backward compatibility with existing patterns
- Extended Synology Active Backup for Business parser to recognize skipped/ignored backup tasks ("genegeerd", "skipped", "ignored") as Warning status when backup was skipped due to previous backup still running
### Changed ### Changed
- Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status")
- Replaced real customer names in parser registry examples with generic placeholders (NTFS Auditing, QNAP Firmware Update, NAKIVO) to prevent customer information in codebase
### Fixed ### Fixed
- Fixed Autotask ticket description being set to NULL when resolving tickets via `update_ticket_resolution_safe` by adding "description" to the optional_fields list, ensuring the original description is preserved during PUT operations - Fixed Autotask ticket description being set to NULL when resolving tickets via `update_ticket_resolution_safe` by adding "description" to the optional_fields list, ensuring the original description is preserved during PUT operations