Files
dtic-DIIAA/automatizacion/mantenimiento_backups.rb

101 lines
2.6 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# [PROC-01] - Mantenimiento de Backups Proxmox (Ruby Edition)
# Lógica: Granular por VMID, Retención 6 días, Destino zfsDISCO1
require 'date'
require 'fileutils'
STORAGE_NAME = "zfsDISCO1"
# NOTA: En Proxmox, la ruta suele ser /mnt/pve/zfsDISCO1 o similar.
# Ajustamos a la ruta montada del storage.
BASE_PATH = "/mnt/pve/#{STORAGE_NAME}/dump"
RETENTION_DAYS = 6
VM_PATTERN = /^srv[v]?-/
def log(message, type = "INFO")
timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S")
puts "[#{timestamp}] [#{type}] #{message}"
end
def get_vmid_list
# Obtener IDs de VMs (QEMU) y Contenedores (LXC)
ids = []
# QEMU VMs
`qm list`.each_line.with_index do |line, idx|
next if idx == 0 # Cabecera
parts = line.split
vmid = parts[0]
name = parts[1]
ids << vmid if name =~ VM_PATTERN
end
# LXC Containers
`pct list`.each_line.with_index do |line, idx|
next if idx == 0
parts = line.split
vmid = parts[0]
name = parts[2] # El nombre suele ser la 3er columna en pct list
ids << vmid if name =~ VM_PATTERN
end
ids.uniq
end
def prune_old_backups(vmid)
log("Iniciando fase de limpieza para VMID: #{vmid}...")
return unless Dir.exist?(BASE_PATH)
# Patrón de archivos de Proxmox: vzdump-[qemu|lxc]-<VMID>-<TIMESTAMP>.*
# Buscamos archivos de este VMID específico
files = Dir.glob("#{BASE_PATH}/vzdump-*-#{vmid}-*")
files.each do |file|
mtime = File.mtime(file)
age_days = (Date.today - mtime.to_date).to_i
if age_days > RETENTION_DAYS
log("Eliminando backup antiguo: #{File.basename(file)} (Antigüedad: #{age_days} días)", "WARN")
begin
FileUtils.rm(file)
rescue => e
log("Error al eliminar #{file}: #{e.message}", "ERROR")
end
end
end
end
def run_backup(vmid)
log("Iniciando backup para VMID: #{vmid} hacia #{STORAGE_NAME}...")
# Usamos --mode stop para asegurar reinicio automático y consistencia
cmd = "vzdump #{vmid} --storage #{STORAGE_NAME} --mode stop --compress zstd"
log("Ejecutando: #{cmd}")
success = system(cmd)
if success
log("Backup completado exitosamente para VMID: #{vmid}", "SUCCESS")
else
log("FALLO en el backup para VMID: #{vmid}", "ERROR")
end
end
# --- EJECUCIÓN PRINCIPAL ---
log("=== INICIO DE CICLO DE MANTENIMIENTO DE BACKUPS ===")
unless Dir.exist?(BASE_PATH)
log("Error: No se encuentra la ruta del storage #{BASE_PATH}. ¿Está montado?", "ERROR")
exit 1
end
vmids = get_vmid_list
log("Nodos detectados para procesar: #{vmids.join(', ')}")
vmids.each do |vmid|
prune_old_backups(vmid)
run_backup(vmid)
puts "-" * 40
end
log("=== FIN DE CICLO DE MANTENIMIENTO ===")