Administrar VMware Server 2.X desde consola

A menudo sólo disponemos de una conexión SSH a nuestro VMware Server, para poder administrar las máquinas virtuales que contiene. Por suerte, VMware ha contemplado esta situación y nos proporciona una serie de comandos que nos facilitarán esta labor.
El resumen de los comandos que habitualmente uso, es el siguiente:

  • Conocer los datastores que tenemos configurados en nuestro servidor:
    vmware-vim-cmd hostsvc/datastore/listsummary
    Al ejecutar este comando, nos mostrará la lista. Lo más importante de esa lista, quizás sea el nombre del datastore y la ruta del mismo.
    vmware-vim-cmd hostsvc/datastore/listsummary \
    | grep 'url =' \
    | perl -ne 'print "$1\n" if($_=~m/=\s+(\S.+),/);'
    De esta forma tendremos las diferentes rutas de nuestros DataStores. Para saber las máquinas virtuales que tenemos configuradas en nuestro equipo, podremos ejecutar los siguientes comandos:
    export LISTADS=`vmware-vim-cmd hostsvc/datastore/listsummary \
    | grep 'url =' \
    | perl -ne 'print "$1\n" if($_=~m/=\s+\"(\S.+)\",/);'`
    export IFS=$'\n'

    for i in $LISTADS
    do
    c=`echo "$i/" | wc -c `
    ds=`vmware-vim-cmd hostsvc/datastore/listsummary \
    | grep -e 'url =' -e 'name =' \
    | grep "$i" -B1 \
    | perl -ne 'print "$1" if ($_=~m/name\s+=\s+\"(.+)",/);' `

    for k in `find $i -iname "*.vmx" `
    do
    echo "[$ds] `echo $k|cut -c $c-` "
    done
    done
  • Para conocer las máquinas virtuales que se están ejecutando en un momento dado, podremos lanza el comando:
    vmrun -T server  -u USUARIO-VMWARE -p CONTRASEÑA  -h https://code:8333/sdk list
  • Para detener una máquina virtual podremos lanzar:
    vmrun -T server  -u USUARIO-VMWARE -p CONTRASEÑA  -h https://code:8333/sdk stop 'MAQUINA_VIRTUAL'
    Donde MAQUINA_VIRTUAL es el nombre de la máquina virtual, que nos aparece al listarlas
  • Para arrancar una máquina virtual podremos lanzar:
    vmrun -T server  -u USUARIO-VMWARE -p CONTRASEÑA  -h https://code:8333/sdk start 'MAQUINA_VIRTUAL'

Podemos encontrar más ayuda en el libro online: VMware Server 2.0 Essentials

e-Accelerator para PHP

Cuando trabajamos con servidores de aplicaciones PHP la estrategia de implantación debe prestar especial interés a los siguientes factores:

  • Por un lado la cantidad de memoria RAM que consumirá cada proceso del servidor Web que se encargará de atender a los clientes. Si nuestro servidor está configurado con demasiados módulos, cada proceso del servidor Web consumirá mucha RAM. Esto supondrá un problema ante altas cargas de trabajo. Pensar que un proceso de Apache sin optimizar puede consumir sobre los 50M de RAM de nuestro servidor.
  • Y por otro lado se debe considerar el tiempo de respuesta del servidor ante cada petición. Un tiempo de respuesta entre 1 y 3 segundos es algo aceptable para interactuar con el usuario. Lo que supere los tres segundos dará la impresión al usuario que el equipo está muy sobrecargado y abandonará la página.

Mientras que para el primer factor la única solución de la que disponemos es aligerar nuestro servidor Web de módulos innecesarios o cambiar por otro más ligero y eficiente en el consumo de memoria, para mejorar el segundo factor tendremos varias alternativas:
  1. Una primera alternativa será usar cachés transparentes inversas configuradas para servir imágenes y los contenidos estáticos, liberando así a nuestro servidor Web de esta carga de trabajo.
  2. Lo siguiente que deberíamos revisar es la configuración multiproceso de nuestro servidor web. Un servidor web Apache 2.x puede ser configurado para manejar las peticiones de diferente forma, desde el punto de vista en que son creados y manejados los subprocesos necesarios que atienden a cada cliente conectado a este

El primer tipo de gestión multiproceso es Prefork:
  • Apache inicia varios subprocesos y cada petición es atendida por uno de estos; cuando termina con esta petición este subproceso podría atender a otro cliente o ser terminado, según al valor de MaxRequestsPer-Child.
  • Es el modo más estable, ya que un error crítico solo afectaría a una petición. Este es el único modo en que se pueden usar módulos / extensiones que no sean Thread-Safe
  • Requiere más recursos (Memoria RAM y CPU) para atender cierto número de peticiones simultaneas, respecto a otras configuraciones. Esto limita drásticamente la escabilidad del servidor
  • Favorece el uso intensivo de PHP. Los aceleradores de PHP no son Thread-Safe, pero al usarlos junto a Prefork podemos justificar el mayor uso de php (o páginas sin ningún tipo de caché, aparte del acelerador en sí).
  • Prefork es la configuración predeterminada en la mayoría de instalaciones.

El segundo tipo es la gestión de procesos que implementa Apache 2.X es Worker:
  • Apache inicia varios subprocesos y estos a su vez mantienen varios hilos (threads) con los cuales procesaran las peticiones. Un subproceso proceso puede atender a varios clientes a la vez, según se indique en ThreadsPerChild.
  • El hecho de que un subproceso pueda manejar varias peticiones a la vez, hace que se requieran menos recursos para atender a cierto número de peticiones simultaneas.
  • El inconveniente de Worker está en que requiere que todos los módulos/extensiones que se vayan a usar sean Thread-Safe, limitando el tipo de procesamiento que se puede llevar a cabo con el servidor web
  • Un fallo crítico (que el subproceso termine repentinamente) afecta a varias peticiones, por eso se requiere que se cumpla el Thread-Safe
  • Ya que no se pueden usar aceleradores de PHP junto a Worker, el uso intensivo de este debería ser evitado con algún tipo de sistema de caché adicional
  • Worker puede ser una buena solución para un servidor de contenido estático.
  • Worker solo está disponible desde Apache 2.x.

Usar aceleradores php como eAccelerator o XCache también debería considerarse como alternativa para optimizar el tiempo de respuesta. Estos aceleradores se integran con nuestro servidor web y el intérprete de php de manera que cuando llega una petición, el fichero PHP se precompila, para que las siguientes peticiones del mismo fichero php no sea necesario volver a recompilar, ganando unos ciclos de CPU a cada petición.
Para poder instalarlo eAccelarator debemos tener instalado el autoconf, y php-devel. Luego ejecutar:
  • Descargar eAccelerator y descomprimir
    cd /opt/software
    wget http://bart.eaccelerator.net/source/0.9.5.3/eaccelerator-0.9.5.2.tar.bz2

    cd /opt
    tar xjvf /opt/software/eaccelerator-0.9.5.2.tar.bz2
  • Compilar eAccelarator
    cd /opt/eaccelerator-0.9.5.2/
    phpize
    ./configure --enable-eaccelerator=shared
    make
    make install
  • Copiar el módulo al directorio de módulos de PHP
    cp /opt/eaccelerator-0.9.5.3/modules/eaccelerator.* \
    /usr/local/lib/php/extensions
  • Y activar el módulo, editando /etc/php.ini, y añadiendo en la zona de las extensiones la línea:
    extension=eaccelerator.so

Reiniciar nuestro servidor Web para aplicar los cambios. Podemos comprobar también si estamos usando algún tipo de acelerador PHP, ejecutando:
php -v

La foto la he sacado del album de Adam Foster en Flickr.

Lambda-probe

Lambda Probe es una herramienta de software libre que permite monitorizar y administrar instancias de Tomcat, ya sea funcionando como standalone o embebidas dentro de JBoss. Lambda Probe se instala fácilmente como una aplicación web contenida en un archivo WAR, dentro de la instancia Tomcat que se quiere monitorizar.

Es aconsejable monitorizar las aplicaciones Java, aunque sólo sea durante las primeras semanas de su puesta en producción. Esta herramienta nos permite preparar informes relacionados con el rendimiento de las instancias de Tomcat y determinar los requisitos mínimos de memoria y de conexiones. A menudo los administradores de sistemas recibimos aplicaciones que deben ser desplegadas pero desconocemos sus requisitos: con esta herramienta al menos tendremos una primera ayuda.

Para usar esta herramienta tendremos que seguir los siguientes pasos:

  1. Descargamos la herramienta del sitio web oficial.
  2. Desplegamos el WAR en el directorio webapps de nuestro Apache Tomcat
  3. Creamos el archivo $TOMCAT_HOME/bin/setenv.sh y le añadimos la siguiente configuración: CATALINA_OPTS=”-server -Xms256m -Xmx300m -XX:MaxPermSize=128m -Dcom.sun.management.jmxremote”. Lo importante es el argumento com.sun.management.jmxremote que prepara la máquina virtual de Java, para que podamos monitorizarla desde lambad-probe.
  4. Accedemos a la aplicación: http://hostname[:port]/probe
  5. Tener correctamente configurado un usuario con el rol manager en $TOMCAT_HOME/conf/tomcat-user.xml, y acceder con ese usuario.

El fichero tomcat-user.xml deberá tener un usuario con los siguientes roles:
<role rolename="manager"/>
<role rolename="tomcat"/>
<role rolename="admin"/>
<role rolename="poweruser"/>
<role rolename="probeuser"/>
<role rolename="poweruserplus"/>
<user username="probeuser" password="secreto"
roles="admin,manager,poweruser,poweruserplus,probeuser"/>

Las cosas de Microsoft

Esta semana tuve que implementar una serie de consultas sobre dos directorios LDAP: un directorio activo de Microsoft y otro OpenLDAP. La intención era comprobar la fecha en la que los usuarios se habian cambiado la contraseña y compararlas. Esta información se almacena en el atributo pwdLastSet,en el directorio activo y en el atributo sambaPwdLastSet en OpenLDAP.

Para el caso de OpenLDAP, ya tenia experiencia con trabajar con este atributo y su valor contiene el TimeStamp Unix de la fecha en la que el usuario se cambió la contraseña: Esto es el número de segundos transcurridos desde las 0 horas del 1 de Enero de 1970 (UTC/GMT). Esta forma de medir el tiempo es bastante habitual y extendida en diferentes lenguajes de programación (Java, Perl, Python, Bash, Ruby) y sistemas (Unix, MySQL, Postgres, Oracle, etc), como encontramos en www.epochconverter.com.

Mi sorpresa sucede cuando descubro el formato de fecha que usa el valor del atributo pwdLastSet del directorio activo: el número de intervalos de 100 nanosegundos, transcurridos desde las 0 horas del 1 de Enero de 1601, tal y como se describe en http://msdn.microsoft.com/en-us/library/ms974598.aspx.

Hice un pequeño programa en C para Unix, con el fin de poder convertir rápidamente desde el formato de Windows al de Unix, y poder usarlo en mis scripts:

#include 
#include

int main (int argc, char *argv[] ) {

/* Comprobar argumentos */
if ( 2> argc ) {
fprintf(stderr,"ERROR: Debes pasar un valor numerico (de ActiveDir: pwdLastSet)\n");
return 1;
}
/* Constante de conversion */
long int c1= 0x19db1ded53e8000L;
/* Obtener el numero en base 10 */
char * pEnd;
long int li1;
li1 = strtol (argv[1],&pEnd, 10 );
/* Convertir a UnixEpoch */
li1 = ( li1 - c1 ) / 10000000 ;

/* Mostrar en pantalla */
printf ("%ld", li1 );
return 0;
}


Después de esto me planteé varias preguntas, a las que no encontré respuesta: ¿por qué Microsoft siempre hace estas cosas?, ¿por qué se empeñan en reinventar lo globalmente aceptado como referencia o estandard por la comunidad? ¿por qué usaron 1601, y no 1901, o 1001? ¿por qué usar intervalos de 100-nanosegundos, y no nanosegundos directamente o microsegundos, o simplemente segundos? ¿qué ganan con todo esto, aparte de torturar a la gente que realizamos integraciones, con algunos de sus deficientes productos?.

La foto la he sacado de www.ecualug.org.

Mover objetos en LDAP con ldapmodify

Para mover objetos LDAP de una rama a otra, tendremos que crearnos un fichero LDIF con el movimiento que queremos hacer, /tmp/mover.ldif(por ejemplo), con el siguiente contenido:

dn: DN_COMPLETO_DEL_OBJETO_A_MOVER
changetype: modrdn
newrdn: CN=NUEVO_CN
deleteoldrdn: 0
newsuperior: DN_DE_LA_RAMA_DONDE_MOVERLO

...donde...
  • DN_COMPLETO_DEL_OBJETO_A_MOVER es distinguised named del objeto que queremos mover, por ejemplo cn=ignacio,ou=midir,c=es.
  • CN=NUEVO_CN, es el nuevo CN que queremos usar en el destino; podremos cambiarlo si queremos renombrar el objeto.
  • deleteoldrdn, nos servirá para copiar o mover el objeto
  • DN_DE_LA_RAMA_DONDE_MOVERLO, especificará el distinguised name de la rama donde llevar el nuevo objeto. Si lo omitimos, sólo estaremos renombrando el objeto.

Luego, para lanzar la modificación podremos ejecutar el comando...
ldapmodify -x -h IP_SERVIDOR -D LOGIN_ADMIN -w -f /tmp/mover.ldif

Cliente OpenLDAP para consultar el directorio activo

El proyecto OpenLDAP nos provee un cliente LDAP que podemos usar para consultar y modificar nuestros directorios LDAP. El problema nos puede aparecer cuando intentamos consultar un directorio activo: Este requiere SSL para poder conectar y a menudo el certificado está autofirmado. Lo primero será obtener el certificado raíz de la CA que firma el certificado de la comunicación LDAPS. Esto lo podremos hacer como cuento en la entrada anterior, y guardarlo en el fichero /etc/openldap/cacerts/CA/miDirectorioActivo.crt.
Luego crear un fichero de configuración de cliente, /etc/openldap/miDirectorioActivo.conf, personalizado que podría tener siguiente contenido:

# See ldap.conf(5) for details
# This file should be world readable but not world writable.


SIZELIMIT 500
URI ldaps://IP_DOMAIN_CONTROLLER/
BASE DC=miAD,DC=local

TLS_CACERT /etc/openldap/cacerts/CA/miDirectorioActivo.crt
TLS_CACERTDIR /etc/openldap/cacerts/CA

Para que nuestro cliente use esta configuración, ejecutaremos:
export LDAPCONF=/etc/openldap/miDirectorioActivo.conf

...y ya podremos lanzar consultas contra nuestro directorio activo, desde los comandos del cliente OpenLDAP:
ldapsearch -x  -H ldaps://IP_DOMAIN_CONTROLLER \
-D "CN=AdminLDAP,DC=miAD,DC=local" \
-w contraseña \
-b "DC=miAD,DC=local"

Esto también nos funcionará para consultar NDS.

Cliente OpenSSL

A menudo necesitamos conectar a un servicio con soporte SSL desde nuestro sistema Linux, y en la mayoría de estas ocasiones nos encontramos que se han usado certificados autofirmados y que no conocemos la CA Raíz que los firma. Para llevar a cabo la conexión con éxito necesitamos confiar en la entidad raíz que firma el certificado.
Un ejemplo podría ser intentar consultar un servicio de directorio como NDS de Novell o directorio activo de Windows desde nuestro cliente desarrollado en Java con JNDI. Para poder conseguirlo, la CA que firma los certificados debe estar incluida en el keyStore del JRE que estamos usando, y para ello, lo primero será obtener la cadena de certificados que se usa en la comunicación. Esto podemos hacerlo, mediante el cliente OpenSSL ejecutando el siguiente comando:

openssl s_client -connect DIR_IP:PUERTO -showcerts

Donde cambiaremos el DIR_IP por la dirección IP del servidor al que queremos conectar y PUERTO por el número de puerto TCP en el que escucha el servicio al que queremos conectar. En la salida del comando, veremos la cadena de certificados codificados en Base64 que podremos copiar a un fichero .crt e incluirlo en nuestro almacén de certificados raíz en los que confiamos.

La imagen la he sacado del album de Darwin Bell en flickr

Inicializando un directorio OpenLDAP 2.4


Uno de los cambios que trae FedoraCore 12 es OpenLDAP 2.4. Esta versión trae entre otros cambios, la obligatoriedad de usar el backend de configuración dinámica. Los que estábamos acostumbrados a usar toda la configuración de nuestros servidores OpenLDAP en /etc/openldap/slapd.conf, este cambio nos pilla un poco desprevenidos. Por suerte la gente de OpenLDAP había contemplado esto y nos facilita la migración.
Si queremos migrar una configuración de OpenLDAP anterior a 2.4, a esta nueva versión, podemos seguir la siguiente secuencia de pasos:

  1. Hacer un backup de la configuración por defecto que trae el nuevo servicio 2.4
    mv /etc/openldap /etc/openldap_original_2.4
  2. Copiar la configuración del OpenLDAP anterior a /etc/openldap.
  3. Migrar la configuración del antiguo servicio a la versión 2.4, en un directorio temporal:
    mkdir /tmp/export
    slaptest -f /etc/openldap/slapd.conf -F /tmp/export/
  4. Instalar la nueva configuración
    mkdir -m 700 /etc/openldap/slapd.d
    cp -R /tmp/export/* /etc/openldap/slapd.d/
  5. Editar el fichero cn=config para editar /etc/openldap/slapd.d
  6. Fijar el login y contraseña del usuario que podrá modificar dinámicamente la configuración. Para ello, editar el fichero /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{0\}config.ldif para añadir las siguientes líneas:
    olcRootDN: cn=admin,cn=config
    olcRootPW: {SSHA}pT8zKlqhV8dieALrkzwAiK8KdoxNV5m
    La contraseña encriptada la podemos obtener ejecutando el comando slappasswd.
  7. Copiar la configuración del monitor de OpenLDAP, de la configuración original que habíamos movido.
    export FILE=/etc/openldap_original_2.4/slapd.d

    cp $FILE/cn=config/olcDatabase\=\{2\}monitor.ldif \
    /etc/openldap/slapd.d/cn=config/
  8. Hacer copia de seguridad del directorio de la base de datos del directorio y preparar el directorio para inicializar el nuevo directorio:
    mv /var/lib/ldap /var/lib/ldap_original
    mkdir -m 700 /var/lib/ldap
    cp /var/lib/ldap_original/DB_CONFIG /var/lib/ldap/
  9. A partir de un backup del antiguo servidor (hecha con slapcat por ejemplo), preparar un fichero ldif básico con donde se cree la raíz del directorio, y las ramas princiaples. Lo añadiremos con el comando slapadd:
    slapadd -l /tmp/estructura_inicial.ldif 
  10. Cambiar los permisos de la base de datos del LDAP, y del directorio de configuración e iniciar el demonio de LDAP, mediante los siguientes comandos:
    chown -R ldap.ldap /var/lib/ldap /etc/openldap
    /etc/init.d/slapd start
  11. Restaurar la copia de seguridad en el directorio que acabamos de crear...
    ldapadd -x -D "cn=admin,ou=XXX,o=carm,c=es" -w CLAVE \
    -f copia_seguridad.ldif
  12. Recuperar la base de datos del directorio y reparar
    /etc/init.d/slapd stop

    slapindex
    slapd_db_recover -h /var/lib/ldap
    slapindex

    chown ldap.ldap -R /var/lib/ldap
    /etc/init.d/slapd start

Y ya tendremos nuestro directorio funcionado. :)

La imagen la he sacado del album de JPhilipson en flickr