[Docs] Armonización integral de bitácoras y protocolo ADN
This commit is contained in:
Executable
+100
@@ -0,0 +1,100 @@
|
||||
#!/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 ===")
|
||||
Reference in New Issue
Block a user