一、管理 FACTS:获取远程主机的 “身份信息”
FACTS 是 Ansible 自动收集的远程主机详细信息(类似 “主机身份证”),包括主机名、IP、系统版本、硬件配置等。通过 FACTS 可以动态获取主机信息,让 Playbook 更灵活
1. 查看远程主机的完整域名(FQDN) "playbook.yml" #vim编辑,查看远程主机(node1)的完整域名(FQDN) 1 --- 2 - name: Dump facts 3 hosts: node1 4 5 tasks: 6 - name: Print all facts 7 debug: 8 var: ansible_facts.fqdn PLAY [Dump facts] ************************************************************************ TASK [Gathering Facts] ******************************************************************* ok: [node1] TASK [Print all facts] ******************************************************************* ok: [node1] => { "ansible_facts.fqdn": "node1.lyk.cloud" -作用:在 node1 主机上执行,通过 debug 模块打印主机的完整域名(FQDN)。 -关键说明: ansible_facts.fqdn 是 FACTS 中的变量,存储主机的完整域名(如 node1.lyk.cloud)。 debug: var=变量名 用于在执行时显示变量的值,方便调试。 [lyk@controller web 09:51:25]$ ansible-playbook playbook.yml 2. 查看远程主机的 IPv4 网络信息 1 --- 2 - name: Dump facts 3 hosts: node1 4 5 tasks: 6 - name: Print all facts 7 debug: 8 var: ansible_facts.default_ipv4 TASK [Print all facts] ******************************************************************* ok: [node1] => { "ansible_facts.default_ipv4": { "address": "10.1.8.11", "alias": "ens33", "broadcast": "10.1.8.255", "gateway": "10.1.8.2", "interface": "ens33", "macaddress": "00:0c:29:1f:2f:2d", "mtu": 1500, "netmask": "255.255.255.0", "network": "10.1.8.0", "type": "ether" } } -作用:打印 node1 的默认 IPv4 网络信息(IP 地址、网关、子网掩码等)。 关键说明: -ansible_facts.default_ipv4 是 FACTS 中存储默认网卡 IPv4 信息的变量,包含 address(IP 地址)、gateway(网关)等子字段。 3. 导出所有 FACTS 到文件 #ansible node1 -m setup > node1.facts:把 node1 的所有信息(不止网络,还有系统、硬件等)导出到文件 [lyk@controller web 09:52:44]$ ansible node1 -m setup > node1.facts #下载到本地电脑,notepad打开,语言选json [lyk@controller web 09:54:04]$ sz node1.facts
二、loop 循环:批量执行重复任务
当需要对多个对象执行相同操作(如安装多个软件、启动多个服务)时,用
loop
循环可以简化 Playbook,避免重复写任务。
1. 批量安装软件包和启动服务
[lyk@controller web 10:39:17]$ vim deploy_web.yml 15 # 第一个任务 16 # 任务具有属性:涵name和模块名等。 17 # name属性,用于简要描述任务 18 - name: latest version of httpd and firewalld installed 19 20 # 指明模块名,也就是要执行的任务 21 yum: 22 23 # 执行要操作的rpm包名称 24 name: 25 # rpm包名称是-开头的列表格式,或者逗号分隔的列表格式 26 - httpd 27 - firewalld 28 29 # 定义软件包的状态,lastet代表升级为最新版本 30 state: latest 31 32 # 第二个任务 33 - name: test html page is installed 34 # copy模块,用于将content属性值写入到目标文件 35 copy: 36 content: "Welcome to {{ ansible_fqdn }}\n" 37 dest: /var/www/html/index.html 38 39 # 第三个任务 40 - name: enabled and start httpd/firewalld 41 # service模块,用于启用并启动httpd服务 42 service: 43 name: "{{ item }}" ##注意对齐 44 enabled: true 45 state: started 46 loop: ##注释任务4,和任务3一起执行httpd/firewalld 47 - httpd 48 - firewalld 49 50 # 第四个任务和任务三一起执行 51 # - name: firewalld enabled and running 52 # # service模块,用于启用并启动firewalld服务 53 # service: 54 # name: firewalld 55 # enabled: true 56 # state: started 57 58 59 # 第五个任务 60 - name: firewalld permits access to httpd service 61 # firewalld,用于放行http服务 62 firewalld: 63 service: http 64 permanent: true 65 state: enabled 66 immediate: yes 67 68 # Playbook中第二个play,-开头表示列表 69 - name: Test intranet web server 70 hosts: localhost 71 become: no 72 tasks: 73 - name: connect to intranet web server 74 # uri模块,用于测试网站是否可以访问 75 uri: 76 url: http://node1 77 return_content: yes 78 status_code: 200 79 80 # yaml格式结束行,一般省略 81 ... [lyk@controller web 10:39:17]$ ansible-playbook deploy_web.yml
2. 循环字典列表:批量创建用户(带不同属性)
[lyk@controller web 09:49:57]$ vim playbook.yml 1 --- 2 - name: add several users 3 hosts: node1 4 gather_facts: no 5 tasks: 6 - name: add user jane 7 user: 8 name: "{{ item }}" 9 groups: "wheel" 10 state: present 11 loop: 12 - jane 13 - joe [lyk@controller web 10:49:01]$ ansible-playbook playbook.yml PLAY [add several users] ************************************************************************** TASK [add user jane] ****************************************************************************** changed: [node1] => (item=jane) changed: [node1] => (item=joe) [lyk@controller web 10:16:10]$ vim playbook.yml 1 --- 2 - name: add several users 3 hosts: node1 4 gather_facts: no 5 tasks: 6 # - name: add user jane 7 # user: 8 # name: "{{ item }}" 9 # groups: "wheel" 10 # state: present 11 # loop: 12 # - jane 13 # - joe 14 - name: add users 15 user: 16 name: "{{ item.name }}" ##改item->item.name 17 groups: "{{ item.groups }}" ##改item->item.groups 18 state: present 19 loop: 20 - name: jane 21 groups: wheel 22 - name: joe 23 groups: root
3. Do-Until 循环:重试直到成功
[lyk@controller web 10:16:10]$ vim playbook.yml 1 - name: test loop 2 hosts: node1 3 gather_facts: no 4 tasks: 5 - shell: ping -c1 -w 2 node2 6 register: result 7 until: result.rc == 0 8 retries: 20 9 delay: 1 #断开node2 [lyk@node2 ~ 09:36:13]$ init 0 #尝试连接 [lyk@controller web 11:21:53]$ ansible-playbook playbook.yml PLAY [test loop] ******************************************************************* TASK [shell] *********************************************************************** FAILED - RETRYING: command (20 retries left). FAILED - RETRYING: command (19 retries left). FAILED - RETRYING: command (18 retries left). ...... #恢复连接node2,正常进入 [lyk@controller web 11:23:15]$ ansible-playbook playbook.yml PLAY [test loop] ******************************************************************* TASK [shell] *********************************************************************** changed: [node1] PLAY RECAP ************************************************************************* node1 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
三、when 条件判断:按需执行任务
when
用于根据条件决定任务是否执行(类似 “如果满足条件就做,否则跳过”),让 Playbook 更智能
1. 基本条件判断(布尔值、变量是否定义)
#vim playbook.yml 1 --- 2 - name: test 3 hosts: node1 4 gather_facts: no 5 vars: 6 run_my_task: true 7 tasks: 8 - name: test when 9 debug: 10 msg: "Hello run task" 11 when: run_my_task [lyk@controller web 11:23:20]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [test when] ******************************************************************* ok: [node1] => { "msg": "Hello run task" } PLAY RECAP ************************************************************************* node1 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 #vim playbook.yml 1 --- 2 - hosts: node1 3 gather_facts: no 4 vars: 5 username: lll #lll也可以不写,主要有username:就行 6 tasks: 7 - debug: 8 msg: "var: username is defined" 9 when: username is defined
2. 判断变量 / 文件 / 设备是否存在
#vim playbook.yml 1 --- 2 - hosts: node1 3 gather_facts: yes 4 tasks: 5 - debug: 6 msg: "sr0 is exist" 7 when: ansible_devices.sr0 is defined [lyk@controller web 11:47:58]$ ansible-playbook playbook.yml PLAY [node1] *********************************************************************** TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [debug] *********************************************************************** ok: [node1] => { "msg": "sr0 is exist" } PLAY RECAP ************************************************************************* node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 #vim playbook.yml 1 --- 2 - name: create and use lv 3 hosts: node1 4 tasks: 5 - name: Create a logical volume of 4000m 6 lvol: 7 vg: research 8 lv: data 9 size: 4000 10 when: ansible_lvm.vgs.research is defined 11 - debug: 12 msg: Volume group does not exist [lyk@controller web 13:30:04]$ ansible-playbook playbook.yml PLAY [create and use lv] *********************************************************** TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [Create a logical volume of 4000m] ******************************************** skipping: [node1] TASK [debug] *********************************************************************** ok: [node1] => { "msg": "Volume group does not exist" #判断文件是否存在 --- - hosts: node1 gather_facts: no vars: file_name: /etc/hosts tasks: - debug: msg: "{{ file_name }} is regular file" when: file_name is file
3. 1根据主机组安装不同软件
1 --- 2 - name: test 3 hosts: node1 4 gather_facts: no 5 vars: 6 username: devops 7 supergroup: wheel 8 tasks: 9 - name: gather user information 10 shell: id {{ username }} 11 register: result 12 - name: Task run if user is in supergroups 13 user: 14 name: "{{ username }}" 15 groups: "{{ supergroup }}" 16 append: yes 17 when: supergroup not in result.stdout [lyk@node1 ~ 13:26:53]$ sudo useradd devops [lyk@controller web 13:49:17]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [gather user information] ***************************************************** changed: [node1] TASK [Task run if user is in supergroups] ****************************************** changed: [node1] PLAY RECAP ************************************************************************* node1 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3.2
#根据不同的主机组在指定节点上安装不同的软件(web 服务器和数据库) #vim "playbook.yml" 1 --- 2 - name: test 3 hosts: node1 node3 4 gather_facts: no 5 tasks: 6 - name: install httpd 7 yum: 8 name: httpd 9 state: present 10 when: inventory_hostname in groups.webs 11 - name: install mariadb 12 yum: 13 name: mariadb 14 state: present 15 when: inventory_hostname in groups.dbs [lyk@controller web 13:49:20]$ vim inventory 1 controller 2 3 [nodes] 4 node1 5 node2 6 node3 7 node4 8 9 [webs] 10 node1 11 node2 12 13 [dbs] 14 node3 15 node4 [lyk@controller web 14:00:07]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [install httpd] *************************************************************** skipping: [node3] ok: [node1] TASK [install mariadb] ************************************************************* skipping: [node1] changed: [node3] PLAY RECAP ************************************************************************* node1 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 node3 : ok=1 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
4. loop + when:循环中过滤执行
示例:当 / 文件系统可用空间大于300000000 安装 mariadb-server
解决方法:通过 ansible_facts 获取 / 文件系统可用空间
#vim "playbook.yml" 1 --- 2 - name: Combining Loops and Conditional Play 3 hosts: node1 4 tasks: 5 - name: install mariadb-server if enough space on root 6 yum: 7 name: mariadb-server 8 state: latest 9 loop: "{{ ansible_mounts }}" 10 when: 11 - item.mount == "/" 12 - item.size_available > 300000000 [lyk@controller web 14:20:44]$ ansible-playbook playbook.yml PLAY [Combining Loops and Conditional Play] **************************************** TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [install mariadb-server if enough space on root] ****************************** skipping: [node1] => (item={u'block_used': 35554, u'uuid': u'b54b3764-2b2b-4a76-a0ec-83e308071ae5', u'size_total': 1063256064, u'block_total': 259584, u'mount': u'/boot', u'block_available': 224030, u'size_available': 917626880, u'fstype': u'xfs', u'inode_total': 524288, u'options': u'rw,relatime,attr2,inode64,noquota', u'device': u'/dev/sda1', u'inode_used': 326, u'block_size': 4096, u'inode_available': 523962}) ok: [node1] => (item={u'block_used': 523935, u'uuid': u'30af660e-85fc-4fa4-b7a8-72102f439059', u'size_total': 53660876800, u'block_total': 13100800, u'mount': u'/', u'block_available': 12576865, u'size_available': 51514839040, u'fstype': u'xfs', u'inode_total': 26214400, u'options': u'rw,relatime,attr2,inode64,noquota', u'device': u'/dev/mapper/centos-root', u'inode_used': 34064, u'block_size': 4096, u'inode_available': 26180336}) PLAY RECAP ************************************************************************* node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
5.register 和 when 联合
示例:当 / 文件系统可用空间大于300000000 安装 mariadb-server
解决方法:通过 shell 获取 / 文件系统可用空间
#vim "playbook.yml" 1 --- 2 - name: test 3 hosts: node1 4 gather_facts: no 5 tasks: 6 - name: get / available 7 shell: df / | awk 'NR==2 {print $4}' 8 register: fs_size 9 - name: install mariadb-server 10 yum: 11 name: mariadb-server 12 state: present 13 when: fs_size.stdout | int >= 300000
一、两个 Playbook 的核心功能
两者的核心逻辑都是:
检查根目录(/)的可用空间
当可用空间满足条件(大于某个值)时,安装 mariadb-server
仅在 node1 主机上执行操作
二、具体区别
对比维度 | loop + ansible_facts 方式 | register + shell 方式 |
---|---|---|
获取磁盘信息的方式 | 使用 Ansible 内置的ansible_facts 收集磁盘信息 |
通过shell 命令(df + awk)手动获取磁盘信息 |
是否需要收集 facts | 需要(默认启用gather_facts: yes ) |
不需要(显式设置gather_facts: no ) |
循环的使用 | 使用loop: "{{ ansible_mounts }}" 遍历所有挂载点 |
不使用循环,直接获取根目录信息 |
条件判断的逻辑 | 1. 先通过item.mount == "/" 筛选根目录挂载点 2. 再判断可用空间是否满足条件 |
直接对 shell 命令返回的根目录可用空间进行判断 |
可用空间的单位 | ansible_facts 返回的是字节(bytes) |
df 命令默认返回的是 KB(千字节) |
适用场景 | 适合需要处理多个挂载点的复杂场景 | 适合只需要检查单个特定目录的简单场景 |
四、Ansible Handlers:任务改变后触发操作
示例:安装软件后重启服务
[lyk@node1 ~ 14:41:45]$ sudo yum remove -y httpd #vim "playbook.yml" 1 --- 2 - name: deploy web server 3 hosts: node1 4 tasks: 5 - name: install packages 6 yum: 7 name: httpd 8 state: present 9 notify: 10 - enable and restart apache 11 12 - name: install httpd-manual 13 yum: 14 name: httpd-manual 15 state: present 16 notify: 17 - enable and restart apache 18 19 - debug: 20 msg: last task in tasks 21 22 handlers: 23 - name: enable and restart apache 24 service: 25 name: httpd 26 state: restarted 27 enabled: yes [lyk@controller web 14:40:28]$ ansible-playbook playbook.yml PLAY [deploy web server] *********************************************************** TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [install packages] ************************************************************ changed: [node1] TASK [install httpd-manual] ******************************************************** changed: [node1] TASK [debug] *********************************************************************** ok: [node1] => { "msg": "last task in tasks" } RUNNING HANDLER [enable and restart apache] **************************************** changed: [node1] PLAY RECAP ************************************************************************* node1 : ok=5 changed=3 unreachable=0 failed=0 skipp #再次执行有区别 [lyk@controller web 14:42:02]$ ansible-playbook playbook.yml PLAY [deploy web server] *********************************************************** TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [install packages] ************************************************************ ok: [node1] TASK [install httpd-manual] ******************************************************** ok: [node1] TASK [debug] *********************************************************************** ok: [node1] => { "msg": "last task in tasks" } PLAY RECAP ************************************************************************* node1 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
meta 模块
在多个任务中间加入meta任务,那么在此之前调用的 handler 会立即处理。
示例:
--- - name: deploy db server hosts: node1 tasks: - name: install mariadb yum: name: - mariadb-server - python3-PyMySQL state: present notify: - enable_and_start_db - meta: flush_handlers - name: add mariadb user mysql_user: name: lyk password: redhat handlers: - name: enable_and_start_db service: name: mariadb state: started
五、错误处理:控制任务失败后的行为
处理 Errors
#node1 [lyk@node1 ~ 15:00:39]$ sudo cp /etc/hosts /etc/myhosts #node2 [lyk@node2 ~ 15:01:26]$ rm -f /etc/myhosts [lyk@controller web 15:02:35]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [Gathering Facts] ************************************************************* ok: [node2] ok: [node1] TASK [show /etc/myhosts] *********************************************************** fatal: [node2]: FAILED! => {"changed": true, "cmd": "cat /etc/myhosts", "delta": "0:00:00.002070", "end": "2025-08-14 15:09:39.413406", "msg": "non-zero return code", "rc": 1, "start": "2025-08-14 15:09:39.411336", "stderr": "cat: /etc/myhosts: 没有那个文件或目录", "stderr_lines": ["cat: /etc/myhosts: 没有那个文件或目录"], "stdout": "", "stdout_lines": []} changed: [node1] TASK [echo end] ******************************************************************** ok: [node1] => { "msg": "echo end" } PLAY RECAP ************************************************************************* node1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 node2 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
ignore_errors
1 --- 2 - name: test 3 hosts: node1 4 tasks: 5 - name: install a not exist package 6 yum: 7 name: notexitpackage 8 state: present 9 ignore_errors: yes 10 register: result 11 - name: debug install result 12 debug: 13 msg: notexitpackage is not exit 14 when: result is failed [lyk@controller web 15:09:39]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [install a not exist package] ************************************************* fatal: [node1]: FAILED! => {"changed": false, "msg": "No package matching 'notexitpackage' found available, installed or updated", "rc": 126, "results": ["No package matching 'notexitpackage' found available, installed or updated"]} ...ignoring TASK [debug install result] ******************************************************** ok: [node1] => { "msg": "notexitpackage is not exit" } PLAY RECAP ************************************************************************* node1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
force_handlers
1 --- 2 - name: test 3 hosts: node1 4 force_handlers: yes 5 tasks: 6 - name: a task which always notifies its handler 7 command: /bin/true 8 notify: restart the sshd 9 10 - name: fails because the package doesn't exist 11 yum: 12 name: notexistpkg 13 state: latest 14 15 handlers: 16 - name: restart the sshd 17 service: 18 name: sshd 19 state: restarted [lyk@controller web 15:10:41]$ ansible-playbook playbook.yml PLAY [test] ************************************************************************ TASK [Gathering Facts] ************************************************************* ok: [node1] TASK [a task which always notifies its handler] ************************************ changed: [node1] TASK [fails because the package doesn't exist] ************************************* fatal: [node1]: FAILED! => {"changed": false, "msg": "No package matching 'notexistpkg' found available, installed or updated", "rc": 126, "results": ["No package matching 'notexistpkg' found available, installed or updated"]} RUNNING HANDLER [restart the sshd] ************************************************* changed: [node1] PLAY RECAP ************************************************************************* node1 : ok=3 changed=2 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
fail 模块
1 - name: test fail module 2 hosts: node1 3 gather_facts: no 4 tasks: 5 - debug: 6 msg: task1 7 - fail: 8 - debug: 9 msg: task3 [lyk@controller web 15:11:41]$ ansible-playbook playbook.yml PLAY [test fail module] ************************************************************ TASK [debug] *********************************************************************** ok: [node1] => { "msg": "task1" } TASK [fail] ************************************************************************ fatal: [node1]: FAILED! => {"changed": false, "msg": "Failed as requested from task"} PLAY RECAP ************************************************************************* node1 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
failed_when
指明什么条件下,判定任务执行失败
- name: test failed_when hosts: node1 tasks: - shell: /root/adduser register: command_result failed_when: "'failed' in command_result.stdout"
环境准备:
[root@node1 ~]# cat /root/adduser #!/bin/bash useradd devops &> /dev/null if [ $? -eq 0 ];then echo add user devops success else echo add user devops failed fi [root@node1 ~]# chmod +x /root/adduser
以上示例:
当devops用户不存在时,shell模块跳过执行。
当devops用户存在时,shell模块执行失败。
以上示例可改写为fail模块和when语句联合使用:
- name: test fail module hosts: node1 tasks: - shell: /root/adduser register: command_result - fail: msg: "add user devops failed" when: "'failed' in command_result.stdout"
changed_when
指明什么条件下,判定任务执行结果为changed。
示例1:
- name: changed_when hosts: node1 tasks: - name: upgrade-database shell: /usr/local/bin/upgrade-database register: result changed_when: "'Success' in result.stdout" notify: - restart_database handlers: - name: restart_database service: name: mariadb state: restarted
环境准备:
[root@node1 ~]# yum install -y mariadb-server [root@node1 ~]# systemctl enable mariadb --now [root@node1 ~]# vim /usr/local/bin/upgrade-database #!/bin/bash mysql -e 'create user lyk@"%" identified by "123";' && mysql -e 'GRANT ALL PRIVILEGES on *.* TO 123@"%";' && echo update database Success [root@node1 ~]# chmod +x /usr/local/bin/upgrade-database
对于command模块和shell模块,只要命令正常执行,结果状态通常都是changed。可以通过返回码和输出结果来判定它们是否做出更改。
关键字 changed_when: false ,让任务结果状态不为changed,只能报告为ok或failed。
示例2:
--- - name: Test When hosts: node1 gather_facts: no tasks: - name: test changed_when shell: cat /etc/redhat-release changed_when: false
Ansible block
示例2:在所有受管节点上创建符合以下要求的逻辑卷:
在research卷组中创建逻辑卷:
逻辑卷名称为data
逻辑卷大小为4000MiB
使用ext4文件系统格式化逻辑卷
将逻辑卷挂载到/data目录
如果无法创建请求的逻辑卷大小,应显示错误信息:Could not create logical volume of that size 并且应改为使用大小800MiB。
如果卷组research不存在,应显示错误信息:Volume does not exist
环境准备:
node1添加20G node2添加20G [root@node1 ~ 15:36:17]# vgcreate research /dev/sdb Physical volume "/dev/sdb" successfully created. Volume group "research" successfully created [root@node2 ~ 15:37:09]# parted /dev/sdb unit MiB mklabel msdos 信息: You may need to update /etc/fstab. [root@node2 ~ 15:37:26]# parted /dev/sdb unit MiB mkpart primary 1 1025 信息: You may need to update /etc/fstab. [root@node2 ~ 15:37:34]# vgcreate research /dev/sdb1 Physical volume "/dev/sdb1" successfully created. Volume group "research" successfully created
vim编辑
[lyk@controller web 16:02:28]$ ansible-doc -l |grep -i lvm aix_filesystem Configure LVM and... aix_lvg Manage LVM volume... lvol Configure LVM log... aix_lvol Configure AIX LVM... lvg Configure LVM vol... [lyk@controller web 16:03:12]$ ansible-doc lvol #进入文件复制 EXAMPLES: - name: Create a logical volume of 512m lvol: vg: firefly lv: test size: 512 1 --- 2 - name: create logical volume 3 hosts: all 4 tasks: 5 - name: create lv 6 block: 7 - name: Create a logical volume of 4000m 8 lvol: 9 vg: research 10 lv: data 11 size: 4000 12 rescue: 13 - name: Could not create logical volume of that size 14 debug: 15 msg: Could not create logical volume of that size 16 - name: Create a logical volume of 800m 17 lvol: 18 vg: research 19 lv: data 20 size: 800 21 always: 22 - name: Create a ext4 filesystem 23 filesystem: 24 fstype: ext4 25 dev: /dev/research/data 26 - name: Create a directory 27 file: 28 path: /data 29 state: directory 30 - name: Mount up device 31 mount: 32 path: /data 33 src: /dev/research/data 34 fstype: ext4 35 state: mounted 36 when: ansible_lvm.vgs.research is defined 37 - name: Volume does not exist 38 debug: 39 msg: Volume does not exist 40 when: ansible_lvm.vgs.research is defined [lyk@controller web 16:37:04]$ ansible-playbook playbook.yml PLAY [create logical volume] ******************************************************* TASK [Gathering Facts] ************************************************************* ok: [node3] ok: [node1] ok: [node2] ok: [node4] ok: [controller] TASK [Create a logical volume of 4000m] ******************************************** skipping: [controller] skipping: [node3] skipping: [node4] [WARNING]: The value 4000 (type int) in a string field was converted to u'4000' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change. fatal: [node2]: FAILED! => {"changed": false, "err": " Volume group \"research\" has insufficient free space (255 extents): 1000 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5} changed: [node1] TASK [Could not create logical volume of that size] ******************************** ok: [node2] => { "msg": "Could not create logical volume of that size" } TASK [Create a logical volume of 800m] ********************************************* [WARNING]: The value 800 (type int) in a string field was converted to u'800' (type string). If this does not look like what you expect, quote the entire value to ensure it does not change. changed: [node2] TASK [Create a ext4 filesystem] **************************************************** skipping: [controller] skipping: [node3] skipping: [node4] changed: [node2] changed: [node1] TASK [Create a directory] ********************************************************** skipping: [controller] skipping: [node3] skipping: [node4] changed: [node2] changed: [node1] TASK [Mount up device] ************************************************************* skipping: [controller] skipping: [node3] skipping: [node4] changed: [node1] changed: [node2] TASK [Volume does not exist] ******************************************************* skipping: [controller] ok: [node2] => { "msg": "Volume does not exist" } ok: [node1] => { "msg": "Volume does not exist" } skipping: [node3] skipping: [node4] PLAY RECAP ************************************************************************* controller : ok=1 changed=0 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0 node1 : ok=6 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 node2 : ok=7 changed=4 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0 node3 : ok=1 changed=0 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0 node4 : ok=1 changed=0 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0