Sei sulla pagina 1di 4

Python DESARROLLO

Cosiendo el loco mundo de la administracin de sistemas con Python

Cosiendo Parches
La librera Fabric de Python hace que sea extremadamente fcil la creacin repetida de scripts de comandos sobre SSH para diversos servidores. POR FRANK WILES
abric [1] es una librera de Python impresionante, que facilita la codificacin de tareas comunes de los sistemas, convirtindolas en sencillas recetas. Chef y Puppet son dos herramientas muy potentes para entornos grandes y complicados, pero a menudo requieren demasiado trabajo para realizar simples configuraciones. Cada vez que tengo que ejecutar una serie de comandos juntos para realizar alguna tarea bsica, cambio de marcha y me creo una tarea con Fabric. La conversin de las tareas diarias de los administradores de sistemas en tareas de Fabric sirven de ayuda para aquellos que tienen que administrar diferentes sistemas. Todos mis proyectos pueden desplegarse por medio del comando fab deploy, ya est trabajando con una configuracin simple o compleja. Las tareas de Fabric se ejecutan con el comando fab. Originalmente slo dispona de unas cuantas funciones, pero con el paso del tiempo, ha crecido bastante, incluyendo muchas, hasta tal punto que podra reemplazar por completo tanto a Puppet como a Chef. Los beneficios y las funciones que incluyen Fabric son: Uso de la conexin SSH existente para acceder a los equipos. Si su usuario puede hacerlo, entonces Fabric tambin. Flexibilidad a la hora de incluir y excluir equipos para realizar ciertas tareas, ya

sea nombrndolos a mano o definiendo roles. Ejecucin en serie o paralela. Ejecucin local de los comandos, como un usuario en un equipo remoto o con sudo. Autodocumentado: si no se est seguro de lo que va a hacer, se pueden ver fcilmente los pasos que ir a realizar. Administracin simple de ficheros con el mdulo fabric.contrib.files.

from fabric.api import * def uptime(): run(uptime)

Esta simple tarea ejecutar el comando uptime en cualquier equipo que se haya definido en la lnea de comandos, por ejemplo:
fab -H localhost uptime

Primeros Pasos
La instalacin de Fabric es sencilla con pip. Tan slo hay que ejecutar:
pip install Fabric

desde la lnea de comandos. Si no se tiene pip instalado, puede instalarse con:


easy_install pip

Se puede ver una lista con las tareas Fabric disponibles ejecutando fab -l. Aqu hay tareas al viejo estilo, de modo que se listar cualquier funcin definida. Sin embargo, se debera utilizar el nuevo estilo para definir las tareas, porque permite especificar qu funciones se encontrarn disponibles como tareas y cules para uso interno muestro un ejemplo utilizando el viejo estilo porque muchos documentos howto an lo usan. Tras introducir
from fabric.api import * def uptime(): run(uptime) @task def get_uptime(): uptime()

desde la lnea de comandos. Fabric busca un fichero denominado fabfile.py en el directorio actual o empezar a retroceder por el rbol de directorios en el que se encuentre buscndolo. Esta solucin facilita la separacin de diferentes tareas en diferentes carpetas para cada proyecto, sin embargo, se puede tambin especificar el fichero fabfile a utilizar con el parmetro -p. Para crear la primera tarea Fabric, vamos a teclear lo siguiente:

ejecutamos fab -l y ahora slo se mostrar la tarea get_uptime y se ocultar la funcin interna uptime (Figura 1). Para ejecutar

WWW.LINUX- MAGAZINE.ES

Nmero 87

45

DESARROLLO Python

Listado 1: uptime() para Varios Servidores


01 [web1.example.com] Executing task get_uptime 02 [web1.example.com] run: uptime 03 11:22 up 17 days, 12:13, 5 users, load averages: 1.03 1.88 1.32 04 [web2.example.com] Executing task get_uptime 05 [web2.example.com] run: uptime 06 11:22 up 12 days, 22:11, 3 users, load averages: 1.43 1.38 1.34

Figura 1: Las tareas disponibles. Las funciones internas usadas por la tarea no se listan.

esta tarea nueva en varios equipos, se puede utilizar el siguiente comando:


fab -H web1.example.com U web2.example.com get_uptime

Este comando abre una conexin SSH con cada servidor listado, ejecuta el comando uptime y muestra los resultados (Listado 1). Se puede ajustar la cantidad de informacin que puede generar desde la lnea de comandos o en el propio cdigo (vase la documentacin [2]). Tener que definir los equipos cada vez es tedioso. Afortunadamente, Fabric facilita la labor. Aqu vamos a utilizar Fabric para realizar un simple despliegue basado en Git para un servidor web definiendo los equipos en los que debera ejecutarse junto con algunos comandos locales y remotos (Listado 2). La Figura 2 muestra cmo aparece en un terminal. Al contrario que con los comandos anteriores, se han definido internamente los equipos en los que deseamos que se ejecuten los comandos, de modo que para ejecutar esta tarea tan slo hay que ejecutar desde la lnea de comandos fab deploy. Lo primero que hay que hacer es utilizar el mdulo interno de Python datetime para construir la cadena para la etiqueta de Git,

que informa de la fecha especfica para desplegar una versin particular. Queremos slo tener que ejecutarlo una vez, de modo que se pone el decorador @runs_once. La tarea deploy() ejecuta la tarea tag_deployment y luego, en cada uno de los servidores web, Fabric se mete en el directorio /home/web/ y ejecuta los comandos que hay dentro de la sentencia with. Por ltimo, se reinicia Apache en cada servidor con sudo.

Roles
A menudo, conforme el nmero de servicios se incrementan, hace falta que algunos comandos se ejecuten slo en ciertos sistemas. En este escenario es donde aparecen los roles. Para definirlos, se puede utilizar env.roldefs de la siguiente forma:
env.hosts = [U foo1, foo2, foo3, U foo4] env.roledefs = { web: [foo1, foo2], db: [foo3, foo4], }

La ejecucin de fab deploy desde la lnea de comandos har: Ejecutar git pull desde el directorio /home/web/ en todos los equipos. Actualizar los requisitos de pip con el fichero /home/web/requirements.txt en todos los equipos. Ejecutar los comandos definidos en update_tables() en un equipo con el rol db. Reiniciar Apache en todos los equipos con el rol web.

Ejecutando Tareas en Paralelo


Por defecto, Fabric ejecuta las tareas definidas secuencialmente. Usando el ejemplo previo, las tareas se ejecutarn en el siguiente orden:
foo1 - get_code foo1 - update_pip foo1 - update_tables foo1 - restart_apache foo2 - get_code foo2 - update_pip foo2 - update_tables ?

Figura 2: Desplegando una tarea Fabric.

Como en el otro ejemplo, suelo trabajar con aplicaciones basadas en Django principalmente y a menudo, necesito crear nuevas tablas de la base de datos y migrar las tablas existentes o crear nuevos formularios. Una tarea de migracin para este proceso actualizara cualquier requisito pip, instalara el cdigo nuevo en todos los equipos y ejecutara la creacin de las tablas y, por ltimo, migrara una vez a un equipo de base de datos (Listado 3).

A menudo, es ms eficiente realizar las acciones en paralelo, especialmente cuando se est tratando con varios servidores al mismo tiempo. En este sentido, las nuevas versiones de Fabric lo soportan. Para ejecutar una tarea existente en paralelo, tan slo hay que utilizar el parmetro -P:
fab -P deploy

Fabric proporciona los decoradores @serial y @parallel para ayudar a controlar mejor las operaciones de las tareas que tengan que ejecutarse en serie o en paralelo, con o sin el parmetro -P.

Pasando Argumentos
Muchas veces, el hecho de poder pasar valores como argumentos puede hacer que una tarea sea realmente reutilizable. Fabric permite pasar argumentos a una tarea por medio de:

46

Nmero 87

WWW.LINUX- MAGAZINE.ES

Python DESARROLLO

Listado 2: Definiendo Servidores


01 from fabric.api * 02 from datetime import datetime 03 04 env.hosts = [web1.example.com, web2.example.com] 05 06 @task 07 @runs_once 08 def tag_deployment(): 09 now = datetime.now() 10 tag_string = now.strftime(deployed_%Y-%m-%d--%H-%M-%S) 11 local(git tag -a %s -m deployed via Fabric % tag_string) 12 local(git push --tags origin master) 13 14 @task 15 def deploy(): 16 execute(tag_deployment) 17 with cd(/home/web/): 18 run(git pull -t origin master) 19 # Cualquier comando aqu se ejcutara en 20 # el directorio /home/web 21 22 # De vuelt al direcrtorio de inicio del usuario 23 sudo(/etc/init.d/apache2 restart)

fab apache:restart

y se utilizan del siguiente modo:


@task def apache(cmd): sudo(/etc/init.d/apache2 %s U % cmd)

def stop(): sudo(/etc/init.d/apache2 U stop) @task def restart(): sudo(/etc/init.d/apache2 U restart)

Este cdigo debera llamar a apache2 seguido por cualquier argumento que se le pase por la lnea de comandos en este caso, restart.

Ahora se podra importar desde cualquier fabfile.py importando el mdulo y Fabric se encargara de crear un espacio de nombres para l:
from fabric.api import * import apache @task def uptime(): run(uptime)

Espacios de Nombres
Con el nuevo estilo para las tareas (por ejemplo, utilizando el decorador @task), se pueden definir espacios de nombres para facilitar la programacin de libreras reutilizables de tareas o simplemente para dividir el cdigo en mdulos lgicos ms pequeos. Los espacios de nombres funcionan importando un mdulo de Python en el que se hayan definido las tareas. El trabajo con Apache es muy comn en mi mundo, de modo que sera conveniente poner estas tareas comunes en una librera para poder utilizarlas desde diferentes proyectos. Si tuviera un fichero apache.py,
from fabric.api import * @task def start(): sudo(/etc/init.d/ apache2 U start) @task

Ejecutando fab -l se mostrara:


Available commands: uptime apache.start apache.stop apache.restart

que podran ejecutarse con fab apache start desde la lnea de comandos. Se le pueden pasar argumentos y utilizar todas las caractersticas propias de Fabric a estas tareas, ya que esta solucin facilita la reorganizacin del cdigo en mdulos sin tener que llegar a tener un fabfile que ocupe miles de lneas.

WWW.LINUX- MAGAZINE.ES

Nmero 87

47

DESARROLLO Python DESARROL

Listado 3: Migrando una Base de Datos Django


01 def get_code(): 02 with cd(/home/web): 03 run(git pull -t origin master) 04 05 def update_pip(): 06 run(pip install -U -r /home/web/requirements.txt) 07 08 @task 09 @runs_once 10 @roles(db) 11 def update_tables(): 12 # Crear nuevas tablas 13 run(./manage.py syncdb) 14 # Migrar tablas y datos existentes 15 run(./manage.py migrate) 16 17 @task 18 @roles(web) 19 def restart_apache(): 20 sudo(/etc/init.d/apache2 restart) 21 22 @task 23 def deploy(): 24 get_code() 25 update_pip() 26 execute(update_tables) 27 execute(restart_apache)

Trabajando con Ficheros


Como cabra esperar, Fabric proporciona algunas herramientas tiles para trabajar con ficheros. Desde la Core API, se pueden utilizar put() y get() para acceder a los ficheros, controlando las rutas locales y remotas. El mdulo contrib.files [3], sin embargo, proporciona funciones ms potentes para las tareas ms comunes: append(filename, text) aade la cadena o la lista de cadenas de caracteres a un fichero si las cadenas no se encuentran ya en el fichero. comment(filename, regex)/uncomment(filename, regex) comenta o descomenta cualquier lnea del fichero que coincida con la expresin regular dada. contains(filename, regex) devuelve True si el fichero contiene la expresin regular. exists(path) devuelve True si la ruta existe en el servidor remoto. first(paths) comprueba una lista de rutas y devuelve la primera ruta de fichero que exista en el servidor remoto. Esta funcin puede ser especialmente til cuando se busque la ruta de ficheros de configuracin o scripts ini en diferentes distribuciones de Linux. La compleja funcin de ficheros upload_template() toma la plantilla de fichero local, la rellena con los valores correspondientes y la sube al servidor

remoto. Aunque por defecto utiliza el formato de cadenas de Python, recomendamos encarecidamente utilizar la opcin para la librera Jinja2 Template, que es mucho ms potente. Adems, el uso de plantillas para los ficheros de configuracin ayuda a reducir el tiempo empleado en la configuracin y depuracin de los problemas del servidor.

Otros Trucos tiles


El listado de los comandos de Fabric con fab -l a menudo proporciona bastante informacin, pero se puede obtener ms definiendo las cadenas de documentacin para cada tarea:
@task def complicated_steps(): Esta tarea nos realiza todoU el trabajo complicado run(...)

mer comando ruidoso, ocultando cualquier salida. Las primeras opciones para la funcin hide(), running, le indica a Fabric que no muestre la salida del comando que se est ejecutando. Esta tarea entonces imprimir un mensaje de estado en rojo y ejecutar another-noisy-command, mostrando todas las salidas, ya que se encuentra fuera del bloque with. Para ejecutar una tarea para un nico rol, incluso si no se encuentra definido de esa forma en el cdigo, se utiliza el parmetro -R:
fab -R nombre_rol nombre_tarea

Otro truco til de Fabric consiste en la habilidad para pasar comandos arbitrarios al grupo de servidores o a los que pertenezcan a algn rol usando el parmetro . Todo lo que vaya detrs de los dos guiones se pasa a los servidores como el comando a ejecutar, por ejemplo:
fab -R web -- uptime

Ahora, ejecutando fab -l se listar complicated_steps como una accin pero se mostrar el comentario entre las triples comillas (tambin conocido como docstrings) junto a ella para refrescar nuestra memoria. Mostrando y ocultando o coloreando la salida, se puede controlar cmo las tareas generan sus resultados por pantalla. El cdigo del Listado 4 imprime una actualizacin del estado en verde y ejecuta el pri-

ejecutar el comando uptime en todos los servidores del rol web. Esta breve introduccin a Fabric no ha hecho ms que araar la superficie de todos sus posibles usos, pero espero que haya proporcionado una buena introduccin para que el lector siga profundizando por su cuenta.

Listado 4: Coloreando la Salida del Cdigo


01 from fabric.api import * 02 from fabric.colors import green, red 03 04 @task 05 def colored_and_silent(): 06 print green(Running noisy command silently...) 07 with settings(hide(running, stdout, stderr)): 08 run(/path/to/noisy-command) 09 print red(Commands are noisy again) 10 run(/path/to/another-noisy-command)

RECURSOS
[1] Fabric: http://fabfile.org [2] Niveles de salida: http://docs.fabfile.org/en/1.4.2/usage/ output_controls.html#hiding-and-orshowing-output-levels [3] API de fichero Remoto: http://docs.fabfile.org/en/1.2.0/api/ contrib/files.hteml

48

Nmero 87

WWW.LINUX- MAGAZINE.ES

Potrebbero piacerti anche