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

miércoles, 12 de junio de 2019

Conexión automática a red Wifi

Ahora que llegan las vacaciones viene bien dar un repaso a todos los portátiles de los alumnos: ejecutar puppet, pkgsync, limpiar los usuarios cacheados,... No solo eso, también durante el curso de vez en cuando nos toca actuar sobre todos los portátiles de un armario para aplicar alguna configuración que nos han pedido o que soluciona un bug pendiente.

Hasta ahora para tener conectividad tras encender los portátiles había 2 alternativas:
  1. Conectarlos por red cableada a las tomas del suelo o un switch del aula.
  2. Iniciar sesión en cada uno de ellos y conectarlos manualmente a la red Wifi del aula.
Evidentemente ambas opciones son bastante reiterativas y aburridas. Lo ideal sería que para estos casos los portátiles se conectasen de forma autónoma a una red wifi y nosotros pudiesemos manejarlos de forma masiva con tmux-cssh.

Y esa es la idea de este post: basándome en un script de conexión que usa en su centro nuestro compañero Esteban lo he adaptado para que se conecte de forma autónoma a una red wifi concreta predefinida tan pronto como la detecte.

El código del script es (nota: he corregido algunas erratas en el script el 8/10/2019):
# cat /usr/local/bin/conecta-default-wifi
#!/bin/bash

idioma=$LC_ALL
export LC_ALL=C

wifi_maestra="WIFI_AULAS"
wifi_key="a12345678"
nombre_conexion="ies"

activado=$(nmcli radio wifi)
if [ "$activado" != "enabled" ]
then
    nmcli radio wifi on #activamos la wifi si no lo esta
fi
conectado=$(nmcli dev status | grep wifi |  grep -w -e 'connected' -e "conectado" | awk ' {print $4}')
if  [ "$conectado" != "$nombre_conexion" ]  # Si no estamos conectados a la wifi maestra...
then
      definida=$(nmcli con | grep wifi | grep -w "$nombre_conexion") #Si ya se definió la conexión en network manager la quitamos, para crearla de nuevo cuando nos conectemos
      if [ -n "$definida" ]
      then
          nmcli con delete "$nombre_conexion"conecta-default-wifi
      fi

      detectada=$(nmcli -f SSID,BSSID,SIGNAL,SECURITY dev wifi list | grep -w "$wifi_maestra")
      if [ -n "$detectada" ]  # Si la wifi maestra está al alcance....
      then
            #Si la wifi maestra está al alcance y no estamos en ella, conectamos automaticamente.
            nmcli dev wifi con "$wifi_maestra" password "$wifi_key" name "$nombre_conexion"
            #Si ya existiese la conession podriamos hacer:  nmcli con up $ssidconfigurado
      fi
fi

export LC_ALL=$idioma

exit 0
Que distribuyo con estas reglas puppet:
file {"/usr/local/bin/conecta-default-wifi":
        owner=>root, group=>root, mode=>755,
        source=>"puppet:///modules/xubuntu18_portatil_ajustes/conecta-default-wifi",
}

cron { "cron_conecta_default_wifi":
           command => "/usr/local/bin/conecta-default-wifi",
           user => root,
           minute => "*/3",
           ensure => present
}
Por tanto tenemos un script y una tarea cron que lo llama cada 3 minutos. El script hace lo siguiente:

  1. Configuramos parámetros para una red wifi con SSID "WIFI_AULAS", una clave fija y un nombre de conexión "ies" para el Network Manager.
  2. Si la tarjeta wifi está apagada en Network Manager, se enciende.
  3. Si la wifi está conectada a un punto wifi, mira si el nombre de la SSID es "WIFI_AULAS". En caso afirmativo, finalizamos el script y no continuamos en los pasos siguientes.
  4. Si existe alguna conexión en Network Manager con el nombre "ies", la borramos. Esto es simplemente para hacer limpieza si ya nos habíamos conectado antes.
  5. Escaneamos las redes wifi circundantes en busca de "WIFI_AULAS". Si la encontramos a nuestro alcance nos conectamos a ella creando una conexión "ies" en Network Manager.
  6. Todo esto se repite cada 3 minutos, de tal forma que tan pronto aparezca en el espectro radioeléctrico la wifi "WIFI_AULAS" el portátil se conectará a ella, desconectando de cualquier otra red wifi en la que estuviera enlazado y permaneciendo conectado mientras esté a su alcance.

Con esto el trabajo queda reducido a llegar al aula con un punto wifi (vale cualquier punto de acceso portátil, incluido un router casero de ADSL) configurado con WIFI_AULAS y la clave indicada, enchufarlo a un punto de red cableado, sacar los portátiles del armario y encenderlos.

En pocos minutos todos estarán conectados a la wifi sin ninguna actuación por nuestra parte y con tmux-cssh o ssh podremos controlarlos. Incluso si tenemos puppet y pgksync en modo automático se ejecutarán sin que tengamos que hacer nada. El punto de acceso solo lo usaremos cuando queramos trabajar de esta manera. El resto del tiempo estará apagado y guardado.


Debido a que te encuentras que la gente mas insospechada se niega a creer la gesta del Apolo XI, ahí va el documental definitivo:



jueves, 6 de junio de 2019

CloudReady: convirtiendo los portátiles en ChromeBooks

Tras la llegada de los portátiles Techcomputer TC11 he liberado un par de docenas de antiguos miniportátiles MSI L1350D y APD P10ALD. Son aparatos bastante antiguos y justitos (ambos con Intel Atom CPU N455 y 2GB de RAM) que ya daban problemas de usabilidad con Ubuntu 18.

Como he hecho en otros equipos obsoletos con buen resultado, probé a instalar FreeBSD/TrueOS pero la verdad es que no he notado mejora significativa. Pienso que la causa pudiera ser el limitado soporte a la tarjeta gráfica Intel que traen.

Luego probé con varias versiones de Android-x86 con idéntico resultado. Estaba a punto de probar Manjaro pero recordé que tenía pendiente testear una distribución que convierten un portátil en un ChromeBook, que es un sistema operativo ligero cuyo escritorio es un navegador Chrome y por tanto solo permite ejecutar dicho software y los plugins que instalemos en él. En algunos centros educativos están empezando a llegar este tipo de equipos. En otros países se usa masivamente en entornos educativos.

De esta manera tenemos un ordenador en el que hacemos login con las credenciales de Google y que solo permite trabajar con el navegador, en la nube (con Google Docs, Google Drive y las extensiones que instalemos de Chrome Web Store).

Por supuesto, el sistema Chrome OS es propietario de Google y no es fácil instalarlo en un equipo que no sea un ChromeBook certificado. Afortunadamente han salido clones y alternativas que remedan bastante bien el espíritu de Chrome OS. Aunque hay varios donde elegir me he decantado para probar por CloudReady en su versión Home (traducido: la gratuita). Tiene también buena pinta este desarrollo chino, ahora que Trump está en guerra comercial con China.

1. Descarga.

Lo descargamos de la página de Neverware. En caso de duda se descarga la imagen en un .zip para OSX. Lo descomprimimos y dentro hay un fichero .bin con la imagen de disco de arranque. La grabamos a un pendrive USB con:
sudo dd if=cloudready.bin of=/dev/sdX bs=4M
Luego reiniciamos el pc y arrancamos con el pendrive. La instalación comenzará.

2. Instalación.

Durante la instalación se borrará el disco completo, no es sencilla una instalación dual. Lo cierto es que CloudReady construye un sistema infernal basado en mas de 20 particiones, la causa al parecer es algo que viene de serie en Chromium OS. Esta estructura no es algo normal en Linux, pero si lo he visto muchas veces en Android.

La primera pantalla de instalación, con la bienvenida y la elección de idioma:


Luego nos pide una cuenta de gmail.com. Esta cuenta será la propietaria ("owner") del sistema instalado y nunca podrá borrarse. Por ello lo mejor es usar en la instalación una cuenta gmail.com genérica que nos permitirá entrar luego el pc. Una vez instalado todo el sistema, cualquier persona que tenga una cuenta de Gmail podrá iniciar sesión libremente sin problema (o usar una cuenta temporal de invitado, si no tiene/quiere usar su cuenta de gmail).


Evidentemente, para que esta cuenta pueda ser validada es necesario que el ordenador esté conectado a Internet, ya sea por cable o wifi. Esto es un imperativo siempre presente un Chromebook: un sistema diseñado para trabajar en la nube necesita Internet constante.

Por último nos pide el idioma de instalacion:


3. Configuración y uso.

Una vez instalado, el sistema reinicia y aparece la pantalla de login con varias posibilidades:


  • Iniciar sesión con la cuenta del propietario.
  • Iniciar sesión con una cuenta válida de Gmail, la cual quedará cacheada para futuros logins offline.
  • Iniciar sesión con una cuenta de invitado, que al cerrar sesión no quedará rastro en el disco duro local de su actividad.
  • Borrar una cuenta de las creadas, excepto la de invitado y propietario.
  • Conectar a una red wifi, necesario para poder iniciar sesión con cuentas de gmail no cacheadas.

Esta es la configuración desde la pantalla de login:


Y esta una pantalla con ya dos cuentas de gmail cacheadas:


Una vez iniciada sesión carga el Google Chrome como única aplicación:


Este sería menú de opciones de la derecha de la barra de tareas:


Y este el menú de la izquierda de la barra:


Si entramos en la configuración vemos las preferencias usuales del Google Chrome, mas varias opciones extra referidas al escritorio de CloudReady:


Comprobando el rendimiento podemos afirmar que no va nada mal. Al tener un Linux subyacente con drivers actualizados y un escritorio con Chrome y sus extensiones de la Chrome Web Store todo va bastante ligerito teniendo en cuenta la poca potencia de esta máquina.

4. Configuración final e imagen Clonezilla para clonar.

Debajo de esto hay un Linux, por lo que podemos acceder a un terminal para configurar otros aspectos. Con la combinación de teclas CTRL-Alt-T entramos en el terminal, llamado "crosh". Una vez dentro con el comando "shell" entramos en una shell parecida a bash.

Las credenciales por defecto para trabajar son chronos/chronos. Si queremos cambiar la contraseña los pasos son:
# sudo mount -o rw,remount /
# sudo passwd chronos
# sudo mount -o ro,remount /
Y después reiniciamos.

Otra cosa que me resulta útil es desactivar la suspensión. Los pasos, tras entrar en el terminal:
# shell
# sudo su
# disable_verity
Reiniciamos la máquina y repetimos los anteriores comandos una vez. Luego hacemos
# mount -o rw,remount /
# cat /sys/class/dmi/id/product_name >> /usr/share/power_manager/suspend_prevention_models
# restart ui
Aquí tenemos bastante soporte y trucos de configuración adicionales.

Una vez tenemos configurado es el momento de hacer una imagen con clonezilla para instalarlo en otros equipos. La creación de la imagen se inicia normalmente, pero al llear a la partición sda16 siempre aborta con este mensaje:
Starting to clone device (/dev/sda16) to image (-)
Reading Super Block
memory needed: 28369449 bytes
bitmap 7397925 bytes, blocks 2*10485760 bytes, checksum 4 bytes
Calculating bitmap... Please wait... 
extfsclone.c: bitmap free count err, partclone get free:57578015 but extfs get 57553763.
Please run fsck to check and repair the file system
Failed to use partclone program to save or restore an image!
Tras muchas pruebas solo puedo afirmar que CloudReady al apaar el sistema siempre deja la partición sda16 en ese estado, provocando un error al crear la imagen. La solución es arrancar clonezilla y, antes de empezar a hacer nada, irnos a un terminal y teclear:
# sudo fsck -a /dev/sda16
Después de esto ya podemos realizar la imagen sin problema. La restauración funciona correctamente.


Esta semana los camaradas chinos nos han sorprendido lanzando un cohete Larga Marcha 11 desde una plataforma marítima.




Espectacular. Con este sistema resulta mucho mas barato y eficiente el envío de satélites.

miércoles, 5 de junio de 2019

Generación del musthave mínimo para pkgsync

Ya vimos en su día como configurar un musthave lo mas pequeño posible. Como ahora estoy configurando los portátiles y algunos equipos nuevos, si quiero dejarlos preparados para pkgsync en primer lugar tengo que generar un musthave a partir de los paquetes instalados y luego purgarlo de paquetes dependientes para quedarlo con el menor tamaño posible. Por ello he unificado ambos procesos en un único script:
# cat genera-musthave-minimo.sh
#!/bin/bash

FICHERO=$HOME/musthave.$HOSTNAME

echo "Generando lista de paquetes instalados en $FICHERO..."
aptitude show "?installed ?not(?priority(required)) ?not(?essential) ?not(?automatic)" | grep -e ^Package -e ^Paquete | cut -f 2 -d " " | sort > $FICHERO
echo "Obteniendo lista de paquetes multiarch..."
aptitude show "?installed ?multiarch(same)" | grep -e ^Package -e ^Paquete | cut -f 2 -d " " > /tmp/same
sort -u -o /tmp/same /tmp/same

echo "Procesando lista de paquetes multiarch..."
for paquete in `cat /tmp/same`
do
        sed -i 's|$paquete||' $FICHERO
        dpkg -l|grep "$paquete:i386" 1>/dev/null && echo "$paquete:i386" >> $FICHERO
        dpkg -l|grep "$paquete:amd64" 1>/dev/null && echo "$paquete:amd64" >> $FICHERO
done
sort -u -o $FICHERO $FICHERO 

#Ahora vamos a purgar los paquetes dependientes y dejar solo los paquetes "primigenios"
if [ ! -f /usr/bin/apt-rdepends ]
then
    echo "Instalando apt-rdepends"
    apt-get install apt-rdepends
fi

cp /dev/null /tmp/musthave.new
cp /dev/null /tmp/musthave.deps

paquetes_explicitos=$(aptitude search '~i !~M' -F '%p' --disable-columns | sort -u)
for i in $paquetes_explicitos
do
   echo -n "Paquete $i"
   if grep $i $FICHERO > /dev/null
   then
        echo " ->instalado por musthave"
        echo $i >> /tmp/musthave.new        
   else
      if grep $i /etc/pkgsync/mayhave > /dev/null
      then
          echo "  ->instalado por mayhave"
      else
          echo "  ->instalado por musthave.d"
      fi
   fi
done
sort -u -o /tmp/musthave.new /tmp/musthave.new

num=1
total=$(wc -l  /tmp/musthave.new)
for i in $(cat /tmp/musthave.new)
do
   echo "Dependencias de $i: $num/$total"
   ((num++))
   apt-rdepends $i |grep Depends: | awk ' { print $2 } ' | sed "/^${i}$/d" >> /tmp/musthave.deps 
done
sort -u -o /tmp/musthave.deps /tmp/musthave.deps
comm -23 /tmp/musthave.new  /tmp/musthave.deps  > $FICHERO.final

echo "Proceso concluido, musthave en $FICHERO.final"

exit 0
Lanzamos el script y tras un intenso proceso que debemos dejar acabar con paciencia, en el fichero "musthave.$HOSTNAME.final" nos quedan los paquetes básicos para que funcione el pkgsync, que suele quedar en un 15% del musthave que obtenemos con el script original. Una vez generado este musthave en un equipo de pruebas lo podemos copiar a mano o por puppet al resto de equipos similares en su ubicación definitiva dentro de /etc/pkgsync/musthave o /etc/pkgsync/musthave.d/*.


Pedazo artículo el de Daniel Marín sobre el Apolo X, ahora que estamos en el 50 aniversario. Seguro que nos tiene preparada una maravilla sobre el Apolo XI en unas semanas.


miércoles, 29 de mayo de 2019

Conectando por ssh a un Clonezilla Live

A veces nos vendría bien conectarnos a la la sesión clonezilla que está ejecutando un compañero o nosotros mismos en otra ubicación, para así poder hacer la clonación desde nuestro puesto de trabajo o ver y depurar las causas de algún error.

Esto no es tan trivial como en un Linux corriente ya que clonezilla arranca como una distribución live con el servicio ssh apagado. Vamos a ver como habilitar el sshd y conectar a la red, permitiendo así la conexión remota desde otra ubicación.

Una vez arrancado clonezilla en el equipo, nos vamos a la shell (ya sea desde el menú o con CTRL-ALT-Fx) y activamos el servicio ssh con:
# sudo service ssh start
A continuación hay que conectar a la red el equipo, para ello nos aseguramos de que tiene un cable ethernet conectado y hacemos:
# sudo ocs-live-netcfg
Que mostrará el asistente de conexión a red. Lo habitual es elegir "dhcp" y apuntar la IP que se recibe.

Una vez hecho esto, el pc con el clonezilla queda a la espera, y desde la otra ubicación podemos conectarnos con:
# ssh user@ip.del.clonezilla
La contraseña por defecto es "live". Una vez conectados en remoto tenemos una shell desde donde realizar las tareas que deseemos sobre la máquina remota, incluyendo lanzar el asistente de clonezilla:
# sudo clonezilla
Si además estamos conectando a una ubicación remota donde hay un compañero, puedes sernos usar el comando "screen" para compartir la sesión y que ambos podamos ver a la vez lo que se hace en una pantalla común. Estos dos enlaces nos muestran como hacerlo:



Este es el tren de 60 satélites Starlink de Elon Musk surcando el cielo. Se pueden observar con unos prismáticos si estamos en una zona de baja contaminación lumínica.

Con este enlace podemos ver en tiempo real por donde va el tren de satélites y nos permite saber cuando pasará por nuestra vertical.

miércoles, 22 de mayo de 2019

TVHeadend: configuración y uso (II)

Seguimos con el Tvheadend. Después de instalarlo, configurarlo y conectarlo a varios streams de IPTV para jugar con ellos, en este post vamos a ver como configurarlo con una tarjeta de TV física.

1. Hardware.

Para ello usaremos una tarjeta TDT PCI. En su día ya estuvimos lidiando con otra parecida. Identifiquemos la tarjeta:
# lspci -nnvv

04:01.0 Multimedia controller [0480]: Philips Semiconductors SAA7134/SAA7135HL Video Broadcast Decoder [1131:7134] (rev 01)
 Subsystem: Creatix Polymedia GmbH Medion 7134 [16be:0003]
 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
 Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
 Latency: 64 (21000ns min, 8000ns max)
 Interrupt: pin A routed to IRQ 16
 Region 0: Memory at febffc00 (32-bit, non-prefetchable) [size=1K]
 Capabilities: [40] Power Management version 1
  Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
  Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
 Kernel driver in use: saa7134
 Kernel modules: saa7134
La carga del driver la he configurado así:
# cat /etc/modprobe.d/saa7134.conf 
options saa7134 card=12 alsa=1
install saa7134 /sbin/modprobe --ignore-install saa7134; /sbin/modprobe saa7134-dvb ; /sbin/modprobe tuner ; /sbin/modprobe tda9887
En el arranque, el syslog recoge estos mensajes de detección:
# dmesg |grep saa
[   13.906748] saa7134: saa7130/34: v4l2 driver version 0, 2, 17 loaded
[   13.906963] saa7134: saa7134[0]: found at 0000:04:01.0, rev: 1, irq: 16, latency: 64, mmio: 0xfebffc00
[   13.906971] saa7134: saa7134[0]: subsystem: 16be:0003, board: Medion 7134 [card=12,insmod option]
[   13.906999] saa7134: saa7134[0]: board init: gpio is 0
[   14.076684] saa7134: i2c eeprom 00: be 16 03 00 54 20 1c 00 43 43 a9 1c 55 d2 b2 92
[   14.076688] saa7134: i2c eeprom 10: 00 ff 86 0f ff 20 ff 00 01 50 32 79 01 3c ca 50
[   14.076690] saa7134: i2c eeprom 20: 01 40 01 02 02 03 01 00 06 ff 00 1f 02 51 96 2b
[   14.076692] saa7134: i2c eeprom 30: a7 58 7a 1f 03 8e 84 5e da 7a 04 b3 05 87 b2 3c
[   14.076694] saa7134: i2c eeprom 40: ff 1d 00 c2 86 10 01 01 00 00 fd 79 44 9f c2 8f
[   14.076696] saa7134: i2c eeprom 50: ff ff ff ff ff ff 06 06 0f 00 0f 00 0f 00 0f 00
[   14.076698] saa7134: i2c eeprom 60: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076701] saa7134: i2c eeprom 70: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076703] saa7134: i2c eeprom 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076705] saa7134: i2c eeprom 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076707] saa7134: i2c eeprom a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076709] saa7134: i2c eeprom b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076711] saa7134: i2c eeprom c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076714] saa7134: i2c eeprom d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076716] saa7134: i2c eeprom e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.076718] saa7134: i2c eeprom f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   14.106696] saa7134: saa7134[0] Board has DVB-T
[   14.106700] saa7134: saa7134[0] Tuner type is 63
[   14.513476] saa7134: saa7134[0]: registered device video0 [v4l2]
[   14.513564] saa7134: saa7134[0]: registered device vbi0
[   14.513639] saa7134: saa7134[0]: registered device radio0
[   14.609062] saa7134_dvb: dvb_init() allocating 1 frontend
[   14.706705] DVB: registering new adapter (saa7134[0])
[   14.706713] saa7134 0000:04:01.0: DVB: registering adapter 0 frontend 0 (Philips TDA10046H DVB-T)...
[   17.115786] saa7134_alsa: saa7134 ALSA driver for DMA sound loaded
[   17.115822] saa7134_alsa: saa7134[0]/alsa: saa7134[0] at 0xfebffc00 irq 16 registered as card -1
[   30.560105] saa7134 0000:04:01.0: DVB: adapter 0 frontend 0 frequency 0 out of range (51000000..858000000)
Y puesto que el driver está bien configurado, crea los dispositivos adecuados en /dev:
# ls -l /dev/dvb/adapter0/*
crw-rw----+ 1 root video 212, 4 may 15 16:49 /dev/dvb/adapter0/demux0
crw-rw----+ 1 root video 212, 5 may 15 16:49 /dev/dvb/adapter0/dvr0
crw-rw----+ 1 root video 212, 3 may 15 16:49 /dev/dvb/adapter0/frontend0
crw-rw----+ 1 root video 212, 7 may 15 16:49 /dev/dvb/adapter0/net0

2. Canales TDT.

Cada zona de España tiene sus propios canales TDT en función del repetidor. Por tanto, según sea nuestra ubicación geográfica debemos conocer que frecuencias se utilizan y qué canales hay disponibles dentro de cada frecuencia. Esto se puede consultar en la página http://www.tdt1.com, donde aparece la información tal que así:


Para no tener que meter las frecuencias a mano, todos los programas de manejo de la TDT (vlc, kaffeine, Tvheadend, ...) cuentan con algún script o fichero de configuración donde vienen las frecuencias de nuestra zona. En el caso de Tvheadend la ubicación de estos ficheros es:
# ls /usr/share/tvheadend/data/dvb-scan/dvb-t/es-*
/usr/share/tvheadend/data/dvb-scan/dvb-t/es-Alava
/usr/share/tvheadend/data/dvb-scan/dvb-t/es-Albacete
/usr/share/tvheadend/data/dvb-scan/dvb-t/es-Alfabia
/usr/share/tvheadend/data/dvb-scan/dvb-t/es-Alicante
...
Como a veces el gobierno reubica las frecuencias con el fin de hacer sitio para la telefonía móvil puede suceder que estos ficheros anteriores estén obsoletos. Afortunadamente hay gente que pone en github un repositorio con ficheros actualizados. Por tanto no está mal comparar el fichero correspondiente a nuestra zona con el del repositorio y actualizarlo si fuese necesario.

3. Configuración de Tvheadend.

Una vez pinchada la tarjeta y arrancado el PC, esta aparece en la configuración de Tvheadend al entrar por su interface web:


A partir de aquí, la secuencia de pasos es bastante parecida a lo hecho en el post anterior:

  • Creamos una red para la TDT: Configuration->DVB Inputs->Networks->Add Network->DVB-T Network (el nombre técnico real de la TDT es "DVB-T"):


    En el formulario seleccionamos "Enabled", damos nombre a la red ("TDT"), y en "Pre-defined muxes" elegimos el fichero de configuración de frecuencias TDT correspondiente a nuestra zona (la que vimos en el apartado previo - en mi caso es "es-Carceres". No es un error: hace años alguien lo escribió mal y la errata se ha perpetuado):


    Al dar a "Create" se crea la red y los muxes asociados a las frecuencias definidas en el fichero de configuración asociado.
  • Ahora hay que vincular la tarjeta de TV y la red, ya que si no Tvheadend no sabe dónde sintonizar las frecuencias definidas para los muxes recién creados. Para ello vamos a Configuration->DVB Inputs->TV Adapters y pinchamos sobre la tarjeta de TV. Aparecerá un formulario para la configuración de la misma. Allí nos aseguramos de que "Enabled" y "Over-the-air EPG" estén activados. En el desplegable "Networks" seleccionamos "TDT", que es la red creada en el paso anterior. Al dar al botón "Save" se guardan y aplican los cambios.

  • Muxes y servicios: ahora los muxes encuentran un "origen" de señal y empiezan a sintonizar los canales. En Configuration->DVB Inputs->Muxes nos aparece la lista de muxes, uno asociado a cada frecuencia (expresada en MHz):


    Dentro de cada mux/frecuencia hay varios canales multiplexados. Esos canales deberían aparecer en la pestaña Configuration->DVB Inputs->Services:


    Nota: en el caso de que no aparezcan los servicios de forma automática podemos volver a la pestaña Muxes y darle al reproductor de cada mux (botón de la columna más a la izquierda que muestra la etiqueta "Play this stream"), eso descarga un fichero con un stream que se abrirá en vlc y mostrará uno de los canales del mux. Al hacer esto se fuerza la detección de los canales y la creación de los servicios correspondientes.

  • Mapeo de los servicios en canales de Tvheadend: una vez tenemos cada uno de los canales de TDT sintonizados metido como servicio en Tvheadend es el momento de decidir que canal queremos que se converta en un canal de Tvheadend.

    Recordemos que Tvheadend distingue entre servicio (un stream de vídeo entrante) y canal (canal de Tvheadend que aparecerá en el interface web, las aplicaciones cliente android y sobre el que podremos programar grabaciones). De esta manera podemos ignorar los canales entrantes que no nos interesen y configurar solo unos cuantos de ellos de cara al usuario final.

    Esto lo hacemos en Configuration->DVB Inputs->Services->Map Selected, que permite mapear los servicios que queramos en canales:


    Una vez mapeado, si nos vamos a Channel EPG->Channel podremos ver el canal recién creado:

    Con esto dicho canal ya estará disponible en los clientes Tvheadend y sobre el podremos programar grabaciones y timeshifts. A partir de aquí sólo tendremos que repetir esto con todos los canales que nos interese tener.

4. Enlaces.

Para escribir este post he tenido que buscar la información en varias fuentes muy interesantes donde se hablan tanto de sintonización TDT como satélite, así que pongo los enlaces usados por si quisieramos ampliar:

Veamos esta foto:


La sonda lunar del Estado Nación Judío de Israel se hace un selfie un ratito antes de estrellarse violentamente contra la Luna, en lugar de aterrizar suavemente. Quizá lo confundió con la franja de Gaza.

jueves, 9 de mayo de 2019

Configuración de pórtatiles TechComputer TC11

Nos han llegado unos portátiles TechComputer TC11, unos clónicos que internamente se identifican (usando dmidecode podemos verlo) como P325J. Traen una imagen de Xubuntu 18 para miniportátiles casi totalmente configurada. Anotaré en esta entrada las modificaciones que vaya haciendo.

Lo primero es definir en /etc/escuela2.0 las variables que identifican al nuevo modelo de equipo, de cara a aplicar reglas puppet:
# cat /etc/escuela2.0
SISTEMA=ubuntu1804
USO=portatiles
HARDWARE=TC11
USUARIO=alumno

Para los portátiles tengo un módulo puppet "xubuntu18_portatil_ajustes", en la cual hay un case por $hardware:

...
case $hardware {
    "TC11": {
       file {"/etc/X11/xorg.conf.d":
            owner => root , group => root , mode => 644 , 
            ensure => directory,
       }

       file {"/etc/X11/xorg.conf.d/10-xorg-tc11.conf":
            owner => root , group => root , mode => 644 , 
            source => "puppet:///modules/xubuntu18_portatil_ajustes/10-xorg-tc11.conf",
       }
       #Cambia resolucion del grub para que en consola aparezca bien el contenido.
       file { "/etc/default/grub":
            source => "puppet:///modules/xubuntu18_portatil_ajustes/grub.default.TC11",
            owner => root , group => root , mode => 644 , 
       }
       exec { "update-grub2":
            subscribe => File ["/etc/default/grub"],
            refreshonly => true
       }
       #Certificado ldap
       file { "/etc/ldap/ssl/ldap-server-pubkey.pem":
            owner => root , group => root , mode => 644 , 
            source => "puppet:///modules/xubuntu18_portatil_ajustes/ldap-server-pubkey.pem",
       }
    }
...

Lo que hacemos es:
  1. Añadir un /etc/X11/xorg.conf.d/10-xorg-tc11.conf con una configuración personalizada de Xorg. Por defecto estos portátiles vienen con una resolución altísima que deja la letra muy pequeña. El fichero 10-xorg-tc11.conf para una resolución de 1360x768 (se pueden probar otras resoluciones posibles usando el comando xrandr en un terminal) sería:
    Section "Device"
            ### Available Driver options are:-
            ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
            ### <string>: "String", <freq>: "<f> Hz/kHz/MHz",
            ### <percent>: "<f>%"
            ### [arg]: arg optional
            #Option "ColorKey" "integer"
            #Option "DRI" "string"
            #Option "CacheLines" "integer"
            #Option "DDC" "boolean"
            #Option "Dac6Bit" "boolean"
            #Option "XvMCSurfaces" "integer"
            #Option "Accel" "boolean"
            #Option "Present" "boolean"
            #Option "AccelMethod" "string"
            #Option "TearFree" "boolean"
            #Option "ReprobeOutputs" "boolean"
            #Option "VideoKey" "integer"
            #Option "XvPreferOverlay" "boolean"
            #Option "Backlight" "string"
            #Option "CustomEDID" "string"
            #Option "FallbackDebug" "boolean"
            #Option "DebugFlushBatches" "boolean"
            #Option "DebugFlushCaches" "boolean"
            #Option "DebugWait" "boolean"
            #Option "HWRotation" "boolean"
            #Option "VSync" "boolean"
            #Option "PageFlip" "boolean"
            #Option "SwapbuffersWait" "boolean"
            #Option "TripleBuffer" "boolean"
            #Option "Tiling" "boolean"
            #Option "LinearFramebuffer" "boolean"
            #Option "RelaxedFencing" "boolean"
            #Option "XvMC" "boolean"
            #Option "Throttle" "boolean"
            #Option "HotPlug" "boolean"
            #Option "Virtualheads" "integer"
            #Option "ZaphodHeads" "string"
            #Option "ZaphodHeads" "LVDS1,VGA1"
            #Option "ZaphodHeads" "0,2:HDMI1,DP2"
            #Option "Position" "0 0"
            #Option "Position" "1024 0"
            #Option "RightOf" "Laptop FoodBar Internal Display"
            #Option "monitor-LVDS" "Laptop FooBar Internal Display"
            #Option "monitor-VGA" "Some Random CRT"
            Identifier  "Card0"
            Driver      "intel"
            BusID       "PCI:0:2:0"
    EndSection
    
    Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        SubSection             "Display"
                Depth               24
                Modes              "1360x768" #Choose the resolution
        EndSubSection
    EndSection
    

  2. De igual manera, el grub aparece con una letra minúscula, para solucionar esto debemos meter un nuevo fichero /etc/default/grub y regenerarlo:
    # If you change this file, run 'update-grub' afterwards to update
    # /boot/grub/grub.cfg.
    # For full documentation of the options in this file, see:
    #   info -f grub -n 'Simple configuration'
    
    GRUB_DEFAULT=0
    GRUB_HIDDEN_TIMEOUT=0
    GRUB_HIDDEN_TIMEOUT_QUIET=true
    GRUB_TIMEOUT=10
    GRUB_TIMEOUT_STYLE=menu
    GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
    GRUB_CMDLINE_LINUX="ipv6.disable=1"
    
    # Uncomment to enable BadRAM filtering, modify to suit your needs
    # This works with Linux (no patch required) and with any kernel that obtains
    # the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
    #GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"
    
    # Uncomment to disable graphical terminal (grub-pc only)
    #GRUB_TERMINAL=console
    
    # The resolution used on graphical terminal
    # note that you can use only modes which your graphic card supports via VBE
    # you can see them in real GRUB with the command `vbeinfo'
    GRUB_GFXMODE=800x600
    
    # Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
    #GRUB_DISABLE_LINUX_UUID=true
    
    # Uncomment to disable generation of recovery mode menu entries
    #GRUB_DISABLE_RECOVERY="true"
    
    # Uncomment to get a beep at grub start
    #GRUB_INIT_TUNE="480 440 1"
    GRUB_DISABLE_OS_PROBER=true
    

  3. Los portátiles no traen /etc/ldap/ssl/ldap-server-pubkey.pem, por lo que si usamos Secure LDAP la autenticación nos fallará. Metemos la clave (cogida de otra máquina que si la traiga) por si nos hace falta.
Seguiremos añadiendo cosas en este mismo post según vayan apareciendo problemas a resolver.


Addenda 17/mayo/2019:

  • Algunos portátiles una vez arrancados no cogen red y dan continuos errores en consola de RTC. Eso se debe a que tienen mal la fecha y debemos pulsar ESC o Supr en el inicio para entrar en la BIOS y meter la fecha correcta manualmente.
  • En algún portátil nos ha sucedido que en el arranque no carga el grub, sino que se muestra:
    Que es una shell de EFI. Eso sucede porque en la BIOS no está configurado bien el orden de arranque de dispositivos, el cual debe ser:

Addenda 20/mayo/2019:
Cuando vamos a consola con CTRL-ALT-F1 todo se ve con letra minúscula, tal como se veía el GRUB inicialmente. La modificación hecha antes para arreglarlo en el GRUB no funciona una vez se ha cargado el sistema.

La solución es hacer un script que cargue un font que sea mas visible. El script se llamará /usr/bin/local/fontset:
#!/bin/sh
setfont /usr/share/consolefonts/Uni3-TerminusBold32x16.psf.gz
Después hacemos ejecutable dicho script y lo invocamos en el inicio de sesión de root, añadiendo al final de /root/.profile:
test "$TERM" == "linux" && /usr/local/bin/fontset
Otra solución que he probado es quedar /etc/default/console-setup así:
# CONFIGURATION FILE FOR SETUPCON
# Consult the console-setup(5) manual page.
ACTIVE_CONSOLES="/dev/tty[1-6]"
CHARMAP="UTF-8"
CODESET="Lat15"
FONTFACE="Terminus"
FONTSIZE="16x32"
VIDEOMODE=
FONT="Lat15-Terminus32x16.psf.gz"
Y ejecutar después:
# cp /usr/share/consolefonts/Lat15-Terminus32x16.psf.gz /etc/console-setup/
# update-initramfs -u
# reboot
Esto hace que el cambio de tamaño de font sea ya desde la petición de login...pero en la consola 2 y sucesivas (CTRL-ALT-F2, F3,..). En la primera consola (CTRL-ALT-F1) no comprendo por qué motivo no se cambia.

Si en lugar de estas 3 últimas líneas hacemos "setupcon" se consigue un resultado similar, pero en las pruebas me he encontrado con que no siempre funciona.


Addenda 22/mayo/2019:

Hemos tenido otro problema con el touchpad, que de manera aleatoria deja de funcionar cuando llevamos un rato trabajando, obligándonos a conectar un ratón USB. Se detecta como un dispositivo SYNA3602:00 0911:5288 Touchpad (podemos verlo con "cat /proc/bus/input/devices") y es manejado por el módulo i2c_hid. Si buscamos en Internet vemos que tiene un pequeño historial de problemas.

La solución propuesta por nuestros compañeros de servicios centrales es actualizar el kernel y sus módulos a la versión 5.0.0-15, lo cual podemos hacer con unas reglas puppet:
package { 'linux-image-5.0.0-15-generic' :
    ensure => "installed" ,
}
package { 'linux-modules-5.0.0-15-generic' :
    ensure => "installed" ,
}
package { 'linux-modules-extra-5.0.0-15-generic' :
    ensure => "installed" ,
}
Y después de esto no vuelve a aparecer el problema del touchpad.


Addenda 23/mayo/2019:

Seguimos con cosas para corregir o mejorar que van descubriendo los compañeros.

En el escritorio de los portátiles parece el disco "sda2" accesible. Esta partición es donde se guarda clonezilla y lo mas adecuado es ocultarla con este fichero de configuración:
# cat /etc/udev/rules.d/99-hide-disks.rules
KERNEL=="sda2", ENV{UDISKS_IGNORE}="1"
Si queremos acceder desde los portátiles a la carpeta compartida /home/instituto hay un pequeño problema con los permisos, que se corrige:
file { "/etc/auto.instituto":
    ensure => file,
    owner => root, group => root, mode => 644,
}

Me despido compartiendo un maravilloso bar que encontré en Bulgaria:


Un buen sitio para un sysadmin y su cerveza.

Listar clientes wifi conectados a un punto de acceso OpenWRT/LEDE

Cuanto tenemos un punto de acceso creado desde un dispositivo con OpenWRT o LEDE en el centro educativo puede suceder que se sature porque hay muchos clientes conectados. Es muy útil saber en cualquier momento cuantos clientes tiene asociados nuestro punto, por si fuera necesario hacer una limpieza.

Esto lo haríamos con el comando:
# iw dev wlan0 station dump | grep Station
o bien con:
# iwinfo wlan0 assoclist
Siendo wlan0 la tarjeta wifi sobre la que se monta el punto de acceso. Una vez averiguadas las MACs podemos hacer limpieza expulsando clientes con:
# ubus call hostapd.wlan0 del_client "{'addr':'00:11:22:33:44:55', 'reason':5, 'deauth':false, 'ban_time':0}"

En el último mes Space X nos ha alegrado con el lanzamiento y aterrizaje exítoso de un Falcon Heavy con carga útil (un satélite Arabsat). El despegue:


El aterrizaje de los dos boosters, siempre me queda estremecido esta imagen:


Y el aterrizaje de la etapa central en la barcaza "Of course, I still love you":


Por desgracia, la etapa central cayó al mar por el fuerte oleaje al volver a tierra, ya que falló el anclaje. No volverá a suceder, seguro.

El alucinante vídeo con todo el aterrizaje:

jueves, 25 de abril de 2019

Monitorizando los puestos del aula con monit (II)

Seguimos desde aquí. Vamos a ampliar añadiendo controles basándonos en esta entrada de mi compañero Esteban:
  • Temperatura de la CPU
  • Temperatura de la placa base
  • Temperatura del disco duro
  • Temperatura de la GPU (tarjeta gráfica)
  • Velocidad ventiladores
  • Estado de las fuentes de alimentación redundantes en el servidor del centro
Todo esto lo haremos usando los comandos sensors, nvidia-smi, hddtemp y hplog.

El comando sensors es el que mas información da, pero el problema es que es muy dependiente del hardware y con él no obtenemos una salida homogénea con los números bien colocaditos, sino distintos formatos de presentación a partir de los cuales extraemos los datos. A eso hay que añadir que no siempre tenemos accesibles todos los valores de temperaturas y/o ventiladores debido a que a veces los comandos sensors y hddtemp no son compatibles con el hardware subyacente.

Con esto así he adaptado los scripts para que sean los mas completos posibles, pero no es descartable irlos ampliando conforme vayamos recibiendo nuevos equipos o actualizaciones que hagan que sensorsse comunique mejor con el hardware.

El fichero de monitorización para todas la máquinas sería (esto se añadiría a la tarea puppet vista en el post anterior):
# cat /etc/monit/conf.d/monitrc.temperatura
check program mbtemperatura with path "/usr/local/bin/mbtemp.sh"
   if status > 60 for 3 cycles then alert
   group temperature

check program cputemperature  with path "/usr/local/bin/cputemp.sh"
   if status > 65 for 3 cycles then alert
   group temperature

check program hddtemperature with path "/usr/local/bin/hddtemp.sh"
   if status > 50 for 3 cycles then alert
   group temperature

check program vgatemperature with path "/usr/local/bin/vgatemp.sh"
   if status > 98 for 3 cycles then alert
   group temperature

check program fanspeed with path "/usr/local/bin/fanspeed.sh"
   if status = 1 for 3 cycles then alert
   group temperature
El script que comprueba la velocidad de los ventiladores (solo funciona en las placas Asus de los servidores LTSP que nos envió Telefónica) sería:
# cat /usr/local/bin/fanspeed.sh
#!/bin/bash
hardware=$(facter hardware)
FANSPEED=0 #
case $hardware in
   "telefonica")
         FANSPEED1=$(sensors |grep "^CPU FAN Speed" | awk '{print $4}')
         FANSPEED2=$(sensors |grep "^CHASSIS2 FAN Speed" | awk '{print $4}')
         test $FANSPEED1 -lt 600 -o $FANSPEED2 -lt 600 && FANSPEED=1       #Si alguno de los ventiladores gira por debajo de los 600RPM se avisa de ello
         ;;
esac
#echo $FANSPEED # for debug only
exit $FANSPEED
Para estos PC, que tienen una placa Asus P5Q DELUXE, la salida de sensors es muy completa:
# sensors
coretemp-isa-0000
Adapter: ISA adapter
Core 0:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 1:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 2:       +43.0°C  (high = +82.0°C, crit = +100.0°C)
Core 3:       +40.0°C  (high = +82.0°C, crit = +100.0°C)

radeon-pci-0100
Adapter: PCI adapter
temp1:        +56.0°C  

atk0110-acpi-0
Adapter: ACPI interface
Vcore Voltage:       +1.13 V  (min =  +0.80 V, max =  +1.60 V)
 +3.3 Voltage:       +3.28 V  (min =  +2.97 V, max =  +3.63 V)
 +5 Voltage:         +5.14 V  (min =  +4.50 V, max =  +5.50 V)
 +12 Voltage:       +12.21 V  (min = +10.20 V, max = +13.80 V)
CPU FAN Speed:      2556 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS1 FAN Speed:    0 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS2 FAN Speed: 3515 RPM  (min =  600 RPM, max = 7200 RPM)
CHASSIS3 FAN Speed:    0 RPM  (min =  600 RPM, max = 7200 RPM)
POWER FAN Speed:       0 RPM  (min =  600 RPM, max = 7200 RPM)
CPU Temperature:     +27.0°C  (high = +60.0°C, crit = +95.0°C)
MB Temperature:      +45.0°C  (high = +45.0°C, crit = +95.0°C)
Por desgracia, en el resto de máquinas que tengo la información es mucho mas limitada.

El script que comprueba la temperatura de la VGA utiliza varios filtros y comandos para extraer a los datos. Su código es:
# cat /usr/local/bin/vgatemp.sh
#!/bin/bash

#ati radeon y nouveau se comprueban con "sensors"
#nvidia se comprueba con nvidia-smi
#intel no se puede monitorizar, no he encontrado herramienta
 
VGATEMP=0
if sensors | grep -q radeon-pci
then
  VGATEMP=$(sensors | sed -n '/radeon-pci/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
else
   if sensors | grep -q nouveau-pci
   then
     VGATEMP=$(sensors | sed -n '/nouveau-pci/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
   else
      if test -f /usr/bin/nvidia-smi
      then
        VGATEMP=$(nvidia-smi -q | grep "GPU Current Temp" | awk '{printf("%d\n",$5)}')
      fi
   fi

fi

#echo $VGATEMP # for debug only
exit $VGATEMP
El script que comprueba la temperatura de la placa base, según el hardware que usemos, sería:
# cat /usr/local/bin/mbtemp.sh
#!/bin/bash
hardware=$(facter hardware)
MBTEMP=0
case $hardware in
   "telefonica") MBTEMP=$(sensors |grep "^MB Temperature:"| awk '{printf $3}'  | tr -d '+°C'  | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   "siatic") MBTEMP=$(sensors | sed -n '/acpitz-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
           ;;
   "infolab" ) MBTEMP=$(sensors | sed -n '/pch_skylake-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)
           ;;

   * ) MBTEMP=$(sensors | sed -n '/acpitz-virtual-0/,/^$/p' | grep "^temp" | tr -d '+°C' | awk '{printf("%d\n",$2 + 0.5)}' | sort -nr | head -1)

        ;;
esac
#echo $MBTEMP # for debug only
exit $MBTEMP
El script que obtiene la temperatura de todos los discos duros y devuelve la mayor entre ellas es:
# cat /usr/local/bin/hddtemp.sh
#!/bin/bash

HDDTEMP=0
DISCOS=$(lsblk  -l | grep disk | cut -f1 -d" ")
for i in $DISCOS
do
  TEMP=$(hddtemp  /dev/$i 2> /dev/null | tr -d "°C " | cut -d":" -f3)
  test -z "$TEMP" && TEMP="0"
  test "$TEMP" -gt "$HDDTEMP" && HDDTEMP="$TEMP"
done

#echo $HDDTEMP # for debug only
exit $HDDTEMP
El script que comprueba la temperatura de la CPU o sus cores y devuelve la mayor:
# cat /usr/local/bin/cputemp.sh
#!/bin/bash
hardware=$(facter hardware)
CPUTEMP=0
case $hardware in
   "telefonica") CPUTEMP=$(sensors |grep "^CPU Temperature"| awk '{printf $3}'  | tr -d '+°C'  | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   "siatic" | "infolab" ) CPUTEMP=$(sensors |grep "^Package id"| awk '{printf $4}'  | tr -d '+°C' | awk '{printf("%d\n",$1 + 0.5)}')
           ;;
   * )  CPUTEMP=$(sensors |grep "^Core "| tr -d '+°C' |  awk '{printf("%d\n",$3 + 0.5)}'  | sort -nr | head -1) #El mayor de los cores
        ;;
esac
#echo $CPUTEMP # for debug only
exit $CPUTEMP
En el caso del servidor del centro tenemos un HP Proliant que gracias al paquete hp-health nos permite acceder a más valores interesantes, como el estado de las dos fuentes de alimentación redundantes que tiene.
# cat /etc/monit/conf.d/monitrc.temperatura
check program mbtemperatura with path "/usr/local/bin/mbtemp.sh"
   if status > 60 then alert
   group temperature

check program cputemperature  with path "/usr/local/bin/cputemp.sh"
   if status > 60 then alert
   group temperature

check program hddtemperature with path "/usr/local/bin/hddtemp.sh"
   if status > 50 then alert
   group temperature

check program fanspeed with path "/usr/local/bin/fanspeed.sh"
   if status = 1 then alert
   group temperature

check program powersupply with path "/usr/local/bin/powersupply.sh"
   if status = 1 then alert
   group temperature
El script de chequeo de ambas fuentes de alimentación sería:
# cat /usr/local/bin/powersupply.sh
#!/bin/bash
fans=$(hplog -p | grep Normal | wc -l)
if [ $fans -ne 2 ] #Verificamos que ambas fuentes estén en estado "normal"
then
   salida=1
else
   salida=0
fi
#echo $salida # for debug only
exit $salida
El script de chequeo de los ventiladores (para el HP Proliant se usa hplog en lugar de sensors) sería:
# cat /usr/local/bin/fanspeed.sh
#!/bin/bash
fans=$(hplog -f | grep Normal | wc -l)
if [ $fans -ne 2 ] #Verificamos que ambos ventiladores estén en estado "normal"
then
   salida=1
else
   salida=0
fi
#echo $salida # for debug only
exit $salida
Nota: los valores de temperatura en monitrc.temperatura los he ido afinando con diversas pruebas a lo largo de 10 días, ya que no es raro que haya máximos puntuales sobre todo cuando se reproducen vídeos. Cada uno debe ir probando y cambiando valores hasta dar con el equilibrio óptimo que no te fría a mensajes y a la vez te alerte cuando algo empiece a ir mal.

Bueno, pues hasta aquí hemos llegado. Si nos salen nuevas cosas que comprobar haremos una tercera parte.

domingo, 14 de abril de 2019

Monitorizando los puestos del aula con monit (I)


Mi compañero Esteban ha publicado en su blog varios artículos muy interesantes sobre monit. Resumidamente: monit es un servicio que se encarga de monitorizar el sistema y asegurarse de que otros servicios funcionan y/o informarnos ante determinados eventos.

Aparte de usarlo en los servidores del centro también viene bien tenerlo en funcionamiento en los ordenadores de los profesores dentro del aula, ya que se ocupan de varias tareas críticas dentro del contexto de sus funciones y es recomendable tener asegurada y controlada su disponibilidad.

1. Configuración de alertas mediante correo.

Para que monit nos notifique cosas la opción más sencilla es que nos envíe correos electrónicos a través de una cuenta de Gmail. En mi caso ya tengo en el centro un servidor de correo postfix que redirige sus correos a través de la cuenta de Gmail, tal como conté en al apartado 2 de la entrada sobre la Gestión de Avisos del SAI usando nut, por lo que lo mas correcto es que los distintos servicios monit que hay por los pc del centro envíen sus alertas al servidor postfix y este a su vez lo reenvíe a través Gmail.

Para que el servidor postfix admita correos de cualquier PC de nuestra red hay que editar su fichero /etc/postfix/main.cf y añadir:
..
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.19.196.0/24
..
smtpd_client_restrictions = permit_mynetworks, reject
Siendo 172.19.196.0 mi red local y no olvidando reiniciar el servicio postfix después.

A continuación, en cada /etc/monit/monitrc añadimos:
.....
set mailserver 172.19.196.X port 25

set alert mi.correo@gmail.com not on {instance}

set mail-format { from: mi.correos@gmail.com
subject: $HOST - $SERVICE $EVENT a $DATE
message: Monit $ACTION $SERVICE a $DATE en $HOST, Descripcion: $DESCRIPTION.
}
Siendo 172.19.196.X el servidor donde está ejecutándose el servicio postfix en mi red y mi.correo@gmail.com la cuenta de correo Gmail usada para notificar las alertas. El "not on {instance}" es un filtro para que no nos envien correos de alerta cada vez que el servicio monit se enciende o se apaga, ya que son bastante molestos.

2. Monitorizando servicios básicos.

En los puestos de los profesores tengo como mínimo 2 servicios críticos: dhcp (para dar IP a los portátiles, thinclients o worskstations de alumnos) y tftp (para la imagen de arranque de thinclients).
# cat /etc/monit/conf.d/monit.dhcp
check process dhcpd matching "dhcpd"
  start program "/etc/init.d/isc-dhcp-server start"
  stop  program "/etc/init.d/isc-dhcp-server stop"
Y:
# cat /etc/monit/conf.d/monit.tftp
check process tftp matching "/usr/sbin/in.tftpd"
  start program "/etc/init.d/tftpd-hpa restart"  # El restart funciona mejor, porque a veces si no se hace stop luego no arranca.
  stop  program "/etc/init.d/tftpd-hpa stop"
De igual manera podemos ir añadiendo ficheros para monitorizar cualquier servicio que juzguemos imprescindible.

3. Monitorizando los puntos wifi.

Otro recurso crítico en las aulas son los puntos wifi para permitir la conexión de portátiles y dispositivos móviles. Por regla general están en la IP 192.168.0.1 de la red interna del aula:
# cat /etc/monit/conf.d/monit.puntowifi
check host punto-wifi  with address 192.168.0.1
      if failed icmp type echo count 5 with timeout 30 seconds then alert
De esta manera si hay algún problema con el punto wifi (bloqueo o desconexión de cables) nos llegará una alerta por correo.

4. Monitorizando la conexión de las pizarras digitales.

Esta es más divertida: las pizarras digitales se conectan por USB y a veces por accidente o por diabluras de los alumnos se desconecta el cable que las une al PC.
# cat /etc/monit/conf.d/monit.pizarra
check program pizarra with path /usr/local/bin/check_pizarra
    if status != 0 then alert
Evidentemente, para este caso no hay orden específica de monit, lo que tenemos es un script que busca la pizarra entre los dispositivos USB y devuelve 1 si no la encuentra.
# cat /usr/local/bin/check_pizarra
#!/bin/bash
# Devuelve 1 para avisar de desconexión, 0 si esá conectada o bien ya se avisó.

pizarra=$(lsusb -d 0b8c: ; lsusb -d 13ff:) # 0b8c:0069  0b8c:0001  13ff:0008 - Pizarras SmartBoard 480/640 y Galneo
if test -z "$pizarra"
then
     if ! test -f /var/cache/no-pizarra
     then
         retorno=1
         touch /var/cache/no-pizarra
     else
         retorno=0 # Ya se avisó, no necesario volver a hacerlo
     fi
else
      retorno=0
      rm -f /var/cache/no-pizarra  # Reconectada, se borra el testigo de aviso.
fi
exit $retorno
De esta manera se avisa de forma inmediata de cualquier desconexión, quedando registrado en el correo el momento en que sucedió por si necesitamos hacer indagaciones posteriores.

5. Monitorizando teclados y ratones.

Al igual que las pizarras digitales, los teclados y ratones en los puestos del profesor son causa de algún que otro problema. Ya traté este tema en otro artículo, pero ahora lo enfocaré para que la detección se haga desde monit:
# cat /etc/monit/conf.d/monit.kbmouse
check program teclado_raton with path /usr/local/bin/check_kb_mouse
    if status != 0 then alert
Siendo el script:
# cat /usr/local/bin/check_kb_mouse
#!/bin/bash

FICHERO=/var/cache/kbvigila

#En teclados Sweex USB, aparece mouse en devices, aun cuando no haya ratón 
#conectado. Con el filtro grep -v kbd eliminamos esas lineas, para que solo
#coja las corresponden a un ratón real.
raton=$(cat /proc/bus/input/devices  | grep -i mouse | grep -v kbd | grep Handlers| wc -l)

#En teclados RML, la cadena es "keykoard" en lugar de "keyboard"
teclado=$(cat /proc/bus/input/devices  | grep -i key[bk]oard | wc -l)

pizarra=$(lsusb -d 13ff:0008) # Pizarra Galneo
if test -n "$pizarra"
then
   #Las pizarras Galneo se identifican como ratón, asi que hay que decrementar el contador
   ((raton--))
fi

test $raton -eq 0  && hayraton="1" ||  hayraton="2"
test $teclado -eq 0 &&  hayteclado="1" || hayteclado="2"

#En hayXXX: Valor "1": no detectado. 
#           Valor "2": detectado. 

#Recupera el estado anterior de teclado y ratón.
if [ -f $FICHERO ]
then
   km_anterior=$(cat $FICHERO)
else
   km_anterior=""
fi
#Estado actual
km_actual="${hayteclado}${hayraton}"

#Si el estado teclado/raton ha cambiado respecto al estado anterior, devuelve 1
#para que haya una alerta
if  [ "$km_anterior" != "$km_actual" ]
then
   retorno=1
   #Guarda el estado actual para la siguiente comprobación.
   echo "${hayteclado}${hayraton}" > $FICHERO   
else
   retorno=0
fi
exit $retorno
Simplemente se comprueba el estado de conexión de teclado/ratón y se compara con el resultado de la comprobación anterior. Si ha variado algo se lanza un aviso.

6. Tarea puppet.

Todo esto lo distribuyo mediante una tarea puppet que aplicaría a las distintos pc de profesor que quiero monitorizar, siendo el init.pp de la tarea:
class  xubuntu18_monit {

        package { "monit": ensure =>installed }

        service { 'monit':
                ensure  => 'running',
                enable  => true,
                require => Package['monit'],
        }

        file { "monitrc":
                path => "/etc/monit/monitrc",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc",
                ensure => file,
                notify  => Service['monit'],  # Reinicia el servicio si el fichero cambia
                require => Package['monit'],
        }

        case $ies_isltsp {
                "si","yes","true" : {  #En los pc con thinclients hay serficio tftp
                        file { "monitrc-tftp":
                                path => "/etc/monit/conf.d/monitrc.tftp",
                                owner => root, group => root, mode => 600,
                                source => "puppet:///modules/xubuntu18_monit/monitrc.tftp",
                                ensure => file, notify  => Service['monit'], require => Package['monit'],
                        }
                }
                default: { 
                }
        }


        file { "monitrc-wifiap":
                path => "/etc/monit/conf.d/monitrc.wifiap",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.wifiap",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "monitrc-pizarra":
                path => "/etc/monit/conf.d/monitrc.pizarra",
                owner => root, group => root, mode => 600,
                source => "puppet:///modules/xubuntu18_monit/monitrc.pizarra",
                ensure => file, notify  => Service['monit'], require => Package['monit'],
        }

        file { "pizarra":
                path => "/usr/local/bin/check_pizarra",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_pizarra",
        }

        file { "kb_mouse":
                path => "/usr/local/bin/check_kb_mouse",
                owner => root, group => root, mode => 755,
                source => "puppet:///modules/xubuntu18_monit/check_kb_mouse",
        }

}
7. Continuará...

Una vez montado el sistema lo seguiré ampliando con más scripts de monitorización de temperaturas de CPU, placa y GPU, espacio en disco, uso de CPU, estado de las fuentes de alimentación, etc. Lo iremos viendo en artículos sucesivos.


Llevamos unas semanas frenéticas para los espaciotrastornados. Podría hablar de:
  • Increíbles fotos de agujeros negros.


  • El éxito completo de la Falcon Heavy de Space con los tres cohetes reutilizados aterrizando suavemente en sus plataformas.


    ¡Eres grande, Elon Musk!

  • Próxima C: otro candidato a planeta rocoso a 4 años luz de nosotros.

Pero no, la imagen es un eclipse de sol desde la superficie Marte, al pasar las lunas Fobos/Deimos delante del astro rey. ¿Quién tomó esta maravillosa imagen? Mi admirada Opportunity:


Impresionante.

jueves, 28 de marzo de 2019

VirtualBoxing Windows (Parte IV)

1. Introducción.

Venimos de aquí:


Voy a darle otra vuelta de tuerca al asunto porque me he encontrado con la tarea de montar un aula con 15 máquinas virtuales con Windows 10.

Podría haber hecho la configuración completa en cada una de las máquinas a mano, pero he preferido escribir una tarea puppet que automatice todo lo posible los pasos descritos en los enlaces anteriores por dos motivos:
  1. Me da pereza repetir lo mismo n veces. Soy administrador de sistemas: pienso que mi tarea consiste en trabajar construyendo cosas divertidas que me evitan trabajar repitiendo cosas aburridas.
  2. Porque en Xubuntu 18 me he propuesto hacer todo lo que pueda desde puppet para facilitar cualquier nueva instalación y la migración futura a Xubuntu 22.

2. Tarea puppet.

La tarea puppet tiene esta estructura:
├── files
│   ├── 15-vbox.conf
│   ├── Oracle_VM_VirtualBox_Extension_Pack-5.2.18.vbox-extpack
│   ├── run_vbox
│   ├── vbox_permisos
│   ├── VirtualBox.xml
│   └── Win10.vbox
└── manifests
    └── init.pp
Siendo el init.pp:
# cat init.pp                                                                           

import "/etc/puppet/defines/*.pp"

class xubuntu18_virtualbox {

        #Deja todo preparado para arrancar una máquina virtual con run_vbox
        #Solo haria falta instalar el fichero con permisos 777 .vdi en la ruta /datos/VirtualBox VMs/VirtualBox/Win10-Choco-Autocad-Office.vdi. Si se cambia hay que editar los ficheros Virtualbox.xml y Win10.box

        package {"virtualbox": ensure => installed}

        package {"virtualbox-guest-additions-iso": ensure => installed }

        line { entorno_virtualbox:
                file => "/etc/environment",
                line => 'export VBOX_USER_HOME="/datos/VirtualBox VMs/VirtualBox"',
                ensure => present
        }

        $dirs = [ "/datos", "/datos/VirtualBox VMs","/datos/VirtualBox VMs/VirtualBox","/datos/VirtualBox VMs/VirtualBox/Win10","/datos/VirtualBox VMs/VirtualBox/Win10/Logs" ]

        file {$dirs:
                ensure => 'directory',
                owner  => 'root',
                group  => 'root',
                mode   => '0777',
                before => [File ["/datos/VirtualBox VMs/VirtualBox/VirtualBox.xml"], File ["/datos/VirtualBox VMs/VirtualBox/Win10/Win10.vbox"], File ["extpack"] ]
        }

        file { "/datos/VirtualBox VMs/VirtualBox/VirtualBox.xml":
                owner => root , group => root , mode => 644 ,
                source => "puppet:///modules/xubuntu18_virtualbox/VirtualBox.xml",
        }

        file { "/datos/VirtualBox VMs/VirtualBox/Win10/Win10.vbox":
                owner => root , group => root , mode => 644 ,
                source => "puppet:///modules/xubuntu18_virtualbox/Win10.vbox",
        }

        file { "extpack":
                path =>"/datos/VirtualBox VMs/VirtualBox/Oracle_VM_VirtualBox_Extension_Pack-5.2.18.vbox-extpack",
                owner => root , group => root , mode => 644 ,
                source => "puppet:///modules/xubuntu18_virtualbox/Oracle_VM_VirtualBox_Extension_Pack-5.2.18.vbox-extpack",
                notify => Exec ["install_extpack"],
                }

        #El accept-license del extpack para instalacion desatendida se consigue instalando una vez a mano y cogiendo el código que nos muestra
        exec { "install_extpack":
                path => "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                command => 'vboxmanage extpack install --replace --accept-license=56be48f923303c8cababb0bb4c478284b688ed23f16d775d729b89a2e8e5f9eb "/datos/VirtualBox VMs/VirtualBox/Oracle_VM_VirtualBox_Extension_Pack-5.2.18.vbox-extpack"',              
                refreshonly => true,
        }


        #El fichero win.desktop para ir a /usr/share/applications se mete desde la tarea pupet xubuntu18_xfce4, junto con el icono. Aqui no lo haremos.

        file {"/usr/bin/run_vbox":
                owner => root , group => root , mode => 777 ,
                source => "puppet:///modules/xubuntu18_virtualbox/run_vbox"
        }

        file {"/usr/bin/vbox_permisos":
                owner => root , group => root , mode => 777 ,
                source => "puppet:///modules/xubuntu18_virtualbox/vbox_permisos"
        }


        case $uso {
                "infolab" : {
                        file {"/etc/lightdm/lightdm.conf.d/15-vbox.conf":
                                owner => root , group => root , mode => 644 ,
                                source => "puppet:///modules/xubuntu18_virtualbox/15-vbox.conf"
                        }
                }
                "siatic"  : {
                        line { permisos:
                                file => "/usr/lib/siatic/poweron.sh",
                                line => "/usr/bin/vbox_permisos",
                                ensure => present
                        }
                        #En las siatic el directorio /datos se monta sobre el disco duro secundario. En los infolabs va en el raiz, ya que hay espacio de sobra en él.
                        line { disco_secundario:
                                file => "/etc/fstab",
                                line => "/dev/sdb1 /datos ext4 rw,relatime,data=ordered 0 0",
                                ensure => present
                        }
                }
                default: { }
        }

}
Básicamente:
  • Instala los paquetes de virtualbox y su "extension pack" (en este caso la 5.2.18, habría que cambiarlo en función del tu Virtualbox).
  • Crea el árbol de directorios /datos/VirtualBox VMs/VirtualBox/Win10, se configura el entorno para que virtualbox trabaje con esos directorios y pone en ellos los ficheros que definen la máquina virtual de Windows 10. Estos 2 ficheros son VirtualBox.xml y Win10.vbox, extraídos de una configuración manual de un virtualbox donde se prepara todo. Aquí cada cual pondrá lo que necesite según su caso.
  • Se instalan los scripts run_vbox, que abrirá la máquina virtual, y vbox_permisos, que en el inicio de sesión configurará los permisos del usuario para hacer funcionar todo.
  • Si es necesario y en función de la máquina, configuramos en fstab la ruta /datos para que se monte sobre la partición de mayor tamaño.

Aquí está el enlace a la tarea puppet completa, con todos los ficheros excepto el .vdi, evidentemente.

La carpeta /datos tiene este contenido (en negrita los ficheros significativos, el resto son creados de forma automática):
datos
└── VirtualBox VMs
        └── VirtualBox
                ├── compreg.dat
                ├── Oracle_VM_VirtualBox_Extension_Pack-5.2.18.vbox-extpack
                ├── selectorwindow.log
                ├── selectorwindow.log.1
                ├── VBoxSVC.log
                ├── VBoxSVC.log.1
                ├── VBoxSVC.log.2
                ├── VBoxSVC.log.3
                ├── VBoxSVC.log.4
                ├── VBoxSVC.log.5
                ├── VBoxSVC.log.6
                ├── VBoxSVC.log.7
                ├── VirtualBox.xml
                ├── VirtualBox.xml-prev
                ├── Win10
                │   ├── Logs
                │   │   ├── VBox.log
                │   │   ├── VBox.log.1
                │   │   └── VBox.log.2
                │   ├── Win10.vbox
                │   └── Win10.vbox-prev
                ├── Win10-Original.vdi
                ├── Win10.vdi
                └── xpti.dat


El fichero Wind10.vdi es la imagen de disco .vdi con el sistema operativo, enlazada desde dentro de Win10.vbox. El fichero Win10-Original.vdi es una copia que hago cada vez que actualizo Win10.vdi, que queda como un fichero de backup por si se estropease la máquina original tener una copia funcional en poco tiempo.

3. Distribución rápida de imágenes vdi.

Los ficheros .vdi son basante pesados (en mi caso una imagen de 27Gb) y distribuirlos por la red entre diferentes máquinas cuando se añade algo y hay que actualizar en todos los puestos se hace interminable.

Para evitarlo lo mejor es que, si tenemos la opción, hagamos esta distribución usando udpcast, que nos permite copiar por multicast una imagen en 15, 20 o más puestos a casi la misma velocidad que si fuese a un único puesto.

La única condición es que todas las máquinas estén conectadas al mismo switch y esté esté configurado para permitir multicast (con IGM Snooping activado y con ciertos controles -dependientes del modelo del switch- para evitar tormentas de red desactivados). Si todo está bien, la transferencia se realizará hacia todas la máquinas receptoras a unos 80-90Mbps, lo cual nos permitirá distribuir la imagen completa en todo el aula en menos de una hora.

La forma de hacerlo es instalar el paquete udpcast en todas las máquinas y en la máquina emisora (que puede ser cualquier PC del aula) hacer:
# udp-sender --file "/datos/VirtualBox VMs/VirtualBox/Win10.vdi" --interface eno1 --min-receivers 15
Mandamos por la tarjeta de red "eno1" hacia 15 receptores.

En los receptores hacemos:
# udp-receiver --file "/datos/VirtualBox VMs/VirtualBox/Win10.vdi" --interface eno1
Como teclear este comando en todos y cada uno de los receptores es bastante aburrido, aconsejo fervientemente usar tmux-cssh recomendado por mi compañero Esteban para abrir una sesión ssh en todos los receptores y escribir/ejecutar en paralelo las órdenes en los 15 puestos. Una pequeña maravilla.

Una vez hecha la copia de la imagen .vdi no hay que olvidar hacer una copia de seguridad en cada máquina y dar permisos 777 a "Win10.vdi" para permitir su acceso desde cualquier usuario que inicie sesión.

Nota: en mi caso he tenido un problema con la transmisión multicast que hacia que la velocidad de copia se redujese a 2-3Mbps. El problema es que en el aula donde estaba trabajando tenía un punto wifi Dlink DIR-860L configurado además como enlace de red entre el emisor y los receptores. El punto wifi limitaba el tráfico sin que yo cayese en ello, y nos ha hecho perder tiempo a mí y a mi compañero David pensando que el problema estaba en el switch del aula. Ojo por tanto con cualquier dispositivo adicional de electrónica de red que pudiera haber el aula, ya que el tráfico multicast puede ser penalizado al pasar por él.