"Después del juego es antes del juego"
Sepp Herberger

domingo, 10 de septiembre de 2017

Activar un usuario windows deshabilitado usando chntpw

Por imperativo legal he tenido que instalar un Windows 7 en una máquina algo antigua. Durante la instalación te pide un nombre de usuario que convertirá en el administrador de la máquina y será con el que por defecto se trabajará. El usuario por defecto es administrador, que te voy a contar...

Bueno, pues despues de hacer esto lo primero es despojar a ese usuario de trabajo de sus permisos de administrador, sacándole del grupo de "Administradores". Tras eso, en dicho grupo solo permanece el usuario "Administrador" que es creado de forma silenciosa durante la instalación. También hay que cambiar la contraseña al usuario "Administrador" por la que queramos que tenga.

Tras esto reiniciamos, vamos a la pantalla de login y vemos ambos usuarios. Pero si intentas acceder con el usuario Administrador te dice que "está deshabilitado". Agarrate: el Windows 7 te permite quedar el sistema sin un administrador válido sin avisarte de ello. ¿Ahora cómo habilito el usuario?.

Bueno, pues la solución está en arrancar con un CD/USB Live de Linux que tenga la herramienta chntpw, ya sea el CD propio o alguno que lo contenga (tipo SystemRescueCD o Ubuntu). Una vez arrancado, montamos la particion de Windows en /mnt (o equivalente) con:
# mount /dev/sda2 /mnt
Normalmente el sistema Windows a partir de su versión 7 está en la partición sda2 o sda3, siendo la sda1 una pequeña partición reservada para hacer el mal a través de UEFI o similar.

Una vez montada, hacemos una copia de seguridad del fichero de configuración de usarios (por si metemos la pata poder restaurar):
# cd /mnt/WINDOWS/System32/config
# cp SAM SAM.backup
Avisamos que alguno de los nombres anteriores podría estar en mayúscula/minúscula, en función del Windows usado.

Una vez hecha la copia de seguridad miramos el fichero con chntpw:
# chntpw /mnt/WINDOWS/System32/config/SAM
chntpw version 0.99.6 110511 , (c) Petter N Hagen

Hive  name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c 
File size 65536 [10000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 298/27544 blocks/bytes, unused: 42/9160 blocks/bytes.


* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0
| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrador                  | ADMIN  | dis/lock |
| 01f7 | DefaultAccount                 |        | dis/lock |
| 01f5 | Invitado                       |        | dis/lock |
| 03ea | Usuario                        |        | *BLANK*  |
...
...
Como se ve, el usario Administrador está bloqueado. Para cambiar esa situación (o para borrar la contraseña si no la conocemos o la hemos olvidado), usamos el parámetro "-i" (pongo en negrita la parte interactiva):
# chntpw +i /mnt/WINDOWS/System32/config/SAM
chntpw version 0.99.6 110511 , (c) Petter N Hagen
Hive  name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c 
File size 65536 [10000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 298/27544 blocks/bytes, unused: 42/9160 blocks/bytes.

* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0

<>========<> chntpw Main Interactive Menu <>========<>

Loaded hives: 

  1 - Edit user data and passwords
      - - -
  9 - Registry editor, now with full write support!
  q - Quit (you will be asked if there is something to save)

What to do? [1] -> 1

===== chntpw Edit User Info & Passwords ====

| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrador                  | ADMIN  | dis/lock |
| 01f7 | DefaultAccount                 |        | dis/lock |
| 01f5 | Invitado                       |        | dis/lock |
| 03ea | Usuario                        |        | *BLANK*  |

Select: ! - quit, . - list users, 0x - User with RID (hex)
or simply enter the username to change: [Administrador] ---pulso Enter---

RID     : 0500 [01f4]
Username: Administrador
fullname: 
comment : Cuenta integrada para la administracion del equipo o dominio
homedir : 

User is member of 1 groups:
00000220 = Administradores (which has 2 members)

Account bits: 0x0211 =
[X] Disabled        | [ ] Homedir req.    | [ ] Passwd not req. | 
[ ] Temp. duplicate | [X] Normal account  | [ ] NMS account     | 
[ ] Domain trust ac | [ ] Wks trust act.  | [ ] Srv trust act   | 
[X] Pwd don't expir | [ ] Auto lockout    | [ ] (unknown 0x08)  | 
[ ] (unknown 0x10)  | [ ] (unknown 0x20)  | [ ] (unknown 0x40)  | 

Failed login count: 0, while max tries is: 0
Total  login count: 1

- - - - User Edit Menu:
 1 - Clear (blank) user password
 2 - Edit (set new) user password (careful with this on XP or Vista)
 3 - Promote user (make user an administrator)
 4 - Unlock and enable user account [probably locked now]
 q - Quit editing user, back to user select
Select: [q] > 4
Unlocked!

Select: ! - quit, . - list users, 0x - User with RID (hex)
or simply enter the username to change: [Administrador] !

<>========<> chntpw Main Interactive Menu <>========<>

Loaded hives: 

  1 - Edit user data and passwords
      - - -
  9 - Registry editor, now with full write support!
  q - Quit (you will be asked if there is something to save)


What to do? [1] -> q

Hives that have changed:
 #  Name
 0  
Write hive files? (y/n) [n] : y
 0   - OK
Y ya podemos ver que está desbloqueado:
# chntpw /mnt/WINDOWS/System32/config/SAM
chntpw version 0.99.6 110511 , (c) Petter N Hagen

Hive  name (from header): <\SystemRoot\System32\Config\SAM>
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c 
File size 65536 [10000] bytes, containing 5 pages (+ 1 headerpage)
Used for data: 298/27544 blocks/bytes, unused: 42/9160 blocks/bytes.


* SAM policy limits:
Failed logins before lockout is: 0
Minimum password length        : 0
Password history count         : 0
| RID -|---------- Username ------------| Admin? |- Lock? --|
| 01f4 | Administrador                  | ADMIN  |          |
| 01f7 | DefaultAccount                 |        | dis/lock |
| 01f5 | Invitado                       |        | dis/lock |
| 03ea | Usuario                        |        | *BLANK*  |
...
...
Si nos hemos fijado en un momento dado nos ha ofrecido la siguiente gama de acciones para realizar sobre el usuario:
 1 - Clear (blank) user password
 2 - Edit (set new) user password (careful with this on XP or Vista)
 3 - Promote user (make user an administrator)
 4 - Unlock and enable user account [probably locked now]
 q - Quit editing user, back to user select
Lo cual nos da una idea de la potencia del comando. Incluye incluso una opción de edición de registro que parece bastante peligrosa y de la que ya habĺe en su día para otra cosa.

Bueno, pues con el entuerto arreglado...¡feliz fin del verano!.

sábado, 12 de agosto de 2017

Listado jerárquico de dispositivos USB

Una cortita: ya vimos en su día cómo listar desde un punto de vista jerárquico los dispositivos PCI de nuestro sistema. Ahora necesitaba hacer lo mismo con los dispositivos USB: conocer el entramado de buses y además saber que ancho de banda tiene cada cúal (es decir, si es USB 1, 2 o 3) y el driver del dispositivo que hubiere conectado.

En esta ocasión el comando es:
# lsusb -t
Veamos ejemplos, empezando por mi PC de sobremesa:
# lsusb -t
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
    |__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 12M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
    |__ Port 2: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/8p, 480M
    |__ Port 5: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 480M
Ahi vemos los diferentes buses y puertos, como están conectados y la velocidad del puerto: 480M para USB2 (driver ehci), 12M para USB1 (driver uhci)y la de 1.5M corresponde a un ratón.

El lsusb a palo seco para este PC es:
# lsusb
Bus 001 Device 003: ID 058f:6362 Alcor Micro Corp. Flash Card Reader/Writer
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 004: ID 1058:10a8 Western Digital Technologies, Inc. Elements Portable (WDBUZG)
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 002: ID 046d:c050 Logitech, Inc. RX 250 Optical Mouse
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Otro ejemplo, con la Rasperry Pi B:
# lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
        |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M
        |__ Port 2: Dev 4, If 0, Class=Vendor Specific Class, Driver=ov519, 12M
        |__ Port 2: Dev 4, If 1, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 2: Dev 4, If 2, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 5, If 0, Class=Mass Storage, Driver=usb-storage, 480M
Se puede ver ahí una webcam que tengo conectada (ov519) así como las tarjetas ethernet (smsc95xx) y audio, que en la Raspberry son dispositivos USB.
xt
Un último ejemplo, con un portátil-tablet:
# lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/11p, 480M
    |__ Port 2: Dev 2, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 2: Dev 2, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 3: Dev 10, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 3: Dev 10, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
    |__ Port 4: Dev 3, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 4: Dev 3, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 5: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
    |__ Port 5: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 6: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 7: Dev 6, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 8: Dev 7, If 0, Class=Vendor Specific Class, Driver=rtsx_usb, 480M
    |__ Port 9: Dev 8, If 0, Class=Human Interface Device, Driver=usbhid, 12M
Aparte de lo anterior, aquí vemos un puerto USB3, con velocidad 5000M y driver xhci.

La mayor utilidad que le saco a este comando es saber que velocidad tiene cada puerto USB de un sistema y como están organizados los distintos hubs usb internos, ya que a veces pinchas un disco duro externo o pendrive en el puerto incorrecto y los trasvases de datos se eternizan. De esta manera podemos identificarlos e incluso etiquetarlos para evitar contratiempos.

Seguimos adelante con el verano, que queda mucho todavía :-).

viernes, 4 de agosto de 2017

Sistema de gestión de turnos y colas.

Hay momentos en que en el centro se forman colas bastante largas, especialmente en época de matriculaciones con la gente de pie durante un largo tiempo. Nos pareció buena idea implementar un sistema de colas con número que tienen en otros sitios, de tal forma que los conserjes irán dando números en orden de llegada, una pantalla visible dirá por que número se va atendiendo y el personal de secretaría podrá incrementar dicho número cuando se quiera pasar al siguiente. La gente podrá estar sentada o salir a dar una vuelta sin tener que estar pendientes de guardar cola.

Empezar desde cero era costoso, pero casi siempre hay alguien que ha abierto camino antes y que nos da todo casi hecho. En este caso es este magnífico blog sobre OpenWrt y otros proyectos interesantes: http://openwrt.tuinstituto.es/sistema-de-gestion-de-colas-de-espera-simple-con-openwrt-y-mqtt.

La infraestructura que necesitamos es:

  • Una pantalla de ordenador en un sitio visible, donde se mostrará el número actual. Dicha pantalla estará conectada a un PC (vale un PC antiguo, una Raspberry PI o una Android Box) capaz de abrir un navegador web, mostrando algo similar a:


  • Un ratón adicional conectado por USB a uno de los PC que ya hay en secretaría. Ese ratón permitirá manipular el número de la cola (botón derecho incrementará el número y botón izquierdo lo decrementará). En el blog de Tuinstituto usan un dispositivo con OpenWRT al que enchufan el ratón para esto, pero yo me lo ahorro y usamos un PC que ya está funcionando al que le ponemos un segundo ratón.
  • Un PC intermedio donde estará la cola que comunica ambos dispostivos y almacena físicamente el número de orden. Este PC no es estrictamente necesario y puede ser tanto el PC de la pantalla como el que maneja la cola, pero en mi caso lo he puesto aparte en uno de los servidores del centro por hacer más completo el sistema y mantener total disponibilidad.

Lo que hace más estimulante para mí esta tarea es el uso de dos prometedoras herramientas que desconocía:

  • mqtt: un protocolo ligerísimo pensado para el uso en IoT (Internet de las Cosas) que permite mandar mensajes mediante colas entre dos puntos de Internet/red local.
  • triggerhappy: un demonio ligerito que permite disparar eventos ante pulsaciones en teclados, ratones y otros dispositivos de entrada.

Parte 1: Implementación de la cola mqtt.

Necesitamos un ordenador donde implementar el servidor mqtt (llamado broker mqtt). Podemos usar servidores públicos que hay en Internet, como los de esta lista para hacer las pruebas, pero es mas correcto implantarlo en un equipo de nuestra confianza.

En Debian el protocolo mqtt se implementa con el paquete mosquitto. La versión que viene de serie con Jessie es un poco anticuada y no soporta que el cliente sea una página web y se comunique por Websockets. Es mas adecuado usar la última versión directamente de su repositorio:
# cat /etc/apt/sources.list.d/mosquitto-jessie.list
deb http://repo.mosquitto.org/debian jessie main
# apt-get update
E instalamos los paquetes:
# apt-get install libmosquitto1 mosquitto mosquitto-clients
# dpkg -l | grep mosqui
ii  libmosquitto1:amd64                   1.4.12-0mosquitto1                   amd64        MQTT version 3.1/3.1.1 client library
ii  mosquitto                             1.4.12-0mosquitto1                   amd64        MQTT version 3.1/3.1.1 compatible message broker
ii  mosquitto-clients                     1.4.12-0mosquitto1                   amd64        Mosquitto command line MQTT clients
Nótese como es la versión 1.4, no la 1.3.4 que viene con Jessie. Ahora ponemos está configuración de puertos y reiniciamos el servidor:
# cat /etc/mosquitto/mosquitto.conf

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

listener 1883
protocol mqtt

listener 8000
protocol websockets 

#port 8000

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d
Ponemos a andar el sistema:
# /etc/init.d/mosquitto restart
Vamos a probarlo: nos suscribimos a una cola llamada "numero" indicando la IP del PC donde hemos instalado el Broker mqtt:
# mosquitto_sub -v -h 172.19.X.Y -t "numero"
El sistema queda esperando a que aparezca algo en la cola. Ahora, desde otro terminal u otro PC hacemos:
# mosquitto_pub -h 172.19.X.Y -t "numero" -m "A-02"
El código "A-02" se enviará a la cola "numero" del broker y todos los que estén suscritos recibirán dicho código de forma inmediata. Podremos verlo si nos vamos al terminal donde ejecutamos mosquitto_sub.

Parte 2: Visor de la cola.

Ahora debemos configurar un visor de la cola que se suscriba a ella, lea su contenido y lo muestre en una página web. Básicamente es un html con código javacript conecta con el broker mediante WebSockets (por eso instalamos la versión 1.4 de mosquitto) y muestra el último valor de la cola:
# cat /var/www/turnos/Suturno.html 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
  <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Su Turno</title>
<style type="text/css">
html, body {
margin: 0px;
height: 100%;
background-color: #000099;
}
@font-face{ 
 font-family: 'Antonio';
 src: url('Antonio-Regular.ttf') format('truetype');
}
#Pagina {
font-family: 'Antonio', Arial, sans-serif;
margin: 0px;
height: 100%;
}
#cabecera {
font-style: normal;
font-weight: bold;
background-color: #000099;
font-size:7vw;
width: 100%;
color: white;
text-align: center;
background-image: url(img/logo_guadalupe.png);
background-position: left center;
background-repeat: no-repeat;
}
#cuerpo {
color: yellow;
text-align: center;
background-color: black;
font-size:22vw;
font-weight: bold;
width: 100%;
height: 60%;
}
#pie {
font-size:7vw;
background-color: #000099;
font-weight: bold;
width: 100%;
height: 20%;
color: white;
font-style: normal;
text-align: center;
}

</style>
    <script src="mqttws31.js" type="text/javascript"></script>
    <script src="jquery.min.js" type="text/javascript"></script>
    <script src="config.js" type="text/javascript"></script>

    <script type="text/javascript">

    var mqtt;
    var reconnectTimeout = 2000;
    function MQTTconnect() {
 if (typeof path == "undefined") {
  path = '/mqtt';
 }
 mqtt = new Paho.MQTT.Client(
   host,
   port,
   path,
   "web_" + parseInt(Math.random() * 100, 10)
 );
        var options = {
            timeout: 3,
            useSSL: useTLS,
            cleanSession: cleansession,
            onSuccess: onConnect,
//            mqttVersion: 3, 
            onFailure: function (message) {
                $('#status').val("Connection failed: " + message.errorMessage + "Retrying");
                setTimeout(MQTTconnect, reconnectTimeout);
            }
        };

        mqtt.onConnectionLost = onConnectionLost;
        mqtt.onMessageArrived = onMessageArrived;

        if (username != null) {
            options.userName = username;
            options.password = password;
        }
        console.log("Host="+ host + ", port=" + port + ", path=" + path + " TLS = " + useTLS + " username=" + username + " password=" + password);
        mqtt.connect(options);
    }

    function onConnect() {
        $('#status').val('Connected to ' + host + ':' + port + path);
        // Connection succeeded; subscribe to our topic
        mqtt.subscribe(topic, {qos: 0});
        $('#topic').val(topic);
    }

    function onConnectionLost(response) {
        setTimeout(MQTTconnect, reconnectTimeout);
        $('#status').val("connection lost: " + responseObject.errorMessage + ". Reconnecting");

    };

    function onMessageArrived(message) {

        var topic = message.destinationName;
        var payload = message.payloadString;

        $('#cuerpo').html(payload);
    };


    $(document).ready(function() {
        MQTTconnect();
    });
    </script>
</head>
<body>
<div id="Pagina">
<input type='text' id='topic' disabled hidden/>
<input type='text' id='status' size="80" disabled hidden/>
<div id="cabecera">IES VIRGEN DE GUADALUPE</div>
<div id="cuerpo">TURNO</div>
<div id="pie">SU TURNO</div>
</div>
</body>
</html>
Existe un fichero config.js con:
/var/www/turnos# cat config.js 
//host = 'broker.hivemq.com'; // hostname or IP address
//port = 8000;                    // Puerto de tipo Websocket
host = '172.19.X.Y';    // hostname or IP address
port = 8000;                    // Puerto de tipo Websocket

topic = 'numero';  // topic to subscribe to
useTLS = false;
username = null;
password = null;
cleansession = true;
// path = '';
El contenido completo de /var/www/turnos es:
# tree /var/www/turnos/
/var/www/turnos/
├── Antonio-Bold.ttf
├── Antonio-Light.ttf
├── Antonio-Regular.ttf
├── config.js
├── img
│   ├── logo_200_original.png
│   ├── logo_guadalupe.jpg
│   └── logo_guadalupe.png
├── jquery.min.js
├── mosquitto-repo.gpg.key
├── mqttws31.js
└── Suturno.html
Y lo descargaremos de este enlace (habrá que adaptar texto y logo). Este código html estará en cualquier máquina que haga de servidor web en la red del centro. Yo he usado el mismo servidor donde está el broker mqtt, pero podría ser cualquier otro.

En la pantalla que muestra el número simplemente habrá un navegador cargado (que soporte javascript, claro) con la siguiente página abierta:
http://servidor-web/turnos/Suturno.html
Yo tengo un Debian con autologin y con el Firefox abriéndose en la página al iniciar sesión.

Parte 3. Controlador de la cola.

Vamos a la parte final: el PC que controla la cola. Empezamos con 3 scripts que incrementarán, decrementarán y resetearan la cola a 0 (no olviden adaptar la IP).
# cat suma_turno.sh
#!/bin/bash

servidor="172.19.X.Y"
topic="numero"

# Obtenemos el ultimo valor guardado C 1 lee el valor y corta la subscripcion
info=$(mosquitto_sub -t $topic -h $servidor -C 1)

# Metemos en un array la letra y el numero
IFS='-' read -r -a array <<< "$info"
letra="${array[0]}"
num="${array[1]}"

if [ $num = "99" ]; then
nuevo_numero="00"
else # Incrementamos en 1 el valor usando base 10
nuevo_numero=$((10#$num + 1))
fi

# Formatea el numero con ceros delante.
n=`printf %02d $nuevo_numero`

# Publica de forma persistente -r la letra-numero
mosquitto_pub -t $topic -h $servidor -m "$letra-$n" -r

exit 0

# cat resta_turno.sh

#!/bin/bash

servidor="172.19.X.Y"
topic="numero"

# Obtenemos el ultimo valor guardado C 1 lee el valor y corta la subscripcion
info=$(mosquitto_sub -t $topic -h $servidor -C 1)

# Metemos en un array la letra y el numero
IFS='-' read -r -a array <<< "$info"
letra="${array[0]}"
num="${array[1]}"

if [ $num = "00" ]; then
nuevo_numero="99"
else # Incrementamos en 1 el valor usando base 10
nuevo_numero=$((10#$num - 1))
fi

# Formatea el numero con ceros delante.
n=`printf %02d $nuevo_numero`
# Publica de forma persistente -r la letra-numero
mosquitto_pub -t $topic -h $servidor -m "$letra-$n" -r

exit 0
# cat reset_turno.sh

#!/bin/bash

servidor="172.19.X.Y"
topic="numero"

mosquitto_pub -t $topic -h $servidor -m "A-00" -r

exit 0
Notemos que hemos llamado a mosquito_sub con "-C 1": esto se hace asi para leer un valor y desconectar, de lo contrario el script quedaría bloqueado eternamente suscrito a la cola.

Estos scripts podríamos ponerlos como accesos directos en el escritorio del PC de secretaría que controlará el sistema de turno. Pero tal como hacen los compañeros de http://openwrt.tuinstituto.es/ queda mucho más práctico y rápido usar un dispositivo dedicado solo para controlar al menos el incremento/decremento.

Esto se consigue con un ratón adicional y triggerhappy. Pinchamos un ratón adicional en el puerto usb y hacemos:
# ls -l /dev/input/by-id
total 0
lrwxrwxrwx 1 root root  9 jun  8 10:22 usb-0461_USB_Optical_Mouse-event-mouse -> ../event3
lrwxrwxrwx 1 root root  9 jun  8 10:22 usb-0461_USB_Optical_Mouse-mouse -> ../mouse0
lrwxrwxrwx 1 root root  9 jun  8 10:22 usb-CHICONY_HP_Basic_USB_Keyboard-event-kbd -> ../event4
lrwxrwxrwx 1 root root 10 jul 10 13:40 usb-PixArt_HP_USB_Optical_Mouse-event-mouse -> ../event16
lrwxrwxrwx 1 root root  9 jul 10 13:40 usb-PixArt_HP_USB_Optical_Mouse-mouse -> ../mouse1
lrwxrwxrwx 1 root root 10 jun  8 10:22 usb-Sonix_Technology_Co.__Ltd._USB_2.0_Camera-event-if00 -> ../event15
Este listado anterior nos muestra los dispositivos de entrada conectados al sistema. El ratón extra que hemos metido aparece en negrita. Debemos por tanto monitorizar /dev/input/event16 (o /dev/input/by-id/usb-PixArt_HP_USB_Optical_Mouse-event-mouse) y eso lo haremos con el paquete triggerhappy, tal como muestran aquí. Instalamos el paquete:
# apt-get install triggerhappy
Y probamos a mano si funciona:
# thd --dump /dev/input/event16
Moviendo el ratón y pulsando botones veremos como salta la ristra de eventos, lo cual nos sirve para identificar cada evento para luego asociar a él un "trigger". Ahora asociamos los eventos que nos interesan (pulsación de ambos botones)
# cat /etc/triggerhappy/triggers.d/raton.conf
BTN_LEFT    1  /usr/bin/suma_turno.sh
BTN_RIGHT   1  /usr/bin/resta_turno.sh
Esto funcionaría para cualquier ratón conectado al sistema, así que tenemos que filtrar para que solo se haga para el ratón adicional, modificando la configuración del demonio tal como se muestra aquí:
# cat /etc/default/triggerhappy
# Defaults for triggerhappy initscript
# sourced by /etc/init.d/triggerhappy
# installed at /etc/default/triggerhappy by the maintainer scripts

#
# This is a POSIX shell fragment
#

# Additional options that are passed to the Daemon.

#Solo captura eventos del raton HP
DAEMON_ARGS="--daemon --triggers /etc/triggerhappy/triggers.d/ --socket /var/run/thd.socket --pidfile $PIDFILE --user nobody /dev/input/by-id/usb-PixArt_HP_USB_Optical_Mouse-event-mouse"

DAEMON_OPTS=""

# The Triggerhappy daemon (thd) drops its root privileges after
# startup and becomes "nobody". If you want it to retain its root
# status (e.g. to run commands only accessible to the system user),
# uncomment the following line or specifiy the user option yourself:
#
# DAEMON_OPTS="--user root"
Con esto, reiniciando el demonio triggerhappy ya podemos comprobar que al pulsar los botones del ratón añadido se incrementa o decrementa el valor de la cola. Esto tiene un reflejo automático en la pantalla de visualización que está suscrita a ella.

Queda un pequeño detalle: el ratón adicional es fiel a su naturaleza y se comporta como un ratón normal, con lo que al moverlo o pulsarlo tendrá un efecto molesto (ya que se moverá el cursor) en el escritorio del PC al que está conectado. Lo ideal es que solo se dedique a controlar la cola y no tenga efecto sobre el cursor y el escritorio. ¿Podemos desvincularlo del escritorio? Si se puede con este script:
# cat /usr/bin/anula_raton_turnos.sh
#!/bin/bash

id=$(xinput list --id-only "PixArt HP USB Optical Mouse")

if [  ! -z "${id##*[!0-9]*}"  ]   #compruebo si es un número
then
  xinput set-int-prop $id "Device Enabled" 8 0  #Lo desactivo
fi
exit 0
Busca el ratón llamado "PixArt HP USB Optical Mouse" y lo desactiva como dispositivo de las X. Aquí habría que adaptar al nombre del ratón que tenga cada cual. Solo queda hacer que esto se ejecute al iniciar sesión y ese ratón dejará de molestar y quedará para su funcion primordial:
# cat # /etc/xdg/autostart/anula_raton_turnos.desktop
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Exec=/usr/bin/anula_raton_turnos.sh
Icon=
Terminal=false
Name[es_ES]=Anula Raton Turnos
Name=controlIES
Comment[es_ES]=
Coment=
Categories=Application;Education;
Y con esto dejamos el verano fluir y ya si escribo algo será puntual que no quiera dejar pasar. A pasarlo bien...

miércoles, 26 de julio de 2017

Un poquito de HTML: imagen que duplica su tamaño al pasar el ratón.

Pues tarde o temprano hay que meterse en cosas de decoración y retocar alguna página web. En esta ocasión me pedían colgar en una página que usamos como intranet del centro unas miniaturas de otras páginas web y añadir un efecto que hiciera que dichas miniaturas aumentasen de tamaño hasta hacerse bien visibles al pasar el cursor del ratón sobre ellas. Como me ha costado un poco averiguar como hacerlo lo dejo aquí para que conste.

En primer lugar tenemos un script que hace capturas de las páginas en cuestión (utilidad wkhtmltoimage), generando un fichero en formato .png y ajustando luego el tamaño (utilidad mogrify):

#!/bin/bash

DESTINO="/var/www/intranet/images"

/usr/bin/wkhtmltoimage --quality 50 http://iesvdeguadalupe.juntaextremadura.net  $DESTINO/ies-webpage.png
/usr/bin/wkhtmltoimage --quality 50 http://iesvirgendeguadalupecc.blogspot.com.es   $DESTINO/ies-blog.png

/usr/bin/mogrify -crop 800x1000+0+0 $DESTINO/ies-blog.png
/usr/bin/mogrify -crop 800x1000+0+0 $DESTINO/ies-webpage.png

exit 0
Este script es llamado periódicamente desde algún crontab para actualizar ambas imágenes conforme se actualizan las webs.

Ahora nos toca mostrar esas imágenes con el efecto de aumento. Tras refrescar mi CSS y buscar un poco en Internet (lo que me ha servido para confirmar que .css es en algunos aspectos un lenguaje funcional: te le dices donde quieres llegar y el se ocupa del cómo). El estilo definido es:
/*============
DIV ZOOMING
=============*/

#boxcontainer{
 position: relative;
 width:650px;
 height: 400px;
}
.box{
 position:relative;
 float:left;
 width:315px;
 height:100%;
 margin:5px;
}
.Inside{    
 position:absolute;
 top:0;
 left:0;
 width:290px;
 height:100%;
 transition:all 0.5s ease-in-out;
 -webkit-transition:all 0.2s ease-in-out;
}
.Inside:hover{
 z-index:100;
 transform: scale(2);
 transform-origin: top right;
}
Se definen los tamaños de las cajas que contendrán ambas imágenes y luego el efecto:
  • En "Inside": indicamos que habrá una transición (el efecto de aumento) y específicamos el tiempo que tomará en realizarse.
  • En "Inside:hover": se define como cambiará "Inside" cuando el ratón pase por encima ("hover"). Se define un z-index de 100 para que esté en primer plano, por encima del resto, la transformación con un reescalado x2 y la dirección del movimiento partiendo de arriba-derecha (había abajo-izquierda).
Por último el HTML que hace uso de los estilos anteriores, que será lo publicado en la Intranet del centro:
<div id="boxcontainer">
  <div class="box">
    <div class="Inside">Blog
      <a href="http://iesvirgendeguadalupecc.blogspot.com.es/" target="_blank">
        <img style="height: 100%; width: 100%; object-fit: contain;" src="/intranet/images/ies-blog.png" alt="" />
      </a>
    </div>
  </div>
  <div class="box">
    <div class="Inside">Web
      <a href="https://iesvdeguadalupe.educarex.es/" target="_blank">
        <img style="height: 100%; width: 100%; object-fit: contain;" src="/intranet/images/ies-webpage.png" alt="" />
      </a>
    </div>
  </div>
</div>
Tenemos las dos imágenes, apuntando a las webs respectivas, dentro de una caja y con el efecto de aumento implantado usando el estilo "Inside". En la siguiente captura vemos el resultado con una de las imágenes en proceso de expansión:


Bueno, nos vamos pero no del todo: publicaremos alguna cosita curiosa más a lo largo de este raro verano.

martes, 27 de junio de 2017

Hacer rollback de paquetes en Manjaro/Arch

El otro día hice una macroactualización de paquetes que me pedía desde hacía tiempo mi Manjaro de casa. A raíz de ello Steam dejó de funcionar, quedaba cargando sin avanzar nada y mis hijos, con un juego recién comprado, estaban bastante nerviosos.

Después de investigar un poco veo que es debido a la actualización del paquete con los drivers nvidia-340. La última versión de los mismos fastidia Steam (y más aplicaciones que usan opengl) tanto en Arch/Manjaro como en Ubuntu. Como no hay paquetes mas modernos todo apuntaba a que había metido la pata hasta el corvejón.

Entonces se me ocurrió: ¿no tendrá Manjaro algún sistema para volver a paquetes antiguos de una forma sencilla?. A fin de cuentas, Manjaro es la distribución de Linux mas molona. Pues si, lo tiene: la herramienta downgrade.

Primero tengo que ver que paquetes tengo instalados y a que paquetes puedo retroceder haciendo "rollback" en el tiempo. Para ello tecleo como root:

 # cd /var/cache/pacman/pkg
# ls -l *nvidia*

-rw-r--r-- 1 root root 20244996 dic 15  2016 lib32-nvidia-340xx-utils-340.101-1-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 20772404 abr  3 16:07 lib32-nvidia-340xx-utils-340.101-6-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4780584 mar 29 18:21 linux44-nvidia-340xx-340.101-12-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4780588 abr  3 16:06 linux44-nvidia-340xx-340.101-14-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4779356 mar  5 09:37 linux44-nvidia-340xx-340.101-9-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4783180 jun 14 23:03 linux44-nvidia-340xx-340.102-2-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4779072 mar  5 09:37 linux49-nvidia-340xx-340.101-11-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4779532 mar 29 18:21 linux49-nvidia-340xx-340.101-14-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4779344 abr  3 16:06 linux49-nvidia-340xx-340.101-18-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4783088 jun 17 16:45 linux49-nvidia-340xx-340.102-3-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4783856 jun 24 12:22 linux49-nvidia-340xx-340.102-4-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root    10508 dic 15  2016 mhwd-nvidia-1:375.26-1-any.pkg.tar.xz
-rw-r--r-- 1 root root    10624 mar  5 09:33 mhwd-nvidia-1:375.39-1-any.pkg.tar.xz
-rw-r--r-- 1 root root    15408 may  5 09:29 mhwd-nvidia-1:375.66-1-any.pkg.tar.xz
-rw-r--r-- 1 root root    10644 dic 15  2016 mhwd-nvidia-304xx-1:304.134-1-any.pkg.tar.xz
-rw-r--r-- 1 root root    10608 dic 15  2016 mhwd-nvidia-340xx-340.101-1-any.pkg.tar.xz
-rw-r--r-- 1 root root     6452 jun 16 19:25 mhwd-nvidia-340xx-340.102-1-any.pkg.tar.xz
-rw-r--r-- 1 root root 23768104 feb 17 18:26 nvidia-340xx-utils-340.101-1-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 23787724 mar  5 09:37 nvidia-340xx-utils-340.101-3-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 23800248 abr  3 16:06 nvidia-340xx-utils-340.101-8-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 23803844 jun 10 14:22 nvidia-340xx-utils-340.102-1-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 10600616 feb 17 18:26 opencl-nvidia-340xx-340.101-1-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 10589732 jun 10 14:23 opencl-nvidia-340xx-340.102-1-x86_64.pkg.tar.xz
Aquí se ve la lista de paquetes cacheados y que puedo instalar. En mi caso el fallo ha venido por actualizar el otro día a nvidia-340xx-utils-340.102-1-x86_64.pkg.tar.xz, generado el 10 de junio. Debo volver a uno anterior, cuando Steam funcionaba, por ejemplo nvidia-340xx-utils-340.101-8-x86_64.pkg.tar.xz del 3 de abril.

El problema es que no solo basta con volver atrás dicho paquete, ya que tiene como dependencias linux49-nvidia-.. y linux44-nvidia-.. y por tanto también tengo que volver a la versión de 3 de abril de ambos paquetes (que son del kernel, por cierto). Las versiones destino son:
-rw-r--r-- 1 root root  4780588 abr  3 16:06 linux44-nvidia-340xx-340.101-14-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root  4779344 abr  3 16:06 linux49-nvidia-340xx-340.101-18-x86_64.pkg.tar.xz
-rw-r--r-- 1 root root 23800248 abr  3 16:06 nvidia-340xx-utils-340.101-8-x86_64.pkg.tar.xz
Empezamos instalando:
# sudo pacman -S downgrade
y hacemos el downgrade de los 3 paquetes:
# sudo downgrade linux49-nvidia-340xx nvidia-340xx-utils linux44-nvidia-340xx 
El comando nos preguntará de forma interactiva que versiones instalar mediante un menú del tipo 1) 2) 3)... simplemente elegimos el paquete correcto en cada una de las listas que nos muestra y le dejamos hacer. Si elegimos paquetes no compatibles (por tema de dependencias) el proceso se interrumpe y nos dice que paquete causa el problema.

Tras instalar los paquetes correctos, reiniciamos al acabar y.... tachán, ya funciona Steam. Ya puedo dormir tranquilo.

Para evitar las preguntas podríamos forzarle a que haga el downgrade instalando nosotros los paquetes directamente con:
# cd /var/cache/pacman/pkg
# pacman -U linux44-nvidia-340xx-340.101-14-x86_64.pkg.tar.xz linux49-nvidia-340xx-340.101-18-x86_64.pkg.tar.xz
nvidia-340xx-utils-340.101-8-x86_64.pkg.tar.xz
También es importante dejar esos paquetes a salvo de futuras actualizaciones en tanto en cuanto no estemos seguros de que el problema persiste. Eso se hace editando /etc/pacman.conf y añadiendo
...
...
IgnorePkg=linux49-nvidia-340xx nvidia-340xx-utils linux44-nvidia-340xx 
...
...
Como siempre, dejo abierta una línea de investigación para volver aquí si hace falta: ¿qué pasa si queremos ir mas atrás y usar paquetes que no están en cache (/var/cache/pacman/pkg)?. Pues si hacemos:
# downgrade
Branch = stable
Downgrading from A.L.A. is disabled on the stable branch. See https://wiki.archlinux.org/index.php/downgrading_packages for more details.
Uso: downgrade , ... [-- ]
ver downgrade(8) para más detalles.
Podemos ver que hay algo llamado "A.L.A." que es el repositorio online de paquetes antiguos. No he investigado más pero queda apuntado que podemos ir mas atrás en el rollback usando esta funcionalidad.

Bueno, pues tarea resuelta, ya podemos relajarnos con unos minutos musicales mientras los niños le dan caña al Steam...


Ocultar particiones Windows en el escritorio Linux

Esta mañana lo ha preguntado un compañero y me ha costado encontrarlo: si tenemos un sistema con arranque dual, al arrancar el Linux el gestor de archivos/escritorio muestra las particiones de Windows, invitando al usuario a entrar allí con un doble click. Al hacerlo, le pedirá unas credenciales de administrador para montarlas.

Lo ideal sería que esas particiones no aparezcan allí ya que molestan sin aportar nada, a no ser que sea necesario su montaje (y en cuyo caso lo mas sencillo es hacerlo en el arranque mediante /etc/fstab). Voy a contarlo aquí para tenerlo más mano para la próxima vez.

La manera de ocultarlas es editar el siguiente fichero:
# cat /etc/udev/rules.d/10-local.rules
KERNEL=="sda2", ENV{UDISKS_IGNORE}="1"
KERNEL=="sda4", ENV{UDISKS_IGNORE}="1"
KERNEL=="sda5", ENV{UDISKS_IGNORE}="1"
Siendo sda2, sda4 y sda5 las particiones de Windows que queremos ocultar en el ejemplo. En el siguiente reinicio ya no aparecerán tentadoras para el doble click.

Para identificar las particiones a ocultar podemos usar, como root, "fdisk -l" para casos normales o "parted /dev/sdX print" si la tabla de particiones está en formato GPT.

Si queremos aplicarlo sobre muchas máquinas lo lógico es poner una regla puppet distribuya /etc/udev/rules.d/10-local.rules a todas ellas.

jueves, 22 de junio de 2017

Proxmox (V): importación de una máquina virtual preexistente / uso de SPICE.

Continuamos esta serie con otra cuestión que quería probar: en el centro tengo varias máquinas virtuales montadas para ser utilizadas de forma local mediante VirtualBox. Una de ellas es una máquina con Windows XP que ejecuta la vetusta aplicacion Geiwin-IES2000, usada para la gestión del alumnado del centro antes de la llegada de Rayuela. Durante la implantación de Rayuela hubo datos antiguos que se "olvidaron" de trasladar y es necesario tener esa aplicación de los 90 para consultar antiguos expedientes.

Hasta hora tenía una máquina virtual que arrancaban los PC de administración desde su Ubuntu cuando querían acceder a los datos. El problema es que tarda un rato en arrancar la máquina para una simple consulta y, por otro lado, tenerla siempre abierta consume recursos del PC local. Esta máquina es una firme candidata a ser exportada a Proxmox, para tenerla siempre encendida y poder conectar a ella de forma rápida cuando se requiera.

Partimos de un fichero .vdi con la imagen de la máquina virtual en VirtualBox (sería la imagen de un Windows XP que ya tengo preparado con Geiwin/IES2000 y alguna otra aplicación viejuna instalada y en funcionamiento) y el objetivo es llavarla a Proxmox. Existe documentación sobre ello, pero voy a contar los pasos que he dado por mi parte y los problemas que he ido encontrando. A grandes rasgos lo que haremos es:

  1. Convertir el fichero de imagen de disco .vdi con la máquina virtual en formato propio de VirtualBox en un fichero .img, con la imagen de disco en formato raw, que es el formato que necesita Proxmox al estar basado internamente en KVM.
  2. Crear la máquina Windows XP en Proxmox, especificando un disco duro en formato .raw alojado en storage->local (en lugar del habitual storage->local-lvm).
  3. Subir la imagen raw de disco al storage de Proxmox sobreescribendo la creada en el paso anterior.
  4. Arrancar y configurar la máquina con el hardware virtual propio de Proxmox.
  5. Configurar SPICE para permitir acceder a la máquina virtual desde un PC remoto de una forma rápida. La idea es verificar si Spice hace tan rápido y ligero el escritorio remoto como cuentan las crónicas.

Vayamos paso a paso.

0. Antes del inicio.

Antes de empezar por el primer paso de conversión del fichero .vdi hay que tomar precauciones para evitar tener un pantallazo azul típico de Windows en el paso nº 4. Como ya comenté en el blog hace siglos (apartado 3 de esta entrada), Windows XP lleva fatal que le cambies de hardware y se venga en forma de pantallazos al arrancar. Da igual que le cambies de una máquina física a otra usando una herramienta de clonado o de un modelo hipervisor para máquinas virtuales a otro, el Windows XP detecta un cambio de hardware y muestra su hermosa pantalla azul.

En nuestro caso vamos a pasar de VirtualBox a Proxmox/KVM y he podido confirmar que no defrauda: un BSOD al arrancar. En versiones modernas de Windows esto se ha ido paliando y es díficil encontrarnos con estas pantallas azules, pero recordemos que estamos tratando con un XP.

La causa de esto son los drivers de la controladora IDE del disco duro. Al arrancar en el nuevo hardware y ver que la controladora IDE ha cambiado no pone una genérica o intenta sortear el problema: da el pantallazo azul y te quedas ahí con cara de tonto. La solución pasa por, antes de mover el Windows XP, ejecutar un programa o script que instala los drivers IDE genéricos mas básicos. Al arrancar en el nuevo sistema no hay fallo e inmediatamente los cambia por unos drivers mas avanzados y adecuados al nuevo hardware.

La herramienta adecuada para esto es la ofrecida en la web de Proxmox llamada mergeide.zip, que encontramos aquí. La descargamos en la máquina virtual VirtualBox antes de copiar el fichero .vdi y la ejecutamos. Modificará el registro para establecer unos driver IDE genéricos. A continuación apagamos la máquina virtual y, sin encenderla de nuevo, convertimos el .vdi a .img según el paso siguiente.

1. Convertir de .vdi a .raw

Esta es sencilla: en la máquina física donde tenemos el VirtualBox ejecutamos:
# VBoxManage clonehd --format RAW Win.vdi Win.img
Siendo Win.vdi la imagen de disco duro origen e .img el disco destino. Tardará un rato en hacerse y generará una imagen .img más grande ya que la .vdi está siempre comprimida.

2. Crear en Proxmox la máquina virtual para Windows XP.

Creamos la máquina de la misma forma que hemos creado cualquier otra, indicando que es un Windows XP y dándole 1Gb de RAM, más que suficiente.



Aquí hay otro problema: el disco duro debe estar en Storage->local en lugar de en Storage->local-lvm. La causa de esto es que luego vamos a dar el cambiazo y sobreescribir la imagen Win.img del paso anterior sobre el disco duro creado por defecto durante la creación de la máquina virtual, de tal manera que el Windows XP ya configurado y preparado va a aparecer allí de golpe. Aquí se ve en el detalle:


Cuando la imagen de disco duro se crea en Storage->local-lvm, se guarda en un "limbo" (el volumen LVM) al cual no podemos acceder directamente para dar el cambiazo. En cambio si se crea en Storage->local, se guarda en la ruta proxmox:/var/lib/vz/imagenes/id-maquina/*.raw, lo cual hace fácil la sustitución de la imagen.

El problema está en que Proxmox por defecto no permite crear las imágenes de disco duro en Storage->local, solo permite crearlas en Storage->local-lvm. Podemos verlo en la siguiente captura realizada durante la creación de la máquina virtual:


Pero buscando un poco en Internet, aquí aparece la solución. El truco está en editar el fichero /etc/pve/storage.cfg y añadir la parte en negrita:

root@proxmox:~# cat /etc/pve/storage.cfg 
dir: local
 path /var/lib/vz
 content iso,vztmpl,backup,images

lvmthin: local-lvm
 thinpool data
 vgname pve
 content rootdir,images
root@proxmox:~# 

Con esto logramos poder crear el disco duro asi:


Con lo cual tendremos fichero .raw que representa la imagen del disco duro en la ruta var/lib/vz/images/id-vm/...

3. Subir la imagen y sobreescribirla.

Esta parte es sencilla, copiamos el fichero .img a la máquina con Proxmox:
# scp Win.img root@proxmox:/root
Y sobreescribimos el fichero ya dentro de Proxmox:
root@proxmox:~# cp /root/Win.img /var/lib/vz/images/102/vm-102-disk-1.raw
Ahora encendemos la máquina con el botón "Start VM" y hará una arranque correcto sin pantallazos azules. Desde "_Console" podremos ver su escritorio:


4. Arrancar y configurar la imagen con los drivers.

En el primer arranque, tras conectar mediante la consola y entrar como administrador del Windows XP veremos que se realiza una autodetección de hardware, debido a que la máquina KVM/Proxmox tiene sus propios dispositivos virtuales (al igual que las tienen las máquinas VirtualBox y Vmware, por ejemplo), para los cuales hay que instalar los drivers adecuados.

Como se ve en la siguiente captura del Administrador de Dispositivos una vez instalados los drivers adecuados, ahí están los dispositivos "Virtio" (serial, balloon y printer).


Para instalar los drivers descargamos la versión estable (a fecha de hoy, la 0.132, probé con otras mas actualizadas y me dieron problemas con Windows XP) de las Spice Guest Tools del enlace siguiente. Aquí está el enlace directo a dicho software.

También podemos bajarnos la imagen ISO con los "drivers Virtio" sueltos desde aquí.

Una vez descargadas las spice-guest-tools las instalamos, quedando así:


Si reiniciamos la máquina virtual ahora si detectará bien todo el hardware e instalará los drivers correctos, quedando como en la captura anterior: todo el hardware detectado sin símbolos de error o aviso.

Un vez hecho esto ya si podemos trabajar con Geiwin y su interfaz tan grunge:


Para que los usuarios rasos de la administración accedan a la máquina virtual y Geiwin hay varias opciones. La más sencilla es que el Windows virtualizado tenga habilitado el escritorio remoto y tenga una ip pública fija configurada en el servidor DHCP, como ya hicimos para Zentyal y RSAT en anteriores entradas. En ese caso los usuarios entrarán con un:
# rdesktop -u usuarioxp -p passwordxp -N -z -P -g 1024x768+0+0  ip-maquina-xp
Simplemente poniendo un acceso directo en el escritorio que ejecute el comando anterior conseguiremos entrar remotamente desde nuestro escritorio Linux.


Si queremos que puedan entrar varios usuarios a la vez no tenemos nada mas que habilitar el acceso concurrente mediante Remote Desktop.

La otra opción de acceso es que entren a través del navegador Web, usando la consola VNC de Proxmox. Evidentemente no les vamos a dar las credenciales del administrador del servidor, pero si podemos crear un usuario ad-hoc dentro del servidor que pueda conectar con la máquina virtual XP.

Para ello creamos un usuario propio de PVE según la siguiente captura:


y luego nos vamos a nuestra máquina virtual con XP y le damos permiso a dicho usuario para acceder a ella con el rol PVEVMUser, que significa que solo puede interactuar con la máquina virtual, pero no modificar su configuración ni la del Proxmox.


Los usuarios cargarán en su navegador la URL https://ip-proxmox:8006 y pondrán las credenciales del usuario limitado (ojo al seleccionar la validación contra Proxmox VE y no contra PAM en la lista desplegable "Realm") y tendrán una visión limitada del entorno, con la máquina accesible mediante la consola:



En ambos casos es interesante deshabilitar a los usuarios regulares la posibilidad de apagar la máquina virtual, que debe estar siempre encendida. Eso lo logro siguiendo estas instrucciones.

La tercera opción, que es usar SPICE, la veremos en el siguiente apartado.

5. Configurar acceso por Spice.

Desde que empecé a mirar esto de Proxmox y KVM he encontrado referencias a SPICE, que se define como un protocolo para conectar de forma remota con el escritorio de las máquinas virtuales a una velocidad que da impresión de ser un escritorio local. Según se dice, SPICE detecta de forma inteligente incluso areas de vídeo y las manda como un stream de vídeo. Copio el fragmento de aquí:
Video Compression

Spice uses loss-less compression for images sent to the client. However, video streams are handled differently. Spice server heuristically identifies video areas and sends them as a video stream coded using M-JPEG. This handling saves a lot of traffic, improving Spice performance, especially in a WAN environment. However, in some circumstances the heuristic behavior might cause low quality images (e.g. identifying updated text area as a video stream). Video streaming can be chosen on server initiation and dynamically at run-time.
Suena prometedor...¿verdad?. Hasta ahora los escritorios remotos que he probado (VNC, Remote Desktop, x2goclient) flaqueaban en el tema de la reproducción de vídeos, tanto de Youtube como por vlc. Tengo curiosidad por ver si SPICE resuelve esto.

Lo primero que debemos hacer es activar SPICE en la configuración de la tarjeta gráfica de la máquina virtual XP (hace falta tenerla detenida):


A continuación arrancamos la máquina XP y nos detecta un cambio en la tarjeta de vídeo, que pasa a identificar con Red Hat QXL GPU, activando el driver SPICE (ya instalado previamente con las Spice-guest-tools) para manejar de forma optimizada el escritorio remoto:


Ahora en la máquina local desde la que conectamos a Proxmox hay que instalar un "cliente SPICE" (que seria similar a un cliente VNC) para poder conectar. Hay clientes para Windows, Linux, Android, OSX, etc.

Como nuestra máquina es Ubuntu instalamos el cliente desde los repositorios con:
# apt-get install virt-viewer
Para acceder basta con abrir Proxmox, ir a la máquina virtual y abrir la lista asociada al botón "_Console", seleccionando la opción "SPICE". Esto descargará un fichero (una especie de "cookie de sesión") que al ejecutarse abrirá el visor remoto.



Al abrir el fichero descargado se ejecutará virt-viewer y tendremos una conexión de escritorio remoto (nótese que tiene un menú que nos permite cosas interesantes, como cambiar la resolución o enviar combinaciones de teclas especiales a la máquina remota):


Después de varias pruebas, incluyendo vídeos, puedo atestiguar que va mas rápido que cualquier escritorio remoto que haya visto antes. El vídeo se reproduce sin saltos y con calidad, como se ve en la captura, donde reproduzco a la vez vídeos de youtube y vlc con tanta fluidez como el QE de un Banco Central.


Si abrimos el administrador de tareas de Windows XP veremos que hay un par de procesos llamados vdagent.exe/vdservice.exe que se encargan de realizar la comunicación optimizada con el virt-viewer. Son los encargados de redirigir vídeo, ratón, teclado y otros dispositivos hardware entre máquina virtual y cliente remoto.

Conectar mediante el interfaz web puede ser un poco engorroso para un usuario raso. Existe la opción de entrar directamente usando un script que realmente simula mediante wget/curl las peticiones web. El script lo descargamos de aquí desde este epígrafe de la Wiki de Proxmox.

Una vez descargado el script, lo guardo con el nombre "spice" y permisos 755. Los parámetros del script son:
 Uso: spice [-u ] [-p ] vmid [node [proxy]]"

   -u username. Default root@pam
   -p password. Default ''
    
    vmid: id for VM
    node: Proxmox cluster node name
    proxy: DNS or IP (use  as default)
Para invocarlo en mi caso haré:
# ./spice -u usuario@pve -p password 102 proxmox64 172.X.Y.Z
Usando el usuario que creamos anteriormente (para permitir la entrada a proxmox de usuarios rasos), suponiendo que la máquina virtual tiene un id 102 y poniendo el nombre del cluster e IP del servidor Proxmox. Vemos como ahora se abre el virt-viewer con el escritorio remoto sin necesidad de utilizar la interfaz web de proxmox:


Como comenté con rdesktop, lo ideal es crear un acceso directo en el escritorio del usuario que ejecute el "/..../spice -u usuario@pve -p password 102 proxmox64 172.X.Y.Z".

Un tema que me quedo en el tintero de momento es que SPICE no solo exporta la parte gráfica del escritorio, también permite exportar el audio y los puertos USB, tal como se comenta aquí. Esta parte no me interesa ahora y la voy a quedar pendiente.

Ya que no son todo alegrías, hay que comentar un problema inesperado: al activar SPICE en la máquina virtual el ratón en el acceso VNC desde Console ya no funciona correctamente, está como descalibrado. No quedará otra opción que usar SPICE o rdesktop una vez activado SPICE en el hardware de la máquina.

Bueno, pues colorín&colorado, la primera temporada de esta serie se ha acabado. Me queda por explorar en un futuro: el tema del audio/usb en SPICE, el uso de del PCI Passthrough para acelerar aún mas el vídeo e indagar la posibilidad de establecer varias sesiones SPICE a la vez contra la misma máquina virtual.