Qué es
El sistema de importación de stencils desde ficheros Visio del Rack editor, reconstruido en jul-2026 (PR #314 motor v1.52.0, #315 UI v1.53.0, QA+modernización .vss v1.54.0, fix EMF v1.54.1). Convierte ficheros de fabricante (Cisco, Eaton, Dell…) en stencils de la librería del tenant.
Rutas por formato
| Formato | Ruta | Dónde corre |
|---|---|---|
.vsdx, .vsd, .vss | libvisio-ng → SVG por página (+ paso EMF→PNG, abajo) | Worker Huey (racks/tasks.py::convert_visio_async) |
.vssx, .vdx | VisioParser (iconos embebidos o placeholder SVG) | Síncrono en el request de analyze |
.svg | Directo (1 fichero = 1 stencil), sanitizado antes del preview | Síncrono |
- Los
.vssmigran a libvisio-ng en el QA de PR 3: la cadena legacyvss2xhtml→EMF→LibreOffice→PNG dejaba los shapes de fabricante casi vacíos (solo taladros y logo con Eaton-Racks) y además hacía OOM con shapes altos (getdata()por píxel sobre PNGs de 2400 px). Toda esa cadena se retiró (convert_vss_masters, flujovss_indexdiferido en confirm). - Los metadatos de un
.vss(nombre real del master,u_height= pulgadas/1.75,half_width< 1.5 in) siguen saliendo devss2raw(binariolibvisio-tools, ~1 s) víaVisioParser.extract_vss_metadata(), y el task los casa con los SVG por número de página del nombre de fichero (orden natural, no lexicográfico — con ≥10 páginassorted()descolocaba nombres, bug cazado en PR 3).
Masters solo-EMF → PNG (v1.54.1, el caso Cisco)
Cisco (y otros fabricantes) no dibujan sus masters con geometría Visio: incrustan el arte como EMF, y libvisio-ng lo envuelve tal cual en <image href="data:image/emf"> — que ningún navegador renderiza (cazado en PROD con Catalyst 9000: 165/165 masters solo-EMF → miniaturas y stencils rotos). El worker aplica ahora un post-paso (racks/utils/visio_parser.py::convert_emf_only_svgs):
svg_is_emf_only()detecta SVGs condata:image/emfy sin primitivas de dibujo.- Los EMF se extraen y se convierten todos en UNA invocación de LibreOffice (el arranque de LO es el coste; perfil propio vía
-env:UserInstallationpara evitar lock clashes) — EMF→SVG vectorial →rsvg-converta 2400 px; fallback por lote EMF→PNG directo. - Postproceso Pillow vectorizado (
_postprocess_stencil_png): blanco→transparente (ImageChops), autocrop por canal alpha, ancho mínimo 800 px. Nuncagetdata()por píxel (OOM del QA PR 3). - El SVG solo-EMF se sustituye por el PNG (mismo base de nombre → el número de página sigue alineando metadatos); si la conversión falla, el master se descarta con warning (mejor ausente que roto).
Los SVG con geometría real (Eaton) no se tocan y conservan calidad vectorial.
Flujo async (sesiones)
POST /api/racks/visio/analyze(gateracks:admin, límite 50 MB) guarda el upload enMEDIA_ROOT/temp/{uuid}/, escribevisio_session.jsonconstatus=processingy encolaconvert_visio_async.- El task convierte, aplica el paso EMF→PNG, sanitiza cada SVG y deja
status=donecon los masters (ostatus=error). Sin modelo de BD: el estado vive en el JSON del temp de la sesión. - El frontend (
static/js/editor/import_export.js, vanilla) hace polling deGET /api/racks/visio/session/{id}cada 2,5 s (tope 4 min; aborta si se cierra el modal) y pinta el grid: miniatura + nombre editable inline + categoría por shape. POST /api/racks/visio/confirm(mismo gate) mueve las imágenes auploads/stencils/, crea losStencily devuelvecategorypor item (el frontend agrupa por carpeta sin recargar).
Seguridad (fixes s220)
- Sanitizador SVG (
racks/utils/svg_sanitizer.py, allowlist con defusedxml) en 3 puntos: SVG subido directo, SVGs de la conversión, y gate final en confirm. confirmexigeracks:admin· anti path-traversal enimage_path(realpath + prefijoMEDIA_ROOT) · límite de subida 50 MB.
Perfil de memoria
libvisio_ng.convert pica ~515 MB de RSS con un .vss de fabricante de 40 MB (Catalyst 9000). En PROD el worker no fija límite; el compose de dev subió el web a 1024M en v1.54.1 (con 512M el kernel mataba el proceso — y ese techo ya mordía a mypy, AUDIT s215).
QA con ficheros reales (PR 3 + v1.54.1)
tests/qa/test_visio_real_vendor_files.py — NO corre en CI (skip si no existe media/temp/qa-visio-src/); fuentes de los ficheros en su docstring. Resultados 13-07-2026: Cisco UCS .vssx 47 MB ✅ · Dell .vssx ✅ · Eaton Racks/UPS .vss ✅ nombres reales y calidad vectorial · .vsdx reales (MikroTik) ✅ · Catalyst 9000 .vss (40 MB, 165 masters EMF) ✅ → PNG nítidos (guardia: skip si el container tiene <900 MB) · el .vss de Cisco UCS (87 MB) rebota limpio en el límite. Dependencias runtime: libvisio-ng (pip, GPL-3 — solo worker), libvisio-tools (apt, metadatos), libreoffice-draw + rsvg-convert (apt, conversión EMF).
Límites conocidos
- Granularidad
.vsdx/.vsd= página, no shape individual. Troceo fino = posible v2. u_heightestimado del tamaño del dibujo — el usuario lo revisa en el grid (editable).get_page_infode libvisio-ng devuelve 0 páginas para.vss— por eso los nombres salen de vss2raw.- Stencils importados rotos ANTES de v1.54.1 no se auto-reparan: borrar y re-importar.