Usuario:Luis.perez/sistemaspyaytozgz/fabric

De WikiEducator
Saltar a: navegación, buscar

Administración de sistemas con Fabric

¿ Qué es Fabric ?

  • Herramienta de línea de comandos y librería para facilitar la administración de sistemas y despliegue de aplicaciones a través de SSH.
  • Los scripts en fabric son python usando el api que provee.
  • Permite ejecutar comandos shell localmente o remotamente, así como subir y bajar ficheros de sistemas remotos.
  • Ejecuta mismas tareas en múltiples hosts definidos.
  • Es capaz de manejar las peticiones de input por parte de los programas ejecutados a través de la shell remota (ej: petición de passwords)

Instalación

  • Instalación en OpenSuse. Ubuntu tiene paquetes para fabric (en precise trae 1.3.2)
  • Usaremos la última release 1.x, a día de hoy 1.5.1
  • Prerequisitos:
    • python
    • python-devel (necesario para hacer build de pycrypto)
    • pip
$ sudo zypper install python python-devel python-pip

Instalaremos la última release con pip:

$ pip install fabric

Documentación completa de la instalación de fabric: http://docs.fabfile.org/en/1.5/installation.html

Herramienta fab y tareas

Fabric trae la herramienta fab, con la que podemos ejecutar funciones (tareas) que escribamos en fabfile.py

# fabfile.py
def hello(name="world"):
    print("Hello {0}".format(name))
$ fab hello
Hello world
 
Done.
  • Se pueden pasar parámetros:
$ fab hello:luis
Hello luis
 
Done.
 
$ fab hello:name=luis
Hello luis
 
Done.
  • Podemos hacer tareas que llamen a tareas, puesto que las tareas son funciones python.

Ejecución de operaciones en local

# fabfile.py
from fabric.api import local
 
def sysinfo():
    cpu_info = local("cat /proc/stat")
    mem_info = local("cat /proc/meminfo")
 
    print(cpu_info)
    print(mem_info)


Ejecución de operaciones en remoto

  • Fabric se encarga de gestionar las conexiones con los hosts remotos sobre los que ejecutar comandos.
  • Se hace cache de conexiones, fab las cierra al terminar.
  • Fabric mantiene una cache de passwords, evitando tener que reintroducirlas constantemente.
# fabfile.py
from fabric.api import local
 
def sysinfo():
    cpu_info = run("cat /proc/stat")
    mem_info = run("cat /proc/meminfo")
 
    print(cpu_info)
    print(mem_info)
  • Si ejecutamos esta operación, dado que no hemos definido ningún host, fabric nos pedirá donde queremos ejecutar las operaciones (user@host)
$ fab sysinfo
No hosts found. Please specify (single) host string for connection:
  • Podemos definir los hosts donde ejecutar las operaciones de forma global al script:
env.hosts = ['192.168.0.11', '192.168.0.20', 'my_server']

Aunque esto asumirá que que el usuario con el que nos autenticamos es el mismo usuario que ejecuta el script.

  • Podemos poner el usuario con el que se ejecutará:
env.hosts = ['luis@192.168.0.11', 'root@192.168.0.20', 'my_server']
  • Podemos especificar hosts para una tarea en concreto:
@hosts('user1@logserver1', 'logserver')
def diskusage():
    disk_usage = run("df -h /dev/sda1")
  • ... o pasar por línea de comandos los hosts
$ fab diskusage --hosts=192.168.0.11

Env y .fabricrc

  • env es un diccionario en el que se pueden almacenar múltilples propiedades que se comparten en todas las tareas
  • Aquí se pueden modificar variables como evv.hosts, env.cwd, env.keepalive, etc.
  • .fabricrc es un fichero de propiedades (por defecto en el home del usuario) con pares clave=valor que aparecerán directamente en env (o modifican propiedades estandar), aunque por ahora está limitado a propiedades tipo String

Roles en Fabric

Se pueden agrupar hosts de forma que se puedan ejecutar tareas para un determinado grupo, usando @roles

env.roledefs.update({
    'locales': ['192.168.1.1', '192.168.1.2'],
    'logservers': ['logserver1, logserver2']
})
 
@roles('logservers')
def diskusage():
    pass
  • También se puede ejecutar sobre un rol en concreto desde línea de comandos:
$ fab -R logservers diskusage

Subiendo y bajando ficheros

put('bin/project.zip', '/tmp/project.zip')
put('*.py', 'cgi-bin/')
put('index.html', 'index.html', mode=0755)
 
get('/path/to/remote_file.txt')

Ejecutando con sudo

  • Fabric también trae soporte para ejecutar comandos en máquinas remotas como "sudo"
sudo("echo '192.168.0.2 importanthost' >> /etc/hosts")


Manejando fallos

  • Cuando una tarea falla, fab aborta la ejecución del resto. Esto es muy útil si utilizamos Fabric como herramienta de builds y despliegue de nuestro proyecto.
def test():
    #exec tests
    pass
 
def pack():
    #package the project
 
def deploy():
    test()
    pack()
    #and then upload and deploy the actual project
  • Si ejecutamos la tarea deploy, pero la ejecución de tests falla, no se realizará ni el empaquetado ni el despliegue.
  • En algunos casos nos interesa manejar manualmente el error (usando warn_only=True):
def exec_local():
    with settings(warn_only=True):
        result = local('./inexistent_file', capture=True)
 
    if result.failed and not confirm("inexistent_file doesn't exist. Continue?"):
        abort("Aborting at user request.")
 
    print("Successfully finished!")
Icon present.gif
Tip: Nótese el uso del context manager 'settings'. sirve para ejecutar acciones dentro de el con variables env.XXX de fabric modificadas. Fuera del bloque, env.warn_only es False. Ver http://docs.fabfile.org/en/1.2.1/usage/env.html para una lista completa de variables de configuración


Context Managers

Además del context manager settings, que ya hemos visto antes, Fabric trae algunos muy útiles:

  • cd(path) - Cambia el directorio de trabajo actual
with cd('/var/www'):
    run('ls')

¿Y no es más fácil ejecutar lo siguiente?:

 run('/var/www')
 run('ls')

No. Fabric no mantiene estado entre conexiones, así que el comando 'ls' se ejecutará sobre el directorio de trabajo por defecto del usuario en el host

  • lcd(path) - Equivalente a cd, pero para local.
  • path(path, behavior='append') - Añade path a la variable de entorno PATH del sistema durante la ejecución de los comandos que encapsule.
  • prefix(command) - Añade command como comando a ejecutar antes de cada comando invocado con run/sudo, añadiéndoselo con &&
  • warn_only() - Equivalente a settings(warn_only=True). Evita que fabric aborte la ejecución, permitiendo controlar errores esperados.
  • hide(*groups) - Oculta el output de fabric, pudiendo pasarle uno o varios niveles (groups). http://docs.fabfile.org/en/1.5/usage/output_controls.html#output-levels
 def my_task():
    with hide('running', 'stdout', 'stderr'):
        run('ls /var/www')

Manejo de ficheros

  • append: Añade una linea (o una lista de lineas) a un fichero, si no existen aún
  • comment y uncomment: Comentan o descomentan una línea de un fichero según una expresión regular (usa sed)
  • contains: Devuelve true si el fichero contiene una línea según una expresión regular
  • exists: Devuelve true si el fichero existe
  • sed: Reemplazo de texto, usando el propio sed de gnu
  • upload_template: Genera un fichero usando un template, y lo sube a la máquina remota. Usa el interpolado de strings de python, empleando un diccionario que se le pasa como pares clave-valor.

Organización de tareas fabric

  • Por defecto busca fabfile.py en el directorio actual de trabajo y recursivamente en los padres de éste
  • Es posible separar tareas en distintos ficheros e importarlas
    • Crear modulo python con tareas
    • Importarlo desde el fabfile.py

diskstats.py:

 @task
 def diskstats():
    res = run("cat /proc/diskstats")
    print(res)

fabfile.py:

 from diskutils import *
 ...

Ejecución de tareas en paralelo en varios hosts

  • Usar el parámetro -P de fab
  • Decorar con @parallel para hacer una tarea explicitamente paralela, o @serial para evitar que sea ejecutada en paralelo con -P

Icon present.gif
Tip: Aquí se ha descrito buena parte de la funcionalidad "core" de Fabric, aunque provee más operaciones y context managers de los aquí descritos. Revisar la documentación de Fabric. Además, el paquete fabric.contrib trae varias utilidades comunes. Echad un vistazo a http://docs.fabfile.org/en/latest/index.html#contrib-api


Cuisine: extensión a fabric

¿ Qué es Cuisine ?

  • Librería para Fabric con tareas comunes. https://github.com/sebastien/cuisine
  • Api también muy simple, crear tareas propias es muy fácil
  • Originalmente desarrollado para Debian/Ubuntu, pero se han portado funcionalidades para otros sistemas, como paquetería yum o zypper.
  • No obstante, portar sus funciones a cualquier otro sistema es relativamente fácil.

Instalación

  • Una vez instalado fabric, añadir cuisine con pip
 $ pip install cuisine

Tareas soportadas

  • Manejo de ficheros y directorios (exists, read, write, append...)
  • Manejo de usuarios y grupos (exists, create, ensure...)
  • Manejo de paquetes (install, ensure, update)
  • Manejo y transformación de texto
  • Funciones para asegurar la presencia de texto y reemplazo del mismo, muy útil para actualizar configuraciones.
  • Y otros como generación de claves RSA, asegurar que un proceso está corriendo, etc.

Ejemplo:

#fabfile.py
def editors_ensure():
    package_ensure(["vim", "emacs"])