El backup completo se crea eligiendo qué viaja: árbol de secciones y dominios (v1.74.0)
Valor para el usuario
Hasta ahora, crear un backup completo solo preguntaba por los vídeos de Signage (v1.72.0) — el resto de la organización viajaba entero, sin poder ver ni elegir qué había dentro. Desde v1.74.0, el diálogo “Full System Backup” abre un árbol con TODO lo que va a viajar, con conteos reales: las secciones del dashboard (Maps, Rows, Rooms y “No Map”, cada una desplegable para ver sus racks y cuántos equipos tiene) y los dominios completos (Monitoring, Wireless, UPS, DSM —con los vídeos como sub-opción bajo él—, Observatory/ITSM, Terminal, Cables y Catálogo). Todo viene marcado por defecto, así que el backup completo de siempre sigue siendo un solo click; desmarcar algo genera un backup parcial, que se descarga como ..._partial.zip y lo declara en su manifest para que nunca se confunda con una copia completa.
Diseñado con Edu en el grill de la mañana del 21-08. Es la primera de cuatro piezas de esta ventana del task #236 — faltan el modo “actualizar en vez de duplicar”, el modal de restauración con el mismo árbol, y un informe final claro.
Cómo usarla
- Admin → Backup & Restore → “Full System Backup” (botón de crear).
- El cliente llama a
GET /api/racks/backup/full/inventory(sustituye al antiguo/estimate) y pinta el árbol en el modalbackup-create-modal— secciones del dashboard con sus racks y dominios con conteos, incluido el peso de los vídeos de Signage bajo DSM. - El botón “All/None” (
toggleBackupTreeAll()) marca o desmarca todo de golpe; desmarcar DSM deshabilita y desmarca automáticamente el sub-selector de vídeos. - Al confirmar,
readBackupTreeSelection()arma{blueprint_ids, include_nomap, domains}— si todo sigue marcado, se envíaselection: null(backup completo clásico, byte-compatible). POST /api/racks/backup/full/startrecibeselection(además deinclude_signage_videos) y encolarun_full_backupcon ella.- La tarea Huey poda la maleta con
prune_backup_data()ANTES de serializar el ZIP; el manifest resultante llevapartial: true+ la selección, y el fichero se nombra con el sufijo_partial.
Implementación
racks/api/export/backup_selection.py(nuevo, 266 LOC):build_backup_inventory(org)arma el árbol — reutiliza la regla de sección del dashboard (“un rack pertenece al mapa de su primera colocación activa; sin colocación → No Map”, la misma que pintaracks.views.index) y calcula conteos por dominio (monitoring,wireless,ups,dsm,itsm,terminal,cables,catalog).normalize_selection(payload)valida/normaliza lo que envía el cliente (None/no-dict → sin selección = completo).prune_backup_data(org, data, selection)podadataen sitio: primero los racks por sección (reutilizandofilter_backup_selection()de [[feature—racks—restore-selectivo-v171]]), luego los planos no elegidos, luego las colecciones completas de los dominios desmarcados, y por último los huérfanos cruzados que deja la caída de fichas de página (cables y referencias de proyectos/players). Reglas decididas en el grill: un parcial solo lleva contenido VIVO (la papelera solo viaja en el completo); los grupos (RackGroup) y las fichas sin página asignada viajan siempre (son el pegamento).racks/api/export/backup.py:write_full_backup_zip()gana el parámetroselection— si no esNone, poda antes de serializar y marcamanifest["partial"] = True+manifest["selection"]. El endpointGET /backup/full/estimatese retira;GET /backup/full/inventorylo sustituye devolviendobuild_backup_inventory(org)completo (los vídeos de Signage ya viajan dentro dedomains.dsm).POST /backup/full/startacepta ahora{"include_signage_videos": bool, "selection": {...}}en el body.racks/tasks.py:run_full_backup(job_id, org_id, include_signage_videos=False, selection=None)propaga la selección awrite_full_backup_zipy añade el sufijo_partialal nombre del ZIP cuando hay selección.- Frontend (
static/js/alpine-components.js,templates/base.html,static/css/components.css):buildBackupTree()pinta el árbol a partir del inventario (checkbox por sección/dominio, desplegable con la lista de racks);readBackupTreeSelection()lo convierte en el payload de selección; el modal nuevobackup-create-modalsustituye al antiguobackup-options-modal(solo vídeos) de [[feature—backup-restore—signage-videos-opcionales-v1-72-0]]. Cache-busting manual aalpine-components.js?v=3entemplates/base.html(footgun conocido del proyecto: JS sin hash de build). - i18n: 28 strings EN nuevos con su capa ES vía
scripts/i18n/add_backup_tree_strings.py(patrón polib ya usado en features anteriores de esta task). - Tests:
tests/api/test_backup_selective.py(6 casos nuevos) + 1 adaptado entests/api/test_backup_scope.py. Área backup/restore verificada en Docker: 22 tests + mypy en verde.
Commits relacionados
1b3de40d(2026-08-21) — feat(backups): motor del backup selectivo por secciones y dominios + diálogo de creación con árbol completo (task #236, ventana) - v1.74.0 (#405).
Véase también
- [[feature—racks—restore-selectivo-v171]]
- [[feature—backup-restore—extended-domains-v1-70-0]]
- [[feature—backup-restore—signage-videos-opcionales-v1-72-0]]
- [[feature—backup-restore—manifest-verificacion-v1-69-0]]
- [[entity—racks—endpoint—backup-full-start]]
- [[entity—racks—service—run-full-backup]]
- [[entity—core—service—backup-service]]
- [[crearack-tech—admin—backup-restore]]