Openstack: Prueba de concepto – Parte 2

En relación a la entrada anterior, he querido mostrar una demostración en un vídeo en YouTube. El vídeo esta grabado sobre la prueba de concepto que monté. En el siguiente gráfico se puede ver la arquitectura:


Existen cuatro nodos de computación, y uno de ellos además, lleva el resto de elementos de Openstack. Todo está funcionando sobre Ubuntu 12.04 y montado con servidores con una única interfaz física.

Para las instancias he descargado las imágenes UEC que ya tiene preparadas Canonical.

El vídeo se podría dividir en dos partes. En la primera parte se muestran los principales comandos para trabajar con imagenes, «flavors», arrancar instancias y terminarlas.

A continuación se hace un repaso por la Dashboard viendo como es sumamente sencillo la creación y despliegue de nuevas instancias. También he aprovechado para trabajar con volúmenes y demostrando que se pueden mover de una instancia a otra manteniendo la información que contienen.

Aquí se puede ver el vídeo:

OpenStack: Prueba de concepto – Parte 1

Estos días he tenido la opción de montar una pequeña prueba de concepto sobre Openstack. La idea es ver como funciona y analizar si en un futuro se podría implementar en un entorno productivo.

Me he basado en la documentación de Cloud – IES Gonzalo Nazareno concretamente en el documento bk-admin-openstack.pdf. También he seguido el libro de «recetas»: OpenStack Cloud Computing Cookbook.

Lo que he montado es básicamente una arquitectura de cuatro nodos. Uno de ellos es el Cloud Controller, donde estará todo el software necesario de Openstack: nova-compute, nova-network, nova-volume, glance y keystone. En los otros tres nodos únicamente se ha instalado el modulo de computación, nova-compute.

El hipervisor elegido para las pruebas ha sido KVM, con la idea de poder tener imagenes de otros sistemas operativos, además de imágenes de distribuciones GNU/Linux.

El esquema lógico sería el siguiente:

Por ciertas limitaciones únicamente he podido disponer de una interfaz de red cableada, por ello he apostado por el diseño mas sencillo con FlatDHCP. Aún así, las instancias son capaces de verse entre si a pesar de correr en diferentes hosts.

Ficheros de configuración:
Tal y como se explica en la documentación, el único fichero que hay que ir tocando es el /etc/nova/nova.conf. Yo copié el que indica en el documento  bk-admin-openstack.pdf y lo adapté a mi entorno. Básicamente hay que cambiar la IP que aparece por cada servicio por la del nodo que yo utilizaba como controlador. El apartado que me dió mas problemas fue el de red. Hay que tener mucho cuidado con los segmentos que se definen para las redes privadas, ya que es posible que se den problemas de routing. El apartado de configuración de red quedó de la siguiente manera:

# NETWORK
network_manager=nova.network.manager.FlatDHCPManager
force_dhcp_release=True
dhcpbridge_flagfile=/etc/nova/nova.conf
dhcpbridge=/usr/bin/nova-dhcpbridge
firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver
my_ip=X.X.3.91
public_interface=eth0
flat_network_bridge=br100
flat_interface=eth1
fixed_range=192.168.221.0/27
floating_range=192.168.221.32/27
routing_source_ip=X.X.3.91
start_guests_on_host_boot=true
resume_guests_state_on_host_boot=true
network_size=10
flat_network_dhcp_start=192.168.221.10
flat_injected=False
force_dhcp_release=True
root_helper=sudo nova-rootwrap

El fichero nova.conf será el mismo en todos los nodos, lo único que habrá que cambiar es la variable my_ip. También hay que tener en cuenta la configuración de la consola vnc para poder acceder desde la interfaz web:

# VNC
novnc_enabled=true
vnc_keymap=es
novncproxy_base_url=http://10.150.3.91:6080/vnc_auto.html
vncserver_proxyclient_address=10.150.3.92
vncserver_listen=10.150.3.92
vnc_console_proxy_url=http://10.150.3.91:6080

Aquí habrá que modificar las IPs en las variables vncserver_proxyclient_address y vncserver_listen. En las otras dos variables se dejará la IP del nodo donde se instala la Dashboard.

Como punto importante, ya en la configuración de Keystone, es necesario configurar las variables de entorno del usuario que vamos a autilizar para manejar los servicios de Nova. Para ello, en el fichero .bahsrc hay que introducir las siguientes líneas (en mi caso en el de root):

export SERVICE_ENDPOINT=»http://X.X.3.91:35357/v2.0″
export SERVICE_TOKEN=PASSWORD
export OS_TENANT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=PASSWORD
export OS_AUTH_URL=»http://X.X.3.91:5000/v2.0/»

Una vez con esto configurado ya podemos empezar a hacer pruebas con Openstack.

Problemas encontrados:
Hasta encontrar la configuración que funciona he tenido que ir jugando con los diferentes flags de los ficheros de configuración. Alguna vez, después de arrancar instancias, se han quedado en un estado inconsistente, siendo imposible el borrado de de las instancias de forma convencional. Para ello hay que conectarse a la base de datos y borrar los datos que hacen referencia a las instancias. Para hacerlo mas sencillo me monté un pequeño script en python que saca un listado de las instancias y permite borrar una o el borrado de todas. El script es el siguiente:

#!/usr/bin/python
#coding: iso-8859-15
import MySQLdb
import sys

db = MySQLdb.connect(host=’HOST’,user=’nova’, passwd=’PASSWORD’, db=’nova’)
cursor = db.cursor()
consulta = ‘select id, uuid from instances’
cursor.execute(consulta)
instances = cursor.fetchall()

for inst in instances:
    print «Instancia: %s UUID: %s» % (str(inst[0]), str(inst[1]))



if «–all» in sys.argv:
    print ‘Limpiando todas las instancias’
    cont = raw_input(‘¿Continuar? (s/n): ‘)
    if cont == ‘s’ or cont == ‘S’:
        for inst in instances:
            id=str(inst[0])
            print ‘Borrando instancia %s’ % id
            consulta = ‘delete from instance_info_caches where id=%s’ % id
            cursor.execute(consulta)
                        consulta = ‘delete from security_group_instance_association where id=%s’ % id
                        cursor.execute(consulta)
                        consulta = ‘delete from instances where id=%s’ % id
                        cursor.execute(consulta)
            db.commit()
        print ‘Todas las instancias borradas’
else:
    id = raw_input(‘Selecciona la instancia a borrar: ‘)
   
    for inst in instances:
        if str(inst[0]) == id:
            print «Se va a borrar la instancia %s con UUID %s» % (str(id), str(inst[1]))
            cont = raw_input(‘¿Continuar? (s/n): ‘)
            if cont == ‘s’ or cont == ‘S’:
                print ‘Borrando instancia %s’ % id
                consulta = ‘delete from instance_info_caches where id=%s’ % id
                cursor.execute(consulta)
                consulta = ‘delete from security_group_instance_association where id=%s’ % id
                cursor.execute(consulta)
                consulta = ‘delete from instances where id=%s’ % id
                cursor.execute(consulta)
                print ‘Ejecute «nova list | grep %s» para confirmar que se ha borrado la instancia’ % str(inst[1])
                db.commit()

En una ocasión no pude borrar la instancia con el script y era porque a la instancia le había asignado un volumen. Al borrar daba un error de clave referenciada en una tabla, con lo que tuve que borrar dicha entrada en la tabla que indicaba el error. Una vez limpiado se pudo borrar con el script.

Es importante, en caso de tener algún problema, revisar los logs. Allí encontraremos muchas pistas de que puede estar fallando y es muy probable que a alguien le haya pasado antes. Los logs de nova se encuentran en /var/logs/nova y los de KVM, no menos importantes, están en /var/logs/libvirt.

OpenStack: esto si es cloud!

Hace unos días me preguntaron si con Linux se puede virtualizar! LOL

Básicamente lo que querían era algo tipo vSphere pero barato (gratis) y con un buen performance. En GNU/Linux básicamente tenemos dos hipervisores a elegir: KVM y XEN. EL primero parece ser el elegido por Canonical o Red Hat entre otros por la integración con el Kernel de Linux. XEN por su lado esta mas ampliamente implementado en grandes infraestructuras como las de Amazon o Rackspace. Además, existe otra opción, la del uso de contenedores de Linux (LXC). No se trata de un modelo que haga uso de un hipervisor, sino que se comparte el Kernel y los recursos entre la máquina anfitriona y los huéspedes.

Viendo todas las posibilidades que existían me puse a investigar algo mas sobre algún tipo de software que permitiera una gestión mas amigable y sin la necesidad de andar todo el tiempo desde linea de comandos. Encontré varias opciones para montar clouds privadas, pero la que mas me llamó la atención fue Openstack.

Openstack es una suite de herramientas que permiten la creación de clouds privadas, públicas e híbridas. Empezó su desarrollo como un proyecto Open Source patrocinado por Rackspace y la NASA. Al tiempo la NASA abandona su desarrollo para centrarse mas en el uso como cliente, pero Rackspace continua con él y poco a poco empieza a recibir colaboraciones de muchas empresas (algunas de ellas algo conocidas: AMD, Intel, Caonical, Suse Linux, Red Hat, Cisco, Dell, HP, IBM, NEC, Yahoo!, etc hasta mas de 150).

Como principales ventajas del uso de Openstack frente a otras soluciones creo que se podrían destacar las siguientes:

  1. Se trata de un sistema abierto, un proyecto Open Source con licencia Apache 2.0. Quizás sea uno de los proyectos Open Source con un mayor crecimiento e implicación por parte de las grandes corporaciones
  2. Cuenta con una gran comunidad. Actualmente cerca de 6700 colaboradores de 87 paises. 
  3. Existe mucha información, principalmente en la Wiki del proyecto Openstack
  4. Elimina el «Vendor Locking». El uso de Openstack no esta ligado a ningún fabricante ni proveedor de software. Se puede utilizar con diferentes hipervisores como KVM, XEN, HyperV o vSphere.
  5. Permite la federación de nubes, algo que puede ser interesante si se quiere tener una infraestructura híbrida.
  6. Como la mayoria de los desarrollos Open Source, tiene un compromiso hacia los estándares. 
  7. Existe gente que dice que es el «Linux of the cloud», haciendo una analogía entre lo que es actualmente Linux y lo que quiere llegar a ser Openstack.

La arquitectura de Openstack es modular, pudiendo instalar todos ellos en un único host o por separado. Esto dependerá del tamaño y el objetivo de la cloud. Para entornos de pruebas lo normal es instalarlo todo en un único nodo.

Los componentes que forman la arquitectura son:

  1. Openstack Compute: Nova. Es el cerebro de la arquitectura y la que permite el control de la nube. Se debe instalar en cada nodo que vaya a formar parte del cloud.
  2. Openstack Object Storage: Swift. Es un sistema de almacenamiento escalable y altamente redundante.
  3. Openstack Image Service: Glance. Repositorio de imagenes y snapshots. Las imagenes sirven como plantillas para la generación de nuevos servidores
  4. Openstack Identity: Keystone. Proporciona un directorio central de usuarios y actua como principal sistema de autenticación.
  5. Openstack Dashboard: Horizon. Proporciona una interfaz gráfica a los usuarios.
  6. Openstack Networking: Quantum (aka nova-network). Se encarga de la gestión de las redes y las direcciones IP que se le asignarán a las instancias.
  7. Openstack Block Storage: Cinder (aka nova-volume). Proporciona un almacenamiento a nivel de bloque persistente. Además se encarga de la creación y el agregado de dichos volúmenes a las instancias.

 En el siguiente gráfico se puede ver la relación entre ellos:

Para hacer pruebas se puede seguir la guia que han desarrollado entre varios institutos: Cloud – IES Gonzalo Nazareno o utilizar una ISO con todo instalado. Tendremos dos opciones:

  1. StackOps Community Edition : CD instalable basado en Ubuntu de la empresa española StackOps para la preparación de entornos de test.        
  2. Ubuntu Cloud Live : Imagen Live con todo ya instalado. En el desktop puedes encontrar las instrucciones para arrancar.

Se puede encontrar mucha información en internet sobre el proyecto, aunque en español escasea. Existen 2 grupos de google, uno español y otro argentino, y recientemente he creado una comunidad en Google+ (espero que empiece a tener algo de vida!):

spain-openstack-user-group@googlegroups.com
openstack-argentina@googlegroups.com
 Comunidad OpenStack en Español

En próximas entradas iré comentando mis experiencias y las configuraciones que he ido probando.

Links de interes:
Página oficial del proyecto: http://www.openstack.org/
Cuenta de twitter oficial: https://twitter.com/OpenStack
Entrada en wikipedia: http://en.wikipedia.org/wiki/OpenStack
Ubuntu cloud: http://www.ubuntu.com/cloud/private-cloud/openstack
Rackspace: http://www.rackspace.com/cloud/openstack/
Proyecto cloud en educación: http://www.gonzalonazareno.org/cloud/

Namebench: Benchmark de DNS

¿Cuales son los mejores DNS para optimizar tu conexión?

Cuando nos damos de alta en un ISP, éste nos suele facilitar unos datos de conexión o el Router preconfigurado, para utilizar sus DNS. Muchas veces estos servidores no son los mejores, y el retardo que agregan puede hacer que notemos que ciertas conexiones vayan más lentas.

Para poder establecer el mejor DNS existe una herramienta alojada en “Google Code”. Esta herramienta hace un chequeo de tiempos de respuesta, y resolución de determinadas direcciones con el fin de determinar cual es el mejor DNS, y por tanto con el que tendremos una resolución de nombres más rápida.

La herramienta se puede descargar de la página web del proyecto Namebench:
http://code.google.com/p/namebench/

Existen varias versiones para diferentes plataformas. En Linux, descargaríamos los fuentes y una vez descomprimido sería tan sencillo como ejecutar el script python:
$ tar xzf namebench-1.3.1-source.tgz
$ cd namebench-1.3.1/
~/namebench-1.3.1$ ls
ChangeLog.txt  COPYING   libnamebench    README.txt  tools
cocoa          data      namebench.py    setup.py
config         JSON.txt  nb_third_party  templates
~/namebench-1.3.1$ python namebench.py
The python-tk (tkinter) library is missing, using the command-line interface.

namebench 1.3.1 – best source (automatic) on 2012-12-07 23:47:28.704379
threads=40/2 queries=250 runs=1 timeout=3.5 health_timeout=3.75 servers=11
——————————————————————————
– Reading Top 2,000 Websites (Alexa): data/alexa-top-2000-domains.txt (0.7MB)
– Reading Cache Latency Test (100% hit): data/cache-hit.txt (0.1MB)
– Reading Cache Latency Test (100% miss): data/cache-miss.txt (0.1MB)
– Reading Cache Latency Test (50% hit, 50% miss): data/cache-mix.txt (0.1MB)
– Skipping /home/xxxxxxx/.config/google-chrome/Default/History (125d old)
– Reading Chromium: /home/xxxxxx/.config/chromium/Default/History (1.2MB)
– Reading Mozilla Firefox: /home/
xxxxxx/.mozilla/firefox/dsvuj7wu.default/places.sqlite (10.0MB)
– Generating tests from Mozilla Firefox (27981 records, selecting 250 automatic)
– Selecting 250 out of 10471 sanitized records (random mode).

– Checking query interception status…
– Checking connection quality: 1/3…3/3
– Congestion level is 2.41X (check duration: 96.46ms)
– Applied 2.41X timeout multiplier due to congestion: 1.2 ping, 9.0 health.
– Checking latest sanity reference
– Building initial DNS cache for 4515 nameservers (40 threads)
– Checking nameserver availability (40 threads): 0/4515……………………………………………………………………………….


Este proceso dura varios minutos, ya que hace múltiples consultas a varios servidores de DNS y una vez terminado procesa las estadísticas para mostrarnos el resultado. En mi caso estos son los resultados que he obtenido:
Fastest individual response (in milliseconds):
———————————————-
Telefonica Movis ################################ 58.84600
Movistar ES      ################################ 59.97086
Localhost IPv4   ################################ 60.54616
InfoTelecom ES   ################################# 60.76503
Terra ES         ################################# 61.05208
BT Espagna ES    ##################################### 68.42899
Neuf Cegetel S3  ######################################### 76.67494
Google Public DN ############################################ 81.78401
UltraDNS-2       ################################################ 89.45608
DynGuide-2       #################################################### 98.44708
OpenDNS-2        ##################################################### 100.60596

Mean response (in milliseconds):
——————————–
Movistar ES      ########################## 122.16
Telefonica Movis ############################# 132.68
Localhost IPv4   ############################# 132.74
Terra ES         ############################### 143.17
Google Public DN ################################ 148.57
UltraDNS-2       ##################################### 171.51
OpenDNS-2        ####################################### 181.24
DynGuide-2       ####################################### 181.68
Neuf Cegetel S3  ############################################ 206.33
InfoTelecom ES   ############################################# 209.36
BT Espagna ES    ##################################################### 249.98

Con estos resultados los DNS propuestos son:
Recommended configuration (fastest + nearest):
———————————————-
nameserver 194.179.1.100   # Movistar ES  
nameserver 194.179.001.101 # Telefonica Movistar-2 ES  
nameserver 127.0.0.1       # Localhost IPv4


Además nos ha guardado un reporte en HTML en /tmp con los resultados y gráficos:

Mean Response DurationMean Duration GraphFastest Individual Response Duration
Fastest Response GraphResponse Distribution Chart (First 200ms)Response Distribution Graph (first 200ms)Response Distribution Chart (Full)

Response Distribution Graph (full)
He remarcado un warning que me ha dado al lanzar por primera vez la aplicación. Al no tener instalado el paquete python-tk me ha lanzado el script automáticamente por línea de comando. Si instalo el paquete python-tk y lo vuelvo a lanzar tendremos una interfaz gráfica donde configurar diferentes parámetros:
$ sudo apt-get install python-tk


Si ya teníamos instalado ese paquete y queremos aún así lanzarlo en modo comando lo lanzaremos con la opción -x:
$ python namebench.py -x

Con la opción -h veremos la ayuda, con todas las opciones disponibles para realizar las diferentes pruebas.

Configurar VLANs para un enlace en un Blade HP con HP Virtual Connect Manager

El objetivo de la siguiente entrada es explicar cómo se debe configurar una red en el HP Virtual Connect Manager para poder conectar determinadas bahías a segmentos de red que cuenten con etiquetado VLAN. 
Debemos tener en cuenta que los switches deben tener una configuración específica para los puertos que van conectados al blade. Estas son:
  1. Los puertos del switch se deben configurar como puertos TRUNK, de forma que todas las tramas se reenvien al blade con etiquetado VLAN.
  2. Cuando se añadan SUS (Shared Uplink Set) adicionales, los puertos del switch conectado al blade tendrán que configurarse para LACP y configuradas en el mismo «Link Aggregation Group».
Para configurarlo, entraremos en la interfaz gráfica del Virtual Connect. Lo primero que deberemos hacer es habilitar el «Map VLAN Tags». Se habilita desde la pestaña «Advanced Settings», desde el panel de configuración de Ethernet. Para acceder a este panel se entra desde el panel de la izquierda del Virtual Connect Manager. Una vez dentro, se selecciona la opción «Map VLAN Tags» y salvamos la configuración.

Una vez habilitado el uso de VLANs se creará un nuevo «Shared Uplink Set». Para este SUS se definen que puertos físicos van a formar parte del mismo y que redes van a poder transmitirse por el mismo, con el identificador de VLAN de cada una. 
En el menú superior de la pantalla principal, se hace click en  «Define» y ahí se selecciona «Shared Uplink Set». Introduciremos un nombre que identifique claramente el Trunk. En el ejemplo se muestra como se han añadido los puertos 1 y 2 de las bahías 1 y 2 del blade. De esta forma, tendremos redundancia ante la caida de alguno de los enlaces y ampliamos el ancho de banda disponible.
Además se definirán los segmentos de red con sus correspondientes VLAN ID. En el ejemplo se definen cuatro segmentos con VLAN ID del 101 al 104.

Ya estamos en disposición de asignar alguno de los segmentos de red definidos a algún servidor. Si queremos crear un perfil nuevo, se creará de igual forma que si fuese una conexión directa (sin VLANs). A la hora de seleccionar la red que se le quiere mapear a una bahía, ya apareceran las redes que se han definido:

Zero-Padding en Bash

Hoy me he encontrado con el problema de tener que generar una secuencia de números desde un terminal con bash. A todos los números de dicha secuencia debían estar formados por tres caracteres con lo que debía añadir ceros de relleno a la izquierda del número.



Buscando un poco me he encontrado con esta interesante entrada donde explica como usar el comando printf basándose en el uso que el autor le da a la función en C.

http://jonathanwagner.net/2007/04/zero-padding-in-bash/

A modo de resumen, para generar la secuencia he utilizado el siguiente bucle:

for i in {1..10}; do printf «%03d\n» $i; done
001
002
003
004
005
006
007
008
009
010


De esta forma me he podido descargar los 100 ficheros secuenciales que me interesaban de una forma rápida y cómoda.

for i in {1..100}; do seq=`printf «%03d\n» $i`; wget $url1$seq$url2; done

Nota: parece que desde la versión 4.1.5 de bash se puede simplificar de la siguiente manera:
$ for i in {01..10}; do echo $i; done
01
02
03
04
05
06
07
08
09
10

Las últimas versiones de las diferentes distribuciones de GNU/Linux ya vienen con una versión de bash superior, con lo que la segunda opción será mas óptima. En sistemas antiguos o con otras shells se podría utilizar la opción con el printf.

Ampliacion Filesystem de root en Solaris 11

En Solaris 10 ya se podía  pero en Solaris 11 es obligatorio la instalación de el filesystem de root con el sistema de ficheros ZFS. ZFS es un sistema de ficheros y gestor de volúmenes en un único software. Esto nos proporcionará múltiples ventajas y opciones de configuración: mirrors, stripes, Raid-Z, etc. El problema que tendremos si queremos ampliar dicho Filesystem y no existe espacio libre en el disco sin particionar es que no podemos añadirle un disco adicional al pool Rpool. La única opción de ampliación de dicho Filesystem pasa por asignar un disco de mayor capacidad, sincronizarlo, separar el mirror y arrancar con el nuevo disco.



Para conseguir ampliar el disco seguiremos los siguientes pasos:
1. Asignamos el nuevo disco (insertamos un disco mayor en un slot libre o asignamos nuevo disco virtual si se trata de una maquina virtual) y lo escaneamos desde Solaris:
root@solaris11:~# cfgadm -l
Ap_Id Type Receptacle Occupant Condition  
c4 scsi-bus connected configured unknown  
c4::dsk/c4t0d0 disk connected configured unknown  
c4::dsk/c4t1d0 disk connected configured unknown

2. En el nuevo disco creamos la partición Fdisk del disco completo. Para ello podemos ejecutar un format, seleccionar el disco y particionarlo con el menú de fdisk. A mi me gusta mas este comando, que nos permite crear el particionado fdiks en una línea:

root@solaris11:~# fdisk -B c4t1d0p0

Podemos verificar el particionado del disco de la siguiente manera:

root@solaris11:~# fdisk -W – c4t1d0p0
* /dev/rdsk/c4t1d0p0 default fdisk table 
* Dimensions: 
* 512 bytes/sector 
* 63 sectors/track 
* 255 tracks/cylinder 
* 5221 cylinders  
…  
…  
* Id Act Bhead Bsect Bcyl Ehead Esect Ecyl Rsect Numsect  
191 128 0 1 1 254 63 1023 16065 83859300  
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 

3. Crear las particiones de solaris (slices en adelante) en el nuevo disco. Para ello podemos copiar el particionado del disco original o con un format particionar el disco nuevo asignándole todos los cilindros al Slice 0. Con la primera opción nos mostrará un warning:

root@solaris11:~# prtvtoc /dev/rdsk/c4t0d0s2 | fmthard -s – /dev/rdsk/c4t1d0s2
fmthard: Partition 2 specifies the full disk and is not equal full size of disk.  
The full disk capacity is 83827170 sectors.  
fmthard: New volume table of contents now in place.

4. Ya estamos en disposición de asignar el disco al pool. Con este comando se ve lo fácil que es crear un mirror con ZFS, a diferencia de lo que ocurria con SVM. Primero verificamos que el pool esta correcto y no tiene fallos y a continuación asignamos el Slice 0 del nuevo disco:

root@solaris11:~# zpool status  
pool: rpool  
state: ONLINE  
scan: none requested  
config:  
    NAME STATE READ WRITE CKSUM  
  rpool ONLINE 0 0 0  
    c4t0d0s0 ONLINE 0 0 0

  errors: No known data errors  
root@solaris11:~# zpool attach -f rpool c4t0d0s0 c4t1d0s0
 
Make sure to wait until resilver is done before rebooting.
5. Con el comando ‘zpool status’ vamos comprobando el estado de la sincronización:

root@solaris11:~# zpool status  
pool: rpool  
state: ONLINE  
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.  
action: Wait for the resilver to complete.  
scan: resilver in progress since Wed Oct 31 17:39:29 2012 2,92G scanned out of 17,0G at 8,76M/s, 0h27m to go 2,92G resilvered, 17,14% done  
config:
  NAME STATE READ WRITE CKSUM
 rpool ONLINE 0 0 0
  mirror-0 ONLINE 0 0 0
   c4t0d0s0 ONLINE 0 0 0
   c4t1d0s0 ONLINE 0 0 0 (resilvering)
errors: No known data errors

6. Será necesario instalar el GRUB en el nuevo disco para asegurarnos que una vez hayamos quitado el disco original el sistema sea capaz de arrancar. Para ello, como hacíamos en Solaris 10, ejecutamos el siguiente comando: 

root@solaris11:~# installgrub -fm /boot/grub/stage1 /boot/grub/stage2 /dev/rdsk/c4t1d0s0

7. Una vez haya terminado la sincronización separamos el pool. Al separar el pool en el nuevo disco se habrá creado un nuevo pool que posteriormente podremos importar:

root@solaris11:~# zpool split rpool rpool2 c4t1d0s0

8. A continuación apagamos el servidor, desconectamos el disco original y arrancamos el sistema con una imagen de Solaris 11, ya sea la versión Live o con el instalador y seleccionando la opción 3 para abrir una shell. Una vez tengamos el promt importaremos el pool que habíamos creado al separar el mirror y lo importaremos con el nombre rpool para que el GRUB sea capaz de encontrarlo:

# zpool import rpool2 rpool 
# zpool export rpool 

9. Una vez se haya exportado el rpool ya podemos reiniciar y debería arrancar ya con el nuevo disco. Es posible que el zpool aún vea el espacio original. Para ello hay que modificar la propiedad autoexpand para que crezca el espacio automáticamente:

root@solaris11:~# zpool set autoexpand=on rpool

10. Dependiendo de la opción elegida en el punto 3, es posible que sea necesario modificar la Slice 0 del disco para asignarle todos los cilindros disponibles.


Configuración básica de red en Solaris 11

En Solaris 11 ha cambiado completamente la configuración de la red. Se ha reescrito por completo el código y los comandos que se venían utilizando hasta ahora ya no sirven.

En la siguiente guía se puede entrar mas en detalle en algunos parámetros avanzados, pero en este post explicaré como realizar las tareas básicas de red:
Para ver el estado físico de las interfaces se utilza el comando «dladm». Este comando ya existía en Solaris 10 pero ahora nos devolverá información sobre el dispositivo, el estado de la interfaz, el link y el nombre del dispositivo virtual (net0, net1, etc) algo parecido a lo que ya estamos acostumbrados a ver en Linux.
Con los subcomandos «show-phys» y «show-link» veremos toda esta información:

Para poder trabajar con una interfaz, lo primero que hay que hacer es activarla. Para ello se utiliza el comando «ipadm create-ip». Una vez creada ya se pueden levantar las IPs que sean necesarias:
Para configurar la IP en una interfaz se utiliza el comando «ipadm create-addr». Se puede definir que se utilice una IP estática o una IP dinámica y por cada interfaz se creará un alias de la forma IFNAME/»alias». De esta forma se identificará unívocamente cada IP levantada sobre la interfaz. Veamos un ejemplo:
Como vemos, la interfaz no la ha levantado. Esto es debido a que originalmente el servidor se instaló utilizando un servidor DHCP. Para permitir que se utilicen direcciones estáticas debemos cambiar el modo NCP a DefaultFixed. Con el comando netadm list podemos ver que el NCP estaba por defecto en Automático:
Una vez configurada la interfaz, lo que debemos hacer es configurar el default gateway para tener salida hacia otras redes. Para ello, se utilizará el comando route, con la opción -p para hacerlo permanente:
Ya la última de las tareas básicas para poder conectarnos a la red es la configuración de DNS. Al haber desactivado el NCP el fichero /etc/nsswitch.conf no queda configurado para utilizar DNS. Para configurarlo hay que editar las propiedades del servicio name-service/switch de la siguiente manera:

# svccfg -s svc:/system/name-service/switch
svc:/system/name-service/switch> select name-service/switch:default
svc:/system/name-service/switch> setprop config/host = astring: «files dns»
svc:/system/name-service/switch:default> refresh
svc:/system/name-service/switch:default> validate
svc:/system/name-service/switch> exit


Si ahora vemos el contenido del fichero /etc/nsswitch.conf vemos que ya incluye la opción de resolver hosts a través de DNS:
# grep dns /etc/nsswitch.conf 
hosts:  files dns
ipnodes:        files dns

Para configurar los servidores DNS y los dominios de búsqueda editaremos las propiedades del servicio dns/client. Al igual que en el caso anterior:

# svccfg -s svc:/network/dns/client
svc:/network/dns/client> setprop config/nameserver=net_address: (8.8.8.8 8.8.4.4)
svc:/network/dns/client> listprop config/nameserver
config/nameserver net_address 8.8.8.8 8.8.4.4
svc:/network/dns/client> setprop config/search= («es.acme.com» «acme.com»)
svc:/network/dns/client> listprop config/search
config/search astring     «es.acme.com» «acme.com»
svc:/network/dns/client> select default
svc:/network/dns/client:default> validate
svc:/network/dns/client:default> refresh
svc:/network/dns/client:default> exit

Podemos ver que el contenido del fichero /etc/resolv.conf se ha actualizado con los parámetros que hemos cambiado y que la resolución ya funciona correctamente:

# more /etc/resolv.conf 

#
# _AUTOGENERATED_FROM_SMF_V1_
#
# WARNING: THIS FILE GENERATED FROM SMF DATA.
#   DO NOT EDIT THIS FILE.  EDITS WILL BE LOST.
# See resolv.conf(4) for details.

domain globalia.com
search es.acme.com acme.com
nameserver 8.8.8.8
nameserver 8.8.4.4

Envio de mails con formato html desde Python

Python es un lenguaje de programación muy potente y sencillo de aprender. Ademas, cuenta con una serie de librerías y módulos con funciones ya implementadas para hacer determinadas acciones comunes. Entre ellas, una que yo suelo utilizar, es la del envío de reportes por mail cuando finalizan mis scripts. Lo interesante es que con un formateo sencillo permite el envío de mensajes con el cuerpo en html, dándoles un mejor aspecto en nuestro gestor de correo.

Se deben importar dos módulos para poder realizar el envío de mails: smtplib y email.mime.text. El primero se encargará de la gestión de la conexión con el servidor de correo, mientras que el segundo servirá para dar la codificación correcta e incluirlo como texto MIME en el cuerpo del mensaje. 
Lo que yo creo es una función a la que le paso el cuerpo del mensaje y se encarga de empaquetarlo y enviarlo. A continuación muestro el ejemplo:
 def sendmail(body):  
smtpserver = 'smtp.dominio.com'
sender='sender@dominio.com'
sysadmin1='receiver1@dominio.com'
sysadmin2='receiver2@dominio.com'
receiver = [ sysadmin1 , sysadmin2 ]
header='''


Envio de mail formateado en HTML


h2 {font-size:14px;margin: 2px;}
h3 {font-size:12px;margin: 2px;}
p {font-size:10px; margin: 2px;}
td {border: 1px outset}


'''
footer=''
msgbdy = open(body, 'rb')
msg = MIMEText(header+msgbdy.read()+footer, 'html')
msgbdy.close()
msg['Subject'] = 'Asunto del mensaje'
msg['From'] = sender
msg['To'] = sysadmin1
msg['CC'] = sysadmin2
correo = smtplib.SMTP(smtpserver)
correo.sendmail(sender, receiver, msg.as_string())
correo.quit()
El código creo que no es muy complicado de entender, pero básicamente crearemos tres variables que concatenaremos con la cabecera, el cuerpo y el cierre del código html. Esto se lo pasaremos a la función MIMEText con un segundo parámetro, ‘html’ que especifica el Content-Type y lo pondremos en la variable msg como cuerpo de mensaje. A continuación se realiza la conexión con el servidor y se envía el mail.

A la funcion le paso como parámetro el nombre del fichero de log, que posteriormente se codificará como un objeto MIME.

En el fichero de log, en lugar de introducirle «retornos de carro», introduzco etiquetas del tipo

,

,
e incluso estilos para modificar el formato de la salida.

SNMP y Trabajo con MIBs

Muchas veces debemos monitorizar elementos que disponen del protocolo SNMP. Normalmente es fácil encontrar el fichero de MIB del dispositivo que queremos monitorizar, ya sea en a través del fabricante o a través de webs de terceros como oidview. Una vez tenemos el fichero de la MIB, ¿que hacemos?¿Como podemos obtener el OID de un nodo en particular?

Como para todo, existirán múltiples formas de trabajar con este fichero, pero para los usuarios de Linux tenemos disponible el paquete «snmp» con un grupo de herramientas que nos servirán para nuestro propósito. Lo primero que deberemos hacer es instalar dicho paquete, si no lo hemos hecho ya antes, con un simple «sudo apt-get install snmp«. Una vez instalado tendremos disponibles comandos como snmpwalk, snmpget o snmptranslate.
En el siguiente ejemplo veremos como obtener el valor de algunas variables que nos pueden interesar para monitorizar un SAI con un adaptador CS121. Con dicho módulo venia su correspondiente CD de utilidades donde podíamos encontrar la MIB del producto, en concreto la RFC1628cs121.MIB. 
Nos podríamos ver tentados por visualizar dicho fichero, pero la sintaxis que utiliza (ASN1) no es la mas amigable para su lectura. 
La herramienta snmptranslate nos sirve para interpretar dicho fichero MIB. A primera vista podríamos analizar el arbol de la mib para evaluar que variables nos pueden interesar en la monitorización, para ello ejecutaremos el siguiente comando, especificando que carge el fichero de MIB del módulo:

julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -Tp 
+–iso(1)
   |
   +–org(3)
      |
      +–dod(6)
         |
         +–internet(1)
            |
            +–mgmt(2)
               |
               +–mib-2(1)
                  |
                  +–upsMIB(33)
                     |
                     +–upsObjects(1)
                     |  |
                     |  +–upsIdent(1)
                     |  |  |
                     |  |  +–upsIdentManufacturer(1)
                     |  |  |
                     |  |  +–upsIdentModel(2)
                     |  |  |
                     |  |  +–upsIdentUPSSoftwareVersion(3)
                     |  |  |
                     |  |  +–upsIdentAgentSoftwareVersion(4)
                     |  |  |
                     |  |  +–upsIdentName(5)
                     |  |  |
                     |  |  +–upsIdentAttachedDevices(6)
                     |  |
                     |  +–upsBattery(2)
                     |  |  |
                     |  |  +– -R– EnumVal   upsBatteryStatus(1)
                     |  |  |        Values: unknown(1), batteryNormal(2), batteryLow(3), batteryDepleted(4)
Si en la herramienta de monitorización podemos cargar el fichero de MIB, con interrogar al dispositivo con el nombre del nodo que nos interesa será suficiente (mas adelante explicaré algún ejemplo). En cambio, muchas herramientas de monitorización no permiten la carga del fichero de MIB y le debemos especificar el OID que queremos interrogar. El árbol de OIDs de la MIB lo podemos ver de la siguiente forma:
julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -To
.1.3
.1.3.6
.1.3.6.1
.1.3.6.1.2
.1.3.6.1.2.1
.1.3.6.1.2.1.33
.1.3.6.1.2.1.33.1
.1.3.6.1.2.1.33.1.1
.1.3.6.1.2.1.33.1.1.1
.1.3.6.1.2.1.33.1.1.2
.1.3.6.1.2.1.33.1.1.3
.1.3.6.1.2.1.33.1.1.4
.1.3.6.1.2.1.33.1.1.5
.1.3.6.1.2.1.33.1.1.6
.1.3.6.1.2.1.33.1.2
.1.3.6.1.2.1.33.1.2.1
.1.3.6.1.2.1.33.1.2.2
.1.3.6.1.2.1.33.1.2.3
.1.3.6.1.2.1.33.1.2.4
.1.3.6.1.2.1.33.1.2.5
.1.3.6.1.2.1.33.1.2.6
.1.3.6.1.2.1.33.1.2.7
.1.3.6.1.2.1.33.1.3
.1.3.6.1.2.1.33.1.3.1
.1.3.6.1.2.1.33.1.3.2
.1.3.6.1.2.1.33.1.3.3
.1.3.6.1.2.1.33.1.3.3.1
.1.3.6.1.2.1.33.1.3.3.1.1
.1.3.6.1.2.1.33.1.3.3.1.2
.1.3.6.1.2.1.33.1.3.3.1.3
.1.3.6.1.2.1.33.1.3.3.1.4
.1.3.6.1.2.1.33.1.3.3.1.5
El problema ahora es que no sabemos cual es la correspondencia entre el OID y el nodo que evaluamos. Esto se soluciona pasando como parámetro en el snmptranslate la opción -Tz, que nos devolverá la forma numérica y etiqueta de todos los objetos:
julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -Tz
«org» «1.3»
«dod» «1.3.6»
«internet» «1.3.6.1»
«mgmt» «1.3.6.1.2»
«mib-2» «1.3.6.1.2.1»
«upsMIB» «1.3.6.1.2.1.33»
«upsObjects» «1.3.6.1.2.1.33.1»
«upsIdent» «1.3.6.1.2.1.33.1.1»
«upsIdentManufacturer» «1.3.6.1.2.1.33.1.1.1»
«upsIdentModel» «1.3.6.1.2.1.33.1.1.2»
«upsIdentUPSSoftwareVersion» «1.3.6.1.2.1.33.1.1.3»
«upsIdentAgentSoftwareVersion» «1.3.6.1.2.1.33.1.1.4»
«upsIdentName» «1.3.6.1.2.1.33.1.1.5»
«upsIdentAttachedDevices» «1.3.6.1.2.1.33.1.1.6»
«upsBattery» «1.3.6.1.2.1.33.1.2»
«upsBatteryStatus» «1.3.6.1.2.1.33.1.2.1»
«upsSecondsOnBattery» «1.3.6.1.2.1.33.1.2.2»
«upsEstimatedMinutesRemaining» «1.3.6.1.2.1.33.1.2.3»
«upsEstimatedChargeRemaining» «1.3.6.1.2.1.33.1.2.4»
«upsBatteryVoltage» «1.3.6.1.2.1.33.1.2.5»
«upsBatteryCurrent» «1.3.6.1.2.1.33.1.2.6»
«upsBatteryTemperature» «1.3.6.1.2.1.33.1.2.7»
«upsInput» «1.3.6.1.2.1.33.1.3»
«upsInputLineBads» «1.3.6.1.2.1.33.1.3.1»
«upsInputNumLines» «1.3.6.1.2.1.33.1.3.2»
«upsInputTable» «1.3.6.1.2.1.33.1.3.3»
«upsInputEntry» «1.3.6.1.2.1.33.1.3.3.1»
«upsInputLineIndex» «1.3.6.1.2.1.33.1.3.3.1.1»
«upsInputFrequency» «1.3.6.1.2.1.33.1.3.3.1.2»
«upsInputVoltage» «1.3.6.1.2.1.33.1.3.3.1.3»
«upsInputCurrent» «1.3.6.1.2.1.33.1.3.3.1.4»
«upsInputTruePower» «1.3.6.1.2.1.33.1.3.3.1.5»

Para obtener mas información de un nodo en concreto primero deberíamos obtener la forma mas completa:

julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -Onf -IR upsInputTruePower
.iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsInput.upsInputTable.upsInputEntry.upsInputTruePower

Ya ejecutando el snmptranslate con el OID completo obtendremos mas información del nodo, con una descripción de la variable, las unidades, la  sintaxis, etc.

julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -Td -OS .iso.org.dod.internet.mgmt.mib-2.upsMIB.upsObjects.upsInput.upsInputTable.upsInputEntry.upsInputTruePower
UPS-MIB::upsInputTruePower
upsInputTruePower OBJECT-TYPE
  — FROM UPS-MIB
  — TEXTUAL CONVENTION NonNegativeInteger
  SYNTAX INTEGER (0..2147483647) 
  DISPLAY-HINT «d»
  UNITS «Watts»
  MAX-ACCESS read-only
  STATUS current
  DESCRIPTION «The magnitude of the present input true power.»
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) upsMIB(33) upsObjects(1) upsInput(3) upsInputTable(3) upsInputEntry(1) 5 }

Para obtener el OID numérico que utilizaremos en la herramienta de monitorización para este nodo ejecutaremos la siguiente consulta:

julian@ubuntu:$ snmptranslate -m «/tmp/RFC1628cs121.MIB» -On UPS-MIB::upsInputTruePower
.1.3.6.1.2.1.33.1.3.3.1.5
Con estos datos ya podemos montar nuestro sistema de monitorización, evaluando únicamente las variables que nos interesen. 
También tendremos dos utilizades que nos permitirán obtener los valores directamente desde el módulo. El snmpwalk hará un recorrido por las ramas del árbol desde el nodo que le especifiquemos mientras que el snmpget nos devolverá el valor específico de un nodo. En ambos métodos podemos especificar el fichero de MIB que queremos utilizar o especificar el OID en formato numérico. Veamos varios ejemplos:
julian@ubuntu:$ snmpget -Os -c comunidad -m «./RFC1628cs121.MIB» -v 1 DireccionIP upsOutputPower.1
upsOutputPower.1 = INTEGER: 700 Watts

julian@ubuntu:$ snmpget -Os -c comunidad -v 1 DireccionIP 1.3.6.1.2.1.33.1.4.4.1.4.1
mib-2.33.1.4.4.1.4.1 = INTEGER: 700

julian@ubuntu:$  snmpwalk -Os -c comunidad -m «./RFC1628cs121.MIB» -v 1 DireccionIP upsInputEntry
upsInputLineIndex.1 = INTEGER: 1
upsInputFrequency.1 = INTEGER: 500 0.1 Hertz
upsInputVoltage.1 = INTEGER: 230 RMS Volts
upsInputCurrent.1 = INTEGER: 0 0.1 RMS Amp
upsInputTruePower.1 = INTEGER: 0 Watts

julian@ubuntu:$ snmptranslate -m «./RFC1628cs121.MIB» -On UPS-MIB::upsInputEntry
.1.3.6.1.2.1.33.1.3.3.1
julian@ubuntu:$  snmpwalk -Os -c comunidad -v 1 DireccionIP .1.3.6.1.2.1.33.1.3.3.1
mib-2.33.1.3.3.1.1.1 = INTEGER: 1
mib-2.33.1.3.3.1.2.1 = INTEGER: 500
mib-2.33.1.3.3.1.3.1 = INTEGER: 230
mib-2.33.1.3.3.1.4.1 = INTEGER: 0
mib-2.33.1.3.3.1.5.1 = INTEGER: 0
Se puede encontrar mas información en los siguientes enlaces: