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

sábado, 14 de mayo de 2016

VirtualBoxing Windows (Parte I)

Bueno, pues aunque la Junta de Extremadura apuesta por Linux, a nosotros nos está obligando a dejar también abierto el acceso Windows en determinadas máquinas de los IES, haga falta o no. El año próximo apostará por la comida sana en los comedores escolares y en consecuencia habrá cubos de pollo KFC junto al menú normal. Libeggggtad de elección ante todo.

Como a nadie de los que deciden se le ocurrió que para administrar un número considerable de puestos Windows y no morir en el intento hace falta un Windows Server, directorio activo y mas herramientas de ese estilo, me veo con que tengo que encontrar una manera cómoda de administrar este tinglado intentando que:

1) Los datos de cada usuario puedan ser guardados en un almacenamiento privado y ubicuo dentro de la red del centro. Los tenemos malacostumbrados con nuestro NFS de Linux a esa facilidad de uso y no van a llevar bien volver a los 90 en materia de almacenamiento de datos.

2) Los Windows se estropean o se contagian de virus con una facilidad pasmosa en un sitio donde se comparten los puestos. Debo garantizar una forma rápida y de coste cero de recuperación de Windows a un estado previo.

3) Muchas veces, con un par de días (o minutos) de antelación te piden instalar un software concreto en una serie de puestos, siendo imposible encontrar un hueco para entrar en el aula y prepararlos todos.

Tras darle una docena de vueltas he llegado a la conclusión de que la mejor solución que se me ocurre es:

1) Ejecutar los Windows en una máquina virtual VirtualBox desde una sesión Linux. Eso permite restaurar un Windows rápidamente a un estado previo o distribuir una imagen nueva con software adicional (simplemente es copiar un fichero .VDI conteniendo el disco duro). Esa distribución se pude hacer incluso por la noche y la restauración de imágenes es inmediata.

2) La máquina virtual será definida a nivel de máquina física, en el directorio /opt. Todos los usuarios que hagan login en la máquina física compartirán maquina virtual, no es operativo que cada usuario tenga una máquina virtual en su home como sería el funcionamiento por defecto de VirtualBox.

Para acceder a ella pondremos un icono con un acceso directo en el panel XFCE, de tal manera que no se llega a ver nunca el entorno VirtualBox completo: pinchas y se abre una ventana que carga un Windows. Adjunto captura con el icono para lanzar Windows desde el panel (el icono azul con la ventanita, que poco original):


3) Puesto que antes de llegar a la máquina virtual el usuario tiene que acceder al Linux con sus credenciales, éste tiene acceso a su $HOME del servidor NFS. Lo que voy a hacer es antes de abrir la máquina virtual mapear el $HOME del usuario sobre la unidad E: del Windows (joder, 2016 y todavía con letras de unidad como el CP/M en los años 70). De esta forma, cuando el usuario de la máquina virtual Windows guarde cosas en la unidad E: lo estará haciendo en un sitio seguro externo a la máquina: su carpeta NFS del servidor central.

Bueno, pues una vez establecidos los principios vamos a lo divertido: manos a la obra, que hay que producir riqueza mas rápido que los políticos producen deuda.

Paso 1) Establecer /opt/... para guardar las máquinas vitruales, usando para ello el fichero /etc/environment ya que permite definir variables globales para todo el sistema, que queda:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
VBOX_USER_HOME="/opt/VirtualBox VMs/VirtualBox"
Debemos reiniciar el sistema para que esto se aplique.

Paso 2) Abrimos VirtualBox y creamos la maquina virtual con un nombre WinX, instalamos en ella Windows, lo activamos con su clave de licencia legal y ponemos todo el software que sea necesario. Al final dentro de /opt debe quedar algo parecido a esta estructura (el run_vbox lo vemos ahora en un rato):
/opt/VirtualBox\ VMs/
    run_vbox
    VirtualBox
        compreg.dat
        selectorwindow.log
        VBoxGuestAdditions_4.3.36.iso
        vbox-ssl-cacertificate.crt
        VBoxSVC.log
        VirtualBox.xml
        VirtualBox.xml-prev
        xpti.dat
    Win10
        Logs
        Win10.vbox
        Win10.vbox-prev
        Win10.vdi
Recoordemos que en Wind10.vdi se encuentra el disco duro de la máquina virtual y será el fichero del que hagamos copias para restaurar el sistema y distribuyamos cuando hayamos añadido algo nuevo al sistema que contiene.

Paso 3) Creamos un script que lanzará de forma automática la máquina virtual con un click, para que el usuario no tenga que hacerlo a través de VirtualBox
# cat /opt/VirtualBox\ VMs/run_vbox
#!/bin/bash

#Poniendo esto  /etc/environment
#export VBOX_USER_HOME="/mnt/VirtualBox VMs/VirtualBox"
#en el arranque lo tendremos para todos los usuarios. Maquinas virtuales en local.

machine="Win10"

running=$(VBoxManage list runningvms | grep $machine)
if  [ -n "$running" ]
then
    zenity --error --text "La máquina $machine ya está funcionando"  
else
   #Si cierran la ventana a lo bruto se hace un shutdown de la máquina. Esto al .vbox de la máquina
   #    <extradataitem name="GUI/LastCloseAction" value="Shutdown"/>
   #o bien con VBoxManage...
   VBoxManage setextradata $machine "GUI/LastCloseAction" "Shutdown"

   #Automontamos la carpeta $HOME en el Windows con el nombre "compartido" en la primera unidad libre (E: normalmente).
   VBoxManage sharedfolder add "$machine" --name "compartido" --hostpath "$HOME" --automount

   #Lanzamos la máquina
   VirtualBox --startvm $machine
fi
Paso 4) Creamos un fichero .desktop para el script anterior:
# cat /usr/share/applications/winx.desktop
[Desktop Entry]
Version=1.0
Name=Windows 8
Comment=Windows 8
Exec="/opt/VirtualBox VMs/run_vbox" 
Terminal=false
Icon=/usr/share/icons/hicolor/win8.png
Type=Application
Categories=Categories=X-XFCE;GTK;Utility;
MimeType=text/html;text/xml;application/xhtml_xml;image/webp;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
X-Ayatana-Desktop-Shortcuts=NewWindow;NewIncognito
El icono /usr/share/icons/hicolor/win8.png sería este:

Paso 5) Para colocar el enlace en el panel XFCE y que esté fijo y visible para que todos los usuarios lo tengan a la vista para lanzar el Windows en el momento en que lo deseen utilizo el método descrito en esta entrada:

El fichero con el xfce4-panel.xml quedaría mas o menos (en negrita lo destacable):
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-panel" version="1.0" unlocked="root">
<property name="panels" type="uint" value="1">
<property name="panel-0" type="empty">
<property name="position" type="string" value="p=8;x=840;y=945"/>
<property name="length" type="uint" value="100"/>
<property name="position-locked" type="bool" value="true"/>
<property name="plugin-ids" type="array">
<value type="int" value="1"/>
<value type="int" value="8"/>
<value type="int" value="9"/>
<value type="int" value="11"/>
<value type="int" value="12"/>
<value type="int" value="13"/>
<value type="int" value="10"/>
<value type="int" value="2"/>
<value type="int" value="3"/>
<value type="int" value="4"/>
<value type="int" value="5"/>
<value type="int" value="6"/>
<value type="int" value="7"/>
</property>
<property name="background-alpha" type="uint" value="80"/>
<property name="background-style" type="uint" value="2"/>
<property name="background-color" type="empty"/>
<property name="background-image" type="string" value="/usr/share/images/PanelWin7.png"/>
<property name="size" type="uint" value="36"/>
<property name="autohide" type="bool" value="false"/>
<property name="length-adjust" type="bool" value="true"/>
<property name="span-monitors" type="bool" value="false"/>
<property name="enter-opacity" type="uint" value="100"/>
<property name="leave-opacity" type="uint" value="100"/>
<property name="mode" type="uint" value="0"/>
<property name="nrows" type="uint" value="1"/>
<property name="disable-struts" type="bool" value="false"/>
</property>
</property>
<property name="plugins" type="empty">
<property name="plugin-1" type="string" value="whiskermenu"/>
<property name="plugin-2" type="string" value="tasklist">
<property name="flat-buttons" type="bool" value="true"/>
</property>
<property name="plugin-3" type="string" value="separator">
<property name="style" type="uint" value="0"/>
<property name="expand" type="bool" value="true"/>
</property>
<property name="plugin-4" type="string" value="systray">
<property name="show-frame" type="bool" value="false"/>
<property name="size-max" type="uint" value="22"/>
<property name="names-visible" type="array">
<value type="string" value="blueman-applet"/>
<value type="string" value="miniaplicación gestor de la red"/>
<value type="string" value="ibus panel"/>
</property>
</property>
<property name="plugin-5" type="string" value="indicator">
<property name="blacklist" type="array">
<value type="string" value="com.canonical.indicator.keyboard"/>
<value type="string" value="com.canonical.indicator.session"/>
<value type="string" value="com.canonical.indicator.datetime"/>
<value type="string" value="libappmenu.so"/>
</property>
<property name="known-indicators" type="array">
<value type="string" value="libapplication.so"/>
<value type="string" value="com.canonical.indicator.power"/>
<value type="string" value="com.canonical.indicator.messages"/>
<value type="string" value="com.canonical.indicator.sound"/>
<value type="string" value="libprintersmenu.so"/>
<value type="string" value="com.canonical.indicator.keyboard"/>
<value type="string" value="com.canonical.indicator.session"/>
<value type="string" value="com.canonical.indicator.bluetooth"/>
<value type="string" value="com.canonical.indicator.datetime"/>
</property>
</property>
<property name="plugin-6" type="string" value="separator">
<property name="style" type="uint" value="0"/>
<property name="expand" type="bool" value="false"/>
</property>
<property name="plugin-7" type="string" value="clock">
<property name="digital-format" type="string" value="%d %b, %H:%M"/>
<property name="mode" type="uint" value="2"/>
</property>
<property name="plugin-8" type="string" value="showdesktop"/>
<property name="plugin-9" type="string" value="places">
<property name="blacklist" type="empty"/>
<property name="known-indicators" type="empty"/>
</property>
<property name="plugin-11" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="google-chrome.desktop"/>
</property>
</property>
<property name="plugin-12" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="rayuela.desktop"/>
</property>
</property>
<property name="plugin-13" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="winx.desktop"/>
</property>
</property>
<property name="plugin-10" type="string" value="actions">
<property name="items" type="array">
<value type="string" value="-lock-screen"/>
<value type="string" value="-switch-user"/>
<value type="string" value="+separator"/>
<value type="string" value="-suspend"/>
<value type="string" value="-hibernate"/>
<value type="string" value="-separator"/>
<value type="string" value="-shutdown"/>
<value type="string" value="-restart"/>
<value type="string" value="-separator"/>
<value type="string" value="+logout"/>
<value type="string" value="-logout-dialog"/>
</property>
<property name="appearance" type="uint" value="0"/>
<property name="invert-orientation" type="bool" value="false"/>
<property name="ask-confirmation" type="bool" value="true"/>
</property>
</property>
<property name="configver" type="int" value="2"/>
</channel>
Paso 6) Con todo ya montado, he hecho vídeo en el que abrimos el Windows y jugamos con el un rato, creando ficheros sobre el $HOME del usuario que está ejecutando todo. Eso garantiza que esos icheros estarán ubicuos en cualquier ordenador de la red y no se quedarán enclaustrados dentro de la máquina virtual Windows. Enlace al vídeo (reproducelo en HD para ver bien los detalles) https://drive.google.com/open?id=0B8np4HndYC-lMmZxWlRSZndIRVE.



Una cuestión interesante es el tema de las licencias. Cada máquina virtual debe tener la licencia correcta, pero si nos dedicamos a copiar VDI de una máquina física a otra, todo va con la misma licencia. ¿Como se soluciona esto?. Sencillo:

  • Aquí contamos como extraer la licencia del Windows que nos viene de serie en cada máquina fisica. Por supuesto, también podemos tener los números de licencia si los hemos comprado por otra vía.
  • Aquí nos cuentan como con un sencillo script .vbs que viene de serie podemos cambiar el código de licencia de un Windows y activarlo fácilmente.

Como colofón me dejo un par de notas que con vías interesantes para explorar en el futuro:
  • Crear un usuario o sesión que abra un VirtualBox a pantalla completa, sin entorno de escritorio gráfico. Todo el escritorio para Windows, pero un Linux por debajo.
  • Encontrar como hacer un mapeo para acceder a los pendrives pinchados en la máquina física.

Con esto podemos decir que todos nuestros usuarios tendrán acceso a Windows en las máquinas donde adoptemos este modelo, les haga falta o no. Ya pueden respirar tranquilas nuestras autoridades.

2 comentarios:

  1. ¡Chapeau Alfonso! Me descubro ante tamaño trabajo de desfacer entuertos. Estoy sintiendo el aliento de mi tic, para que le instale el Mblock en el win de los infolabs...Si no le vendo esto es porque ya está obnubilado por la opción "Windows" en el grub, como Don Quijote, cuando sólo veía gigantes donde los demás vemos "xubuntu"...

    ResponderEliminar
  2. Bueno, se lo puedes vender con lo que comento arriba: 1)
    los usuarios tendrán acceso a su home de Linux, nadie perderá sus documentos porque se los borre otro / 2) si un windows falla o peta se lo restauras en cuestión de minutos, no hay que esperar a cargar y configurar una imagen / 3) si bloqueas las actualizaciones en las imagenes virtualbox, no le robará nunca mas tiempo el "Espere, aplicando actualizaciones..." al comienzo o final de las clases.

    ResponderEliminar