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

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.


lunes, 19 de junio de 2017

Proxmox (IV): Unimos un cliente Windows al dominio Zentyal y probamos el login de usuarios de dominio y las GPO.

Bueno, pues ya tenemos nuestro controlador de dominio funcionando en la máquina con Zentyal, vamos ahora a darle uso. Necesitamos un Windows para que se una al dominio y hacer pruebas con él. Además vamos a instalar las herramientas RSAT para administrar el dominio y crear las GPO a través de las cuales administraremos nuestros clientes Windows.

Podríamos usar un Windows en una máquina física, pero al igual que Esteban prefiero crear (ya que estamos en ello) una máquina virtual en Proxmox donde meter el Windows que usaremos para el RSAT y las pruebas. Así queda todo recogidito.

1. Instalación de Windows 10 en una máquina virtual en Proxmox.

Necesitamos una ISO de Windows 10 que bajamos de aquí. Yo he bajado la version "Windows 10 Anniversary Update", la más reciente. No olvidemos tener a mano el código de licencia para ponerlo en su momento.

Ya sabemos los pasos, subimos a Storage->local la ISO descargada:


Creamos la maquina virtual con nombre "rsat" o el que sea, y seguimos todos los pasos ya vistos en la entrada anterior:


Al final estas son las características de la máquina creada:


No olvidar marcar "Start at boot" con "Yes" para que la máquina arranque sola con Proxmox:


Una vez definida, le damos a Start y nos vamos a consola, viendo el logotipo usual de Mordor:


Seguimos los pasos habituales de instalación:





Elegimos "Cuenta sin conexión", nada de crear una cuenta en microsoft.live.com. A la cuenta local la llamamos "usuario", ponemos la contraseña que nos parezca y decimos que tururú de Cortana:




Y finalmente ya tenemos el escritorio en marcha:


Le cambiamos el nombre a la máquina a "rsat64" y dejamos que reinicie.


2. Unir la máquina al dominio.

Ahora vamos a unir rsat64 al dominio instituto.extremadura.es alojado en la máquina Zentyal. Lo primero que vamos a hacer es irnos al panel de control de Zentyal en https://zentyal64:8443 y crear un nuevo usuario en el dominio que nos servirá para probar el proceso de login y añadir máquinas al mismo. Podríamos usar el usuario "Administrador" que ya existe en el dominio, pero tengo la costumbre de hacerlo con un usuario distinto de cuando trabajaba en ICM en Madrid.


Damos el boton "+" de color verde y rellenamos el formulario:


Ya está creado el usuario "admin" en el árbol ldap:


Vamos a unir ahora rsat64 al dominio usuando el usuario admin. Abrimos el menú y vamos a "Sistema":


Elegimos "Conectarse a la red del trabajo o el colegio", que traducido significa "Unirse a un dominio":


Elegimos "Conectar" y la opción de abajo "Unir este dispositivo a un dominio local de Active Directory":


Y cuando nos pida el dominio le decimos "instituto.extremadura.es".


Vaya, nos da error. Dice que no encuentra el dominio, ¿qué está pasando?. Vamos a explicarlo: no se está resolviendo "instituto.extremadura.es" ya que no lo encuentra usando el servicio DNS proporcionado por el centro. Debemos darnos cuenta de que ahora hay 2 servicios DNS en marcha dentro de nuestra red: el propio del centro y el nuevo que hemos añadido con Zentyal. Este último es imprescindible para que el Dominio funcione.

Si no tuviesemos un DNS propio anterior al que hemos montado con Zentyal sería sencillo de resolver configurando dicho DNS en la configuración de red del Windows. Esto también puede hacerse así si los Windows están dentro de una VLAN privada independiente de la red general, pero no es ese mi caso.

Hay varias soluciones para esto:
  1. Cambiar la configuración del Windows 10 (o del DHCP que le sirve) para que tenga como servidor DNS el que trae el propio Zentyal64, poniendo su IP como servidor DNS del centro. El problema es que eso hará que no usemos el DNS que ya tenemos en la red y no puedan resolverse otros servicios propios del centro dentro. No es una buena solución.
  2. Cambiar la configuración del servicio DHCP para que proporcione 2 IP de servidores DNS a todas la máquinas: la propia del centro y la del Zentyal64. No está mal, pero estaremos dando a máquinas Linux y Android un servidor DNS que no les va a servir para nada.
  3. En nuestros centros tenemos un servicio de PowerDNS Recursor que nos permite añadir servidores DNS especiales en función de dominio. Podemos decirle que para las búsquedas de .extremadura.es use el Zentyal64, sin tocar para nada el resto de configuración en los clientes. Es un método transparente, centralizado y que funciona, así que es el que he adoptado para mi caso.
Mi compañero Esteban usa una técnica similar.

Para ello me voy al servidor donde corre powerdns y retoco su configuración añadiendo la parte en negrita:

root@servidor:/etc/powerdns# head /etc/powerdns/recursor.conf 
#################################
# forward-zones Zones for which we forward queries, comma separated domain=ip pairs
#
# forward-zones=
# Antes era: forward-zones=gobex.pri=xx.yy.zz.aa,juntaextremadura.pri=xx.yy.zz.aa,eco.pri=xx.yy.zz.aa,gob.es=xx.yy.zz.aa

forward-zones=gobex.pri=xx.yy.zz.aa,juntaextremadura.pri=xx.yy.zz.aa,eco.pri=xx.yy.zz.aa,gob.es=xx.yy.zz.aa,extremadura.es=ip.del.servidor.zentyal

#################################
# forward-zones-recurse Zones for which we forward queries with recursion bit, comma separated domain=ip pairs
............
............
............
............
Reinicimos el servicio:
root@servidor:/etc/powerdns# /etc/init.d/pdns-recursor restart
[ ok ] Restarting pdns-recursor (via systemctl): pdns-recursor.service.
root@servidor:/etc/powerdns# 
Ahora desde una máquina linux hacemos ping al dominio viendo que ya si resuelve. El resto de los pings a otras máquinas de la red y hacia el exterior también resuelven correctamente.
root@INFOLAB-OXX:/root# ping instituto.extremadura.es
PING instituto.extremadura.es (ip.del.servidor.zentyal) 56(84) bytes of data.
64 bytes from zentyal64.vguadalupe (ip.del.servidor.zentyal): icmp_seq=1 ttl=64 time=0.409 ms
64 bytes from zentyal64.vguadalupe (ip.del.servidor.zentyal): icmp_seq=2 ttl=64 time=0.443 ms
^C
Ahora volvemos a intentar unir el Windows 10 a "instituto.extremadura.es"...¡bingo! ahora pide usuario y contraseña para hacerlo. Especificamos el usuario "admin" que definimos anteriormente.


Se agrega esa cuenta al pc local:


Y nos pide reiniciar para hacer efectiva la unión al dominio.

Vemos ahora que la pantalla de login muestra el nuevo usuario y permite validar contra el dominio con la sintaxis típica de las redes windows "instituto\nombre-usuario". Para validar con usuarios locales se haría "rsat64\nombre-usuario".


Simplemente entraremos con el usuario "instituto\admin" y la contraseña indicada, se creará el perfil de usuario (proceso que siempre tarda una eternidad en la primera entrada) y con eso habremos confirmado que el equipo está unido al dominio y funcionando.

Por supuesto, si en el directorio activo tenemos mas usuarios creados (por ejemplo, usuarios para el personal o los alumnos del centro), tambien podremos probar a autenticarnos con ellos en cualquier máquina que unamos al dominio.

3. Instalar herramientas de administración del dominio.

Una vez unidos al dominio y autenticados, vamos a instalar en nuestro Windows 10 virtualizado las herramientas de Administacion Remota de Windows. Las descargamos de la página web e instalamos:




Puede ser que no se deje instalar al principio, ya que un Windows 10 recién instalado tiene que actualizarse varias veces. Si hace falta reiniciamos y repetimos la instalación hasta que funcione correctamente.

Una vez instalado podemos hacer uso de las herramientas de administración, como son varias las sacamos al escritorio desde el menú de Herramientas Administrativas de Windows. Las utilidades añadidas por el paquete RSAT que usaremos son:

  • Usuarios y equipos de Active Directory
  • Group Policy Management
  • DNS

Las sacamos al escritorio para acceder fácilmente a ellas:


Si entramos en "Usuarios y equipos de Active Directory" veremos el arbol ldap donde están esos datos en el servidor Zentyal. Veamos los usuarios:


Desde aquí podríamos añadir o borrar usuarios tal como hicimos desde el interfaz web de Zentyal.

Una vista de los equipos (de momento, solo hemos añadido uno al dominio):


La misma vista desde el interfaz web de Zentyal:


La utilidad de "Usuarios y equipos de Active Directory" realmente puede ser sustituida por el interfaz Web de Zentyal, aunque no está mal tenerla para algunas tareas.

En cambio, la creación de Directivas de Grupo si que debe realizarse impepinablemente desde una de las utilidades RSAT, ya que no existe herramienta web en Zentyal para ellas. Vamos a verlo en el siguiente apartado.

4. Creación y aplicación de directivas de grupo.

Como dijimos antes, las directivas de grupo o GPO permiten aplicar configuraciones generales de todo tipo a las máquinas del dominio de forma centralizada. Hay gran variedad de ellas como bien vemos en el blog de mi compañero Esteban o buscando en Internet. No son tan flexibles como las tareas puppet de un sistema Linux con las que se puede configurar cualquier cosa, ya que las GPO ofrecen un sistema de cerrado de configuraciones posibles, pero aún así son útiles para fijar (de tal forma que el usuario no podrá cambiar localmente) muchas configuraciones de forma global y sin tener que meternos a editar el registro de los Windows.

Vamos a ver un ejemplo de como crear una GPO tal como nos cuesta Esteban, inspeccionar como se almacena en Zentyal y como se aplican a una máquina unida al dominio.

Abrimos la herramienta Group Policy Management y vamos a la rama "Objetos de Directiva de Grupo":


Con el botón derecho abrimos el menú contextual y damos a "Nuevo", creando un nuevo objeto llamado Politicas_IES, donde se guardarán configuraciones que se aplicarán a todas las máquinas del dominio.


Seleccionamos el objeto Politicas_IES y damos a "Editar". Eso nos lleva al editor de políticas para definir toda la configuración. No voy a entrar en detalles porque está profusamente explicado en Internet, simplemente comentar que voy a meter tres políticas:

  • La primera para quitar la opción "Instalar actualizaciones y apagar" en el apagado de los Windows del dominio.
  • La segunda para indicar un fondo de escritorio fijo para todos los Windows del dominio.
  • Otra para fijar https://www.educarex.es como página de inicio en Internet Explorer en todos los Windows del dominio.

En las dos capturas siguientes, en el panel de la derecha podemos seleccionar la pestaña "Configuración" y ver todas las configuraciones definidas dentro de la política.



Las políticas así definidas se guardan dentro del servidor Zentyal, en la ruta /var/lib/samba/sysvol, como podemos ver en la siguiente captura:


Por último hay que vincular el objeto para que se aplique sobre todo el dominio. Vamos a la rama instituto.extremadura.es y con el botón derecho seleccionamos "Vincular un GPO existente", eligiendo "Politicas_IES".



Aquí aparece ya conectada a la rama:


Ahora sí reiniciamos la maquina rsat64 y entramos con un usuario de dominio vemos como se aplican las directivas (tanto las de equipo como de usuario):


Desde una ventana de comandos del Windows podemos forzar la aplicacion de politicas
Microsoft Windows [Versión 10.0.15063]
(c) 2017 Microsoft Corporation. Todos los derechos reservados.

C:\Users\admin>gpupdate /force
Actualizando directiva...

La actualización de la directiva de equipo se completó correctamente.
Se completó correctamente la Actualización de directiva de usuario.
Y ver si se han aplicado a posteriori:
C:\Users\admin>gpresult /r

Herramienta de resultados para la Directiva de grupos del
sistema operativo Microsoft (R) Windows (R) v2.0
© 2017 Microsoft Corporation. Todos los derechos reservados.

Creado el ‎16/‎06/‎2017 a las 13:23:18


RSOP datos para INSTITUTO\admin en RSAT64 : modo de inicio de sesión
---------------------------------------------------------------------

Configuración del sistema operativo: Estación de trabajo miembro
Versión del sistema operativo:       10.0.15063
Nombre de sitio:                   n/a
Perfil móvil:             n/a
Perfil local:                        C:\Users\admin
¿Conectado a un vínculo de baja velocidad?: No


CONFIGURACIÓN DE USUARIO
-------------------------
    CN=administrador dominio,CN=Users,DC=instituto,DC=extremadura,DC=es
    Última vez que se aplicó la Directiva de grupo: 16/06/2017 a las 13:21:56
    Directivas de grupo aplicadas desdezentyal64.instituto.extremadura.es
    Umbral del vínculo de baja velocidad de las Directivas de grupo:500 kbps
    Nombre de dominio:                   INSTITUTO
    Tipo de dominio:                     Windows 2000

    Objetos de directiva de grupo aplicados
    ----------------------------------------
        Politicas_IES

    Los objetos GPO siguientes no se aplicaron porque fueron filtrados
    -------------------------------------------------------------------
        Directiva de grupo local
            Filtrar:  No aplicado (vacío)

        Default Domain Policy
            Filtrar:  No aplicado (vacío)

    El usuario es parte de los siguientes Grupos de seguridad
    ---------------------------------------------------------
        Domain Users
        Todos
        Administradores
        Usuarios
        NT AUTHORITY\INTERACTIVE
        INICIO DE SESIÓN EN LA CONSOLA
        Usuarios autentificados
        Esta compañía
        LOCAL
        Domain Admins
        Denied RODC Password Replication Group
        Nivel obligatorio alto

C:\Users\admin>
Por otro lado, también existe la herramienta "rsop.msc" que nos muestra de forma gráfica las políticas aplicadas.

Bueno, pues con esto acabamos esta parte. Ya solo es cuestión de crear usuarios (alumnos y profesores), añadir equipos Windows al dominio y crear políticas para ellos. También puede ser interesante en el futuro explorar el tema del uso de carpetas personales y/o carpetas compartidas.

Nos vemos pronto con un último reto (por ahora) con Proxmox.