
🌐 También en: English · Deutsch · Français
En el homelab tengo un HPE ProLiant DL20 Gen10 Plus que ejecuta Debian 13 sin hacer ruido. Debian, es decir: no RedHat, no un derivado de RedHat, nada con lo que el Service Pack for ProLiant (SPP) de HPE quiera hablar cuando se trata de la vía de actualización instalable y nativa del sistema operativo. El instalador de paquetes nativo del SPP se basa en RPM, y punto. Debian recibe un educado encogimiento de hombros. 🤷
Normalmente eso no importaría demasiado –el firmware no caduca de la noche a la mañana–, pero quería comprobar si la máquina necesitaba algo de cariño. Spoiler: sí, un poco. iLO 5 iba una versión por detrás (3.20 frente a la 3.21 publicada), y quería la foto completa en lugar de perseguir a mano un PDF de changelog para cada componente: System ROM, SPS, el firmware de la tarjeta de red y lo que sea que viva en ese inventario de firmware de 14 elementos. Quería la experiencia de «arrancar una herramienta, dejar que lo escanee todo y que me diga qué está desactualizado». Esa herramienta existe. Se llama SUM (Smart Update Manager), viene dentro de la ISO del SPP y –esto es lo crucial– la variante de ISO arrancable no se preocupa de lo que tengas instalado en los discos. Arranca su propio entorno. En teoría, totalmente independiente del sistema operativo. Problema de Debian resuelto, ¿no? 😌
Querido lector: no fue tan sencillo. Nunca lo es.
💾 Primer acto: la HP USB Key Utility repite su mayor fracaso
Quien me lea desde hace tiempo quizá recuerde un artículo anterior en el que ya libré exactamente esta batalla con la herramienta oficial de HPE para pasar ISO a USB. Entonces ya era vieja. Ahora es más vieja. Y sigue sin funcionar de forma fiable: la misma historia, otro día; fallos silenciosos y un pendrive cuya existencia el menú de arranque del servidor se niega educadamente a reconocer. HPE no parece estar dedicándole mucho cariño a esta herramienta, y se nota. 🪦
🔌 Segundo acto: Rufus en modo DD, y parada en seco
Plan B: Rufus, concretamente en modo DD, el modo que escribe la imagen como una copia de bloques en bruto, bit a bit, en lugar de la reinterpretación habitual de ISO a FAT32 que hace Rufus. Justo lo que quiere una ISO híbrida arrancable. Lo conecté, arranqué desde él… y simplemente se detuvo, a mitad de arranque, aparentemente por algún lugar cerca de GRUB. Ni un limpio «dispositivo no arrancable» ni un mensaje de error útil: simplemente colgado. Sinceramente, no tengo ni idea de por qué, y en algún momento, en un homelab, el «no sé por qué» tiene que convertirse en «siguiente». ➡️
📡 Tercer acto: iLO no necesita ningún pendrive
iLO Advanced tiene Virtual Media: apuntas la unidad de CD/DVD virtual de iLO a una ISO y el servidor arranca desde ella como si fuera una unidad óptica real, transmitida por la red. Y, sinceramente, cuando caí en la cuenta, lo vi clarísimo: objetivamente es la mejor manera de hacerlo, dramas de herramientas aparte. El servidor vive en el sótano, en un rack, haciendo sus cosas de rack en un sótano. El método del pendrive implica: bajar, abrir el rack, encontrar el puerto correcto, enchufar el pendrive, volver a subir, hacer la actualización y bajar otra vez a recoger el pendrive cuando termine. Dos viajes al sótano para una sola actualización de firmware, solo para que un objeto físico toque brevemente un puerto físico. Transmitiendo la ISO por la red, puedo hacerlo todo desde mi escritorio, en una silla cómoda, con un café ☕, sin que el hardware llegue a enterarse de que tengo un pendrive. Merecía la pena pelearse con unas cuantas capas de disparates de software.
Salvo que –y aquí es donde la interfaz de Virtual Media de iLO revela discretamente su opinión al respecto– no acepta subir un archivo desde el navegador. Quiere una URL. Vale, tengo máquinas Linux por ahí, seguro que puedo servir un (1) archivo ISO por HTTP. 🙃
🐔🥚 Cuarto acto: el huevo, la gallina y la VM que vivía en la máquina equivocada
Mi parte favorita, porque caí de lleno y solo me di cuenta del error en pleno facepalm.
Primer impulso: servir la ISO desde una VM Linux que ya tenía funcionando. Dos minutos, listo, medio virtual montado y yo muy satisfecho conmigo mismo. Luego llegó el momento de reiniciar de verdad el DL20 para que arrancara desde esa imagen montada.
Lo cual –seguro que lo ves venir desde la órbita 🛰️– también reinició la VM que estaba sirviendo la ISO, porque esa VM vive en ese mismo servidor físico. Una dependencia circular perfecta: el servidor necesita la ISO para arrancar, y la ISO la sirve algo que necesita que el servidor esté encendido. En cuanto empezó el reinicio, mi servidor de archivos desapareció en pleno vuelo, e iLO se quedó sosteniendo un CD-ROM virtual conectado a absolutamente nada. Inventario de firmware después: sin cambios, hasta el último dígito, porque no se había leído nada más allá del saludo inicial del montaje.
Lección reaprendida por las malas: cuando reinicias un host físico, todo lo que ese host aloja cae con él. Todo un descubrimiento, lo sé. 🤦
🖥️ Quinto acto: servir la ISO desde algo que de verdad se quede encendido
Solución: servir la ISO desde el cliente Windows, una máquina a la que el estado de alimentación del DL20 le da exactamente igual. El servidor web integrado de Python parecía la solución obvia de dos segundos:
python -m http.server 8000Apunté iLO hacia él, lo monté, reinicié en el menú de arranque único, seleccioné el CD/DVD virtual… y seguía sin arrancar limpiamente. Progreso, pero no éxito. Hora de pensar de verdad en lo que estaba pasando en lugar de lanzarle herramientas.
🕵️ Interludio: por qué un CD-ROM virtual no es una descarga
La verdadera chicha técnica de toda esta saga: montar una ISO por la red no es lo mismo que descargar un archivo.
Una unidad óptica real no se absorbe entera en memoria de antemano. El gestor de arranque lee sectores concretos bajo demanda, saltando por la estructura del disco tal y como dicta el formato del sistema de archivos ISO9660: unos pocos bytes del catálogo de arranque por aquí, un fragmento de archivo en algún punto intermedio por allá. Virtual Media emula exactamente ese comportamiento por HTTP: iLO lanza peticiones del tipo «dame los bytes del 5.368.709.120 al 5.368.711.168, por favor», un trocito minúsculo, en un desplazamiento arbitrario, de un archivo de 9,8 GB.
El mecanismo HTTP pensado justo para esto es la petición Range (Range: bytes=X-Y), que se responde con 206 Partial Content y la cabecera Content-Range correspondiente, con solo el trozo solicitado.
El clásico http.server de Python no hace esto. En absoluto. Lo probé directamente: envié una petición Range para un trozo de 1 KB y recibí 200 OK y el archivo completo de 9,8 GB, con la cabecera Range totalmente ignorada. Con un archivo pequeño, técnicamente incorrecto, pero nadie se da cuenta. Con una ISO del SPP de 9,8 GB a la que se le pide cada minúscula lectura de sector, es la diferencia entre instantáneo y prácticamente infinito ♾️, lo que, desde el punto de vista de iLO, se parece exactamente a una unidad virtual rota o vacía.
La solución es un diminuto sustituto directo:
python -m pip install rangehttpserver
python -m RangeHTTPServer --bind 0.0.0.0 8000(Fíjate en el python -m pip en lugar de un pip a secas: en una instalación nueva de Python en Windows, pip.exe no siempre está en el PATH, aunque python.exe sí lo esté. Llamar a pip como módulo a través del intérprete evita el problema por completo.)
🔥 Giro argumental: el cortafuegos contraataca
Cambié de servidor, volví a probar la petición Range y… nada, esta vez un rotundo tiempo de espera de conexión agotado en lugar de una respuesta incorrecta. No un «no hay nadie en casa» (eso parecería una conexión rechazada), sino «los paquetes se desvanecen en el vacío»: la firma clásica de un cortafuegos que descarta el tráfico en silencio en lugar de rechazarlo abiertamente.
Resultó que el Firewall de Windows Defender había bloqueado discretamente el nuevo servidor: la ejecución anterior de http.server ya había recibido en algún momento un clic en «Permitir», pero lanzarlo como python -m RangeHTTPServer contaba, al parecer, como un contexto de programa lo bastante distinto como para necesitar su propio aviso de permiso, uno que se me había pasado. Una excepción del cortafuegos después 🔓, por fin desaparecieron los dos problemas a la vez:
HTTP/1.0 206 Partial Content
Content-Range: bytes 1000-2000/9844506624
Accept-Ranges: bytesAccesible y con soporte de Range. Justo lo que una unidad óptica virtual quiere ver. ✅
📋 Lo que había realmente, versión a versión
Para quien tenga curiosidad por saber cómo es el inventario de firmware de un DL20 Gen10 Plus: 14 componentes, obtenidos directamente de la API Redfish de iLO en lugar de ir haciendo clic página a página por la interfaz gráfica:
- iLO 5 – v3.20 (una versión por detrás; ya ha salido la 3.21)
- System ROM (activa) – U60 v2.64
- System ROM (ranura redundante/de respaldo) – U60 v2.50, rezagada a propósito, para eso está la ranura de respaldo
- Intelligent Provisioning, SPS, TPM, la tarjeta de red integrada BCM5720, el controlador de vídeo y el firmware de ambos discos
Toda la gracia de arrancar la ISO del SPP en lugar de perseguir a mano cada archivo .fwpkg uno por uno: SUM lo analiza todo de una pasada y me dice exactamente qué está desactualizado. Sin necesidad de RedHat, sin necesidad de pendrive, sin necesidad de un segundo viaje al sótano. 🎉
🎓 La moraleja de la historia
Tres herramientas fallaron o fallaron a medias antes de que una funcionara de verdad, y esa solo funcionó cuando dejé de tratar «servir un archivo por HTTP» como un problema resuelto y recordé que el medio virtual no descarga, sino que lee sectores, igual que una unidad física. Súmale un aviso del cortafuegos que se me pasó en un parpadeo, y ya tienes una buena tarde dedicada a algo que debería haber sido una tarea de cinco minutos. Las actualizaciones de firmware en el homelab: nunca tan sencillas como «hacer clic en actualizar», siempre una oportunidad de reaprender algo que técnicamente ya sabías. 😅
Próximamente: lo que sea que SUM encuentre de verdad cuando arranque como es debido. No te lo pierdas.
📸 Abajo tienes unas cuantas capturas de pantalla del viaje: Rufus fallando en silencio, el inventario de firmware de Redfish y las cabeceras de la petición Range por fin con buena pinta.










