@@ -486,14 +486,14 @@ def _handle_reboot_and_verification(self, host: Host, vm_mapping: Optional[VMMap
486486 return None # Success - no error report needed
487487
488488 def _cleanup_old_snapshots (self , vm_mapping : VMMapping ):
489- """Clean up old automated snapshots."""
489+ """Clean up old automated snapshots based on retention policy or count limit ."""
490490 try :
491- retention_days = self .update_config .get ('snapshot_retention_days' , 7 )
492491 prefix = self .update_config .get ('snapshot_name_prefix' , 'pre-update' )
493492
494493 snapshots = self .proxmox_client .list_snapshots (vm_mapping .node , vm_mapping .vmid )
495- cutoff_time = datetime .now () - timedelta (days = retention_days )
496494
495+ # Filter to only automated snapshots with valid timestamps
496+ automated_snapshots = []
497497 for snapshot in snapshots :
498498 snap_name = snapshot .get ('name' , '' )
499499 if not snap_name .startswith (prefix ):
@@ -503,14 +503,45 @@ def _cleanup_old_snapshots(self, vm_mapping: VMMapping):
503503 try :
504504 timestamp_str = snap_name [len (prefix ) + 1 :] # Remove prefix and dash
505505 snap_time = datetime .strptime (timestamp_str , '%Y%m%d-%H%M%S' )
506-
507- if snap_time < cutoff_time :
508- logger .info (f"Deleting old snapshot { snap_name } for VM { vm_mapping .vmid } " )
509- self .proxmox_client .delete_snapshot (vm_mapping .node , vm_mapping .vmid , snap_name )
510-
506+ automated_snapshots .append ({
507+ 'name' : snap_name ,
508+ 'time' : snap_time
509+ })
511510 except (ValueError , IndexError ) as e :
512511 logger .debug (f"Could not parse snapshot timestamp for { snap_name } : { e } " )
513512 continue
513+
514+ # Sort by timestamp, newest first
515+ automated_snapshots .sort (key = lambda x : x ['time' ], reverse = True )
516+
517+ snapshots_to_delete = []
518+
519+ # Check per-host max_snapshots limit first (takes precedence)
520+ if vm_mapping .max_snapshots is not None :
521+ # Keep only the newest max_snapshots, delete the rest
522+ if len (automated_snapshots ) > vm_mapping .max_snapshots :
523+ snapshots_to_delete = automated_snapshots [vm_mapping .max_snapshots :]
524+ logger .info (f"Per-host snapshot quota: keeping { vm_mapping .max_snapshots } newest snapshots "
525+ f"for VM { vm_mapping .vmid } , deleting { len (snapshots_to_delete )} older ones" )
526+ else :
527+ # Fall back to time-based retention policy
528+ retention_days = self .update_config .get ('snapshot_retention_days' , 7 )
529+ cutoff_time = datetime .now () - timedelta (days = retention_days )
530+
531+ snapshots_to_delete = [
532+ snap for snap in automated_snapshots
533+ if snap ['time' ] < cutoff_time
534+ ]
535+
536+ if snapshots_to_delete :
537+ logger .info (f"Time-based retention: deleting { len (snapshots_to_delete )} snapshots "
538+ f"older than { retention_days } days for VM { vm_mapping .vmid } " )
539+
540+ # Delete the snapshots
541+ for snap in snapshots_to_delete :
542+ snap_name = snap ['name' ]
543+ logger .info (f"Deleting old snapshot { snap_name } for VM { vm_mapping .vmid } " )
544+ self .proxmox_client .delete_snapshot (vm_mapping .node , vm_mapping .vmid , snap_name )
514545
515546 except Exception as e :
516547 logger .warning (f"Failed to cleanup old snapshots for VM { vm_mapping .vmid } : { e } " )
0 commit comments