Files
takana/docs/runbooks/kde-qemu-desktop.md
T
Sergio 97ceb72411 takana etapa 5b: los 59 docs de diseño, runbooks y ADR
645 líneas. Los ADR entran porque en este repo SON documentos vivos, no
registros inmutables: el 0013 tiene 5 commits, el 0009 dos. Eso se comprobó
antes de decidir, no se asumió por convención general.

EXCLUIDOS por ser REGISTRO o generado: docs/evidencia/ (6), el HANDOFF de la
noche de KDE (1) y docs/state/ (24, se regenera solo). Reescribir un comando
dentro de una evidencia la falsifica.

Y el ADR 0016 se excluye de todo barrido, con un aviso adentro para el próximo
que barra: habla SOBRE el renombre, así que necesita seguir diciendo 'hammer'.
El barrido se lo llevó puesto y lo dejó titulado 'Renombre del sistema: takana
→ takana'; revertido.

Congelados, verificados uno por uno con controles: /opt/hammer, /var/lib/hammer,
/usr/bin/hammer, /mnt/vvv/hammer, la URL de gitea, hammer-farm.service,
hammer-live-install.sh, BRIEFING-hammer.md, hammerd, hammer-recover y
HAMMER_LIVE.
2026-09-09 19:25:51 +00:00

9.7 KiB
Raw Blame History

Runbook — relanzar el escritorio KDE Plasma 6 en QEMU

Plasma 6 renderizado 100% por software (QPainter + llvmpipe) sobre virtio-gpu, en la cadena soberana de takana (LLVM 18 + mesa desde fuente). Sin GPU real. Cerrado 2026-07-20 tras resolver 5 bugs estructurales + 2 de cursor (ver kde-metal-qemu-desktop en memoria y git log del frente kde/qemu:). Este runbook es sólo para relanzar y verificar, no para rediagnosticar.

Relanzar (caso normal — la imagen ya existe)

cd ~/hammer
# la ventana gtk necesita el X del laptop (Xwayland de mirada):
DISPLAY=:0 GDK_BACKEND=x11 TIMEOUT=1800 DISP=gtk bash scripts/kde/run-qemu-desktop.sh
  • Abre una ventana gtk con el virtio-gpu. Bootea UEFI → kernel → arje-zero → Plasma pinta solo (~30-45s).
  • TIMEOUT=1800 = auto-kill a los 30 min (omitir para dejarlo indefinido; matarlo a mano con el kill de abajo).
  • DISP=none = headless (sólo serial, para diagnóstico sin ventana ni interferir con mirada).
  • Toda la config que lo hace funcionar (los 7 fixes) vive en scripts/kde/plasma-start-qemu.sh, que se hornea en la imagen. No hace falta setear nada a mano.

Verificar sin mirar la ventana (oráculo screendump)

La ventana gtk se congela si mirada reinicia su Xwayland (QEMU sigue vivo por dentro). Para ver el scanout REAL del guest, independiente de la ventana:

cd ~/hammer
printf 'screendump %s/shot.ppm\n' "$PWD" | socat - unix-connect:work/qemu-monitor.sock
magick shot.ppm /tmp/shot.png        # y abrir /tmp/shot.png ; luego: rm shot.ppm

Salud por el serial (no necesita la ventana):

grep -a 'STATUS +' work/qemu-desktop-serial.log | tail -3   # kwin=1 plasmashell=1 = vivo
grep -ac 'código 139' work/qemu-desktop-serial.log          # crashes de kwin (÷3: cada línea sale x3)

Matar / cerrar

pkill -KILL -f 'qemu-sys[t]em-x86_64 -machine q35'          # el [t] evita auto-matar el propio comando

Reconstruir la imagen (si se tocó una receta KDE, mesa/llvm, o plasma-start)

cd ~/hammer
bash scripts/kde/qemu-desktop-image.sh      # funde base+kde-rootfs, inyecta llvmpipe/musl, hornea plasma-start
# necesita en store/: *-mesa-llvmpipe, *-llvm18, y los rootfs work/{metal-rootfs,kde-metal-rootfs}

Rebuild ~40s (host-side, hardlinks + artefactos ya sellados; no compila nada). Luego relanzar.

Los 7 fixes que lo hacen andar (por si algo regresa)

Todos en plasma-start-qemu.sh salvo -vga none (en run-qemu-desktop.sh):

Fix Sin él
GBM_ALWAYS_SOFTWARE=1 segfault al init (virtio sin 3D tratado como HW → vtable NULL)
KWIN_DRM_USE_MODIFIERS=0 negro total (virtio rechaza AddFB2WithModifiers con EINVAL)
KWIN_DRM_DEVICES=<card virtio> doble output (efifb+virtio) rompe buffers (redundante con -vga none)
KWIN_COMPOSE=Q (QPainter) kwin segfaltea en el rasterizador llvmpipe (lp_rast_clear_color)
-vga none pantalla clavada en TianoCore (VGA-std por defecto + simpledrm roban el scanout)
XCURSOR_THEME=breeze_cursors + kcminputrc Failed to load cursor theme "default" (cursor invisible)
KWIN_FORCE_SW_CURSOR=1 cursor aparece/desaparece (plano HW de virtio no se presenta)

Gotchas de operación

  • Lectura STALE del serial: no se trunca hasta que el run-script arranca QEMU (tras el rebuild ~40s). Un until grep 'escritorio arriba' matchea el run ANTERIOR. Esperá un marcador único del run nuevo: rm -f work/qemu-monitor.sock antes de lanzar y until [ -S work/qemu-monitor.sock ]; do sleep 2; done.
  • pkill -f qemu... se auto-mata (el patrón matchea el propio comando) → usar siempre qemu-sys[t]em.
  • "Se queda en TianoCore" tras varios relanzamientos: el work/qemu-desktop-OVMF_VARS.fd persistente acumula boot entries stale → rm -f work/qemu-desktop-OVMF_VARS.fd (el run-script lo recrea limpio).
  • Serial triplicado: cada línea sale ×3 (say tee a console+ttyS0). "139: 3" = 1 crash real.
  • El escritorio queda sólo con wallpaper+panel; sin discos/energía reales (no hay udisksd/upowerd en el rootfs) ni efectos GL pesados (llvmpipe no los soporta). Es esperado, no un fallo.

Prerrequisitos

  • work/hammer-kde-qemu.img (la imagen; si falta, reconstruir arriba).
  • OVMF: /usr/share/edk2/x64/OVMF_CODE.4m.fd + OVMF_VARS.4m.fd.
  • Herramientas host: qemu-system-x86_64, socat, magick (ImageMagick) para el screendump.
  • Para la ventana gtk: sesión gráfica del laptop viva (DISPLAY=:0). Headless (DISP=none) no la necesita.

Relacionado: memoria kde-metal-qemu-desktop, frente-escritorio-kde, arranque-grafo-mirada.

2026-09-03 — verificar el escritorio SIN humano delante (gioser, TCG, sin socat)

Este runbook asumía el laptop: DISP=gtk para ver la ventana y socat para el monitor. En gioser no hay ninguna de las dos cosas —es un vServer sin /dev/kvm y sin socat— y aun así se puede verificar todo, incluido hacer clic. Las tres piezas:

# 1. la imagen y el rootfs viven en el VOLUMEN (/mnt/vvv está al 98%), y el STAGE también:
#    sin STAGE= el install-image-efi hardlinkea de /mnt/cosecha a work/ y muere con EXDEV.
E=/mnt/cosecha/escritorios
BASE=$E/base-rootfs KDE=$E/kde-rootfs MERGED=$E/kde-qemu-rootfs \
IMG=$E/hammer-kde-qemu.img STAGE=$E/.stage-kde bash scripts/kde/qemu-desktop-image.sh

# 2. arrancar headless (cae solo a TCG: gioser no tiene KVM; Plasma pinta en ~2 min)
IMG=$E/hammer-kde-qemu.img SERIAL=work/kde-qemu-serial.log MON=work/kde-monitor.sock \
  VARS=work/kde-OVMF_VARS.fd TIMEOUT=1200 DISP=none bash scripts/kde/run-qemu-desktop.sh &
  1. el monitor de QEMU por socket unix desde python, que reemplaza a socat:
import socket, time
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); s.connect('work/kde-monitor.sock')
time.sleep(.5); s.recv(65536)
def cmd(c, p=.6):
    s.sendall((c+'\n').encode()); time.sleep(p)
    try: s.recv(200000)
    except: pass
cmd('screendump /mnt/cosecha/escritorios/shot.ppm', 4)   # el scanout REAL del guest

Hacer CLIC sin ventana — y por qué el ratón es relativo

info mice dice QEMU PS/2 Mouse: movimiento RELATIVO, así que no hay «ir a (x,y)». La maniobra que sí funciona es fijar contra una esquina y moverse desde ahí:

cmd('mouse_move -3000 3000', 2)   # clava el puntero en la esquina INFERIOR IZQUIERDA
cmd('mouse_move 10 -8', 1)        # y desde la esquina, al lanzador del panel
cmd('mouse_button 1', .5); cmd('mouse_button 0', 8)

sendkey también anda (sendkey alt-f2, sendkey k, …) y la combinación arranca krunner —se ve en el log de kwin— pero la ventana de krunner no llegó a pintar en dos intentos. Queda anotado como pendiente propio, separado del bug de abajo.

Lo que estas dos herramientas destaparon el 2026-09-03

  1. El panel salía con el reloj y nada más, y no era el panel: eran los ICONOS. Los .so de todos los applets estaban instalados; lo que faltaba era breeze-icons. Ver el commit «escritorios: KDE y GNOME corrían SIN tema de iconos». Evidencia: ../evidencia/plasma6-qemu-2026-09-03-panel-con-iconos.png — kickoff, gestor de tareas, bandeja (notificaciones, volumen, teclado, red), reloj y «mostrar escritorio», todos pintando.

  2. El lanzador de aplicaciones NO ABRE, y el diálogo de error lo dice entero:

    qrc:/qt/qml/plasma/applet/org/kde/plasma/kickoff/main.qml:191:25: Type FullRepresentation unavailable
    .../Header.qml:18:1: module "org.kde.coreaddons" is not installed
    

    recipes/incoming-kde/kcoreaddons.toml pasa -DKCOREADDONS_USE_QML=OFF (la cabecera lo dice: «QML bindings / python / docs apagados»), así que el módulo QML org.kde.coreaddons no se construye. Evidencia: ../evidencia/plasma6-qemu-2026-09-03-kickoff-sin-coreaddons.png. yupana radio kcoreaddons = 71, o sea que prenderlo es una campaña de granja, no un ticket.

Regla que sale de las dos: una captura donde el escritorio «pinta» NO prueba que el escritorio funcione. El barrido barato que sí lo prueba es cruzar los import de los .qml instalados contra los módulos QML con qmldir que hay en el rootfs; así salió org.kde.coreaddons y, de yapa, org.kde.kscreenlocker y org.kde.newstuff.core, que también faltan.

El arreglo, verificado con UN build (2026-09-03)

-DKCOREADDONS_USE_QML=ON + un solo takana build kcoreaddons (56 s) instala usr/lib/qt6/qml/org/kde/coreaddons/{libkcoreaddonsplugin.so,qmldir,…}. Hidratado ESE artefacto en el rootfs y rehecha la imagen, el menú abre: usuario, buscador, Favoritos / Todas las aplicaciones, y las pestañas Aplicaciones / Lugares / Sesión (../evidencia/plasma6-qemu-2026-09-03-menu-abre.png). Escribiendo konsole en el buscador y Enter, la terminal arranca y corre — uname -a da el kernel 6.16.12 de takana y konsole --version da 25.04.3 (../evidencia/plasma6-qemu-2026-09-03-konsole-uname.png).

Es la cadena completa del escritorio por primera vez: panel → menú → búsqueda → app → shell.

Se probó con UN build a propósito: la cascada de 71 es de granja y no hacía falta pagarla para saber si el arreglo era el correcto. Las 71 quedan como deuda declaradaescritorio-kde 192/263— y la imagen de hoy corre con un kcoreaddons más nuevo que aquel contra el que enlazaron sus consumidores. Eso es legítimo porque lo que cruza es un SONAME (misma versión, misma ABI, sólo se suma un módulo QML); es la misma regla que decidió la promoción de pipewire. Lo que NO se puede es hidratar dos artefactos distintos en la misma ruta.

⚠ El aviso rojo Could not find '', starting '/bin/sh' instead de konsole era real y NO venía de /etc/passwd (que dice /bin/sh): konsole lee $SHELL, y este getty no es un login shell. Arreglado exportándolo en plasma-start-qemu.sh.