Files
Ricardo Monla 892019fa22 [A04.P005] DASUTEN: Pipeline refactorizado + Documentación + Informes
Refactorización del pipeline de backups DASUTEN:

1. Flujo simplificado (un solo destino):
   - Backup directo a X:\ (share srv-ns8)
   - Eliminado paso intermedio E:\BK_SQL\sysdasuten\
   - Reducido de 3 ubicaciones a 2 (X: → /var/tmp/)

2. Módulo común DasuExecutor (lib/dasu_executor.rb):
   - Centraliza ejecución PowerShell en dasu-sql4
   - Centraliza verificación de archivos en fenix
   - Elimina código repetido en 6 drones (-52% líneas)

3. Drones refactorizados:
   - dasuten_exportar_srvv-fenix.rb (FULL → X:)
   - dasuten_exportar_diferencial_srvv-fenix.rb (DIF → X:)
   - dasuten_transferir_srvv-fenix-srv-ns8.rb (simplificado)
   - dasuten_restaurar_dasu-sql4.rb (usa DasuExecutor)
   - dasuten_restaurar_diferencial_dasu-sql4.rb (usa DasuExecutor)
   - dasuten_download_drive-dasu-sql4.rb (usa DasuExecutor)
   - dasuten_verificar-integridad_dasu-sql4.rb (usa DasuExecutor)

4. Integración BKPs mantenida:
   - T8-T15: Tareas individuales
   - C7: dasuten_full (pipeline semanal)
   - C8: dasuten_diferencial (pipeline diario)

5. Documentación actualizada:
   - A04.P006_Backups-DASUTEN.md: flujo simplificado + módulo común
   - Lecciones aprendidas agregadas

6. Nuevos archivos:
   - Informes técnicos DASUTEN (docs/informes/2026-04_DASUTEN-migracion/)
   - A01.P011/P012: Documentación de drones y pipeline
   - proc_linux.rb, ops.rb: Utilitarios del ecosistema

7. Scripts legacy (para referencia):
   - orquestador_pipeline.rb, orquestador_pipeline_diferencial.rb
   - dasuten_upload_srv-ns8-drive.rb
2026-04-14 20:06:06 -03:00

173 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Genera PDF del informe ejecutivo desde Markdown usando Chrome headless."""
import markdown
import subprocess
import sys
import os
SRC = "01_informe_ejecutivo_DASUTEN.md"
OUT = "01_informe_ejecutivo_DASUTEN.pdf"
TMP = "/tmp/_informe_tmp.html"
# Leer markdown
with open(SRC, "r", encoding="utf-8") as f:
md_text = f.read()
# Convertir a HTML
html_body = markdown.markdown(md_text, extensions=["tables", "fenced_code"])
# Envolver con estilos profesionales
html = f"""<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
@page {{
size: A4;
margin: 25mm 20mm 25mm 20mm;
}}
body {{
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #1a1a2e;
max-width: 100%;
}}
h1 {{
font-size: 20pt;
font-weight: 700;
color: #0f3460;
margin-top: 0;
border-bottom: 3px solid #0f3460;
padding-bottom: 8px;
}}
h2 {{
font-size: 15pt;
font-weight: 600;
color: #16213e;
margin-top: 28px;
border-bottom: 1.5px solid #e0e0e0;
padding-bottom: 5px;
page-break-after: avoid;
}}
h3 {{
font-size: 12pt;
font-weight: 600;
color: #1a1a2e;
margin-top: 20px;
page-break-after: avoid;
}}
p, li {{
text-align: justify;
orphans: 3;
widows: 3;
}}
blockquote {{
border-left: 4px solid #0f3460;
margin: 0 0 16px 0;
padding: 12px 16px;
background: #f8f9fa;
font-size: 10pt;
color: #333;
}}
blockquote p {{
margin: 4px 0;
text-align: left;
}}
table {{
width: 100%;
border-collapse: collapse;
margin: 16px 0;
font-size: 10pt;
page-break-inside: avoid;
}}
th {{
background: #0f3460;
color: white;
font-weight: 600;
padding: 8px 12px;
text-align: left;
}}
td {{
padding: 7px 12px;
border-bottom: 1px solid #e0e0e0;
}}
tr:nth-child(even) {{
background: #f8f9fa;
}}
hr {{
border: none;
border-top: 1px solid #ccc;
margin: 24px 0;
}}
ul {{
padding-left: 20px;
}}
li {{
margin-bottom: 4px;
}}
em {{
color: #555;
}}
strong {{
color: #0f3460;
}}
code {{
background: #f0f0f0;
padding: 2px 5px;
border-radius: 3px;
font-size: 9.5pt;
}}
</style>
</head>
<body>
{html_body}
</body>
</html>"""
# Guardar HTML temporal
with open(TMP, "w", encoding="utf-8") as f:
f.write(html)
# Generar PDF con Chrome headless
result = subprocess.run([
"google-chrome",
"--headless",
"--disable-gpu",
"--no-sandbox",
"--disable-software-rasterizer",
f"--print-to-pdf={OUT}",
"--print-to-pdf-no-header",
TMP
], capture_output=True, text=True)
if os.path.exists(OUT):
size = os.path.getsize(OUT) / 1024
print(f"✅ PDF generado: {OUT} ({size:.0f} KB)")
else:
print(f"❌ Error al generar PDF")
print(result.stderr)
sys.exit(1)
# Limpiar
os.remove(TMP)