Skip to content

Commit d4ab201

Browse files
authored
Merge pull request #131 from stackhpc/block_device_ids
Fix block_devices to not rely on device path
2 parents 4352108 + 00950d5 commit d4ab201

File tree

3 files changed

+75
-20
lines changed

3 files changed

+75
-20
lines changed

ansible/roles/block_devices/README.md

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ This is a convenience wrapper around the ansible modules:
1111

1212
It includes logic to handle OpenStack-provided volumes appropriately both for appliance instances and the Packer build VM.
1313

14+
To avoid issues with device names changing after e.g. reboots, devices are identified by serial number and mounted by filesystem UUID.
15+
1416
Requirements
1517
------------
1618

@@ -20,7 +22,7 @@ Role Variables
2022
--------------
2123

2224
- `block_devices_partition_state`: Optional. Partition state, 'present' or 'absent' (as for parted) or 'skip'. Defaults to 'present'.
23-
- `block_devices_device`: Required. Path to block device, e.g. '/dev/sda'. See `community.general.parted:device` and `community.general.filesystem:dev`.
25+
- `block_devices_serial`: Required. Serial number of block device. For an OpenStack volume this is the volume ID.
2426
- `block_devices_number`: Required. Partition number, e.g 1 for "/dev/sda1". See `community.general.parted:number`.
2527
- `block_devices_fstype`: Required. Filesystem type, e.g.'ext4'. See `community.general.filesystem:fstype`
2628
- `block_devices_resizefs`: Optional. Grow filesystem into block device space, 'yes' or 'no' (default). See `community.general.filesystem:resizefs` for applicable fileysystem types.
@@ -51,7 +53,7 @@ Example Playbook
5153
The example variables below create an `ext4` partition on `/dev/sdb1` and mount it as `/mnt/files` with the default owner/group:
5254

5355
```yaml
54-
block_devices_device: /dev/sdb
56+
block_devices_serial: a1076455-da55-4e0c-bac8-ccc4698cff97
5557
block_devices_number: 1
5658
block_devices_fstype: ext4
5759
block_devices_path: /mnt/files
@@ -61,25 +63,12 @@ This does the same:
6163

6264
```yaml
6365
block_devices_configurations:
64-
- device: /dev/sdb
66+
- serial: a1076455-da55-4e0c-bac8-ccc4698cff97
6567
number: 1
6668
fstype: ext4
6769
path: /mnt/files
6870
```
6971

70-
This creates 'ext4' partitions on `/dev/sdb1` on `server` and `/dev/sdc1` on `server2`, both mounted at `/mnt/files`:
71-
72-
```yaml
73-
block_devices_fstype: ext4
74-
block_devices_path: /mnt/files
75-
block_devices_number: 1
76-
block_devices_configurations:
77-
- device: /dev/sdb
78-
hostnames: server1
79-
- device: /dev/sdc
80-
hostnames: server2
81-
```
82-
8372
License
8473
-------
8574

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/python
2+
3+
# Copyright: (c) 2021, StackHPC
4+
# Apache 2 License
5+
6+
DOCUMENTATION = r'''
7+
---
8+
module: block_devices
9+
10+
short_description: Return block device paths by serial number.
11+
12+
options: (none)
13+
14+
author:
15+
- Steve Brasier (@sjpb)
16+
'''
17+
18+
RETURN = r'''
19+
devices:
20+
description: dict with device serial numbers as keys and full paths (e.g. /dev/sdb) as values
21+
type: dict
22+
return: always
23+
'''
24+
25+
import json
26+
27+
from ansible.module_utils.basic import AnsibleModule
28+
29+
def run_module():
30+
module_args = dict()
31+
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
32+
result = {"changed": False}
33+
_, stdout, _ = module.run_command("lsblk --paths --json -O", check_rc=True)
34+
35+
device_info = json.loads(stdout)['blockdevices']
36+
result['devices'] = dict((item['serial'], item['name']) for item in device_info)
37+
module.exit_json(**result)
38+
39+
def main():
40+
run_module()
41+
42+
43+
if __name__ == '__main__':
44+
main()

ansible/roles/block_devices/tasks/main.yml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,55 @@
1+
- name: Enumerate block device paths by serial number
2+
block_devices:
3+
register: _block_devices
4+
15
- name: Create partitions
26
parted:
3-
device: "{{ item.get('device', block_devices_device) }}"
7+
device: "{{ _device }}"
48
number: "{{ item.get('number', block_devices_number) }}"
59
state: "{{ item.get('partition_state', block_devices_partition_state) }}"
610
when: "item.get('partition_state', block_devices_partition_state) != 'skip'"
711
loop: "{{ block_devices_configurations }}"
12+
vars:
13+
_device: "{{ _block_devices.devices[ item.get('serial', block_devices_serial) ] }}"
814

915
- name: Create filesystems
1016
filesystem:
1117
fstype: "{{ item.get('fstype', block_devices_fstype) }}"
12-
dev: "{{ item.get('device', block_devices_device) }}{{ item.get('number', block_devices_number) }}"
18+
dev: "{{ _device }}{{ item.get('number', block_devices_number) }}"
1319
resizefs: "{{ item.get('resizefs', block_devices_resizefs) }}"
1420
state: "{{ item.get('filesystem_state', block_devices_filesystem_state) }}"
1521
when: "item.get('filesystem_state', block_devices_filesystem_state) != 'skip'"
1622
loop: "{{ block_devices_configurations }}"
23+
vars:
24+
_device: "{{ _block_devices.devices[ item.get('serial', block_devices_serial) ] }}"
25+
26+
- name: Get filesystem UUIDs
27+
command:
28+
cmd: "lsblk {{ _device }}{{ item.get('number', block_devices_number) }} --noheadings --output UUID"
29+
loop: "{{ block_devices_configurations }}"
30+
vars:
31+
_device: "{{ _block_devices.devices[ item.get('serial', block_devices_serial) ] }}"
32+
register: block_devices_uuids
33+
changed_when: false
34+
check_mode: no
1735

1836
- name: Ensure mount point exists
1937
file:
2038
path: "{{ item.get('path', block_devices_path) }}"
2139
state: directory
2240
loop: "{{ block_devices_configurations }}"
2341

24-
- name: Mount filesystems
42+
- name: Mount filesystems by UUID
2543
mount:
2644
path: "{{ item.get('path', block_devices_path) }}"
27-
src: "{{ item.get('device', block_devices_device) }}{{ item.get('number', block_devices_number) }}"
45+
src: "UUID={{ _uuid }}"
2846
fstype: "{{ item.get('fstype', block_devices_fstype) }}"
2947
state: "{{ item.get('mount_state', block_devices_mount_state) }}"
48+
vars:
49+
_uuid: "{{ block_devices_uuids.results[block_devices_idx].stdout }}"
3050
loop: "{{ block_devices_configurations }}"
51+
loop_control:
52+
index_var: block_devices_idx
3153

3254
- name: Set owner/group for mounted directory
3355
file:

0 commit comments

Comments
 (0)