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:
¿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:
OPERADOR | EJEMPLO |
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:
- 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.
- 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.
- 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.
- Ignorar errores: Si se desea ignorar errores en una tarea específica, se puede agregar la cláusula «ignore_errors: true» en la tarea.
- 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.
- 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:
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
- ¿Cómo configurar los repositorios Extra Packages for Enterprise Linux o EPEL?
- Tutorial de Logical Volume Manager o LVM
Mi pasión por la tecnología me lleva constantemente a explorar las últimas tendencias y aplicaciones, buscando siempre formas de implementar soluciones innovadoras que mejoren la eficiencia. En puerto53.com comparto contenido valioso para ayudar a otros profesionales y entusiastas de la informática a navegar y dominar el complejo mundo de la tecnología. Mi especialidad en Linux RedHat.
Más sobre mí en el este enlace,
muy buena guía