Tutorial de Ansible

Recientemente me he estado mirando herramientas de automatización de tareas ejecutar en todos los servidores de manera masiva. Es algo imprescindible cuando tienes que administrar cerca de mil servidores. Pero, empecemos por el principio:

Tabla de contenidos

¿Qué es Ansible?

Ansible es una herramienta de automatización de TI de código abierto que permite la gestión de la configuración, la implementación de aplicaciones y la orquestación de tareas en un entorno de TI. Con Ansible, los administradores de sistemas pueden definir, implementar y administrar la infraestructura de manera más eficiente y consistente.

Ansible se basa en una arquitectura de cliente-servidor y utiliza un lenguaje de script simple y legible llamado YAML para definir las tareas que se deben realizar en los sistemas remotos. Ansible se ejecuta a través de SSH o WinRM (para sistemas Windows), lo que permite la gestión y el control de sistemas heterogéneos en diferentes plataformas.

Una de las principales características de Ansible es su facilidad de uso y su capacidad para automatizar tareas complejas con un mínimo de configuración y sin necesidad de conocimientos avanzados de programación. Esto lo hace ideal para implementaciones de infraestructura escalables y repetibles en entornos de TI empresariales. Además, Ansible tiene una gran comunidad de usuarios y una amplia gama de módulos y complementos para extender su funcionalidad.

¿Cómo funciona Ansible?

Su funcionamiento es muy sencillo. Podemos ejecutar comandos de sistema operativo en remoto o podemos utilizar módulos predefinidos, llamados playbooks que realizan multitud de tareas.

Ansible utiliza una arquitectura de cliente-servidor para automatizar tareas en los sistemas remotos. El servidor de Ansible, también conocido como controlador, se encarga de administrar los sistemas remotos. El cliente, también conocido como agente, se instala en los sistemas remotos y se comunica con el controlador a través de una conexión segura SSH o WinRM.

El proceso de automatización de Ansible se basa en la ejecución de módulos, que son programas o scripts que realizan tareas específicas en los sistemas remotos. Los módulos se ejecutan a través de los Playbooks de Ansible, que son archivos YAML que contienen una serie de tareas y la información necesaria para su ejecución.

Los Playbooks de Ansible definen qué módulos se deben ejecutar y en qué orden. Cada tarea en el Playbook se ejecuta en el sistema remoto y devuelve un estado (éxito, falla o cambio). Ansible utiliza este estado para determinar si debe realizar la siguiente tarea en el Playbook.

Además, Ansible utiliza Inventories (inventarios) para definir los sistemas remotos que se van a administrar y los grupos en los que se pueden organizar. Esto permite a los administradores de sistemas definir y personalizar fácilmente qué tareas se ejecutan en qué sistemas.

Veamos un ejemplo.

Acceso a la documentación interna de Ansible

Ansible es un producto muy extenso y seguramente vamos a necesitar ayuda a la hora de configurar algún módulo o plugin que necesitemos utilizar. Para ello, tenemos a nuestra disposición el comando ansible-doc.

A continuación, os muestro algún ejemplo de funcionamiento de este comando.

  • ansible-doc -h muestra la ayuda interna del propio comando. También podremos acceder a ella con man ansible-doc.
  • ansible-doc -l muestra un listado con todos los plugins disponibles y, por lo tanto, podemos obtener ayuda.
[root@server1 ~]# ansible-doc -l |more
a10_server                                                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server object                                                                           
a10_server_axapi3                                             Manage A10 Networks AX/SoftAX/Thunder/vThunder devices                                                                                          
a10_service_group                                             Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service groups                                                                          
a10_virtual_server                                            Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual servers                                                                         
aci_aaa_user                                                  Manage AAA users (aaa:User)                                                                                                                     
aci_aaa_user_certificate                                      Manage AAA user certificates (aaa:UserCert)                                                                                                     
aci_access_port_block_to_access_port                          Manage port blocks of Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:PortBlk)                                    
aci_access_port_to_interface_policy_leaf_profile              Manage Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk)                               
aci_access_sub_port_block_to_access_port                      Manage sub port blocks of Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:SubPortBlk)                             
aci_aep                                                       Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP, infra:ProvAcc)                                                         
aci_aep_to_domain                                             Bind AEPs to Physical or Virtual Domains (infra:RsDomP)                                                                                         
aci_ap                                                        Manage top level Application Profile (AP) objects (fv:Ap)                                                                                       
aci_bd                                                        Manage Bridge Domains (BD) objects (fv:BD)                                                                                                      
aci_bd_subnet                                                 Manage Subnets (fv:Subnet)                                                    

Imaginemos que necesitamos ayuda sobre el plugin de inventario:

[root@server1 ~]# ansible-doc -t inventory -l
advanced_host_list  Parses a 'host list' with ranges                                                                                                                                                          
auto                Loads and executes an inventory plugin specified in a YAML config                                                                                                                         
aws_ec2             EC2 inventory source                                                                                                                                                                      
aws_rds             rds instance source                                                                                                                                                                       
azure_rm            Azure Resource Manager inventory plugin                                                                                                                                                   
cloudscale          cloudscale.ch inventory source                                                                                                                                                            
constructed         Uses Jinja2 to construct vars and groups based on existing inventory                                                                                                                      
docker_machine      Docker Machine inventory source                                                                                                                                                           
docker_swarm        Ansible dynamic inventory plugin for Docker swarm nodes                                                                                                                                   
foreman             foreman inventory source                                                                                                                                                                  
gcp_compute         Google Cloud Compute Engine inventory source                                                                                                                                              
generator           Uses Jinja2 to construct hosts and groups from patterns                                                                                                                                   
gitlab_runners      Ansible dynamic inventory plugin for GitLab runners                                                                                                                                       
hcloud              Ansible dynamic inventory plugin for the Hetzner Cloud                                                                                                                                    
host_list           Parses a 'host list' string                                                                                                                                                               
ini                 Uses an Ansible INI file as inventory source                                                                                                                                              
k8s                 Kubernetes (K8s) inventory source                                                                                                                                                         
kubevirt            KubeVirt inventory source                                                                                                                                                                 
linode              Ansible dynamic inventory plugin for Linode                                                                                                                                               
netbox              NetBox inventory source                                                                                                                                                                   
nmap                Uses nmap to find hosts to target                                                                                                                                                         
online              Online inventory source                                                                                                                                                                   
openshift           OpenShift inventory source                                                                                                                                                                
openstack           OpenStack inventory source                                                                                                                                                                
scaleway            Scaleway inventory source                                                                                                                                                                 
script              Executes an inventory script that returns JSON                                                                                                                                            
toml                Uses a specific TOML file as an inventory source                                                                                                                                          
tower               Ansible dynamic inventory plugin for Ansible Tower                                                                                                                                        
virtualbox          virtualbox inventory source                                                                                                                                                               
vmware_vm_inventory VMware Guest inventory source                                                                                                                                                             
vultr               Vultr inventory source                                                                                                                                                                    
yaml                Uses a specific YAML file as an inventory source                                                                                                                                          
[root@server1 ~]# 

*[root@server1 ~]# ansible-doc -t inventory host_list
> HOST_LIST    (/usr/lib/python3.6/site-packages/ansible/plugins/inventory/host_list.py)

        Parses a host list string as a comma separated values of hosts This plugin only applies to inventory strings that are not paths and contain a comma.

  * This module is maintained by The Ansible Community
        METADATA:
          status:
          - preview
          supported_by: community
        

EXAMPLES:

# define 2 hosts in command line
    # ansible -i '10.10.2.6, 10.10.2.4' -m ping all

    # DNS resolvable names
    # ansible -i 'host1.example.com, host2' -m user -a 'name=me state=absent' all

    # just use localhost
    # ansible-playbook -i 'localhost,' play.yml -c local


[root@server1 ~]# 

De la misma manera, obtendríamos ayuda sobre un módulo de Ansible que quisiéramos utilizar. Por ejemplo, el yum:

[root@server1 ~]# ansible-doc -l |grep -i yum
yum                                                           Manages packages with the `yum' package manager                                                                                                 
yum_repository                                                Add or remove YUM repositories                                                                                                                  
[root@server1 ~]# ansible-doc -t module yum
> YUM    (/usr/lib/python3.6/site-packages/ansible/modules/packaging/os/yum.py)

        Installs, upgrade, downgrades, removes, and lists packages and groups with the `yum' package manager. This module only works on Python 2. If you require Python
        3 support see the [dnf] module.

  * This module is maintained by The Ansible Core Team
  * note: This module has a corresponding action plugin.

OPTIONS (= is mandatory):

- allow_downgrade
        Specify if the named package and version is allowed to downgrade a maybe already installed higher version of that package. Note that setting
        allow_downgrade=True can make this module behave in a non-idempotent way. The task could end up with a set of packages that does not match the complete list of
        specified packages to install (because dependencies between the downgraded package and others can cause changes to the packages which were in the earlier
        transaction).
        [Default: no]
        type: bool
        version_added: 2.4

- autoremove
        If `yes', removes all "leaf" packages from...

Instalar Ansible

Comenzamos por el principio. Instalamos Ansible:

[root ~]# rpm -qa |grep -i ansible
ansible-2.3.1.0-3.el7.noarch
[root~]#

[hpddpers~]$ ansible --version
ansible 2.3.1.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
python version = 2.7.5 (default, May 3 2017, 07:55:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-14)]
[hpddpers~]$

Configurar Ansible

Como cada usuario del sistema operativo puede utilizar Ansible, podemos crearnos una configuración personalizada. Así que creo el directorio “ansible” en mi perfil y copio dentro el fichero /etc/ansible/ansible.cfg:

[hpddpers@ansible]$ pwd
/root/home/hpddpers/ansible
[hpddpersansible]$ ll ansible.cfg
-rw-r–r–. 1 hpddpers uxsup3 18186 Aug 24 10:08 ansible.cfg
[hpddpers@ansible]$

Personalizamos algunas directivas de este fichero:

[hpddpers@ansible]$ grep -v «#» ansible.cfg |grep -v ^$
[defaults]
inventory = inventario/ –> Es el directorio donde voy a guardar la configuración de los servidores con los que voy a trabajar remotamente
roles_path = /etc/ansible/roles:/usr/share/ansible/roles
host_key_checking = False
timeout = 60
log_path = ./ansible.log –> Es el fichero de log donde se van a guardar los registros de ansible que haga con mi usuario
retry_files_save_path = retry –> El el fichero donde ansible dejará constancia de los servidores en los que hayan fallado las tareas a ejecutar
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
connect_timeout = 30
connect_retries = 30
connect_interval = 1
[accelerate]
[selinux]
[colors]
[diff]
[hpddpers@ansible]$

[hpddpers@ansible]$ pwd
/root/home/hpddpers/ansible
[hpddpers@ansible]$ ll
total 160
-rw-r–r–. 1 hpddpers uxsup3 18186 Aug 24 10:08 ansible.cfg
-rw-r–r–. 1 hpddpers uxsup3 124595 Aug 24 11:35 ansible.log
-rw-r–r–. 1 hpddpers uxsup3 650 Aug 24 10:43 createuser.yaml
-rw-r–r–. 1 hpddpers uxsup3 348 Aug 24 10:45 deleteuser.yaml
drwxr-xr-x. 2 hpddpers uxsup3 51 Aug 24 10:48 inventario
-rwxr–r–. 1 hpddpers uxsup3 257 Aug 24 10:11 lista_groups.sh
-rwxr–r–. 1 hpddpers uxsup3 210 Aug 24 10:10 lista_hosts.sh
drwxr-xr-x. 2 hpddpers uxsup3 30 Aug 24 10:43 retry
[hpddpers@ansible]$

Mejora de la velocidad de ejecución de Ansible

Por defecto, Ansible ejecuta cada uno de los módulos de un playbook en bloques de dos servidores. Es decir, si dentro del playbook hacemos una llamada al módulo «yum», éste se ejecutará en los servidores 1 y 2 al mismo tiempo, luego en el 3 y 4, luego en el 5 y 6, y así sucesivamente.

Esta manera de trabajar puede ser muy lenta cuando trabajamos con cientos de servidores.

Para mejorar este punto, lo que podemos hacer es configurar la directiva «forks = 20» en el fichero ansible.cfg para que Ansible trabaje con bloques de 20 servidores.

Creación del inventario de Ansible para acceder a los servidores remotos

El inventario de Ansible es un archivo o una serie de archivos que definen los sistemas o hosts que Ansible administrará y ejecutará tareas en ellos. El inventario contiene información sobre los hosts, como sus direcciones IP, nombres de host, grupos de hosts y variables de host, que se utilizan para definir los entornos y la configuración de los sistemas que se administrarán.

El inventario de Ansible se puede escribir en diferentes formatos, como INI, YAML o JSON. El formato INI es el más utilizado y tiene la siguiente sintaxis básica:

[group_name]
host1 ansible_host=192.168.1.10 ansible_user=root ansible_ssh_pass=mypassword
host2 ansible_host=192.168.1.11 ansible_user=root ansible_ssh_pass=mypassword

En este ejemplo, el inventario tiene un grupo llamado «group_name» y dos hosts definidos en él, «host1» y «host2». Cada host tiene definidas sus direcciones IP, nombre de host y credenciales de autenticación para conectarse al host y ejecutar tareas.

Además de la información del host, el inventario también puede definir variables de host y grupos de hosts. Las variables de host son variables específicas de cada host que se pueden utilizar en los Playbooks y Roles de Ansible para configurar y personalizar el sistema de destino. Los grupos de hosts son agrupaciones lógicas de hosts que se pueden utilizar para ejecutar tareas en múltiples hosts simultáneamente.

Por ejemplo, en el siguiente inventario, se define un grupo llamado «webservers» que incluye los hosts «host1» y «host2», y se define una variable de host «web_port» con el valor 80 para el grupo «webservers»:

[webservers]
host1 ansible_host=192.168.1.10 ansible_user=root ansible_ssh_pass=mypassword
host2 ansible_host=192.168.1.11 ansible_user=root ansible_ssh_pass=mypassword

[webservers:vars]
web_port=80

En este ejemplo, la variable «web_port» se puede utilizar en los Playbooks y Roles de Ansible para configurar el puerto web en los hosts del grupo «webservers».

El inventario de Ansible se puede configurar en diferentes formas, como en un archivo local o remoto, o utilizando una herramienta de descubrimiento de host para dinámicamente descubrir los sistemas que se administrarán. La configuración del inventario se especifica en el archivo de configuración de Ansible llamado «ansible.cfg».

En resumen, el inventario de Ansible es un archivo o una serie de archivos que definen los sistemas o hosts que Ansible administrará y ejecutará tareas en ellos. El inventario contiene información sobre los hosts, como sus direcciones IP, nombres de host, grupos de hosts y variables de host, que se utilizan para definir los entornos y la configuración de los sistemas que se administrarán. El inventario se puede configurar de diferentes formas y se especifica en el archivo de configuración de Ansible llamado «ansible.cfg».

Veamos un ejemplo sencillo:

[hpddpers@inventario]$ pwd
/root/home/hpddpers/ansible/inventario
[hpddpers@inventario]$ cat servidores.txt
#Servidores que pertenecen al grupo TEST
[TEST]
# Si el DNS no resuelve los nombres de los servidores, podemos indicar su IP
server1 ansible_host=30.34.79.13
server2 ansible_host=30.34.79.33

# Variables globales para todos los servidores del grupo test
[TEST:vars]
ansible_password=Mi_Contraseña

#ansible_user=Mi_usuario_de_sistema
# No es necesario contraseña si se ha configurado una relación de confianza previamente
#ansible_ssh_pass=XXXX
# Configuramos las credenciales de root para que Ansible ejecute las tareas con este usuario
ansible_become=True
ansible_become_method=su
ansible_become_user=root
ansible_become_pass=Contraseña_del_usuario_root
[hpddpers@inventario]$

Consultamos los servidores que hemos configurado para que Ansible pueda realizar alguna acción sobre ellos:

[hpddpers@ansible]$ ansible all -i inventario/servidores.txt --list-hosts --limit "$LIMIT"

hosts (2):
server1
server2
[hpddpers@ansible]$

Lo mismo pero a nivel de grupo:

[hpddpers@ansible]$ ansible TEST -i inventario/servidores.txt  -m debug -a var=group_names
server1 | SUCCESS => {
"group_names": [
"TEST"
]
}
server2 | SUCCESS => {
"group_names": [
"TEST"
]
}

Podemos crear un segundo fichero de servidores:

[hpddpers@ansible]$ cat inventario/servidores2.txt
[WS]
servidor1
servidor2

[BD]
bd1
servidor1

[AS]
servidor2
servidor3
[hpddpers@ansible]$

Y ver los servidores que pertenecen al grupo WS, o al WS y AS o a la intersección de ambos grupos, por ejemplo:

[hpddpers@ansible]$ ansible all -i inventario/servidores2.txt --list-hosts --limit "WS"
hosts (2):
servidor1
servidor2
[hpddpers@ansible]$ ansible all -i inventario/servidores2.txt --list-hosts --limit "WS:AS"
hosts (3):
servidor1
servidor2
servidor3
[hpddpers@ansible]$ ansible all -i inventario/servidores2.txt --list-hosts --limit "WS:&AS"
hosts (1):
servidor2
[hpddpers@ansible]$

Ejecución de comandos con Ansible en servidores remotos

Vamos a ejecutar el comando “id” en los servidores del grupo TEST (he deshabilitado el acceso como root del fichero de configuración). Utilizamos el modo adhoc:

[hpddpers@ansible]$ ansible TEST -i inventario/servidores.txt -a id
server1 | SUCCESS | rc=0 >>
uid=8402895(hpddpers) gid=45005(uxsup3) groups=45005(uxsup3) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

server2| SUCCESS | rc=0 >>
uid=8402895(hpddpers) gid=45005(uxsup3) groups=45005(uxsup3)

Vamos a ejecutar un comando más complejo, con tuberías. Para ello, usamos el modo shell:

[hpddpers@ansible]$ ansible TEST -i inventario/servidores.txt -m shell -a "ls -la |grep hpddpers"
server1| SUCCESS | rc=0 >>
drwx------. 4 hpddpers uxsup3 4096 Aug 24 10:19 .
drwx------ 3 hpddpers uxsup3 4096 Aug 24 10:19 .ansible
-rw-------. 1 hpddpers uxsup3 1315 Jul 19 09:30 .bash_history
-rw-r--r--. 1 hpddpers uxsup3 18 Sep 26 2014 .bash_logout
-rw-r--r--. 1 hpddpers uxsup3 176 Sep 26 2014 .bash_profile
-rw-r--r--. 1 hpddpers uxsup3 124 Sep 26 2014 .bashrc
drwx------. 2 hpddpers uxsup3 4096 Aug 24 06:15 .ssh

server2| SUCCESS | rc=0 >>
drwx------. 4 hpddpers uxsup3 4096 Aug 24 10:19 .
drwx------. 3 hpddpers uxsup3 4096 Aug 24 10:19 .ansible
-rw-------. 1 hpddpers uxsup3 1866 Jun 19 08:28 .bash_history
-rw-r--r--. 1 hpddpers uxsup3 18 Jan 27 2011 .bash_logout
-rw-r--r--. 1 hpddpers uxsup3 176 Jan 27 2011 .bash_profile
-rw-r--r--. 1 hpddpers uxsup3 124 Jan 27 2011 .bashrc
drwx------. 2 hpddpers uxsup3 4096 Aug 24 06:15 .ssh
-rw-------. 1 hpddpers uxsup3 754 May 11 2015 .viminfo

Vuelvo a habilitar las credenciales de root para crear un usuario en los dos servidores del grupo TEST:

[hpddpers@ansible]$ ansible TEST -i inventario/servidores.txt -m user -a «name=kk state=present»
server1| SUCCESS => {
«changed»: true, –> Significa que Ansible ha hecho un cambio en el servidor para ejecutar esta tarea
«comment»: «»,
«createhome»: true,
«group»: 52835,
«home»: «/home/kk»,
«name»: «kk»,
«shell»: «/bin/bash»,
«state»: «present»,
«system»: false,
«uid»: 52835
}
server2| SUCCESS => {
«changed»: true,
«comment»: «»,
«createhome»: true,
«group»: 52834,
«home»: «/home/kk»,
«name»: «kk»,
«shell»: «/bin/bash»,
«state»: «present»,
«system»: false,
«uid»: 52834
}
[hpddpers@ansible]$

Si volvemos a ejecutar el comando, observaremos que ya no ha realizado ningún cambio, al haberlo hecho con anterioridad:

[hpddpers@ansible]$ ansible TEST -i inventario/servidores.txt -m user -a «name=kk state=present»
server1| SUCCESS => {
«append»: false,
«changed»: false,
«comment»: «»,
«group»: 52835,
«home»: «/home/kk»,
«move_home»: false,
«name»: «kk»,
«shell»: «/bin/bash»,
«state»: «present»,
«uid»: 52835
}
server2| SUCCESS => {
«append»: false,
«changed»: false,
«comment»: «»,
«group»: 52834,
«home»: «/home/kk»,
«move_home»: false,
«name»: «kk»,
«shell»: «/bin/bash»,
«state»: «present»,
«uid»: 52834
}
[hpddpers@ansible]$

Podemos comprobar que la tarea se ha realizado entrando a los servidores o en remoto desde Ansible:

[root@la02sui0 ~]# id kk
uid=52834(kk) gid=52834(kk) groups=52834(kk)
[root@la02sui0 ~]#

[hpddpers@ansible]$ ansible TEST -a "id kk"
la02sui1 | SUCCESS | rc=0 >>
uid=52835(kk) gid=52835(kk) groups=52835(kk)

la02sui0 | SUCCESS | rc=0 >>
uid=52834(kk) gid=52834(kk) groups=52834(kk)
[hpddpers@ansible]$

Eliminamos el usuario creado anteriormente:

[hpddpers@ansible]$ ansible TEST -m user -a «name=kk state=absent«
la02sui0 | SUCCESS => {
«changed»: true,
«force»: false,
«name»: «kk»,
«remove»: false,
«state»: «absent»
}
la02sui1 | SUCCESS => {
«changed»: true,
«force»: false,
«name»: «kk»,
«remove»: false,
«state»: «absent»
}
[hpddpers@ansible]$

[hpddpers@ansible]$ ansible TEST -a «id kk»
la02sui1 | FAILED | rc=1 >>
id: kk: No such user

la02sui0 | FAILED | rc=1 >>
id: kk: No such user

[hpddpers@ansible]$

Ejecutar comandos Shell Script

Podemos ejecutar comandos Shell Script (bash) desde la línea de comandos de Ansible. Ejemplo:

[root@server1 Ansible]# ansible TEST -i inventario/test.txt -m shell -a 'echo $TERM'
server2 | CHANGED | rc=0 >>
xterm

[root@lhpilox01 Ansible]#

ATENCIÓN: Algunos comandos pueden necesitar que se carguen las variables de entorno del usuario, por lo que lo ejecutaríamos de la siguiente manera:

shell: bash -lc ‘/tmp/vmware-tools-distrib/vmware-install.pl’

El parametro «-l» de bash carga las variables de entorno del usuario que ejecuta el comando vmware-install.pl.

También podemos configurar las variables de entorno en el propio playbook:

- name: Nombre del playbook
  hosts: all
  gather_facts: false
  environment:
    PATH: "/bin:/sbin:/usr/bin:/usr/sbin:.:/usr/local/bin"

Ejecutar múltiples comandos con Ansible

Si en vez de un solo comando queremos ejecutar más de uno en la misma línea con Ansible, utilizaremos la directiva «shell» de Ansible de la siguiente manera:

- name: Probar dos comandos
    shell: |
       /usr/bin/chmod -R 755 /mi_filesystem
       /mi_filesystem/mi_script.sh
    become: yes

Ejecutar un script local en un servidor remoto

Si hemos creado un script local en bash podemos ejecutarlo masivamente en servidores remotos con Ansible sin necesidad de copiarlo a cada uno de ellos manualmente. Lo haremos así:

Código fuente del Playbook

[root@lhpilox01 Ansible]# cat playbooks/check_multipath.yml
- hosts: TEST
  tasks:
     - name: Chequeo multipath
       script: /planific/bin/admsys/check_multipath.sh
       register: out
       tags:
       - checkmultipath

     - debug: var=out.stdout_lines
     - local_action: copy content={{ out.stdout }} dest="/planific/bin/admsys/Ansible/log/check_multipath.{{ inventory_hostname }}.out"
       tags:
       - checkmultipath
[root@lhpilox01 Ansible]#

Ejecución del playbook con el script local

[root@server1 Ansible]# ansible-playbook playbooks/check_multipath.yml -i inventario/test.txt -v
Using /planific/bin/admsys/Ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/test.txt did not meet host_list requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/Ansible/inventario/test.txt did not meet script requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/Ansible/inventario/test.txt did not meet yaml requirements, check plugin documentation if this is unexpected

PLAY [TEST] **************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
ok: [server1.ecs.hp.com]
ok: [server2]

TASK [Chequeo multipath] *************************************************************************************************************************************************************************
changed: [server1] => {"changed": true, "rc": 0, "stderr": "Shared connection to server1 closed.rn", "stderr_lines": ["Shared connection to server1 closed."], "stdout": "server1;0 paths failedrnserver1;54 paths activernserver1;Red Hat Enterprise Linux Server release 6.9 (Santiago)rnserver1;2.6.32-696.20.1.el6.x86_64rnserver1;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)rnserver1;Device Mapper - Driver version:    4.33.1rnserver1;HBA 05:00.0 - QLogic Fibre Channel HBA Driverrnserver1;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-krnserver1;HBA 05:00.1 - QLogic Fibre Channel HBA Driverrnserver1;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-krn", "stdout_lines": ["server1;0 paths failed", "server1;54 paths active", "server1;Red Hat Enterprise Linux Server release 6.9 (Santiago)", "server1;2.6.32-696.20.1.el6.x86_64", "server1;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)", "server1;Device Mapper - Driver version:    4.33.1", "server1;HBA 05:00.0 - QLogic Fibre Channel HBA Driver", "server1;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-k", "server1;HBA 05:00.1 - QLogic Fibre Channel HBA Driver", "server1;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-k"]}
changed: [server2] => {"changed": true, "rc": 0, "stderr": "Shared connection to server2 closed.rn", "stderr_lines": ["Shared connection to server2 closed."], "stdout": "server2;0 paths failedrnserver2;57 paths activernserver2;Red Hat Enterprise Linux Server release 6.9 (Santiago)rnserver2;2.6.32-696.20.1.el6.x86_64rnserver2;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)rnserver2;Device Mapper - Driver version:    4.33.1rnserver2;HBA 05:00.0 - QLogic Fibre Channel HBA Driverrnserver2;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-krnserver2;HBA 05:00.1 - QLogic Fibre Channel HBA Driverrnserver2;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-krn", "stdout_lines": ["server2;0 paths failed", "server2;57 paths active", "server2;Red Hat Enterprise Linux Server release 6.9 (Santiago)", "server2;2.6.32-696.20.1.el6.x86_64", "serer2;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)", "server2;Device Mapper - Driver version:    4.33.1", "server2;HBA 05:00.0 - QLogic Fibre Channel HBA Driver", "server2;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-k", "server2;HBA 05:00.1 - QLogic Fibre Channel HBA Driver", "server2;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-k"]}

TASK [debug] *************************************************************************************************************************************************************************************
ok: [server1] => {
    "out.stdout_lines": [
        "server1;0 paths failed",
        "server1;54 paths active",
        "server1;Red Hat Enterprise Linux Server release 6.9 (Santiago)",
        "server1;2.6.32-696.20.1.el6.x86_64",
        "server1;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)",
        "server1;Device Mapper - Driver version:    4.33.1",
        "server1;HBA 05:00.0 - QLogic Fibre Channel HBA Driver",
        "server1;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-k",
        "server1;HBA 05:00.1 - QLogic Fibre Channel HBA Driver",
        "server1;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-k"
    ]
}
ok: [server2] => {
    "out.stdout_lines": [
        "server2;0 paths failed",
        "server2;57 paths active",
        "server2;Red Hat Enterprise Linux Server release 6.9 (Santiago)",
        "server2;2.6.32-696.20.1.el6.x86_64",
        "server2;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)",
        "server2;Device Mapper - Driver version:    4.33.1",
        "server2;HBA 05:00.0 - QLogic Fibre Channel HBA Driver",
        "server2;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-k",
        "server2;HBA 05:00.1 - QLogic Fibre Channel HBA Driver",
        "server2;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-k"
    ]
}

TASK [copy] **************************************************************************************************************************************************************************************
changed: [server2 -> localhost] => {"changed": true, "checksum": "879550a71645dd447bb0d0f44fb07ee2c140cb26", "dest": "/planific/bin/admsys/Ansible/log/check_multipath.server2.out", "gid": 0, "group": "root", "md5sum": "2b095c9b763c576df7cfe8d2a932ca3d", "mode": "0644", "owner": "root", "size": 506, "src": "/root/.ansible/tmp/ansible-tmp-1558444377.09-156345710637833/source", "state": "file", "uid": 0}
changed: [server1 -> localhost] => {"changed": true, "checksum": "2d7e11c889851e60abc539c059644ac8f0711345", "dest": "/planific/bin/admsys/Ansible/log/check_multipath.server1.out", "gid": 0, "group": "root", "md5sum": "8843d6629b7f0e00cd8aa544f6480232", "mode": "0644", "owner": "root", "size": 506, "src": "/root/.ansible/tmp/ansible-tmp-1558444376.75-97728370581421/source", "state": "file", "uid": 0}

PLAY RECAP ***************************************************************************************************************************************************************************************
server1 : ok=4    changed=2    unreachable=0    failed=0
server2 : ok=4    changed=2    unreachable=0    failed=0

[root@lhpilox01 Ansible]# ll log
total 175
-rw-r--r-- 1 root root 174232 May 21 15:12 ansible.log
-rw-r--r-- 1 root root    506 May 21 15:12 check_multipath.server1.out
-rw-r--r-- 1 root root    506 May 21 15:12 check_multipath.server2.out
[root@server1 Ansible]#

Salida del script

Se genera un fichero para cada servidor.

[root@server1 Ansible]# cat log/check_multipath.server1.out
server1;0 paths failed
server1;54 paths active
server1;Red Hat Enterprise Linux Server release 6.9 (Santiago)
server1;2.6.32-696.20.1.el6.x86_64
server1;Device Mapper - Library version:   1.02.117-RHEL6 (2016-12-13)
server1;Device Mapper - Driver version:    4.33.1
server1;HBA 05:00.0 - QLogic Fibre Channel HBA Driver
server1;HBA 05:00.0 - Driver version: 8.07.00.08.06.0-k
server1;HBA 05:00.1 - QLogic Fibre Channel HBA Driver
server1;HBA 05:00.1 - Driver version: 8.07.00.08.06.0-k
[root@server1 Ansible]#

Automatización de tareas con RUNDECK

¿Qué es un playbook de Ansible?

Los Playbooks son una característica clave de Ansible y se utilizan para definir y orquestar las tareas que se deben realizar en los sistemas remotos. Los Playbooks de Ansible son archivos escritos en formato YAML, lo que los hace fáciles de leer y entender. Un Playbook contiene una serie de tareas que se ejecutan en orden, y cada tarea define qué módulos se deben ejecutar y cómo se deben configurar.

Cada tarea en un Playbook tiene una identificación única y una breve descripción que la describe. Las tareas también pueden contener variables, que se utilizan para personalizar la tarea para cada sistema remoto en el que se ejecuta. Ansible incluye un conjunto completo de módulos que se pueden utilizar en los Playbooks, desde tareas simples como la creación de usuarios y la configuración de archivos, hasta tareas más complejas como la implementación de aplicaciones y la orquestación de tareas a través de múltiples sistemas.

Además, los Playbooks se pueden utilizar para automatizar tareas de configuración y aprovisionamiento de infraestructura, lo que permite a los administradores de sistemas definir y orquestar tareas complejas en múltiples sistemas. Ansible proporciona una amplia gama de módulos y complementos que se pueden utilizar para extender la funcionalidad de los Playbooks y personalizarlos según las necesidades específicas del entorno de TI.

Si todavía te parece un poco confuso el funcionamiento de los playbooks de Ansible, vamos a utilizar un ejemplo para explicar su arquitectura, aunque a lo largo de este documento, veremos más:

---
- name: Instalar y configurar Apache
  hosts: webservers
  become: true

  tasks:
    - name: Actualizar paquetes
      apt:
        update_cache: yes
      when: ansible_os_family == 'Debian'

    - name: Instalar Apache
      apt:
        name: apache2
        state: latest
      when: ansible_os_family == 'Debian'

    - name: Configurar página de inicio
      copy:
        src: index.html
        dest: /var/www/html/index.html
        owner: root
        group: root
        mode: '0644'

    - name: Iniciar servicio Apache
      service:
        name: apache2
        state: started
        enabled: true

Este Playbook consta de cuatro tareas, que se describen a continuación:

  • El nombre del Playbook se define en la primera línea del archivo. En este caso, el nombre es «Instalar y configurar Apache».
  • La línea «hosts» especifica en qué sistemas remotos se ejecutará el Playbook. En este caso, el Playbook se ejecutará en todos los servidores que se encuentren en el grupo «webservers».
  • La línea «become» se utiliza para habilitar la elevación de privilegios (sudo o similar) en los sistemas remotos, lo que permite a Ansible realizar tareas como usuario root o similar.
  • Las tareas se definen en la sección «tasks». Cada tarea tiene un nombre y define qué módulo se debe ejecutar y cómo se debe configurar.
  • En la primera tarea, se utiliza el módulo «apt» para actualizar los paquetes en los sistemas Debian.
  • En la segunda tarea, se utiliza el módulo «apt» para instalar la última versión de Apache en los sistemas Debian.
  • En la tercera tarea, se utiliza el módulo «copy» para copiar un archivo de índice HTML en el directorio de la página de inicio de Apache.
  • En la cuarta tarea, se utiliza el módulo «service» para iniciar y habilitar el servicio Apache en los sistemas Debian.

En resumen, la arquitectura de un Playbook de Ansible consta de varias secciones que definen el nombre del Playbook, los sistemas remotos en los que se ejecutará, las tareas que se realizarán y los módulos que se utilizarán para realizar esas tareas. Las tareas se ejecutan en orden y pueden incluir condiciones para asegurar que se ejecuten solo en sistemas específicos.

Ejecutar un comando en un servidor remoto desde un Playbook

Igual que ejecutamos un comando en un servidor remoto con Ansible, mediante la invocación de la shell, también podemos realizar esta operación desde un playbook. Veamo un ejemplo:

Código fuente del playbook

[root@lhpilox01 Ansible]# cat playbooks/send_command.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Ejecutar comando
    command: id
    register: myid
[root@lhpilox01 Ansible]#

Chequear la sintaxis del playbook

Antes de ejecutar el playbook conviene saber si hay algún error de sintaxis en el código fuente. Lo haremos con el siguiente comando:

ansible-playbook Nombre_Playbook.yml --syntax-check

Ejecución

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "HOSTS=lhpilox01" -i inventario/david playbooks/send_command.yml -vv
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: send_command.yml ***********************************************************************************************************************************************************************
1 plays in playbooks/send_command.yml

PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/send_command.yml:1
ok: [lhpilox01]
META: ran handlers

TASK [Ejecutar comando] **************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/send_command.yml:3
changed: [lhpilox01] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.004737", "end": "2019-09-23 08:46:49.044521", "rc": 0, "start": "2019-09-23 08:46:49.039784", "stderr": "", "stderr_lines": [], "stdout": "uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)", "stdout_lines": ["uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)"]}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Enviar un comando con las credenciales de root

A través de los parámetros de Ansible, también podemos enviar las credenciales correspondientes para convertirnos en root y ejecutar el comando como si fuésemos root. Para ello, vamos a utilizar el playbook anterior pero ahora también vamos a personalizar el comando que vamos a enviar. Luego, lo ejecutaremos con las credenciales correspondientes:

Código fuente del playbook

[root@lhpilox01 Ansible]# cat playbooks/send_command.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Ejecutar comando
    command: "{{ COMANDO }}"
    register: myid
[root@lhpilox01 Ansible]#

Ejecución

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "HOSTS=lhpilox01 ansible_user=hpddpers ansible_password=ContraseñaSecretaDelUsuario ansible_become=True ansible_become_method=su ansible_become_user=root ansible_become_pass=ContraseñaSecretaDelUsuarioRoot COMANDO=id" -i inventario/david playbooks/send_command.yml -vv
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: send_command.yml ***********************************************************************************************************************************************************************
1 plays in playbooks/send_command.yml

PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/send_command.yml:1
ok: [lhpilox01]
META: ran handlers

TASK [Ejecutar comando] **************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/send_command.yml:3
changed: [lhpilox01] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.005444", "end": "2019-09-23 09:41:42.869148", "rc": 0, "start": "2019-09-23 09:41:42.863704", "stderr": "", "stderr_lines": [], "stdout": "uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)", "stdout_lines": ["uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)"]}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Como podemos observar en los parámetros de ejecución del playbook, estamos pasando las credenciales del usuario root y nos convertimos a el mediante su. Lo remarco en negrita:

ansible-playbook –extra-vars «HOSTS=lhpilox01 ansible_user=hpddpers ansible_password=ContraseñaSecretaDelUsuario ansible_become=True ansible_become_method=su ansible_become_user=root ansible_become_pass=ContraseñaSecretaDelUsuarioRoot COMANDO=id» -i inventario/david playbooks/send_command.yml -vv

Solicitar la contraseña del usuario remoto por línea de comandos

Inventario de pruebas

Voy a utilizar el siguiente inventario de servidores para esta prueba:

[root@lhpilox01 Ansible]# cat inventory/david
[CENTRALIZADOR]
lhpilox01

[PRUEBAS]
lansibd0
[root@lhpilox01 Ansible]#

Contenido del Playbook

  • Become: yes –> Sirve para convertirnos en root
  • Si ponemos become_user, especificamos el usuario al que nos queremos convertir.
[root@lhpilox01 Ansible]# cat /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Generar fichero limits.conf
    template:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/limits.conf
       dest: /etc/security/limits.conf
       mode: '0644'
       backup: yes
    become: yes
    #become_user: apache
[root@lhpilox01 Ansible]#

Ejecución del Playbook

  • -e «HOSTS=PRUEBAS»  –> Grupo de servidores que tengo definido en el inventario
  • –user hpddpers  –> Es mi usuario de HPSA
  • –ask-pass –> Solicito que me pregunte mi contraseña
  • –become-method su –> Nos convertiremos a otro usuario mediante el comando “su”
  • –ask-become-pass –> Solicito que pregunte la contraseña del usuario al que nos convertimos
  • -i inventory/david –> Inventario de servidores de pruebas que estoy utilizando
  • /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml -vv –> Playbook a ejecutar
[root@lhpilox01 Ansible]# ansible-playbook -e "HOSTS=PRUEBAS" --user hpddpers --ask-pass --become-method su --ask-become-pass -i inventory/david /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml -vv
[WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
SSH password:
SU password[defaults to SSH password]:
/planific/bin/admsys/Ansible/inventory/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: limits.yml *****************************************************************************************************************************************************************************
1 plays in /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml

PLAY [PRUEBAS] ***********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml:1
ok: [lansibd0]
META: ran handlers

TASK [Generar fichero limits.conf] ***************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/limits.yml:7
changed: [lansibd0] => {"backup_file": "/etc/security/limits.conf.15442.2019-10-03@11:21:44~", "changed": true, "checksum": "126e109a76ba260a26f72c524ce582e75fec2017", "dest": "/etc/security/limits.conf", "gid": 0, "group": "root", "md5sum": "f832f75581b59d21122df855afb20aa0", "mode": "0644", "owner": "root", "secontext": "unconfined_u:object_r:etc_t:s0", "size": 2518, "src": "/root/home/hpddpers/.ansible/tmp/ansible-tmp-1570094502.03-197689005320199/source", "state": "file", "uid": 0}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
lansibd0                   : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Creación y eliminación de usuarios

Creamos el fichero yaml:

[hpddpers@ansible]$ cat createuser.yaml
- name: Prueba de creacion de usuario
#hosts: all
hosts: TEST
#hosts: la02sui0
gather_facts: false
vars:
kk_group: kk
kk_group_id: 8481
kk_user: kk
kk_user_id: 8497
kk_passwd: Pass8497ISIM
tasks:
- name: Creo group kk
group:
name: "{{ kk_group }}"
gid: "{{ kk_group_id }}"
state: present
- name: Creo user kk
user:
name: "{{ kk_user }}"
uid: "{{ kk_user_id }}"
group: "{{ kk_group }}"
password: "{{ kk_passwd |password_hash('sha512') }}"
state: present
update_password: on_create # Solo cambia la contraseña cuando se crea el usuario

Ejecutamos el comando para crear el usuario con el playbook:

[hpddpers@ansible]$ ansible-playbook createuser.yaml
PLAY [Prueba de creacion de usuario] *********************************************************************************************************************

TASK [Creo group kk] *************************************************************************************************************************************
changed: [la02sui1]
changed: [la02sui0]

TASK [Creo user kk] **************************************************************************************************************************************
changed: [la02sui1]
changed: [la02sui0]

PLAY RECAP ***********************************************************************************************************************************************
server1: ok=2 changed=2 unreachable=0 failed=0
server2: ok=2 changed=2 unreachable=0 failed=0

Creamos el módulo para eliminar el usuario:

[hpddpers@ansible]$ cat deleteuser.yaml
- name: Prueba de creacion de usuario
#hosts: all
hosts: TEST
#hosts: server1
gather_facts: false
vars:
kk_group: kk
kk_user: kk
tasks:
- name: Elimino user kk
user:
name: "{{ kk_user }}"
state: absent
- name: Elimino group kk
group:
name: "{{ kk_group }}"
state: absent

Y lo ejecutamos:

[hpddpers@ansible]$ ansible-playbook deleteuser.yaml
PLAY [Prueba de creacion de usuario] *********************************************************************************************************************

TASK [Elimino user kk] ***********************************************************************************************************************************
changed: [la02sui1]
changed: [la02sui0]

TASK [Elimino group kk] **********************************************************************************************************************************
ok: [la02sui1]
ok: [la02sui0]

PLAY RECAP ***********************************************************************************************************************************************
server1: ok=2 changed=1 unreachable=0 failed=0
server2 : ok=2 changed=1 unreachable=0 failed=0

Ansible también utiliza variables internas que podemos utilizar dentro de los ficheros yaml. Las podremos extraer con el comando: ansible TEST -m setup

Añadir una línea a un fichero de texto

[root@server1 Ansible]# cat playbooks/add_text_to_file.yml
- hosts: TEST
  tasks:
  - lineinfile:
     path: /tmp/david.txt
     line: 'Línea 3'
[root@server1 Ansible]#

Validación

Como vemos, al final del fichero de texto se ha añadido la línea «Línea 3».

Fichero original:
[root@server1 ~]# cat david.txt
Línea 1
Línea 2
[root@server1 ~]#

Fichero tras la ejecución del playbook:
[root@lremdot1 tmp]# cat david.txt
Línea 1
Línea 2
Línea 3
[root@server1 tmp]#

Sustitución de una cadena de texto

Ahora, vamos a sustituir “Línea 3” por “Línea 4”.

[root@server1 Ansible]# cat playbooks/replace_text.yml
- hosts: TEST
  tasks:
  - lineinfile:
     path: /tmp/david.txt
     regexp: 'Línea 3'
     line: 'Línea 4'
[root@server1 Ansible]#

Añadir una línea de texto antes de una línea

Antes del texto “Línea 4” vamos a insertar el texto “Línea 3”.

[root@server1 Ansible]# cat playbooks/add_text_to_file_before.yml
- hosts: TEST
  tasks:
  - lineinfile:
     path: /tmp/david.txt
     insertbefore: '^Línea 4'
     line: 'Línea 3'
[root@server1 Ansible]#

Añadir una línea de texto al final del archivo (append)

Para añadir una línea de texto al final de un fichero, utilizaremos la directiva «insertafter: EOF» dentro del Playbook:

[root@lhpilox01 Ansible]# cat playbooks/post-provisioning/RHEL7/HIST.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - lineinfile:
     path: /etc/profile
     line: "export HISTTIMEFORMAT='%F %T '"
     insertafter: EOF
     state: present
  become: yes
[root@lhpilox01 Ansible]#

Me gusta mucho utilizar lineinfile para recoger información de muchos servidores y guardarla en un archivo local para tenerla agrupada en un único fichero:

[root@server1 rearcron]# cat rearcron.yml
  - name: Get rear cron information
    register: croninfo
    shell: "crontab -l |grep -i mkbackup"
    ignore_errors: yes
    poll: 5
    become: yes
  - name: Save information
    local_action:
       module: lineinfile
       path: crontab_rear.txt
       line: "{{ inventory_hostname }};{{ croninfo.stdout }}"
    ignore_errors: yes
    poll: 5
    become: yes

[root@server1 rearcron]#

[root@server1 rearcron]# cat crontab_rear.txt
server2;30 04 02 * * /usr/sbin/rear -v mkbackup >/dev/null 2>&1
server3.8788.1286.ecs.hp.com;00 00 10 * * /usr/sbin/rear -v mkbackup > /dev/null 2>&1
[root@server1 rearcron]#

Eliminar texto

Eliminamos el texto «Línea 4».

[root@server1 Ansible]# cat playbooks/remove_text.yml
- hosts: TEST
  tasks:
  - lineinfile:
     path: /tmp/david.txt
     regexp: 'Línea 4'
     state: absent
[root@server1 Ansible]#

Insertar múltiples líneas en un fichero de texto

Anteriormente hemos insertado una sola línea en un fichero de texto, pero si queremos añadir más de una, utilizaremos blokinline en vez de lineinfile. Veamos un ejemplo:

[root@lhpilox01 RHEL7]# cat logrotate.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Copiar la plantilla de rotacion de logs de Sistemas UNIX
    template:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/LOGROTATE/script/logrotate.sh
       dest: /planific/bin/admsys/logrotate.sh
       mode: '0700'
       backup: no
  - name: Configuracion de cron
    blockinfile:
      path: /var/spool/cron/root
      marker: "# ANSIBLE - Mantenimiento logrotate.status"
      block: |
         # Mantenimiento del archivo /var/lib/logrotate.status
         00 00 1 * * /planific/bin/admsys/logrotate.sh >/dev/null 2>&1
  become: yes
[root@lhpilox01 RHEL7]#

Si ejecutamos el Playbook, veremos que en el fichero de texto se han registrado las siguientes entradas al final del mismo:

[root@lansibd0 ~]# crontab -l |tail -6
# ANSIBLE - Mantenimiento logrotate.status
# Mantenimiento del archivo /var/lib/logrotate.status
00 00 1 * * /planific/bin/admsys/logrotate.sh >/dev/null 2>&1
# ANSIBLE - Mantenimiento logrotate.status
[root@lansibd0 ~]#

Aprende más sobre el mantenimiento de logs con logrotate

Ejecutar Playbooks con Parámetros en la Línea de Comandos

Es muy habitual crear una plantilla de Ansible con variables en su interior cuyo valor se recoge desde la línea de comandos. Para ello, utilizaremos la sintaxis Jinja2 y, a modo de ejemplo, escribiremos un fichero de texto pasándole el contenido en un parámetro de la línea de comandos:

Código fuente del Playbook

[root@lhpilox01 Ansible]# cat playbooks/add_text_to_file_var.yml
- hosts: lhpilox01
  tasks:
  - lineinfile:
     path: /tmp/david.txt
     line: "{{ texto }}"
[root@lhpilox01 Ansible]#

La variable {{ texto }} es la que pasaremos por parámetros en la línea de comandos cuando ejecutemos el Playbook.

Ejecución del Playbook

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "texto=David" -i inventario/test.txt playbooks/add_text_to_file_var.yml -v
Using /planific/bin/admsys/Ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/test.txt did not meet host_list requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/Ansible/inventario/test.txt did not meet script requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/Ansible/inventario/test.txt did not meet yaml requirements, check plugin documentation if this is unexpected

PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
ok: [lhpilox01]

TASK [lineinfile] ********************************************************************************************************************************************************************************
changed: [lhpilox01] => {"backup": "", "changed": true, "msg": "line added"}

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Podemos observar que hemos pasado por parámetros el valor de la variable texto. Lo vemos en «texto=David». Como podemos comprobar, se ha escrito ese nombre en el fichero indicado en el Playbook:

[root@lhpilox01 Ansible]# cat /tmp/david.txt
David
[root@lhpilox01 Ansible]#

Configurar un timeout a una tarea (task) de un playbook

Con el objetivo de que no se nos quede colgado un playbook de Ansible cuando lo ejecutamos contra cientos de servidores diferentes, es una buena práctica configurar un timeout en aquellas tareas que sabemos que podrían causar algún problema como, por ejemplo, una conexión SSH a un servidor inaccesible.

Para ello, dentro de la tarea del playbook, configuraremos las directivas «async» y «poll», como podemos ver a continuación:

[root@server1 ExecuteCommand]# cat execute_command.yml
  - name: Execute Command
    command: /usr/bin/ssh -o ConnectTimeout=10 Hostname_Inaccesible id
    ignore_errors: yes
    async: 45
    poll: 5
    become: yes
[root@server1 ExecuteCommand]#

Si una de las tareas falla o no se ha podido ejecutar en el timout especificado, veremos un mensaje similar al siguiente:

fatal: [test.com]: FAILED! => {"changed": false, "msg": "async task did not complete within the requested time - 45s"}
...ignoring
changed: [test.com]

async significa que vamos a ejecutar una tarea con un tiempo máximo de ejecución establecido. En el ejemplo anterior eran 45 segundos.

poll significa que vamos a testear el estado de la tarea cada cierto tiempo. En el ejemplo anterior eran 5 segundos.

Autentificarse con un usuario y contraseña y ejecutar un comando en remoto

Vamos a ejecutar el comando «id» en un servidor remoto una vez nos hayamos autentificado con el usuario y la contraseña que pasamos por parámetros:

Código fuente del playbook

[root@lhpilox01 Ansible]# cat playbooks/nsu.yml
- hosts: lhpilox01
  vars:
    remote_user: var={{ user }}
    password: var={{ pass }}
  tasks:
   - name: Ejecutar id
     command: id

Ejecución

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "user=hpddpers pass=ContraseñaSecreta" -i inventario/test.txt playbooks/nsu.yml -v
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/test.txt did not meet host_list requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/Ansible/inventario/test.txt did not meet yaml requirements, check plugin documentation if this is unexpected
 [WARNING]: Found variable using reserved name: remote_user


PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
ok: [lhpilox01]

TASK [Ejecutar id] *******************************************************************************************************************************************************************************
changed: [lhpilox01] => {"changed": true, "cmd": ["id"], "delta": "0:00:00.004495", "end": "2019-09-19 11:14:57.645141", "rc": 0, "start": "2019-09-19 11:14:57.640646", "stderr": "", "stderr_lines": [], "stdout": "uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)", "stdout_lines": ["uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)"]}

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Llamar a un Playbook dentro de otro Playbook

Es posible hacer una llamada a un playbook existente desde dentro de otro playbook que estemos creando. Por ejemplo, antes habíamos creado un playbook para sustituir una línea de texto y, además, contenía variables.

Bien, vamos a llamar a este playbook desde dentro de otro que sustituirá una línea del fichero sshd_conf y reiniciará el servicio. Veamos cómo funciona:

Playbook para sustituir una línea de texto

[root@lhpilox01 Ansible]# cat playbooks/replace_text.yml
- name: Reemplazar texto
  lineinfile:
    path: "{{ file }}"
    regexp: "{{ OriginalText }}"
    line: "{{ NewText }}"
[root@lhpilox01 Ansible]#

Playbook que realiza la llamada al anterior y reinicia el servicio de SSH

[root@lhpilox01 Ansible]# cat playbooks/disallow_root_login.yml
- hosts: lhpilox01
  tasks:
  - name: Establecer PermirRootLogin no
    include: replace_text.yml
    vars:
       file: /etc/ssh/sshd_config
       OriginalText: "# PermitRootLogin yes"
       NewText: "PermitRootLogin no"

  - name: restart SSH
    service:
       name: sshd
       state: restarted
[root@lhpilox01 Ansible]#

Como podemos observar, hacemos la llamada al primer playbook desde la línea include: replace_text.yml y, justo debajo, asignamos el valor de las variables que necesita este playbook para trabajar.

Más abajo reiniciamos el servicio SSHD para aplicar el cambio. Veamos el resultado de su ejecución:

[root@lhpilox01 Ansible]# ansible-playbook playbooks/disallow_root_login.yml -i inventario/david -v
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
ok: [lhpilox01]

TASK [Reemplazar texto] **************************************************************************************************************************************************************************
changed: [lhpilox01] => {"backup": "", "changed": true, "msg": "line replaced"}

TASK [restart SSH] *******************************************************************************************************************************************************************************
changed: [lhpilox01] => {"changed": true, "name": "sshd", "state": "started"}

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=3    changed=2    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Si queremos reiniciar un servicio de RedHat7, es decir, con systemctl, configuraremos el Playbook de Ansible de la siguiente manera:

 - name: restart Network
    systemd:
       name: network
       state: restarted
Como vemos, sustituimos "service" por "systemd".

Personalizar el log de un Playbook de Ansible

Si queremos guardar el log de un Playbook de Ansible en un path o con un nombre personalizado, utilizaremos el comando tee de Linux, tal y como podemos ver a continuación:

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "HOSTS=lhpilox01 ansible_user=hpddpers ansible_password=js0Kal&Ma@P1h( ansible_become=True ansible_become_method=su ansible_become_user=root ansible_become_pass=R3sfriad0s2016 COMANDO=id" -i inventario/david playbooks/send_command.yml -vv |tee /tmp/send_command.log

Revisamos el fichero generado:

[root@lhpilox01 Ansible]# head -10 /tmp/send_command.log
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: send_command.yml ***********************************************************************************************************************************************************************
[root@lhpilox01 Ansible]#

Trabajando con archivos, directorios y permisos

Con Ansible podemos realizar Playbooks que copien un archivo, un directorio de manera recursiva, modique los permisos o descromprima un fichero tar. Veamos algunos ejemplo:

Copiar un fichero local a un servidor remoto

- name: Copiar el fichero ssh.tar
    copy:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/USERLOGS/ssh.tar
       dest: /home/userlogs
       owner: userlogs
       group: userlogsgrp
       mode: '0700'

Copiar un fichero desde el servidor remoto al servidor local

Si queremos copiar una serie de ficheros, por ejemplo, *.tar.gz que están en un servidor remoto al servidor local, lo haremos de la siguiente manera:

[root@server1 SystemInventory]# cat execute_script.yml
- name: Get System Info
  script: generate_files_tar_gz.sh
  ignore_errors: yes
  poll: 5
  become: yes

- name: Find tar.gz files
  find:
    paths: "/tmp/"
    recurse: no
    patterns: "{{ ansible_hostname }}*.tar.gz"
  register: files_to_copy

- name: Copy tar.gz files
  fetch:
    src: "{{ item.path }}"
    dest: logs
  with_items: "{{ files_to_copy.files }}"
  become: yes
[root@server1 SystemInventory]#

Copiar un fichero que ya esté en el servidor remoto a otra ubicación

En este caso, utilizaremos la directiva remote_src: yes

- name: Configuracion de la zona horaria
    copy:
       src: /usr/share/zoneinfo/Europe/Madrid
       dest: /etc/localtime
       owner: root
       group: root
       mode: '0644'
       remote_src: yes

Modificar permisos de un fichero

- name: Modificar permisos id_rsa userlogs
    file:
       path: /home/userlogs/.ssh/id_rsa
       owner: userlogs
       group: userlogsgrp
       mode: '0700'

Crear un fichero vacío

 - name: Crear el fichero wrapper.sendlogs.sh
    file:
       path: /home/userlogs/scripts/wrapper.sendlogs.sh
       state: touch
       owner: userlogs
       group: userlogsgrp
       mode: '0755'

Crear un directorio

- name: Crear directorio .ssh
    file:
       path: /home/userlogs/.ssh
       state: directory
       owner: userlogs
       group: userlogsgrp
       mode: '0700'

Eliminar un archivo de los servidores remotos

El código fuente del Playbook, sería el siguiente:

[root@server1 Ansible]# cat playbooks/remove_file.yml
- hosts: TEST
  tasks:
  - file:
       path: /tmp/check_multipath.sh
       state: absent
[root@server1 Ansible]#

La directiva que se encarga de eliminar el fichero es «state: absent».

La ejecución es igual que el resto de Playbooks que hemos ejecutado hasta ahora.

Descomprimir un fichero tar

  - name: Descrompmir ssh.tar
    unarchive:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/USERLOGS/ssh.tar
       dest: /home/userlogs

Modificar una entrada en cron

Queremos sustituir la siguiente entrada de cron:

#Ansible: Backup bootable REAR
00 00 01 * * /usr/sbin/rear -v mkbackup > /dev/null 2>&1

por:

#Ansible: Backup bootable REAR
20 00 01 * * /usr/sbin/rear -v mkbackup > /dev/null 2>&1

El playbook a utilzar es el siguiente:

[root@server1cron]# cat cron.yml
  - name: Remove cron entry
    cron:
       name: "Backup bootable REAR"
       state: absent
  - name: Add cron entry
    cron:
       name: "Backup bootable REAR"
       minute: "20"
       hour: "00"
       day: "01"
       job: "/usr/sbin/rear -v mkbackup > /dev/null 2>&1"
       user: "root"
       state: present
    become: yes
[root@server1cron]#

Como podemos observar, hemos utilizado el módulo «cron» de Ansible.

Condicionales (directiva when)

Cuando realizamos un programa o un flujo de trabajo, lo normal es que necesitemos configurar condiciones. Por ejemplo, ejecuta el comando «X» si el sistema operativo es RedHat 6, si no, ejecuta el comando «Y» si el sistema operativo es RedHat 7. Es el típico bucle if then else de cualquier lenguaje de programación.

Con Ansible también podemos configurar condiciones para que se ejecuten tareas de un Playbook si se cumplen. Veamos un ejemplo:

OPERADOREJEMPLO
Igual«{{ max_memory }} == 512»
Menor que«{{ min_memory }} < 512»
Mayor que«{{ min_memory }} > 512»
Menor o igual que«{{ min_memory }} <= 512»
Mayor o igual que«{{ min_memory }} >= 512»
No es igual a«{{ min_memory }} != 512»
La variable existe«{{ min_memory }} is defined»
La variable no existe«{{ min_memory }} is not defined»
Valor booleano true (1)«{{ available_memory }}»
Valor booleano false (0)«not {{ available_memory }}»
El valor está presente en una variable o en un array«{{ users }} in users[«administrators»]»
tasks:
  - name: "Apagar Todos los Sistemas CentOS 6 y Debian 7"
    command: /sbin/shutdown -t now
    when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
          (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")

Salir de un playbook cuando no se cumple una condición

Pongamos por caso que no queremos que se ejecute ninguna tarea de un playbook si un servidor tiene menos de 2GB de RAM. En este caso, la primera tarea que tendremos que implementar será la del chequeo de memoria. Lo haremos así:

- name: Comprobamos si el servidor tiene mas de 2GB de RAM
    fail: msg="not enough RAM"
    when: ansible_memory_mb.real.total < 2048

Cuando ejecutemos el playbook de manera masiva, veremos que habrán fallado aquellos servidores en los que no se cumplía esta condición:

server1 : ok=17   changed=16   unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
server2 : ok=17   changed=16   unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
server3 : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
server4 : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Ejecutar una acción en función de la versión del sistema operativo

En el siguiente playbook, observamos que se ejecutan diferentes acciones en función de si el servidor remoto es un RedHat 6, un 7 o un 8.

  - name: Create directory
    file:
       path: /tmp/CarbonBlack
       state: directory

  - name: Copy Software for RHEL6
    copy:
      src: CarbonBlack/RHEL6/emea-carbonblacklinuxinstaller-v6.3.4.10012-default_group.tar
      dest: /tmp/CarbonBlack
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '6'

  - name: Copy Software for RHEL7
    copy:
      src: CarbonBlack/RHEL7_RHEL8/emea-carbonblacklinuxinstaller-latest-default_group.tar
      dest: /tmp/CarbonBlack
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '7'

  - name: Copy Software for RHEL8
    copy:
      src: CarbonBlack/RHEL7_RHEL8/emea-carbonblacklinuxinstaller-latest-default_group.tar
      dest: /tmp/CarbonBlack
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '8'

  - name: untar software in RHEL6
    unarchive:
       src: /tmp/CarbonBlack/emea-carbonblacklinuxinstaller-v6.3.4.10012-default_group.tar
       dest: /tmp/CarbonBlack
       remote_src: yes
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '6'

  - name: untar software in RHEL7
    unarchive:
       src: /tmp/CarbonBlack/emea-carbonblacklinuxinstaller-latest-default_group.tar
       dest: /tmp/CarbonBlack
       remote_src: yes
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '7'

  - name: untar software in RHEL8
    unarchive:
       src: /tmp/CarbonBlack/emea-carbonblacklinuxinstaller-latest-default_group.tar
       dest: /tmp/CarbonBlack
       remote_src: yes
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '8'

  - name: Execute installer for RHEL6
    shell: /tmp/CarbonBlack/CarbonBlackClientSetup-linux-v6.3.4.10012.sh
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '6'

  - name: Execute installer for RHEL7
    shell: /tmp/CarbonBlack/CarbonBlackClientSetup-linux-v7.0.3.15300.sh
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '7'

  - name: Execute installer for RHEL8
    shell: /tmp/CarbonBlack/CarbonBlackClientSetup-linux-v7.0.3.15300.sh
    become: yes
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '8'

  - name: Delete directory
    file:
       state: absent
       path: /tmp/CarbonBlack

Bucles loop

Como en todo lenguaje de programación, también podemos preparar bucles for en Ansible:

tasks:
    - command: echo {{ numero }}
      loop: [ 0, 2, 4, 6, 8, 10 ]
      when: numero > 3

También podemos configurar cada ítem del bucle en diferentes líneas en lugar de añadirlos todos en una sola. Veamos un ejemplo:

- hosts: todos
  become: true
  user: ansible
  tasks:
     - name: Instalar vsftps y httpd
       dnf:
          name: "{{ item }}"
          state: latest
    loop:
       - vsftpd
       - httpd

Vamos a poner un ejemplo más con loop en el que chequearemos sin el fichero /etc/audit/audit.rules existen o no una serie de directivas y dará el mensaje de «OK» o » NO OK», dependiendo de si existen o no:

- name: Check audit rules
  command: grep -E "^{{ item }}" /etc/audit/audit.rules
  register: result
  ignore_errors: true
  loop:    
    - "# Reboot"
    - "-a exit,always -F arch=b64 -S execve -F path=/usr/sbin/reboot -k reboot"
    - "-a exit,always -F arch=b64 -S execve -F path=/usr/sbin/poweroff -k reboot"
    - "# dnf/yum"
    - "-a always,exit -F perm=x -F path=/usr/bin/dnf -F key=software-installer"
    - "-a always,exit -F perm=x -F path=/usr/bin/yum -F key=software-installer"
  changed_when: false
  become: yes
- name: Show results
  debug:
    msg: "Rule {{ item.item }} {{ 'exists: OK' if item.rc == 0 else 'does not exist: NO OK' }}"
  loop: "{{ result.results }}"

Uso de Variables Globales o Internas de Ansible

Ansible incorpora una serie de variables internas o globales que podemos utilizar en nuestros playbooks. Son las siguientes:

[root@server1 Ansible]# ansible server1 -i inventario/david -m setup
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
server1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.48.0.29",
            "30.32.0.15"
        ],
        "ansible_all_ipv6_addresses": [],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "09/21/2015",
        "ansible_bios_version": "6.00",
        "ansible_cmdline": {
            "KEYBOARDTYPE": "pc",
            "KEYTABLE": "us",
            "LANG": "en_US.UTF-8",
            "SYSFONT": "latarcyrheb-sun16",
            "crashkernel": "129M@48M",
            "noacpi": true,
            "noapic": true,
            "quiet": true,
            "rd_LVM_LV": "vg00/swapvol",
            "rd_NO_DM": true,
            "rd_NO_LUKS": true,
            "rd_NO_MD": true,
            "ro": true,
            "root": "/dev/mapper/vg00-rootvol"
        },
        "ansible_date_time": {
            "date": "2019-10-01",
            "day": "01",
            "epoch": "1569933506",
            "hour": "14",
            "iso8601": "2019-10-01T12:38:26Z",
            "iso8601_basic": "20191001T143826475593",
            "iso8601_basic_short": "20191001T143826",
            "iso8601_micro": "2019-10-01T12:38:26.475989Z",
            "minute": "38",
            "month": "10",
            "second": "26",
            "time": "14:38:26",
            "tz": "CEST",
            "tz_offset": "+0200",
            "weekday": "Tuesday",
            "weekday_number": "2",
            "weeknumber": "39",
            "year": "2019"
        },
        "ansible_default_ipv4": {
            "address": "10.48.0.29",
            "alias": "eth0",
            "broadcast": "10.48.0.255",
            "gateway": "10.48.0.1",
            "interface": "eth0",
            "macaddress": "00:50:56:40:05:31",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "10.48.0.0",
            "type": "ether"
        },
        "ansible_default_ipv6": {},
        "ansible_device_links": {
            "ids": {
                "dm-0": [
                    "dm-name-vg00-rootvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jClaowrdCyuxd6nBgFWTcTQz59zF6uym2v"
                ],
                "dm-1": [
                    "dm-name-vg00-swapvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCml1d0by8fdcXVq3G0CabrOhd7QX4WfwM"
                ],
                "dm-10": [
                    "dm-name-vg00-optvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRSd4Cy464hzdd4nscD0XzRo2u7pDOq35"
                ],
                "dm-11": [
                    "dm-name-vg00-rhomevol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCnPOnADsLze2q34yP0IXQXR9FDeyljNCD"
                ],
                "dm-12": [
                    "dm-name-vg00-tmpvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRQgH5N2Zrsp8SEca6BgWgevv4mZYNQM3"
                ],
                "dm-13": [
                    "dm-name-vg00-varvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRR6UkdFOnfARG4KisOuGoulT82zjNF9U"
                ],
                "dm-14": [
                    "dm-name-vg00-auditvol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jC9rJKMBCuWcoB8OqwcVGux4mMiMQJKOaS"
                ],
                "dm-15": [
                    "dm-name-vg00-lvstats",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCmth3Lt4kDU5PJEszjQV65BgBmawJkclx"
                ],
                "dm-16": [
                    "dm-name-vg00-lvplanific",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCnErxQJa7F60inZewhicngWY5NT6FJpbT"
                ],
                "dm-2": [
                    "dm-name-vgPostreSQL-lvbackuppostgres",
                    "dm-uuid-LVM-9O97Dnqf3HPQ1aPzwDnKkvGNehS7ZnuYv1LfXKUvMjrB3SuHBusDxTz04LNMQVdq"
                ],
                "dm-3": [
                    "dm-name-vgMySQL-lvbackupmysql",
                    "dm-uuid-LVM-635QxprwX3wn1G3Rx1bMLfr3k6OJVX2OYCjxRYRZCXKaDQqR7foGWhwpbdiI1FX8"
                ],
                "dm-4": [
                    "dm-name-vgrear-lvrear",
                    "dm-uuid-LVM-Mt4umDnrUMYdJWDjzHbnO9TkH3fbfOAHewn6LFj6Z4fiN022PyeSWBi73LPBXzDn"
                ],
                "dm-5": [
                    "dm-name-vgrear-lvopenv",
                    "dm-uuid-LVM-Mt4umDnrUMYdJWDjzHbnO9TkH3fbfOAHcC0VWc6ZCFTzfNWdD0yx7bg0zYf7sHS3"
                ],
                "dm-6": [
                    "dm-name-vgall01-lvall01",
                    "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2kyMeTRSFGQn1CTpaUlDBTjpXSdMtmUr1"
                ],
                "dm-7": [
                    "dm-name-vgall01-lvISO",
                    "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2BgmwtdQ4dXL1Ki0Wn00Y7O0IkYQk3I7R"
                ],
                "dm-8": [
                    "dm-name-vgall01-lvcg2html",
                    "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2hxja23rkSNETXW5LfypLgFxiwMwHQZGy"
                ],
                "dm-9": [
                    "dm-name-vg00-homevol",
                    "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCj2kQZ7papqXRgyqbYLNkH3YToeS8Frga"
                ],
                "sda": [
                    "scsi-36000c29d91260c62ccb19b0dc0deeacb",
                    "wwn-0x6000c29d91260c62ccb19b0dc0deeacb"
                ],
                "sda1": [
                    "scsi-36000c29d91260c62ccb19b0dc0deeacb-part1",
                    "wwn-0x6000c29d91260c62ccb19b0dc0deeacb-part1"
                ],
                "sda2": [
                    "lvm-pv-uuid-M5Pni5-y74T-7tlf-pcmv-6Oib-52Vw-rYggnv",
                    "scsi-36000c29d91260c62ccb19b0dc0deeacb-part2",
                    "wwn-0x6000c29d91260c62ccb19b0dc0deeacb-part2"
                ],
                "sdb": [
                    "scsi-36000c292e059424c9b29c339e63789ea",
                    "wwn-0x6000c292e059424c9b29c339e63789ea"
                ],
                "sdb1": [
                    "lvm-pv-uuid-frVXS9-jwVV-djci-GhDG-jeFB-tZte-VmWbYn",
                    "scsi-36000c292e059424c9b29c339e63789ea-part1",
                    "wwn-0x6000c292e059424c9b29c339e63789ea-part1"
                ],
                "sdc": [
                    "scsi-36000c29bfc20fc8e375a32f9323158dc",
                    "wwn-0x6000c29bfc20fc8e375a32f9323158dc"
                ],
                "sdc1": [
                    "lvm-pv-uuid-0b2nTr-JtxA-3u4y-jFSv-O7db-G16u-TD9387",
                    "scsi-36000c29bfc20fc8e375a32f9323158dc-part1",
                    "wwn-0x6000c29bfc20fc8e375a32f9323158dc-part1"
                ],
                "sdd": [
                    "scsi-36000c2938ec36ca2fb75e037c30b8a84",
                    "wwn-0x6000c2938ec36ca2fb75e037c30b8a84"
                ],
                "sdd1": [
                    "lvm-pv-uuid-UhOknb-6uvu-aKRk-qt3p-oKof-E6xd-Odqza0",
                    "scsi-36000c2938ec36ca2fb75e037c30b8a84-part1",
                    "wwn-0x6000c2938ec36ca2fb75e037c30b8a84-part1"
                ],
                "sde": [
                    "scsi-36000c295ec89d6cb12074b793ef98328",
                    "wwn-0x6000c295ec89d6cb12074b793ef98328"
                ],
                "sde1": [
                    "lvm-pv-uuid-aylc2t-41iN-5ckz-bpgd-dTeP-ku2k-kNmqGT",
                    "scsi-36000c295ec89d6cb12074b793ef98328-part1",
                    "wwn-0x6000c295ec89d6cb12074b793ef98328-part1"
                ],
                "sdf": [
                    "scsi-36000c29633772a181f903ddf1c316676",
                    "wwn-0x6000c29633772a181f903ddf1c316676"
                ],
                "sdf1": [
                    "lvm-pv-uuid-dwADLJ-T68x-4dDi-PScW-B8sp-xmKT-dQNh37",
                    "scsi-36000c29633772a181f903ddf1c316676-part1",
                    "wwn-0x6000c29633772a181f903ddf1c316676-part1"
                ],
                "sdg": [
                    "scsi-36000c291a950c2984f08ae0bc633dc57",
                    "wwn-0x6000c291a950c2984f08ae0bc633dc57"
                ],
                "sdg1": [
                    "lvm-pv-uuid-pqIDtW-hj0b-X1og-qc1y-HddW-wcFS-xyhAnL",
                    "scsi-36000c291a950c2984f08ae0bc633dc57-part1",
                    "wwn-0x6000c291a950c2984f08ae0bc633dc57-part1"
                ],
                "sdh": [
                    "scsi-36000c29809f1442b56eb44baffb6f89f",
                    "wwn-0x6000c29809f1442b56eb44baffb6f89f"
                ],
                "sdi": [
                    "scsi-36000c29318bea84db794357ca3620d7b",
                    "wwn-0x6000c29318bea84db794357ca3620d7b"
                ],
                "sdi1": [
                    "lvm-pv-uuid-Hyog2W-uisc-bZLG-1Gyo-SxA3-2fJJ-lD6c0Q",
                    "scsi-36000c29318bea84db794357ca3620d7b-part1",
                    "wwn-0x6000c29318bea84db794357ca3620d7b-part1"
                ],
                "sdj": [
                    "scsi-36000c296afa076a2fbfafc3035ad1cd8",
                    "wwn-0x6000c296afa076a2fbfafc3035ad1cd8"
                ],
                "sdj1": [
                    "lvm-pv-uuid-zS8kl1-xWk0-ckA1-IaHR-d5vH-0kYo-LOkIf2",
                    "scsi-36000c296afa076a2fbfafc3035ad1cd8-part1",
                    "wwn-0x6000c296afa076a2fbfafc3035ad1cd8-part1"
                ],
                "sdk": [
                    "scsi-36000c29bb46aa96ed360ff416c9abc79",
                    "wwn-0x6000c29bb46aa96ed360ff416c9abc79"
                ],
                "sdk1": [
                    "lvm-pv-uuid-KWD76w-fCCp-OjPC-RVG1-pcuS-H1rs-zVZCST",
                    "scsi-36000c29bb46aa96ed360ff416c9abc79-part1",
                    "wwn-0x6000c29bb46aa96ed360ff416c9abc79-part1"
                ],
                "sdl": [
                    "lvm-pv-uuid-aVbMe2-WXTP-wp1u-p03J-Q0XG-mA0W-ItF9Jd",
                    "scsi-36000c2965bc8abf5231ef2c27b1692bd",
                    "wwn-0x6000c2965bc8abf5231ef2c27b1692bd"
                ],
                "sdm": [
                    "lvm-pv-uuid-51zrd1-E3Kc-kgGe-RBB0-zAg6-3EuT-ARbfcQ",
                    "scsi-36000c293acb7222949909466483f636b",
                    "wwn-0x6000c293acb7222949909466483f636b"
                ],
                "sdn": [
                    "scsi-36000c29b5f0d89b9c373f64d283963b5",
                    "wwn-0x6000c29b5f0d89b9c373f64d283963b5"
                ],
                "sdn1": [
                    "lvm-pv-uuid-Lc2L6v-yalf-ARzm-THyY-vR0y-2tVL-yQTE6T",
                    "scsi-36000c29b5f0d89b9c373f64d283963b5-part1",
                    "wwn-0x6000c29b5f0d89b9c373f64d283963b5-part1"
                ],
                "sdo": [
                    "lvm-pv-uuid-o1CQaT-vf3j-X0wb-eVz8-Bhag-xf0K-lrU5dH",
                    "scsi-36000c29ca6d8937536f8768d4bb47a12",
                    "wwn-0x6000c29ca6d8937536f8768d4bb47a12"
                ],
                "sr0": [
                    "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
                ]
            },
            "labels": {},
            "masters": {
                "sda2": [
                    "dm-0",
                    "dm-1",
                    "dm-10",
                    "dm-11",
                    "dm-12",
                    "dm-13",
                    "dm-14",
                    "dm-15",
                    "dm-16",
                    "dm-9"
                ],
                "sdb1": [
                    "dm-6"
                ],
                "sdc1": [
                    "dm-4"
                ],
                "sdd1": [
                    "dm-4"
                ],
                "sde1": [
                    "dm-3"
                ],
                "sdf1": [
                    "dm-4",
                    "dm-5"
                ],
                "sdg1": [
                    "dm-2"
                ],
                "sdi1": [
                    "dm-4"
                ],
                "sdj1": [
                    "dm-6",
                    "dm-7",
                    "dm-8"
                ],
                "sdk1": [
                    "dm-4"
                ],
                "sdl": [
                    "dm-2"
                ],
                "sdm": [
                    "dm-3"
                ],
                "sdn1": [
                    "dm-3"
                ],
                "sdo": [
                    "dm-4"
                ]
            },
            "uuids": {
                "dm-0": [
                    "ea0df34a-b668-4288-9d3b-2c398d22c7ff"
                ],
                "dm-1": [
                    "8e70ce75-316b-401c-9586-ce284a791df9"
                ],
                "dm-10": [
                    "4c0615d5-0799-4868-a84d-d534bdad150d"
                ],
                "dm-11": [
                    "4dbd06dd-3e26-4b72-96c2-ba32fca85cb3"
                ],
                "dm-12": [
                    "795f2f3f-5e87-4bdb-8655-6b26e95c2e22"
                ],
                "dm-13": [
                    "5b19014e-b729-4a2f-95f1-70cf708d08df"
                ],
                "dm-14": [
                    "de8e0bcb-b3a8-4440-ad76-4fb3794832fd"
                ],
                "dm-15": [
                    "0ee65968-5cbf-45ed-b0eb-a172e48f330d"
                ],
                "dm-16": [
                    "9f6c5bbf-cc6a-43a9-8fae-87e1dd35346c"
                ],
                "dm-2": [
                    "2f70082b-de00-4138-b803-d9ddf4229637"
                ],
                "dm-3": [
                    "f0504c66-364a-4e3c-bd52-fb04d9ce1dbc"
                ],
                "dm-4": [
                    "52d76fb4-e32b-4f0f-a820-913d1ad732b8"
                ],
                "dm-5": [
                    "ff996c91-4e5b-4208-8752-6877f2171ef2"
                ],
                "dm-6": [
                    "ec8e6ab0-ffc0-4b91-9487-4a5728f292bd"
                ],
                "dm-7": [
                    "3308ac24-1577-4db9-93e0-0fbaeeaf9c0d"
                ],
                "dm-8": [
                    "4f34671b-4104-4e80-95e1-588bef862974"
                ],
                "dm-9": [
                    "bdd23f20-60d0-4b4b-a534-4b342a1fc8bf"
                ],
                "sda1": [
                    "0f16c4b2-0018-44d2-aa9e-e2c4e959c064"
                ],
                "sdh": [
                    "a3aa6f96-7edf-4b8a-8915-1fdbba3ff6fe"
                ]
            }
        },
        "ansible_devices": {
            "dm-0": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-rootvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jClaowrdCyuxd6nBgFWTcTQz59zF6uym2v"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "ea0df34a-b668-4288-9d3b-2c398d22c7ff"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "18874368",
                "sectorsize": "512",
                "size": "9.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-1": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-swapvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCml1d0by8fdcXVq3G0CabrOhd7QX4WfwM"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "8e70ce75-316b-401c-9586-ce284a791df9"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "8388608",
                "sectorsize": "512",
                "size": "4.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-10": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-optvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRSd4Cy464hzdd4nscD0XzRo2u7pDOq35"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "4c0615d5-0799-4868-a84d-d534bdad150d"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "4194304",
                "sectorsize": "512",
                "size": "2.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-11": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-rhomevol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCnPOnADsLze2q34yP0IXQXR9FDeyljNCD"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "4dbd06dd-3e26-4b72-96c2-ba32fca85cb3"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "4194304",
                "sectorsize": "512",
                "size": "2.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-12": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-tmpvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRQgH5N2Zrsp8SEca6BgWgevv4mZYNQM3"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "795f2f3f-5e87-4bdb-8655-6b26e95c2e22"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "12582912",
                "sectorsize": "512",
                "size": "6.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-13": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-varvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCRR6UkdFOnfARG4KisOuGoulT82zjNF9U"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "5b19014e-b729-4a2f-95f1-70cf708d08df"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "20971520",
                "sectorsize": "512",
                "size": "10.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-14": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-auditvol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jC9rJKMBCuWcoB8OqwcVGux4mMiMQJKOaS"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "de8e0bcb-b3a8-4440-ad76-4fb3794832fd"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "3145728",
                "sectorsize": "512",
                "size": "1.50 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-15": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-lvstats",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCmth3Lt4kDU5PJEszjQV65BgBmawJkclx"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "0ee65968-5cbf-45ed-b0eb-a172e48f330d"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "1024000",
                "sectorsize": "512",
                "size": "500.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-16": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-lvplanific",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCnErxQJa7F60inZewhicngWY5NT6FJpbT"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "9f6c5bbf-cc6a-43a9-8fae-87e1dd35346c"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "1024000",
                "sectorsize": "512",
                "size": "500.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-2": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgPostreSQL-lvbackuppostgres",
                        "dm-uuid-LVM-9O97Dnqf3HPQ1aPzwDnKkvGNehS7ZnuYv1LfXKUvMjrB3SuHBusDxTz04LNMQVdq"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "2f70082b-de00-4138-b803-d9ddf4229637"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "1258266624",
                "sectorsize": "512",
                "size": "599.99 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-3": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgMySQL-lvbackupmysql",
                        "dm-uuid-LVM-635QxprwX3wn1G3Rx1bMLfr3k6OJVX2OYCjxRYRZCXKaDQqR7foGWhwpbdiI1FX8"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "f0504c66-364a-4e3c-bd52-fb04d9ce1dbc"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "1363116032",
                "sectorsize": "512",
                "size": "649.98 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-4": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgrear-lvrear",
                        "dm-uuid-LVM-Mt4umDnrUMYdJWDjzHbnO9TkH3fbfOAHewn6LFj6Z4fiN022PyeSWBi73LPBXzDn"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "52d76fb4-e32b-4f0f-a820-913d1ad732b8"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "11324530688",
                "sectorsize": "512",
                "size": "5.27 TB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-5": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgrear-lvopenv",
                        "dm-uuid-LVM-Mt4umDnrUMYdJWDjzHbnO9TkH3fbfOAHcC0VWc6ZCFTzfNWdD0yx7bg0zYf7sHS3"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "ff996c91-4e5b-4208-8752-6877f2171ef2"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "209715200",
                "sectorsize": "512",
                "size": "100.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-6": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgall01-lvall01",
                        "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2kyMeTRSFGQn1CTpaUlDBTjpXSdMtmUr1"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "ec8e6ab0-ffc0-4b91-9487-4a5728f292bd"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "3028287488",
                "sectorsize": "512",
                "size": "1.41 TB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-7": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgall01-lvISO",
                        "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2BgmwtdQ4dXL1Ki0Wn00Y7O0IkYQk3I7R"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "3308ac24-1577-4db9-93e0-0fbaeeaf9c0d"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "67108864",
                "sectorsize": "512",
                "size": "32.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-8": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vgall01-lvcg2html",
                        "dm-uuid-LVM-5xjsuCwWWSUXb4VTo2QtvSKEzIEhzFy2hxja23rkSNETXW5LfypLgFxiwMwHQZGy"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "4f34671b-4104-4e80-95e1-588bef862974"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "3072000",
                "sectorsize": "512",
                "size": "1.46 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "dm-9": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [
                        "dm-name-vg00-homevol",
                        "dm-uuid-LVM-Q4JH79dThqBCt0fg92JyJkEcPaJH02jCj2kQZ7papqXRgyqbYLNkH3YToeS8Frga"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "bdd23f20-60d0-4b4b-a534-4b342a1fc8bf"
                    ]
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "8388608",
                "sectorsize": "512",
                "size": "4.00 GB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop0": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop1": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop2": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop3": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop4": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop5": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop6": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "loop7": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram0": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram1": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram10": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram11": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram12": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram13": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram14": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram15": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram2": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram3": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram4": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram5": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram6": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram7": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram8": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "ram9": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "",
                "sectors": "32768",
                "sectorsize": "512",
                "size": "16.00 MB",
                "support_discard": "0",
                "vendor": null,
                "virtual": 1
            },
            "sda": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29d91260c62ccb19b0dc0deeacb",
                        "wwn-0x6000c29d91260c62ccb19b0dc0deeacb"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sda1": {
                        "holders": [],
                        "links": {
                            "ids": [
                                "scsi-36000c29d91260c62ccb19b0dc0deeacb-part1",
                                "wwn-0x6000c29d91260c62ccb19b0dc0deeacb-part1"
                            ],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "0f16c4b2-0018-44d2-aa9e-e2c4e959c064"
                            ]
                        },
                        "sectors": "409600",
                        "sectorsize": 512,
                        "size": "200.00 MB",
                        "start": "2048",
                        "uuid": "0f16c4b2-0018-44d2-aa9e-e2c4e959c064"
                    },
                    "sda2": {
                        "holders": [
                            "vg00-rootvol",
                            "vg00-swapvol",
                            "vg00-homevol",
                            "vg00-optvol",
                            "vg00-rhomevol",
                            "vg00-tmpvol",
                            "vg00-varvol",
                            "vg00-auditvol",
                            "vg00-lvstats",
                            "vg00-lvplanific"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-M5Pni5-y74T-7tlf-pcmv-6Oib-52Vw-rYggnv",
                                "scsi-36000c29d91260c62ccb19b0dc0deeacb-part2",
                                "wwn-0x6000c29d91260c62ccb19b0dc0deeacb-part2"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-0",
                                "dm-1",
                                "dm-10",
                                "dm-11",
                                "dm-12",
                                "dm-13",
                                "dm-14",
                                "dm-15",
                                "dm-16",
                                "dm-9"
                            ],
                            "uuids": []
                        },
                        "sectors": "209303552",
                        "sectorsize": 512,
                        "size": "99.80 GB",
                        "start": "411648",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "209715200",
                "sectorsize": "512",
                "size": "100.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29d91260c62ccb19b0dc0deeacb"
            },
            "sdb": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c292e059424c9b29c339e63789ea",
                        "wwn-0x6000c292e059424c9b29c339e63789ea"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdb1": {
                        "holders": [
                            "vgall01-lvall01"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-frVXS9-jwVV-djci-GhDG-jeFB-tZte-VmWbYn",
                                "scsi-36000c292e059424c9b29c339e63789ea-part1",
                                "wwn-0x6000c292e059424c9b29c339e63789ea-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-6"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c292e059424c9b29c339e63789ea"
            },
            "sdc": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29bfc20fc8e375a32f9323158dc",
                        "wwn-0x6000c29bfc20fc8e375a32f9323158dc"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdc1": {
                        "holders": [
                            "vgrear-lvrear"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-0b2nTr-JtxA-3u4y-jFSv-O7db-G16u-TD9387",
                                "scsi-36000c29bfc20fc8e375a32f9323158dc-part1",
                                "wwn-0x6000c29bfc20fc8e375a32f9323158dc-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-4"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29bfc20fc8e375a32f9323158dc"
            },
            "sdd": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c2938ec36ca2fb75e037c30b8a84",
                        "wwn-0x6000c2938ec36ca2fb75e037c30b8a84"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdd1": {
                        "holders": [
                            "vgrear-lvrear"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-UhOknb-6uvu-aKRk-qt3p-oKof-E6xd-Odqza0",
                                "scsi-36000c2938ec36ca2fb75e037c30b8a84-part1",
                                "wwn-0x6000c2938ec36ca2fb75e037c30b8a84-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-4"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c2938ec36ca2fb75e037c30b8a84"
            },
            "sde": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c295ec89d6cb12074b793ef98328",
                        "wwn-0x6000c295ec89d6cb12074b793ef98328"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sde1": {
                        "holders": [
                            "vgMySQL-lvbackupmysql"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-aylc2t-41iN-5ckz-bpgd-dTeP-ku2k-kNmqGT",
                                "scsi-36000c295ec89d6cb12074b793ef98328-part1",
                                "wwn-0x6000c295ec89d6cb12074b793ef98328-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-3"
                            ],
                            "uuids": []
                        },
                        "sectors": "1048562487",
                        "sectorsize": 512,
                        "size": "499.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "1048576000",
                "sectorsize": "512",
                "size": "500.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c295ec89d6cb12074b793ef98328"
            },
            "sdf": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29633772a181f903ddf1c316676",
                        "wwn-0x6000c29633772a181f903ddf1c316676"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdf1": {
                        "holders": [
                            "vgrear-lvrear",
                            "vgrear-lvopenv"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-dwADLJ-T68x-4dDi-PScW-B8sp-xmKT-dQNh37",
                                "scsi-36000c29633772a181f903ddf1c316676-part1",
                                "wwn-0x6000c29633772a181f903ddf1c316676-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-4",
                                "dm-5"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29633772a181f903ddf1c316676"
            },
            "sdg": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c291a950c2984f08ae0bc633dc57",
                        "wwn-0x6000c291a950c2984f08ae0bc633dc57"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdg1": {
                        "holders": [
                            "vgPostreSQL-lvbackuppostgres"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-pqIDtW-hj0b-X1og-qc1y-HddW-wcFS-xyhAnL",
                                "scsi-36000c291a950c2984f08ae0bc633dc57-part1",
                                "wwn-0x6000c291a950c2984f08ae0bc633dc57-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-2"
                            ],
                            "uuids": []
                        },
                        "sectors": "1048562487",
                        "sectorsize": 512,
                        "size": "499.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "1048576000",
                "sectorsize": "512",
                "size": "500.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c291a950c2984f08ae0bc633dc57"
            },
            "sdh": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29809f1442b56eb44baffb6f89f",
                        "wwn-0x6000c29809f1442b56eb44baffb6f89f"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": [
                        "a3aa6f96-7edf-4b8a-8915-1fdbba3ff6fe"
                    ]
                },
                "model": "Virtual disk",
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29809f1442b56eb44baffb6f89f"
            },
            "sdi": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29318bea84db794357ca3620d7b",
                        "wwn-0x6000c29318bea84db794357ca3620d7b"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdi1": {
                        "holders": [
                            "vgrear-lvrear"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-Hyog2W-uisc-bZLG-1Gyo-SxA3-2fJJ-lD6c0Q",
                                "scsi-36000c29318bea84db794357ca3620d7b-part1",
                                "wwn-0x6000c29318bea84db794357ca3620d7b-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-4"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29318bea84db794357ca3620d7b"
            },
            "sdj": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c296afa076a2fbfafc3035ad1cd8",
                        "wwn-0x6000c296afa076a2fbfafc3035ad1cd8"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdj1": {
                        "holders": [
                            "vgall01-lvall01",
                            "vgall01-lvISO",
                            "vgall01-lvcg2html"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-zS8kl1-xWk0-ckA1-IaHR-d5vH-0kYo-LOkIf2",
                                "scsi-36000c296afa076a2fbfafc3035ad1cd8-part1",
                                "wwn-0x6000c296afa076a2fbfafc3035ad1cd8-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-6",
                                "dm-7",
                                "dm-8"
                            ],
                            "uuids": []
                        },
                        "sectors": "1048562487",
                        "sectorsize": 512,
                        "size": "499.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "1048576000",
                "sectorsize": "512",
                "size": "500.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c296afa076a2fbfafc3035ad1cd8"
            },
            "sdk": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29bb46aa96ed360ff416c9abc79",
                        "wwn-0x6000c29bb46aa96ed360ff416c9abc79"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdk1": {
                        "holders": [
                            "vgrear-lvrear"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-KWD76w-fCCp-OjPC-RVG1-pcuS-H1rs-zVZCST",
                                "scsi-36000c29bb46aa96ed360ff416c9abc79-part1",
                                "wwn-0x6000c29bb46aa96ed360ff416c9abc79-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-4"
                            ],
                            "uuids": []
                        },
                        "sectors": "2097141102",
                        "sectorsize": 512,
                        "size": "999.99 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097152000",
                "sectorsize": "512",
                "size": "1000.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29bb46aa96ed360ff416c9abc79"
            },
            "sdl": {
                "holders": [
                    "vgPostreSQL-lvbackuppostgres"
                ],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "lvm-pv-uuid-aVbMe2-WXTP-wp1u-p03J-Q0XG-mA0W-ItF9Jd",
                        "scsi-36000c2965bc8abf5231ef2c27b1692bd",
                        "wwn-0x6000c2965bc8abf5231ef2c27b1692bd"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-2"
                    ],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "209715200",
                "sectorsize": "512",
                "size": "100.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c2965bc8abf5231ef2c27b1692bd"
            },
            "sdm": {
                "holders": [
                    "vgMySQL-lvbackupmysql"
                ],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "lvm-pv-uuid-51zrd1-E3Kc-kgGe-RBB0-zAg6-3EuT-ARbfcQ",
                        "scsi-36000c293acb7222949909466483f636b",
                        "wwn-0x6000c293acb7222949909466483f636b"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-3"
                    ],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "104857600",
                "sectorsize": "512",
                "size": "50.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c293acb7222949909466483f636b"
            },
            "sdn": {
                "holders": [],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "scsi-36000c29b5f0d89b9c373f64d283963b5",
                        "wwn-0x6000c29b5f0d89b9c373f64d283963b5"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {
                    "sdn1": {
                        "holders": [
                            "vgMySQL-lvbackupmysql"
                        ],
                        "links": {
                            "ids": [
                                "lvm-pv-uuid-Lc2L6v-yalf-ARzm-THyY-vR0y-2tVL-yQTE6T",
                                "scsi-36000c29b5f0d89b9c373f64d283963b5-part1",
                                "wwn-0x6000c29b5f0d89b9c373f64d283963b5-part1"
                            ],
                            "labels": [],
                            "masters": [
                                "dm-3"
                            ],
                            "uuids": []
                        },
                        "sectors": "209712447",
                        "sectorsize": 512,
                        "size": "100.00 GB",
                        "start": "63",
                        "uuid": null
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "209715200",
                "sectorsize": "512",
                "size": "100.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29b5f0d89b9c373f64d283963b5"
            },
            "sdo": {
                "holders": [
                    "vgrear-lvrear"
                ],
                "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
                "links": {
                    "ids": [
                        "lvm-pv-uuid-o1CQaT-vf3j-X0wb-eVz8-Bhag-xf0K-lrU5dH",
                        "scsi-36000c29ca6d8937536f8768d4bb47a12",
                        "wwn-0x6000c29ca6d8937536f8768d4bb47a12"
                    ],
                    "labels": [],
                    "masters": [
                        "dm-4"
                    ],
                    "uuids": []
                },
                "model": "Virtual disk",
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "1048576000",
                "sectorsize": "512",
                "size": "500.00 GB",
                "support_discard": "0",
                "vendor": "VMware",
                "virtual": 1,
                "wwn": "0x6000c29ca6d8937536f8768d4bb47a12"
            },
            "sr0": {
                "holders": [],
                "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
                "links": {
                    "ids": [
                        "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "VMware IDE CDR10",
                "partitions": {},
                "removable": "1",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "cfq",
                "sectors": "2097151",
                "sectorsize": "512",
                "size": "1024.00 MB",
                "support_discard": "0",
                "vendor": "NECVMWar",
                "virtual": 1
            }
        },
        "ansible_distribution": "RedHat",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/redhat-release",
        "ansible_distribution_file_search_string": "Red Hat",
        "ansible_distribution_file_variety": "RedHat",
        "ansible_distribution_major_version": "6",
        "ansible_distribution_release": "Santiago",
        "ansible_distribution_version": "6.10",
        "ansible_dns": {
            "nameservers": [
                "10.48.33.10",
                "10.48.33.11",
                "10.48.33.12"
            ],
            "search": [
                "cpd1pre.intranet.gencat.cat",
                "cpd1.intranet.gencat.cat"
            ]
        },
        "ansible_domain": "7143.1286.ecs.hp.com",
        "ansible_effective_group_id": 45005,
        "ansible_effective_user_id": 8402895,
        "ansible_env": {
            "HOME": "/root/home/hpddpers",
            "LANG": "en_US.UTF-8",
            "LOGNAME": "hpddpers",
            "MAIL": "/var/mail/hpddpers",
            "PATH": "/usr/local/bin:/bin:/usr/bin",
            "PWD": "/root/home/hpddpers",
            "SHELL": "/bin/bash",
            "SHLVL": "2",
            "SSH_CLIENT": "30.32.0.15 44350 22",
            "SSH_CONNECTION": "30.32.0.15 44350 30.32.0.15 22",
            "SSH_TTY": "/dev/pts/3",
            "TERM": "xterm",
            "USER": "hpddpers",
            "_": "/usr/bin/python"
        },
        "ansible_eth0": {
            "active": true,
            "device": "eth0",
            "features": {
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "netns_local": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_checksumming": "on",
                "rx_vlan_filter": "on [fixed]",
                "rx_vlan_offload": "on [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on",
                "tx_checksum_ipv4": "off",
                "tx_checksum_ipv6": "off",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksum_unneeded": "off",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_lockless": "off [fixed]",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_tcp6_segmentation": "off",
                "tx_tcp_ecn_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "on [fixed]",
                "udp_fragmentation_offload": "off [fixed]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "10.48.0.29",
                "broadcast": "10.48.0.255",
                "netmask": "255.255.255.0",
                "network": "10.48.0.0"
            },
            "macaddress": "00:50:56:40:05:31",
            "module": "e1000",
            "mtu": 1500,
            "pciid": "0000:02:00.0",
            "promisc": false,
            "speed": 1000,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "ether"
        },
        "ansible_eth0_1": {
            "ipv4": {
                "address": "30.32.0.15",
                "broadcast": "30.32.0.255",
                "netmask": "255.255.255.0",
                "network": "30.32.0.0"
            }
        },
        "ansible_fips": false,
        "ansible_form_factor": "Other",
        "ansible_fqdn": "server1.7143.1286.ecs.hp.com",
        "ansible_hostname": "server1",
        "ansible_interfaces": [
            "lo",
            "eth0_1",
            "eth0"
        ],
        "ansible_is_chroot": false,
        "ansible_iscsi_iqn": "",
        "ansible_kernel": "2.6.32-754.12.1.el6.x86_64",
        "ansible_lo": {
            "active": true,
            "device": "lo",
            "features": {
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "on [fixed]",
                "netns_local": "on [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_checksumming": "on [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on [fixed]",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksum_unneeded": "off [fixed]",
                "tx_checksumming": "on",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_lockless": "on [fixed]",
                "tx_scatter_gather": "on [fixed]",
                "tx_scatter_gather_fraglist": "on [fixed]",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "off [fixed]",
                "udp_fragmentation_offload": "on",
                "vlan_challenged": "on [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "host",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0"
            },
            "mtu": 65536,
            "promisc": false,
            "timestamping": [
                "rx_software",
                "software"
            ],
            "type": "loopback"
        },
        "ansible_local": {},
        "ansible_lsb": {
            "codename": "Santiago",
            "description": "Red Hat Enterprise Linux Server release 6.10 (Santiago)",
            "id": "RedHatEnterpriseServer",
            "major_release": "6",
            "release": "6.10"
        },
        "ansible_machine": "x86_64",
        "ansible_machine_id": "e51e1d0b3c2dc0830c065aaf00000034",
        "ansible_memfree_mb": 233,
        "ansible_memory_mb": {
            "nocache": {
                "free": 872,
                "used": 1004
            },
            "real": {
                "free": 233,
                "total": 1876,
                "used": 1643
            },
            "swap": {
                "cached": 28,
                "free": 3334,
                "total": 4095,
                "used": 761
            }
        },
        "ansible_memtotal_mb": 1876,
        "ansible_mounts": [
            {
                "block_available": 1325421,
                "block_size": 4096,
                "block_total": 2322270,
                "block_used": 996849,
                "device": "/dev/mapper/vg00-rootvol",
                "fstype": "ext3",
                "inode_available": 463305,
                "inode_total": 589824,
                "inode_used": 126519,
                "mount": "/",
                "options": "rw",
                "size_available": 5428924416,
                "size_total": 9512017920,
                "uuid": "ea0df34a-b668-4288-9d3b-2c398d22c7ff"
            },
            {
                "block_available": 79766,
                "block_size": 1024,
                "block_total": 198337,
                "block_used": 118571,
                "device": "/dev/sda1",
                "fstype": "ext2",
                "inode_available": 51146,
                "inode_total": 51200,
                "inode_used": 54,
                "mount": "/boot",
                "options": "rw,nodev",
                "size_available": 81680384,
                "size_total": 203097088,
                "uuid": "0f16c4b2-0018-44d2-aa9e-e2c4e959c064"
            },
            {
                "block_available": 894056,
                "block_size": 4096,
                "block_total": 1032112,
                "block_used": 138056,
                "device": "/dev/mapper/vg00-homevol",
                "fstype": "ext3",
                "inode_available": 261829,
                "inode_total": 262144,
                "inode_used": 315,
                "mount": "/home",
                "options": "rw,nosuid,nodev",
                "size_available": 3662053376,
                "size_total": 4227530752,
                "uuid": "bdd23f20-60d0-4b4b-a534-4b342a1fc8bf"
            },
            {
                "block_available": 282546,
                "block_size": 4096,
                "block_total": 516052,
                "block_used": 233506,
                "device": "/dev/mapper/vg00-optvol",
                "fstype": "ext3",
                "inode_available": 116219,
                "inode_total": 131072,
                "inode_used": 14853,
                "mount": "/opt",
                "options": "rw,nodev",
                "size_available": 1157308416,
                "size_total": 2113748992,
                "uuid": "4c0615d5-0799-4868-a84d-d534bdad150d"
            },
            {
                "block_available": 459009,
                "block_size": 4096,
                "block_total": 516052,
                "block_used": 57043,
                "device": "/dev/mapper/vg00-rhomevol",
                "fstype": "ext3",
                "inode_available": 130610,
                "inode_total": 131072,
                "inode_used": 462,
                "mount": "/root/home",
                "options": "rw,nosuid,nodev",
                "size_available": 1880100864,
                "size_total": 2113748992,
                "uuid": "4dbd06dd-3e26-4b72-96c2-ba32fca85cb3"
            },
            {
                "block_available": 1385829,
                "block_size": 4096,
                "block_total": 1548176,
                "block_used": 162347,
                "device": "/dev/mapper/vg00-tmpvol",
                "fstype": "ext3",
                "inode_available": 392618,
                "inode_total": 393216,
                "inode_used": 598,
                "mount": "/tmp",
                "options": "rw,nosuid,nodev",
                "size_available": 5676355584,
                "size_total": 6341328896,
                "uuid": "795f2f3f-5e87-4bdb-8655-6b26e95c2e22"
            },
            {
                "block_available": 1326099,
                "block_size": 4096,
                "block_total": 2580302,
                "block_used": 1254203,
                "device": "/dev/mapper/vg00-varvol",
                "fstype": "ext3",
                "inode_available": 625087,
                "inode_total": 655360,
                "inode_used": 30273,
                "mount": "/var",
                "options": "rw,nodev",
                "size_available": 5431701504,
                "size_total": 10568916992,
                "uuid": "5b19014e-b729-4a2f-95f1-70cf708d08df"
            },
            {
                "block_available": 351756,
                "block_size": 4096,
                "block_total": 387036,
                "block_used": 35280,
                "device": "/dev/mapper/vg00-auditvol",
                "fstype": "ext3",
                "inode_available": 98288,
                "inode_total": 98304,
                "inode_used": 16,
                "mount": "/var/log/audit",
                "options": "rw,noexec,nosuid,nodev",
                "size_available": 1440792576,
                "size_total": 1585299456,
                "uuid": "de8e0bcb-b3a8-4440-ad76-4fb3794832fd"
            },
            {
                "block_available": 68765265,
                "block_size": 4096,
                "block_total": 372563692,
                "block_used": 303798427,
                "device": "/dev/mapper/vgall01-lvall01",
                "fstype": "ext4",
                "inode_available": 92964202,
                "inode_total": 94633984,
                "inode_used": 1669782,
                "mount": "/AL",
                "options": "rw,acl",
                "size_available": 281662525440,
                "size_total": 1526020882432,
                "uuid": "ec8e6ab0-ffc0-4b91-9487-4a5728f292bd"
            },
            {
                "block_available": 238044,
                "block_size": 1024,
                "block_total": 487652,
                "block_used": 249608,
                "device": "/dev/mapper/vg00-lvstats",
                "fstype": "ext4",
                "inode_available": 127635,
                "inode_total": 128016,
                "inode_used": 381,
                "mount": "/stats",
                "options": "rw",
                "size_available": 243757056,
                "size_total": 499355648,
                "uuid": "0ee65968-5cbf-45ed-b0eb-a172e48f330d"
            },
            {
                "block_available": 268489,
                "block_size": 1024,
                "block_total": 487652,
                "block_used": 219163,
                "device": "/dev/mapper/vg00-lvplanific",
                "fstype": "ext4",
                "inode_available": 127729,
                "inode_total": 128016,
                "inode_used": 287,
                "mount": "/planific",
                "options": "rw",
                "size_available": 274932736,
                "size_total": 499355648,
                "uuid": "9f6c5bbf-cc6a-43a9-8fae-87e1dd35346c"
            },
            {
                "block_available": 38142548,
                "block_size": 4096,
                "block_total": 1393321310,
                "block_used": 1355178762,
                "device": "/dev/mapper/vgrear-lvrear",
                "fstype": "ext4",
                "inode_available": 278995857,
                "inode_total": 353894400,
                "inode_used": 74898543,
                "mount": "/REAR",
                "options": "rw",
                "size_available": 156231876608,
                "size_total": 5707044085760,
                "uuid": "52d76fb4-e32b-4f0f-a820-913d1ad732b8"
            },
            {
                "block_available": 33606733,
                "block_size": 4096,
                "block_total": 167683180,
                "block_used": 134076447,
                "device": "/dev/mapper/vgMySQL-lvbackupmysql",
                "fstype": "ext4",
                "inode_available": 42594658,
                "inode_total": 42598400,
                "inode_used": 3742,
                "mount": "/Backup_MySQL",
                "options": "rw",
                "size_available": 137653178368,
                "size_total": 686830305280,
                "uuid": "f0504c66-364a-4e3c-bd52-fb04d9ce1dbc"
            },
            {
                "block_available": 2942657,
                "block_size": 4096,
                "block_total": 8224220,
                "block_used": 5281563,
                "device": "/dev/mapper/vgall01-lvISO",
                "fstype": "ext4",
                "inode_available": 2097043,
                "inode_total": 2097152,
                "inode_used": 109,
                "mount": "/ISO",
                "options": "rw",
                "size_available": 12053123072,
                "size_total": 33686405120,
                "uuid": "3308ac24-1577-4db9-93e0-0fbaeeaf9c0d"
            },
            {
                "block_available": 116483,
                "block_size": 4096,
                "block_total": 369772,
                "block_used": 253289,
                "device": "/dev/mapper/vgall01-lvcg2html",
                "fstype": "ext4",
                "inode_available": 94384,
                "inode_total": 96000,
                "inode_used": 1616,
                "mount": "/cfg2html",
                "options": "rw",
                "size_available": 477114368,
                "size_total": 1514586112,
                "uuid": "4f34671b-4104-4e80-95e1-588bef862974"
            },
            {
                "block_available": 5391462,
                "block_size": 4096,
                "block_total": 25770312,
                "block_used": 20378850,
                "device": "/dev/mapper/vgrear-lvopenv",
                "fstype": "ext4",
                "inode_available": 6551271,
                "inode_total": 6553600,
                "inode_used": 2329,
                "mount": "/usr/openv",
                "options": "rw",
                "size_available": 22083428352,
                "size_total": 105555197952,
                "uuid": "ff996c91-4e5b-4208-8752-6877f2171ef2"
            },
            {
                "block_available": 13428522,
                "block_size": 4096,
                "block_total": 154782658,
                "block_used": 141354136,
                "device": "/dev/mapper/vgPostreSQL-lvbackuppostgres",
                "fstype": "ext4",
                "inode_available": 39307783,
                "inode_total": 39321600,
                "inode_used": 13817,
                "mount": "/BackupPostgreSQL",
                "options": "rw",
                "size_available": 55003226112,
                "size_total": 633989767168,
                "uuid": "2f70082b-de00-4138-b803-d9ddf4229637"
            },
            {
                "block_available": 244872551,
                "block_size": 4096,
                "block_total": 257998016,
                "block_used": 13125465,
                "device": "/dev/sdh",
                "fstype": "ext4",
                "inode_available": 65535989,
                "inode_total": 65536000,
                "inode_used": 11,
                "mount": "/CASOS_ESPECIALES",
                "options": "rw",
                "size_available": 1002997968896,
                "size_total": 1056759873536,
                "uuid": "a3aa6f96-7edf-4b8a-8915-1fdbba3ff6fe"
            }
        ],
        "ansible_nodename": "server1",
        "ansible_os_family": "RedHat",
        "ansible_pkg_mgr": "yum",
        "ansible_processor": [
            "0",
            "AuthenticAMD",
            "AMD Opteron(TM) Processor 6238"
        ],
        "ansible_processor_cores": 1,
        "ansible_processor_count": 1,
        "ansible_processor_threads_per_core": 1,
        "ansible_processor_vcpus": 1,
        "ansible_product_name": "VMware Virtual Platform",
        "ansible_product_serial": "NA",
        "ansible_product_uuid": "NA",
        "ansible_product_version": "None",
        "ansible_python": {
            "executable": "/usr/bin/python",
            "has_sslcontext": false,
            "type": "CPython",
            "version": {
                "major": 2,
                "micro": 6,
                "minor": 6,
                "releaselevel": "final",
                "serial": 0
            },
            "version_info": [
                2,
                6,
                6,
                "final",
                0
            ]
        },
        "ansible_python_version": "2.6.6",
        "ansible_real_group_id": 45005,
        "ansible_real_user_id": 8402895,
        "ansible_selinux": {
            "status": "disabled"
        },
        "ansible_selinux_python_present": true,
        "ansible_service_mgr": "upstart",
        "ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBAIR0ZC1exbxG31Ulg8kb0SKxZaz42ocQ4SseWoaIGZpD+be8AaALccO4SsS8p8yj2klIznlAx3E6aYurxmnuEV++5SjbmsRL0F2fyAxx+t4Pc8blOdm+N635rCYvGR+rNtw0X8Lx9YLTFmiyr3OitOmnkRvF3OXezcK/CoAJtCVtAAAAFQCOh8ibRhyaba9a/tZmKlHK7wZpSQAAAIAERFpLppj/9rcDqM2S5XxmAn01/YgBK9QbISCbNpTQjtg7s8PBT+5JW//1mj4K3pNMOoJx47yRjCCPOlw6ns9dIgyxYl8ur6AOr4Hp4akmzg1SWvU3/ydNTSl8FHLr3+mFamEM0GhUrHXI90nRSXqqpfwYawJtZpUuuCdQMKyOtQAAAIAzHSAlHi8emeojUBm5o4+3d7ZJnpKUFwONHJ3xfJ8pfrrGh76abMRzzF89zNpUVAc8m1zyqYX17wNREc29RAF+B4wmKD6mbkaxS5w86yHUxj1aSA0mA2HRo5kurtqHRJfIusigDqGG51neN+RaPuxey+Bd1kjHuGiy85q7Ltq7Kg==",
        "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAABIwAAAQEAnoU9A1+CN7EFHDVSHMY6FnxXVA3xrjJeW3/WmjoWY2hPFF6UcP4iFf12t5nqCPK4mv5m9TAtviBtmI5rbeqw0JI0NSv0lYqLt8GCHly9vPguRp863QUAvqm9nRlOrdW/IGHhREpJYwXG2tfvgccVdLSbNkwctOvuRvg9DBhB1YxOemgQEi3Q742qi+3QkLZcEyoWiwLzxK/AW3u+R5e81z4Z9xL68aqOz2NJQ5QLSJ1iGgUU9nWoQMos+VywylFQKQCN1T8Q4MeoH+UVOZcskgrQylMcAsOvdbNsMQxU0nKGVkDNEugEM+X1K0xZOMu4nSHA+ezJ71/939xDihFdEw==",
        "ansible_swapfree_mb": 3334,
        "ansible_swaptotal_mb": 4095,
        "ansible_system": "Linux",
        "ansible_system_capabilities": [
            ""
        ],
        "ansible_system_capabilities_enforced": "True",
        "ansible_system_vendor": "VMware, Inc.",
        "ansible_uptime_seconds": 11415836,
        "ansible_user_dir": "/root/home/hpddpers",
        "ansible_user_gecos": "David Martinez,,personal,david.martinez.perales@dxc.com",
        "ansible_user_gid": 45005,
        "ansible_user_id": "hpddpers",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 8402895,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_type": "VMware",
        "gather_subset": [
            "all"
        ],
        "module_setup": true
    },
    "changed": false
}
[root@server1 Ansible]#

Si quisiéramos acceder a alguna de ellas, llamaríamos al nombre de la variable de Ansible por su nombre. Por ejemplo, ansible.distribution:

[root@lhpilox01 playbooks]# cat send_command_if_os.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Ejecutar comando
    command: "{{ COMANDO }}"
    when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
[root@lhpilox01 playbooks]#

O trabajar con variables del inventario de Ansible como, por ejemplo, con los grupos en combinación con la sintaxis JINJA2, de la cuál, hablo más abajo:

{% for host in groups['PRE'] + groups['WEBSERVERS'] %}

o

{% for host in groups['PRE']|union(groups['WEBSERVERS'] %}

También podemos trabajar con grupos de Ansible sin utilizar JINJA2. El fichero Yaml, tendría que incluir el nombre de los grupos que cumplen la condición, de la siguiente manera:

when: ('PRE' in group_names) or ('WEBSERVERS' in group_names)

o

when: ['PRE', 'WEBSERVERS'] | intersect(group_names) | count > 0

Si queremos trabajar con bucles «if…else», también lo podemos hacer. Veamos un ejemplo:

Código fuente del Playbook

[root@lhpilox01 Ansible]# cat playbooks/post-provisioning/RHEL7/resolv.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Generar fichero resolv.conf
    template:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/resolv.conf.j2
       dest: /etc/resolv.conf
       mode: '0644'
       backup: yes
    become: yes
[root@lhpilox01 Ansible]#

Código fuente de la plantilla JINJA2

Si el grupo que figura en el inventario de Ansible es PRO, configuraremos unos servidores de DNS diferentes en el fichero resolv.conf. Aquí es donde interviene el bucle if…else, tal y como podemos comprobar a continuación:

[root@lhpilox01 Ansible]# cat playbooks/post-provisioning/RHEL7/config_templates/resolv.conf.j2
{% if 'PRO' in group_names %}
search cpd1.intranet.gencat.cat cpd1pre.intranet.gencat.cat
nameserver 10.48.33.10
nameserver 10.48.33.11
nameserver 10.48.33.12
{% else  %}
search cpd1pre.intranet.gencat.cat cpd1.intranet.gencat.cat
nameserver 10.49.33.10
nameserver 10.49.33.11
nameserver 10.49.33.12
{% endif %}
[root@lhpilox01 Ansible]#

Configuración del inventario de pruebas

Lógicamente, en el inventario de Ansible debe figurar el nombre del grupo de servidores «PRO»:

[root@lhpilox01 Ansible]# cat playbooks/post-provisioning/RHEL7/config_templates/resolv.conf.j2
{% if 'PRO' in group_names %}
search cpd1.intranet.gencat.cat cpd1pre.intranet.gencat.cat
nameserver 10.48.33.10
nameserver 10.48.33.11
nameserver 10.48.33.12
{% else  %}
search cpd1pre.intranet.gencat.cat cpd1.intranet.gencat.cat
nameserver 10.49.33.10
nameserver 10.49.33.11
nameserver 10.49.33.12
{% endif %}
[root@lhpilox01 Ansible]#

Ejecución del Playbook

Prestar especial atención a la variable HOSTS=PRO, que hace referencia a los servidores del grupo de Ansible llamado PRO en el fichero de inventario:

[root@lhpilox01 Ansible]# ansible-playbook -e "HOSTS=PRO" --user hpddpers --ask-pass --become-method su --ask-become-pass -i inventory/david /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/resolv.yml -vv
ansible-playbook 2.7.9
  config file = /planific/bin/admsys/Ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /planific/bin/admsys/Ansible/ansible.cfg as config file
SSH password:
SU password[defaults to SSH password]:
/planific/bin/admsys/Ansible/inventory/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: resolv.yml *****************************************************************************************************************************************************************************
1 plays in /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/resolv.yml

PLAY [PRO] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/resolv.yml:1
ok: [lansibd0]
META: ran handlers

TASK [Generar fichero resolv.conf] ***************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/resolv.yml:3
changed: [lansibd0] => {"backup_file": "/etc/resolv.conf.15405.2019-10-04@08:47:30~", "changed": true, "checksum": "d5c7b7b3e8b921aff6176f4bdc04d890f72c6b3f", "dest": "/etc/resolv.conf", "gid": 0, "group": "root", "md5sum": "d03d899fac7afaaf2e576db51e380672", "mode": "0644", "owner": "root", "secontext": "system_u:object_r:net_conf_t:s0", "size": 129, "src": "/root/home/hpddpers/.ansible/tmp/ansible-tmp-1570171641.29-54998608965087/source", "state": "file", "uid": 0}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
lansibd0                   : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Comprobamos que el Playbook ha configurado los servidores de DNS correctos:

[root@lansibd0 ~]# cat /etc/resolv.conf
search cpd1.intranet.gencat.cat cpd1pre.intranet.gencat.cat
nameserver 10.48.33.10
nameserver 10.48.33.11
nameserver 10.48.33.12
[root@lansibd0 ~]#

Chequear si un servicio de Linux está activado o no

En este caso, como no cambiamos ningún fichero de configuración, ni activamos ni desactivamos ningún servicio, si no que solamente queremos saber si se encuentra activado, tendremos que utilizar el parámetro changed_when: false. Por ese mismo motivo tampoco utilizo el módulo «service» de Ansible.

[root@server1 CheckService]# cat check_service.yml
  - name: Check Service Status in RHEL6
    shell: "/sbin/service smb status"
    args:
       warn: false
    register: SERVICE_STATUS_RHEL6
    changed_when: false
    become: yes
    ignore_errors: yes
    async: 600
    poll: 25
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '6'

  - name: Check Service Status in RHEL7
    shell: "systemctl is-enabled smb"
    args:
       warn: false
    register: SERVICE_STATUS_RHEL7
    changed_when: false
    become: yes
    ignore_errors: yes
    async: 600
    poll: 25
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '7'

  - name: Check Service Status in RHEL8
    shell: "systemctl is-enabled smb"
    args:
       warn: false
    register: SERVICE_STATUS_RHEL8
    changed_when: false
    become: yes
    ignore_errors: yes
    async: 600
    poll: 25
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '8'

  - name: Save Service Status to a file (RHEL6)
    local_action: copy content="{{ inventory_hostname }};{{ SERVICE_STATUS_RHEL6.stdout }}" dest="STATUS/RHEL6/service_status_{{ inventory_hostname }}.out"
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '6'

  - name: Save Service Status to a file (RHEL7)
    local_action: copy content="{{ inventory_hostname }};{{ SERVICE_STATUS_RHEL7.stdout }}" dest="STATUS/RHEL7/service_status_{{ inventory_hostname }}.out"
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '7'

  - name: Save Service Status to a file (RHEL8)
    local_action: copy content="{{ inventory_hostname }};{{ SERVICE_STATUS_RHEL8.stdout }}" dest="STATUS/RHEL8/service_status_{{ inventory_hostname }}.out"
    when: ansible_distribution == "RedHat" and ansible_distribution_major_version == '8'

[root@server1 CheckService]#

Etiquetar tareas en Ansible (tags)

En Ansible podemos etiquetar tareas mediante la directiva «tags». Sirve para que podamos ejecutar una o varias tareas de un Playbook con muchas tareas, en vez de ejecutarlas todas. Por ejemplo:

- hosts: all
  tasks:
  - name: Ejecutar el comando 1
    command: comando 1
    tags: comando1

  - name: Ejecutar el comando 2
    command: comando 2
    tags: comando2

  - name: Ejecutar el comando 3
    command: comando 3
    tags: comando3

Si solamente queremos ejecutar las tareas 1 y 3 del playbook, lo ejecutaremos de la siguiente manera:

ansible-playbook --tags comando1,comando3 tagsplaybook.yml

En caso de que tengamos un playbook principal que va llamando a otros playbooks hijos mediante includes, los tags de cada tarea que nos interese se deben declarar tanto en las tareas del playbook principal como en las tareas de los playbooks hijos.

Ocultar las credenciales en un fichero YML

En los playbooks anteriores hemos pasado las variables de acceso por SSH por línea de comandos y configurándolas en el propio inventario de servidores, pero esto puede ser un problema de seguridad o si tenemos varios usuarios que pueden ejecutar los mismos playbooks pero cada uno con sus propias credenciales.

Para solucionar esto, podemos crear un fichero personalizado de credenciales con permisos restrictivos para que ningún otro usuario del sistema pueda leerlas.

Fichero de credenciales

[root@lhpilox01 LUNs_PVs_Ansible]# cat root_credentials.yml
ansible_become: yes
ansible_become_method: su
ansible_become_user: root
ansible_become_pass: Contraseña_Secreta_de_root
[root@lhpilox01 LUNs_PVs_Ansible]#

Configuración del playbook

Dentro del playbook hacemos una llamada al fichero de credenciales. Para este ejemplo he puesto el fichero que acabo de crear pero también lo podemos configurar como una variables para que el resto de usuarios pueda llamar a su propio fichero de credenciales:

[root@lhpilox01 LUNs_PVs_Ansible]# cat inventario.yml
- hosts: "{{ HOSTS }}"

  tasks:
  - include_vars: /planific/bin/admsys/LUNs_PVs_Ansible/root_credentials.yml

  - name: Ejecutando luns.sh
    script: /planific/bin/admsys/LUNs_PVs_Ansible/luns.sh
    register: luns

  - debug: var={{ item }}
    with_items:
    - luns.stdout

  - local_action: copy content={{ luns.stdout }} dest="/planific/bin/admsys/LUNs_PVs_Ansible/luns.txt"

  - name: Ejecutando pvs.sh
    script: /planific/bin/admsys/LUNs_PVs_Ansible/pvs.sh
    register: pvs

  - debug: var={{ item }}
    with_items:
    - pvs.stdout

  - local_action: copy content={{ pvs.stdout }} dest="/planific/bin/admsys/LUNs_PVs_Ansible/pvs.txt"
[root@lhpilox01 LUNs_PVs_Ansible]#

Ejecución del playbook

[root@lhpilox01 LUNs_PVs_Ansible]#  ansible-playbook -e "HOSTS=la01wai0.7376.1286.ecs.hp.com"  --user hpddpers --ask-pass -i /planific/bin/admsys/LUNs_PVs_Ansible/servers.txt /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml -vv
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
SSH password:
/planific/bin/admsys/LUNs_PVs_Ansible/servers.txt did not meet host_list requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/LUNs_PVs_Ansible/servers.txt did not meet script requirements, check plugin documentation if this is unexpected
/planific/bin/admsys/LUNs_PVs_Ansible/servers.txt did not meet yaml requirements, check plugin documentation if this is unexpected

PLAYBOOK: inventario.yml *************************************************************************************************************************************************************************
1 plays in /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml

PLAY [la01wai0.7376.1286.ecs.hp.com] *************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:1
ok: [la01wai0.7376.1286.ecs.hp.com]
META: ran handlers

TASK [include_vars] ******************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:4
ok: [la01wai0.7376.1286.ecs.hp.com] => {"ansible_facts": {"ansible_become": true, "ansible_become_method": "su", "ansible_become_pass": "R3sfriad0s2016", "ansible_become_user": "root"}, "ansible_included_var_files": ["/planific/bin/admsys/LUNs_PVs_Ansible/root_credentials.yml"], "changed": false}

TASK [Ejecutando luns.sh] ************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:6
changed: [la01wai0.7376.1286.ecs.hp.com] => {"changed": true, "rc": 0, "stderr": "Shared connection to la01wai0.7376.1286.ecs.hp.com closed.\r\n", "stderr_lines": ["Shared connection to la01wai0.7376.1286.ecs.hp.com closed."], "stdout": "\r\nla01wai0;/dev/sda;107.4;GB\r\nla01wai0;/dev/sdb;53.7;GB\r\n", "stdout_lines": ["", "la01wai0;/dev/sda;107.4;GB", "la01wai0;/dev/sdb;53.7;GB"]}

TASK [debug] *************************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:10
ok: [la01wai0.7376.1286.ecs.hp.com] => (item=luns.stdout) => {
    "item": "luns.stdout",
    "luns.stdout": "\r\nla01wai0;/dev/sda;107.4;GB\r\nla01wai0;/dev/sdb;53.7;GB\r\n"
}

TASK [copy] **************************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:14
ok: [la01wai0.7376.1286.ecs.hp.com -> localhost] => {"changed": false, "checksum": "204d5129a0f710160d1862fcb13214f750b54aa7", "dest": "/planific/bin/admsys/LUNs_PVs_Ansible/luns.txt", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/planific/bin/admsys/LUNs_PVs_Ansible/luns.txt", "size": 57, "state": "file", "uid": 0}

TASK [Ejecutando pvs.sh] *************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:16
changed: [la01wai0.7376.1286.ecs.hp.com] => {"changed": true, "rc": 0, "stderr": "Shared connection to la01wai0.7376.1286.ecs.hp.com closed.\r\n", "stderr_lines": ["Shared connection to la01wai0.7376.1286.ecs.hp.com closed."], "stdout": "\r\nla01wai0;/dev/sda2;vg00;99.80g;14.30g\r\nla01wai0;/dev/sdb1;vgserveis;50.00g;40.00g\r\n", "stdout_lines": ["", "la01wai0;/dev/sda2;vg00;99.80g;14.30g", "la01wai0;/dev/sdb1;vgserveis;50.00g;40.00g"]}

TASK [debug] *************************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:20
ok: [la01wai0.7376.1286.ecs.hp.com] => (item=pvs.stdout) => {
    "item": "pvs.stdout",
    "pvs.stdout": "\r\nla01wai0;/dev/sda2;vg00;99.80g;14.30g\r\nla01wai0;/dev/sdb1;vgserveis;50.00g;40.00g\r\n"
}

TASK [copy] **************************************************************************************************************************************************************************************
task path: /planific/bin/admsys/LUNs_PVs_Ansible/inventario.yml:24
ok: [la01wai0.7376.1286.ecs.hp.com -> localhost] => {"changed": false, "checksum": "b704a769985d6ff170139b2e2cdc8d48dd9e4f92", "dest": "/planific/bin/admsys/LUNs_PVs_Ansible/pvs.txt", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/planific/bin/admsys/LUNs_PVs_Ansible/pvs.txt", "size": 85, "state": "file", "uid": 0}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
la01wai0.7376.1286.ecs.hp.com : ok=8    changed=2    unreachable=0    failed=0

[root@lhpilox01 LUNs_PVs_Ansible]# 

Gestión de errores de Ansible

En Ansible, la gestión de errores se gestiona automáticamente de manera predeterminada. Si una tarea falla en una máquina remota, Ansible detiene la ejecución y devuelve un mensaje de error en la salida estándar.

Además, Ansible tiene una serie de mecanismos de gestión de errores que pueden ayudar a manejar errores y fallas en los Playbooks. Algunos de los mecanismos de gestión de errores en Ansible incluyen:

  1. Manejo de errores por defecto: Ansible tiene un conjunto de tareas predeterminadas que manejan los errores. Por ejemplo, si una tarea falla, Ansible intentará revertir la tarea ejecutando la acción opuesta, para dejar el sistema en el estado anterior.
  2. Tareas fallidas: se puede usar la cláusula «failed_when» en una tarea para controlar cuándo una tarea debe considerarse fallida. Por ejemplo, se puede especificar que una tarea debe fallar si un archivo no existe o si un comando devuelve un código de salida diferente de cero.
  3. Manejo de errores de conexión: Si se produce un error de conexión al conectarse a una máquina remota, Ansible intentará volver a conectarse varias veces antes de reportar un error.
  4. Ignorar errores: Si se desea ignorar errores en una tarea específica, se puede agregar la cláusula «ignore_errors: true» en la tarea.
  5. Capturar errores: Ansible permite capturar la salida de un comando o script en una variable y usarla en una tarea posterior, lo que permite un mejor manejo de errores.
  6. Tareas de recuperación: Ansible admite la definición de tareas de recuperación que se ejecutan si una tarea falla en una máquina remota.

Ejemplo con la cláusula failed_when:

Supongamos que se tiene una tarea que ejecuta un comando «ls» en una máquina remota y se desea que la tarea falle si no se encuentra un archivo específico en el directorio. En este caso, se puede usar la cláusula «failed_when» para especificar que la tarea debe considerarse fallida si la salida del comando «ls» no contiene el archivo específico.

- name: Comprobar archivo en directorio
  command: ls
  register: result
  failed_when: "'archivo-especifico' not in result.stdout"

En este ejemplo, la tarea «Comprobar archivo en directorio» ejecuta el comando «ls» y guarda la salida en la variable «result». Luego, la cláusula «failed_when» se usa para especificar que la tarea debe considerarse fallida si la cadena «archivo-especifico» no está en la salida del comando «ls». Si el archivo no está presente en el directorio, la tarea fallará y se informará como tal en la salida de Ansible.

La cláusula «failed_when» es muy útil cuando se necesita personalizar las condiciones bajo las cuales una tarea debe considerarse fallida o tener éxito.

Ejemplo con la cláusula ignore_errors:

Supongamos que se tiene una tarea que ejecuta un comando «rm» en una máquina remota para eliminar un archivo, pero si el archivo no existe, se desea que la tarea continúe sin fallar. En este caso, se puede usar la cláusula «ignore_errors» para evitar que la tarea falle si el archivo no está presente en el sistema.

- name: Eliminar archivo
  command: rm archivo-a-eliminar.txt
  ignore_errors: yes

En este ejemplo, la tarea «Eliminar archivo» ejecuta el comando «rm archivo-a-eliminar.txt» en la máquina remota. La cláusula «ignore_errors: yes» indica a Ansible que debe continuar ejecutando el playbook incluso si el archivo «archivo-a-eliminar.txt» no existe y el comando «rm» devuelve un código de error.

La cláusula «ignore_errors» es muy útil cuando se desea ejecutar una tarea que puede fallar bajo ciertas condiciones, pero se desea que el playbook continúe ejecutándose sin interrupciones. Sin embargo, es importante tener en cuenta que si se usa esta cláusula en exceso, puede ocultar problemas reales en el sistema que deben ser abordados.

Ejemplo sobre la captura de errores con Ansible:

Supongamos que se tiene una tarea que ejecuta un comando «grep» en una máquina remota para buscar una cadena en un archivo, pero si la cadena no se encuentra, se desea que se capture el error y se registre en el log de Ansible. En este caso, se puede usar la cláusula «register» para guardar la salida del comando «grep» en una variable, y luego usar la cláusula «failed_when» para especificar que la tarea debe considerarse fallida si la salida del comando contiene un error.

- name: Buscar cadena en archivo
  command: grep "cadena-busqueda" archivo-a-buscar.txt
  register: grep_result
  failed_when: "'ERROR:' in grep_result.stderr"
  ignore_errors: yes

- name: Registrar errores en log
  debug:
    msg: "Se encontró un error al buscar la cadena: {{ grep_result.stderr }}"
  when: grep_result|failed

En este ejemplo, la tarea «Buscar cadena en archivo» ejecuta el comando «grep» en la máquina remota y guarda la salida en la variable «grep_result». La cláusula «failed_when» se usa para especificar que la tarea debe considerarse fallida si la salida del comando contiene la cadena «ERROR:». La cláusula «ignore_errors» se usa para evitar que la tarea falle si la cadena no se encuentra en el archivo.

Luego, la tarea «Registrar errores en log» usa la cláusula «debug» para registrar en el log de Ansible si se encontró un error al buscar la cadena. La cláusula «when» se usa para verificar si la tarea «Buscar cadena en archivo» falló, lo que indica que se produjo un error.

La captura de errores en Ansible es importante para garantizar que se manejen adecuadamente los errores y se registren en los registros para su posterior análisis.

Ansible Tower

Ansible Tower es una interfaz WEB para administrar Ansible de una manera visual.

Instalación de la Versión Oficial de RedHat

Voy a instalar Ansible Tower en un Linux CentOS 7 con 4GB de RAM. Lo primero que haré será instalar los paquetes de yum correspondientes:

yum -y install epel-release
yum -y install ansible vim curl

A continuación, me descargo la última versión del producto:

mkdir /tmp/ansibletower
cd /tmp/ansibletower/
curl -k -O https://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz
tar xvf ansible-tower-setup-latest.tar.gz
cd ansible-tower-setup-3.5.2-1

Editamos la información del fichero de inventario:

vi inventory

[root@ansiblesrv ansible-tower-setup-3.5.2-1]# cat inventory
[tower]
localhost ansible_connection=local

[database]

[all:vars]
admin_password='MyPassword'

pg_host=''
pg_port=''

pg_database='awx'
pg_username='awx'
pg_password='PgPassword'

rabbitmq_username=tower
rabbitmq_password='RBPassword'
rabbitmq_cookie=cookiemonster

# Isolated Tower nodes automatically generate an RSA key for authentication;
# To disable this behavior, set this value to false
# isolated_key_generation=true
[root@ansiblesrv ansible-tower-setup-3.5.2-1]#

Procedemos con la instalación de Ansible Tower:

./setup.sh

Establecemos una contraseña de acceso a la consola para el usuario administrador (admin):

[root@ansiblesrv ~]# awx-manage changepassword admin
Changing password for user 'admin'
Password:
Password (again):
Password changed successfully for user 'admin'
[root@ansiblesrv ~]#

Una vez finalizada la instalación, podremos acceder a la consola de Ansible Tower por HTTPS:

Consola de Ansible Tower

Para desinstalarlo, ejecutaremos el comando:

yum remove ansible-tower

Instalación de la Versión Libre o Community (AWX) con Dockers

Como en la versión anterior, instalamos los repositorios y dependencias necesarias:

yum install -y epel-release

yum install -y yum-utils device-mapper-persistent-data lvm2 ansible git python-devel python-pip python-docker-py vim-enhanced

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce -y

Arrancamos el servicio de Dockers:

systemctl start docker
systemctl enable docker

Descargamos el repositorio de AWX de GitHub:

git clone https://github.com/ansible/awx.git
cd awx
git clone https://github.com/ansible/awx-logos.git

Configuramos el fichero de inventario de Ansible:

cd installer
vi inventory

[root@ansiblesrv installer]# grep -v "#" inventory |grep -v ^$
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
[all:vars]
dockerhub_base=ansible
awx_secret_key=awxpassword
awx_task_hostname=awx
awx_web_hostname=awxweb
postgres_data_dir=/var/lib/pgdocker
host_port=80
host_port_ssl=443
docker_compose_dir=/var/lib/awx
pg_username=awx
pg_password=awxpass
pg_admin_password=postgrespass
pg_database=awx
pg_port=5432
rabbitmq_password=awxpass
rabbitmq_erlang_cookie=cookiemonster
admin_user=admin
admin_password=password
create_preload_data=True
secret_key=awxsecret
awx_official=true
project_data_dir=/var/lib/awx/projects
[root@ansiblesrv installer]#

Instalamos Ansible Tower (AWX):

ansible-playbook -i inventory install.yml -vv

Después de la instalación ya podremos acceder a la consola por HTTPS como en el apartado anterior.

Creación de Playbooks de Ansible con JINJA2

JINJA2 es un lenguaje de programación para la creación de plantillas compatible con Ansible, en el que podemos insertar los siguientes tipos de código:

  • {% … %} – Condiciones if…else
  • {{ … }} – Insertamos variables (ya lo hemos visto anteriormente)
  • {# … #} – Insertamos comentarios dentro del código para describir qué hace

Para mostrar su utilidad, vamos a crear una plantilla para el fichero de configuración /etc/resolv.conf con condiciones, es decir, si es para un servidor de producción, se utilizarán unos DNSs concretos pero si no, se utilizarán otros.

Para saber que el tipo de entorno en el que vamos a trabajar, pasaremos una variable de Ansible que leerá la plantilla escrita en JINJA2.

Código fuente de la plantilla JINJA2

[root@lhpilox01 Ansible]# cat playbooks/resolv.j2
{% if ENV == "PRO" %}
nameserver 10.48.33.10
nameserver 10.48.33.11
nameserver 10.48.33.12
{% else %}
nameserver 10.49.33.10
nameserver 10.49.33.11
nameserver 10.49.33.12
{% endif %}
[root@lhpilox01 Ansible]#

Código fuente del Playbook

[root@lhpilox01 Ansible]# cat playbooks/resolv.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Generar fichero resolv.conf
    template:
       src: resolv.j2
       dest: /tmp/resolv.conf
[root@lhpilox01 Ansible]#

Ejecución del Playbook

[root@lhpilox01 Ansible]# ansible-playbook --extra-vars "HOSTS=lhpilox01 ENV=PRO" -i inventario/david playbooks/resolv.yml -vv
 [WARNING] Ansible is being run in a world writable directory (/planific/bin/admsys/Ansible), ignoring it as an ansible.cfg source. For more information see https://docs.ansible.com/ansible/devel/reference_appendices/config.html#cfg-in-world-writable-dir
ansible-playbook 2.7.9
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.6/site-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.6.6 (r266:84292, Aug  9 2016, 06:11:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]
Using /etc/ansible/ansible.cfg as config file
/planific/bin/admsys/Ansible/inventario/david did not meet host_list requirements, check plugin documentation if this is unexpected

PLAYBOOK: resolv.yml *****************************************************************************************************************************************************************************
1 plays in playbooks/resolv.yml

PLAY [lhpilox01] *********************************************************************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/resolv.yml:1
ok: [lhpilox01]
META: ran handlers

TASK [Generar fichero resolv.conf] ***************************************************************************************************************************************************************
task path: /planific/bin/admsys/Ansible/playbooks/resolv.yml:3
changed: [lhpilox01] => {"changed": true, "checksum": "4d9da048ea4febaa3beab549ce3f7c46e5b2b746", "dest": "./resolv.conf", "gid": 45005, "group": "uxsup3", "md5sum": "1cef5857e7d86192cf72ae83c3b2617b", "mode": "0644", "owner": "hpddpers", "size": 69, "src": "/root/home/hpddpers/.ansible/tmp/ansible-tmp-1569840462.78-109557576510887/source", "state": "file", "uid": 8402895}
META: ran handlers
META: ran handlers

PLAY RECAP ***************************************************************************************************************************************************************************************
lhpilox01                  : ok=2    changed=1    unreachable=0    failed=0

[root@lhpilox01 Ansible]#

Resultado

Como podemos observar, hemos pasado la variable ENV=PRO en la línea de comandos del Playbook para que JINJA2 sepa que estamos hablando del entorno de producción. Como resultado, se ha generado el fichero /tmp/resolv.conf que hemos configurado en el Playbook con los DNSs de producción indicados en la plantilla JINJA2:

[root@lhpilox01 Ansible]# cat /tmp/resolv.conf
nameserver 10.48.33.10
nameserver 10.48.33.11
nameserver 10.48.33.12
[root@lhpilox01 Ansible]#

Llamar a variables de Ansible desde plantillas de JINJA2

Desde una plantilla JINJA2 podemos utilizar variables de Ansbile. A modo de ejemplo, crearemos el fichero /etc/sysconfig/network-scripts/route-eth0, en el que se configuran las rutas estáticas en sistemas Linux RedHat.

En este fichero, configuraremos las mismas rutas para todos los servidores, a excepción del default gateway que no siempre es el mismo y tenemos que obtener este valor desde una variable de Ansible.

Código fuente de la plantilla JINJA2

[root@lhpilox01 RHEL7]# cat /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/route-eth0.j2
ADDRESS0=15.84.40.0
NETMASK0=255.255.255.0
GATEWAY0={{ ansible_default_ipv4.gateway }}

Configuraríamos todas las rutas restantes con la misma sintaxis (ADDRESS1...)

Como vemos, el campo GATEWAY0 es la variable de Ansible que obtiene el default gateway que ya está configurado en el sistema operativo.

Código fuente del Playbook

[root@lhpilox01 RHEL7]# cat addroutes.yml
- hosts: "{{ HOSTS }}"
  tasks:
  - name: Generar fichero route-eth0
    template:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/route-eth0.j2
       dest: /etc/sysconfig/network-scripts/route-eth0
       mode: '0644'
       backup: yes
  - name: restart Network
    systemd:
       name: network
       state: restarted
  become: yes
[root@lhpilox01 RHEL7]# 

Definir el resultado de un comando de sistema como variable de Ansible

Es posible que nos interese ejecutar un comando de sistema con Ansible y definir su salida como una variable de Ansible que luego podemos utilizar, por ejemplo, en una plantilla Jinja2.

El siguiente ejemplo lo tuve que utilizar para definir las rutas de cientos de servidores, cada uno con su rango de IP distininto y, por lo tanto, su ruta a definir, distinta también.

Como veremos a continuación, con la directiva «register» de Ansible, definimos la salida del comando «ip» como variable de Ansible:

[root@lhpilox02 RHEL7]# cat addroutes.yml
  - name: Obtener ruta 30
    shell: "/usr/sbin/ip addr |/usr/bin/grep eth0:1 |/usr/bin/awk '{print $2}' |/usr/bin/rev |/usr/bin/cut -c6- |rev |sed 's/$/1/'"
    register: RUTA30
  - set_fact:
       RUTA30: "{{ RUTA30.stdout }}"
  - name: Add routes Paso 1 - Generar fichero route-eth0
    template:
       src: /planific/bin/admsys/Ansible/playbooks/post-provisioning/RHEL7/config_templates/route-eth0.j2
       dest: /etc/sysconfig/network-scripts/route-eth0_test
       mode: '0644'
       backup: yes
    become: yes
  - name: Add routes Paso 2 - Restart Network
    systemd:
       name: network
       state: restarted
    become: yes
[root@lhpilox02 RHEL7]#
  • register: RUTA30: Registramos la variable RUTA30 como variable de Ansible.
  • set_fact: Dentro de esta sección indicamos que el contenido de la variable RUTA30 es el resultado del comando (RUTA30.stdout).

La variable RUTA30 la podemos utilizar dentro de una plantilla JINJA2 como cualquier otra variable:

[root@lhpilox02 config_templates]# cat route-eth0.j2
ADDRESS0=15.84.40.0
NETMASK0=255.255.255.0
GATEWAY0={{ RUTA30 }}

Uso de Roles de Ansible

Los Roles son una característica de Ansible que permiten organizar y reutilizar tareas y Playbooks de manera modular y escalable. En lugar de definir todas las tareas en un solo archivo de Playbook, los Roles permiten separar las tareas en unidades lógicas y reutilizables llamadas Roles.

Un Rol de Ansible es una estructura de directorios que contiene tareas, archivos de variables, plantillas y otros archivos necesarios para ejecutar un conjunto de tareas relacionadas en un sistema remoto. Los Roles permiten la reutilización de código y la modularidad, lo que hace que los Playbooks de Ansible sean más fáciles de mantener y actualizar.

Los Roles se organizan en una estructura de directorios específica que se parece a esto:

roles/
    role1/
        tasks/
            main.yml
        handlers/
            main.yml
        files/
            file1
            file2
        templates/
            template1.j2
            template2.j2
        vars/
            main.yml
        defaults/
            main.yml
        meta/
            main.yml
    role2/
        tasks/
            main.yml
        handlers/
            main.yml
        ...

Cada Rol consta de varias carpetas que contienen diferentes tipos de archivos:

  • tasks: contiene tareas que se ejecutan en el sistema remoto.
  • handlers: contiene tareas que se ejecutan solo cuando se invoca un «handler», que es un evento que se desencadena cuando una tarea en el Playbook cambia algo en el sistema remoto.
  • files: contiene archivos que se copian tal cual en el sistema remoto.
  • templates: contiene plantillas Jinja2, que se utilizan para generar archivos en el sistema remoto.
  • vars: contiene variables específicas del Rol.
  • defaults: contiene valores predeterminados de variables.
  • meta: contiene información sobre el Rol, como las dependencias del Rol.

Para utilizar un Rol en un Playbook, se debe especificar el nombre del Rol en el archivo de Playbook. Por ejemplo, si tenemos un Rol llamado «webserver», podemos usarlo en un archivo de Playbook de la siguiente manera:

---
- name: Instalar y configurar servidor web
  hosts: webservers
  become: true

  roles:
    - webserver

En este ejemplo, el Playbook instalará y configurará un servidor web en todos los servidores del grupo «webservers» utilizando el Rol «webserver». Ansible buscará el Rol «webserver» en la carpeta «roles» del directorio de trabajo del Playbook.

En resumen, los Roles son una característica clave de Ansible que permiten la organización modular y la reutilización de tareas y Playbooks. Cada Rol es una estructura de directorios que contiene tareas, variables, plantillas y otros archivos necesarios para ejecutar un conjunto de tareas relacionadas en un sistema remoto. Los Roles se pueden utilizar en un archivo de Playbook para instalar y configurar aplicaciones en múltiples sistemas de manera modular y escalable.

Te puede interesar

COMPÁRTEME

1 comentario en «Tutorial de Ansible»

Deja un comentario