Volver a la wiki

Import Visio v2 — arquitectura del motor y la UI

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

FormatoRutaDónde corre
.vsdx, .vsd, .vsslibvisio-ng → SVG por página (+ paso EMF→PNG, abajo)Worker Huey (racks/tasks.py::convert_visio_async)
.vssx, .vdxVisioParser (iconos embebidos o placeholder SVG)Síncrono en el request de analyze
.svgDirecto (1 fichero = 1 stencil), sanitizado antes del previewSíncrono

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):

  1. svg_is_emf_only() detecta SVGs con data:image/emf y sin primitivas de dibujo.
  2. 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:UserInstallation para evitar lock clashes) — EMF→SVG vectorial → rsvg-convert a 2400 px; fallback por lote EMF→PNG directo.
  3. Postproceso Pillow vectorizado (_postprocess_stencil_png): blanco→transparente (ImageChops), autocrop por canal alpha, ancho mínimo 800 px. Nunca getdata() por píxel (OOM del QA PR 3).
  4. 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)

  1. POST /api/racks/visio/analyze (gate racks:admin, límite 50 MB) guarda el upload en MEDIA_ROOT/temp/{uuid}/, escribe visio_session.json con status=processing y encola convert_visio_async.
  2. El task convierte, aplica el paso EMF→PNG, sanitiza cada SVG y deja status=done con los masters (o status=error). Sin modelo de BD: el estado vive en el JSON del temp de la sesión.
  3. El frontend (static/js/editor/import_export.js, vanilla) hace polling de GET /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.
  4. POST /api/racks/visio/confirm (mismo gate) mueve las imágenes a uploads/stencils/, crea los Stencil y devuelve category por item (el frontend agrupa por carpeta sin recargar).

Seguridad (fixes s220)

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

Subir