Introducción
Todo lo que hay en Escritorio funciona.
También son once clics, y los vas a hacer cada día.
isard es un comando que hace lo mismo desde el terminal:
$ isard create dev --template ubuntu
$ isard start dev --wait
$ isard ssh dev
Tres líneas, y la tercera te deja en una shell de una máquina que no existía cuando empezaste a escribir.
Es un programa en Python que habla con la misma API con la que habla la web de la Generalitat.
No hay una segunda plataforma ni ningún acceso privilegiado: todo lo que puede hacer isard lo podrías hacer con clics, y todo lo que no puede hacer lo sigues teniendo que hacer con clics.
Entorno de trabajo
isard está publicado en PyPI, así que instálalo como herramienta global con Tool:
$ uv tool install isard
Resolved 24 packages in 412ms
Installed 24 packages in 63ms
Installed 1 executable: isard
Comprueba que está:
$ isard version
isard 0.3.0
Necesita Python 3.11 o más reciente.
No tienes que ir a buscarlo: si el del sistema es más antiguo, uv descarga un Python adecuado para la herramienta, y ese es buena parte del motivo para instalarla así.
Para actualizarla más adelante:
$ uv tool upgrade isard
Iniciar sesión
Todos los comandos necesitan tu cuenta de la Generalitat, la misma que escribiste en el navegador en la página anterior.
Ejecuta uno y mira:
$ isard list
Gencat username (@edu.gencat.cat is added for you): 12345678a
Password:
Funciona, y el miércoles ya estarás harto.
Pon las credenciales en el entorno:
$ export GENCAT_USERNAME="12345678a"
$ export GENCAT_PASSWORD="la-teva-contrasenya"
El sufijo @edu.gencat.cat se añade solo, así que el nombre de usuario es la forma corta: tu DNI, letra incluida.
Las variables de entorno mueren con el terminal, así que lo que de verdad quieres es un fichero .env en el directorio donde trabajas:
GENCAT_USERNAME=12345678a
GENCAT_PASSWORD=la-teva-contrasenya
isard lo lee del directorio actual cada vez que se ejecuta.
Dónde vive la sesión
Iniciar sesión como es debido es lento: es un baile SAML a través del proveedor de identidad de la Generalitat, con varias redirecciones, y tarda un par de segundos.
Hacerlo en cada comando sería insoportable, así que isard lo hace una vez y guarda el resultado en caché:
~/.config/isard/session.json |
la sesión de Gencat |
~/.config/isard/isardvdi.json |
el token de IsardVDI |
Los dos se escriben con chmod 600: los puedes leer tú y nadie más.
En Windows están en %APPDATA%\isard\.
La sesión se comprueba a sí misma antes de cada llamada y se renueva cuando ha caducado, así que nunca tienes que pensar en esto.
isard login fuerza un inicio de sesión nuevo y muestra lo que ha obtenido:
$ isard login
Authenticating with Gencat...
Gencat session cached at /Users/david/.config/isard/session.json
Authenticating with IsardVDI...
IsardVDI session cached at /Users/david/.config/isard/isardvdi.json
-- Gencat Session --
Username : 12345678a@edu.gencat.cat
Display name : David de Mingo
Email : david@optersoft.com
Organization : Institut
Session ID : 8f2a1c4e-...
Expires at : 2026-08-14 19:42:11 UTC
Expires in : 07:58:22
Gencat valid : Yes
IsardVDI valid : Yes
Y isard logout tira las dos:
$ isard logout
Logged out successfully
Ese es el comando que debes usar en una máquina compartida, y el que debes probar cuando algo se comporta como si fueras otra persona.
Qué tengo
isard list es la vista de Escritorios, en texto:
$ isard list
NAME STATE IP OS
box-1 Started 10.2.76.37 Ubuntu 24.04
box-2 Stopped - Ubuntu 24.04
dev Started 192.168.122.214 Fedora 44
Cuatro columnas, ordenadas por nombre.
Un - en la columna IP significa que la máquina está detenida, o que está en marcha y no ha informado de ninguna dirección: el caso de la página anterior.
Añade --hardware y irá a preguntar de qué está hecha cada una:
$ isard list --hardware
NAME STATE IP OS CPU MEMORY
box-1 Started 10.2.76.37 Ubuntu 24.04 2 vCPU 4096 MB
box-2 Stopped - Ubuntu 24.04 2 vCPU 4096 MB
dev Started 192.168.122.214 Fedora 44 4 vCPU 8192 MB
Son dos columnas más y una llamada a la API por plantilla, así que es un poco más lento.
También es el comando que responde a por qué me he quedado sin cuota.
Qué plantillas hay
Antes de crear nada tienes que saber a partir de qué crearlo:
$ isard template
-- Available Templates --
NAME DESCRIPTION OS
fedora-server-44 Fedora Server, netinst Fedora
ubuntu-24-04-desktop Ubuntu 24.04 Desktop Ubuntu
ubuntu-24-04-server Ubuntu 24.04 Server Ubuntu
windows-11-t3 Windows 11 Windows
La lista de tu centro es más larga y casi todo no es lo que buscas, así que fíltrala:
$ isard template --filter ubuntu
-- Available Templates (filtered by 'ubuntu') --
NAME DESCRIPTION OS
ubuntu-24-04-desktop Ubuntu 24.04 Desktop Ubuntu
ubuntu-24-04-server Ubuntu 24.04 Server Ubuntu
--filter es una simple búsqueda de subcadena en el nombre, sin distinguir mayúsculas y minúsculas.
--hardware también funciona aquí, y vale la pena echarle un vistazo: te dice lo grande que es la máquina que crea cada plantilla antes de que crees ninguna.
$ isard template --filter ubuntu --hardware
-- Available Templates (filtered by 'ubuntu') --
NAME DESCRIPTION OS CPU MEMORY DISK
ubuntu-24-04-desktop Ubuntu 24.04 Desktop Ubuntu 2 vCPU 4096 MB 40 GB
ubuntu-24-04-server Ubuntu 24.04 Server Ubuntu 2 vCPU 4096 MB 40 GB
Las plantillas que tu centro ha desactivado no aparecen.
Si falta una que te dijeron que estaría, ese es el motivo, y es una incidencia para Àtom, no un error de la herramienta.
Crear un escritorio
$ isard create dev --template ubuntu-24-04-server
Matched template: 'ubuntu-24-04-server'
✓ Desktop 'dev' created successfully!
Dos vCPU, 4 GB de RAM, y las interfaces Default y Wireguard: la misma forma que los valores por defecto del formulario, salvo que la de Wireguard siempre está.
Esto último es deliberado, y es el motivo por el que la herramienta es agradable de usar: la interfaz que te olvidas de marcar es la interfaz que necesitas cuarenta minutos después, y añadirla luego cuesta un reinicio.
Si no pones --template, te da la lista para que elijas:
$ isard create dev
Select a template:
1. fedora-server-44 [Fedora]
2. ubuntu-24-04-desktop [Ubuntu]
3. ubuntu-24-04-server [Ubuntu]
4. windows-11-t3 [Windows]
Select (1-4): 3
Eso va bien a mano y no sirve de nada en un script, así que --filter filtra esa lista igual que filtra template.
No hace falta que escribas bien el nombre
Vuelve a mirar esto:
$ isard create dev --template ubuntu-24-04-server
Nadie escribe eso dos veces.
Por eso isard no te lo exige. Prueba:
$ isard create dev --template ubuntu
Hay dos plantillas con ubuntu en el nombre, así que pregunta:
$ isard create dev --template ubuntu
Select a template:
1. ubuntu-24-04-desktop [Ubuntu]
2. ubuntu-24-04-server [Ubuntu]
Select (1-2): 2
Ahora prueba un nombre que no sea ambiguo:
$ isard create dev --template fedora
Matched template: 'fedora-server-44'
✓ Desktop 'dev' created successfully!
Un solo candidato, así que dice cuál ha elegido y sigue.
Y ahora escríbelo mal a propósito:
$ isard start bx-1
Matched: 'box-1'
La regla de debajo tiene tres pasos, en orden:
- una coincidencia exacta, sin distinguir mayúsculas y minúsculas: se toma en silencio, porque es lo que querías decir;
- si no la hay, todos los nombres que son lo bastante parecidos (Jaro-Winkler ≥ 0.5) o que contienen lo que has escrito;
- esa lista, ordenada por cercanía.
Si queda uno, se usa, con una línea Matched: para que veas qué ha pasado. Si quedan dos o más, se abre el selector. Si no queda ninguno, es un error que lista todos los escritorios que tienes, y normalmente basta para que veas la errata tú mismo.
Un trozo corto es un nombre válido. isard start box encuentra box-1 si es el único.
Arrancar y detener
$ isard start dev
✓ Desktop 'dev' starting
El comando vuelve inmediatamente, porque arrancar una máquina tarda un rato y no hay motivo para secuestrarte el terminal.
Que es justo lo contrario de lo que quieres cuando lo siguiente que haces es conectarte:
$ isard start dev
$ isard ssh dev
Error: connection refused
La máquina todavía no estaba en marcha.
--wait lo arregla: el comando no vuelve hasta que el escritorio está en marcha:
$ isard start dev --wait
⠹ Waiting for 'dev' to start...
✓ Desktop 'dev' is running
--wait es lo que hace que la herramienta se pueda usar en scripts. Sin él, cada línea después de start es una carrera.
La paciencia por defecto es de 120 segundos. Una máquina grande, o una tarde ajetreada, pide más:
$ isard start dev --wait --timeout 300
Detener tiene la misma forma:
$ isard stop dev --wait
⠹ Waiting for 'dev' to stop...
✓ Desktop 'dev' is stopped
EjercicioEspérala
Arranca box-1 dos veces: una sin --wait y otra con él.
Cronometra las dos.
Mostrar la solución
$ time isard start box-1
✓ Desktop 'box-1' starting
real 0m1.9s
$ isard stop box-1 --wait
$ time isard start box-1 --wait
✓ Desktop 'box-1' is running
real 0m24.3s
La primera no es más rápida. Simplemente ha dejado de medir.
Reservar
Algunos escritorios no se pueden arrancar cuando quieras: el caso habitual es uno con GPU.
$ isard start gpu-box
Error: this desktop needs a booking before it can start.
No es un fallo, es una cola. --book reserva la franja y luego arranca:
$ isard start gpu-box --book --wait
✓ Booked 60 minutes
✓ Desktop 'gpu-box' is running
--book-minutes cambia la hora. Eso es GPU.
Borrar
$ isard delete dev
Delete desktop 'dev'? [y/N]:
La respuesta por defecto es no, que es la correcta para cualquier cosa que lleve un delete.
Responde y y el escritorio va a la papelera, de donde todavía se puede recuperar.
Dos opciones cambian eso, y van juntas:
$ isard delete dev --permanent --yes
✓ Desktop 'dev' deleted permanently
--permanent se salta la papelera. --yes se salta la pregunta.
Las dos son buenas en un script y malas a mano. Un script que se para a preguntar es un script que se cuelga; una persona a la que no se pregunta es una persona que borra el trabajo de la semana pasada.
Abrirlo
isard view abre la pantalla del escritorio:
$ isard view dev
Matched: 'dev'
✓ Desktop is running
Launching remote-viewer...
Hace por ti todo el baile del .vv de la página anterior (descarga el fichero SPICE, decodifica el certificado, abre remote-viewer) y, si el escritorio estaba detenido, primero lo arranca y espera.
Si remote-viewer no está instalado, lo instala:
| Windows | descarga y desempaqueta el MSI, sin necesidad de administrador |
| macOS | Homebrew, desde el tap jeffreywildman/homebrew-virt-manager |
| Fedora | dnf install virt-viewer |
| Ubuntu, Debian | apt install virt-viewer |
--no-install lo desactiva, que es lo que quieres si prefieres hacerlo tú.
Llegar a él
isard ssh te deja en una shell en la máquina:
$ isard ssh dev
isard@dev:~$
Detrás de esa sola línea pasan muchas cosas (una clave que hay que registrar, un bastión en el puerto 443, un escritorio que se arranca si estaba detenido) y es todo el contenido de Bastión.
Lo que importa aquí es la otra forma.
Con un comando después de --, isard ssh no es interactivo:
$ isard ssh dev -- uname -a
Linux dev 6.8.0-51-generic #52-Ubuntu SMP x86_64 GNU/Linux
Esa es la línea que hace que toda la herramienta valga la pena.
La salida del comando es la salida del comando, su código de salida es su código de salida, y todo lo que escribe isard va a stderr, así que una tubería nunca tiene que filtrar líneas del indicador de actividad de tus datos:
$ isard ssh dev -- 'cat /etc/os-release' | grep VERSION_ID
VERSION_ID="24.04"
Puedes pasar un directorio entero a través de él:
$ tar czf - src | isard ssh dev -- 'tar xzf - -C /home/isard'
Toda una clase en un bucle
Junta las piezas y el sentido de un comando frente a un formulario se vuelve evidente:
$ for n in 1 2 3; do
> isard create box-$n --template ubuntu-24-04-server
> isard start box-$n --wait
> done
✓ Desktop 'box-1' created successfully!
✓ Desktop 'box-1' is running
✓ Desktop 'box-2' created successfully!
✓ Desktop 'box-2' is running
✓ Desktop 'box-3' created successfully!
✓ Desktop 'box-3' is running
Tres máquinas, una línea, ningún clic.
Desmontarlas es el mismo bucle al revés:
$ for n in 1 2 3; do isard delete box-$n --yes; done
Y ejecutar el mismo comando en todas es otro más:
$ for n in 1 2 3; do
> echo "== box-$n"
> isard ssh box-$n -- 'uptime'
> done
== box-1
11:42:03 up 2 min, 0 users, load average: 0.08, 0.03, 0.01
== box-2
11:42:09 up 2 min, 0 users, load average: 0.11, 0.04, 0.01
== box-3
11:42:14 up 1 min, 0 users, load average: 0.15, 0.05, 0.01
La lista completa de comandos
--help la muestra, y vale la pena leerla una vez:
$ isard --help
Usage: isard [OPTIONS] COMMAND [ARGS]...
Manage IsardVDI virtual desktops on the Gencat educational platform.
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ login Log in to Gencat (SAML) and IsardVDI, then show the session │
│ summary. │
│ logout Clear cached authentication sessions and per-desktop SSH │
│ confirmations. │
│ version Show the version of the isard CLI tool. │
│ list List IsardVDI desktops for the authenticated user. │
│ build Build a template from a YAML profile: install, configure, promote. │
│ create Create a new desktop from an existing template. │
│ start Start a stopped desktop. │
│ stop Stop a running desktop. │
│ hardware Show a desktop's vCPU and memory, or change them on a stopped │
│ desktop. │
│ delete Delete a desktop — move it to the recycle bin, or erase it │
│ permanently. │
│ view Open a desktop in remote-viewer over SPICE. │
│ ssh Open an SSH session to a desktop via the IsardVDI bastion. │
│ template List available templates, or create one from media. │
│ media List, add, or delete media (the ISO library). │
│ seed Build a local cloud-init / kickstart seed ISO. │
│ vpn Join the desktop network over IsardVDI's WireGuard VPN. │
╰──────────────────────────────────────────────────────────────────────────────╯
Cada subcomando también acepta --help, y esa es la respuesta a qué opciones tenía start.
hardware es nuevo: lee la vCPU y la memoria de un escritorio y, en uno detenido, puede cambiar el tamaño de las dos.
Cuatro de estos tienen una página propia:
vpn→ Redssh→ Bastióntemplate,build,media,seed→ Plantillas
También es una biblioteca
isard es un paquete de Python, y todo lo que hace el comando se puede importar:
from isard import get_desktops, login_to_isardvdi
session = login_to_isardvdi("12345678a@edu.gencat.cat", "la-teva-contrasenya")
for desktop in get_desktops(session):
print(desktop.name, desktop.state)
box-1 Started
box-2 Stopped
dev Started
No lo necesitarás a menudo: un bucle de shell cubre casi todo lo que quiere un script.
Vale la pena saber que existe para el día que quieras revisar treinta máquinas e informar de cuáles siguen en marcha, porque eso es un programa, no un bucle.
Ejercicios
EjercicioDe la nada a una shell
Partiendo de cero escritorios, consigue una shell en una máquina Fedora llamada lab usando solo el terminal.
Mostrar la solución
$ isard template --filter fedora
-- Available Templates (filtered by 'fedora') --
NAME DESCRIPTION OS
fedora-server-44 Fedora Server, netinst Fedora
$ isard create lab --template fedora
Matched template: 'fedora-server-44'
✓ Desktop 'lab' created successfully!
$ isard start lab --wait
✓ Desktop 'lab' is running
$ isard ssh lab
[isard@lab ~]$
Cuatro comandos, y --template fedora bastó para el tercero.
EjercicioQué máquinas tengo en marcha
Escribe un comando que muestre solo los nombres de tus escritorios arrancados.
Mostrar la solución
$ isard list | awk '$2 == "Started" { print $1 }'
box-1
dev
isard list es una tabla simple en stdout, así que pasa por awk, grep y wc como cualquier otro texto.
Ese es el segundo motivo para preferir un comando a un formulario, después del bucle.
EjercicioAmbigüedad deliberada
Tienes box-1, box-2 y box-3.
¿Qué pasa con isard stop box? ¿Y con isard stop box-2?
Mostrar la solución
El primero abre un selector, porque coinciden tres escritorios:
$ isard stop box
Select a desktop:
1. box-1 (Started)
2. box-2 (Started)
3. box-3 (Started)
Select (1-3):
El segundo es una coincidencia exacta, así que se toma en silencio, sin ninguna línea Matched:.
Exacta significa exacta: la búsqueda aproximada no se ejecuta nunca.
EjercicioApágalo todo, en una línea
Detén todos los escritorios que tienes sin nombrar ninguno.
Mostrar la solución
$ isard list | awk 'NR > 1 && $2 == "Started" { print $1 }' | while read n; do
> isard stop "$n" --wait
> done
✓ Desktop 'box-1' is stopped
✓ Desktop 'dev' is stopped
NR > 1 descarta la fila de cabecera.
Lee el bucle antes de ejecutarlo. Está a tres comandos de ser uno que los borra, y --yes no preguntaría.
EjercicioEl fichero de sesión
Encuentra los dos ficheros donde isard guarda tu sesión y comprueba sus permisos.
Luego cierra la sesión y vuelve a comprobarlo.
Mostrar la solución
$ ls -l ~/.config/isard/
total 24
-rw------- 1 david staff 1204 14 Aug 11:31 isardvdi.json
-rw------- 1 david staff 2841 14 Aug 11:31 session.json
$ isard logout
Logged out successfully
$ ls -l ~/.config/isard/
total 0
-rw------- es 600: tú, y nadie más en la máquina.
Esos ficheros son un token firmado, es decir, son tu sesión: cualquiera que pueda leer uno es tú, hasta que caduque.
Proyecto
Prepara un directorio de trabajo al que puedas volver durante el resto del curso.
- Crea un directorio,
isard/, con un.envque contenga tus credenciales y un.gitignoreque contenga.env. - Escribe un script de shell
up.shque cree y arranque tres máquinas Ubuntu Server, debox-1abox-3, esperando a cada una. - Escribe
down.sh, que las detenga y borre las tres sin preguntar. - Haz los dos ejecutables y ejecútalos.
Mostrar la solución
# up.sh
#!/bin/sh
set -e
for n in 1 2 3; do
isard create "box-$n" --template ubuntu-24-04-server
isard start "box-$n" --wait --timeout 300
done
isard list
# down.sh
#!/bin/sh
for n in 1 2 3; do
isard delete "box-$n" --yes
done
$ chmod +x up.sh down.sh
$ ./up.sh
✓ Desktop 'box-1' created successfully!
✓ Desktop 'box-1' is running
...
Dos cosas en las que fijarse.
set -e está en up.sh y no en down.sh: si falla la creación de la segunda máquina quieres parar, pero si falla el borrado de la segunda sigues queriendo que la tercera desaparezca.
Y el nombre de la plantilla está escrito entero. --template ubuntu habría abierto un selector, y un script no tiene a nadie que lo responda.