I have an Ansible playbook(version 2.9), which initially displays the available block devices using lsblk command. The playbook is
- hosts: localhost
tasks:
- name: define variable
shell: lsblk -oMOUNTPOINT,NAME --json
register: lsblk_output
- debug:
msg: "{{ lsblk_output.stdout }}"
The output of the lsblk command with JSON format, lsblk -oMOUNTPOINT,NAME --json is
ok: [localhost] => {
"msg": {
"blockdevices": [
{
"mountpoint": "/snap/core18/2246",
"name": "loop0"
},
{
"mountpoint": "/snap/core18/2253",
"name": "loop1"
},
{
"mountpoint": "/snap/core20/1169",
"name": "loop2"
},
{
"mountpoint": "/snap/lxd/21803",
"name": "loop3"
},
{
"mountpoint": "/snap/core20/1242",
"name": "loop4"
},
{
"mountpoint": "/snap/lxd/21835",
"name": "loop5"
},
{
"mountpoint": "/snap/snapd/14066",
"name": "loop6"
},
{
"mountpoint": "/snap/snapd/13640",
"name": "loop7"
},
{
"children": [
{
"mountpoint": "/boot/efi",
"name": "sda1"
},
{
"mountpoint": "/boot",
"name": "sda2"
},
{
"children": [
{
"children": [
{
"mountpoint": "/",
"name": "ubuntu--vg-ubuntu--lv"
},
{
"mountpoint": null,
"name": "ubuntu--vg-clean"
}
],
"mountpoint": null,
"name": "ubuntu--vg-ubuntu--lv-real"
},
{
"children": [
{
"mountpoint": null,
"name": "ubuntu--vg-clean"
}
],
"mountpoint": null,
"name": "ubuntu--vg-clean-cow"
}
],
"mountpoint": null,
"name": "sda3"
}
],
"mountpoint": null,
"name": "sda"
},
{
"children": [
{
"mountpoint": null,
"name": "datavg-datavol1"
}
],
"mountpoint": null,
"name": "sdb"
}
]
}
}
If I modify the above shell command to lsblk -oMOUNTPOINT,NAME --json | jq '.blockdevices[] | select(.mountpoint == null) | .name'
The output is
TASK [debug] *************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "\"sda\"\n\"sdb\""
}
But, I need only one drive name based on the fact that the drive contains the "mountpoint": "/". The expected output is sda. How else can I modify the above shell command, so that a recursive search is carried out and I get the desired output?
CodePudding user response:
The registered variable lsblk_output.stdout is a string that contains the JSON data. You have to read the dictionary from the string by from_yaml (or by from_json, whatever you prefer). Then take the attribute blockdevices and select the mountpoint. For example, given the data
lsblk_output:
stdout:
blockdevices:
- children:
- mountpoint: /
name: nvme0n1p6
- mountpoint: /export
name: nvme0n1p7
mountpoint: null
name: nvme0n1
- children:
- mountpoint: /root2
name: nvme0n2p6
- mountpoint: /export2
name: nvme0n2p7
mountpoint: null
name: nvme0n2
the query below gives the name of the '/' mountpoint
- debug:
msg: "{{ (lsblk_output.stdout|from_yaml).blockdevices|
json_query(query)|
flatten }}"
vars:
query: "[].*[?mountpoint == '/'].name"
msg:
- nvme0n1p6
CodePudding user response:
If you gather_facts
, you can take advantage of the ansible_mounts
fact instead of running lsblk
.
A task such as below can filter out the disk/partition mounted at /
.
- name: show root disk
debug:
msg: "{{ ansible_mounts | json_query(query) | first }}"
vars:
query: "[?mount == '/'].device"
Results like:
ok: [localhost] => {
"msg": "/dev/sda1"
}