lvg: add UUID reset and active state management feature (#6682)

* lvg: add UUID reset, rename, active switch feature

* Add changelog fragment for 6682

* Fix Sanity 2.15,devel tests

* Fix issue with LVM autoactivation

* Remove rename implementation

Add active/inactive states
Fix errors when a PV is missing

Apply suggestions from code review
Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/lvg.py

Co-authored-by: Felix Fontein <felix@fontein.de>

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Laszlo Szomor 2023-06-19 08:59:02 +02:00 committed by GitHub
commit 24aeedbc15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 682 additions and 79 deletions

View file

@ -18,10 +18,20 @@
block:
- import_tasks: setup.yml
- import_tasks: setup_missing_pv.yml
- import_tasks: test_indempotency.yml
- import_tasks: test_grow_reduce.yml
- import_tasks: test_pvresize.yml
- import_tasks: test_active_change.yml
- import_tasks: test_active_create.yml
- import_tasks: test_uuid_reset.yml
always:
- import_tasks: teardown.yml
- import_tasks: teardown_missing_pv.yml

View file

@ -5,7 +5,7 @@
- name: "Create files to use as a disk devices"
command: "dd if=/dev/zero of={{ remote_tmp_dir }}/img{{ item }} bs=1M count=10"
with_sequence: 'count=2'
with_sequence: 'count=4'
- name: "Show next free loop device"
command: "losetup -f"
@ -21,7 +21,23 @@
- name: "Create loop device for file"
command: "losetup -f {{ remote_tmp_dir }}/img2"
- name: "Show next free loop device"
command: "losetup -f"
register: loop_device3
- name: "Create loop device for file"
command: "losetup -f {{ remote_tmp_dir }}/img3"
- name: "Show next free loop device"
command: "losetup -f"
register: loop_device4
- name: "Create loop device for file"
command: "losetup -f {{ remote_tmp_dir }}/img4"
- name: "Affect name on disk to work on"
set_fact:
loop_device1: "{{ loop_device1.stdout }}"
loop_device2: "{{ loop_device2.stdout }}"
loop_device3: "{{ loop_device3.stdout }}"
loop_device4: "{{ loop_device4.stdout }}"

View file

@ -0,0 +1,18 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: "Prepare VG for missing PV"
lvg:
vg: vg_with_missing_pv
pvs:
- "{{ loop_device3 }}"
- "{{ loop_device4 }}"
- name: Save loop_device4 pvid
shell: "pvs -ouuid --noheadings {{ loop_device4 }} | xargs -n1 | tr -d '-'"
register: loop_device4_pvid_result
- name: Detach loop_device4
command: "losetup -d {{ loop_device4 }}"

View file

@ -6,13 +6,25 @@
- name: Remove test volume group
lvg:
vg: testvg
force: true
state: absent
- name: Remove LVM devices
loop:
- "{{ loop_device1 | default('') }}"
- "{{ loop_device2 | default('') }}"
- "{{ loop_device3 | default('') }}"
when:
- item|length > 0
command: "lvmdevices --deldev {{ item }}"
ignore_errors: true
- name: Detach loop devices
command: "losetup -d {{ item }}"
loop:
- "{{ loop_device1 | default('') }}"
- "{{ loop_device2 | default('') }}"
- "{{ loop_device3 | default('') }}"
when:
- item != ''
@ -20,4 +32,4 @@
file:
path: "{{ remote_tmp_dir }}/img{{ item }}"
state: absent
with_sequence: 'count=2'
with_sequence: 'count=4'

View file

@ -0,0 +1,8 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Remove loop_device4 LVM device
command: "lvmdevices --delpvid {{ loop_device4_pvid_result.stdout }}"
ignore_errors: true

View file

@ -0,0 +1,153 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Create volume group on disk device
lvg:
vg: testvg
pvs: "{{ loop_device1 }}"
- name: Create logical volumes on volume group
loop:
- lv1
- lv2
lvol:
vg: testvg
lv: "{{ item }}"
size: 2m
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: initial_lv_status_result
- name: Assert all lv in testvg are active
loop: "{{ initial_lv_status_result.stdout_lines }}"
assert:
that:
- "'active' == '{{ item }}'"
- name: Deactivate volume group
lvg:
state: inactive
vg: testvg
register: vg_deactivate_result
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: deactivated_lv_status_result
- name: Do all assertions to verify expected results
assert:
that:
- vg_deactivate_result is changed
- "'active' not in deactivated_lv_status_result.stdout"
- name: Deactivate volume group again to verify idempotence
lvg:
state: inactive
vg: testvg
register: repeated_vg_deactivate_result
- name: Verify vg deactivation idempontency
assert:
that:
- repeated_vg_deactivate_result is not changed
- name: Activate volume group in check mode
lvg:
state: active
vg: testvg
register: check_mode_vg_activate_result
check_mode: true
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: check_mode_activate_lv_status_result
- name: Verify VG activation in check mode changed without activating LVs
assert:
that:
- check_mode_vg_activate_result is changed
- "'active' not in check_mode_activate_lv_status_result.stdout"
- name: Activate volume group
lvg:
state: active
vg: testvg
register: vg_activate_result
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: activate_lv_status_result
- name: Verify vg activation
assert:
that:
- vg_activate_result is changed
- name: Assert all lv in testvg are active
loop: "{{ activate_lv_status_result.stdout_lines }}"
assert:
that:
- "'active' == '{{ item }}'"
- name: Activate volume group again to verify idempontency
lvg:
state: active
vg: testvg
register: repeated_vg_activate_result
- name: Verify vg activation idempontency
assert:
that:
- repeated_vg_activate_result is not changed
- name: Deactivate lv2 in testvg
lvol:
vg: testvg
lv: lv2
active: false
- name: Activate volume group again to verify partially activated vg activation
lvg:
state: active
vg: testvg
register: partial_vg_activate_result
- name: Verify partially activated vg activation
assert:
that:
- partial_vg_activate_result is changed
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: activate_partial_lv_status_result
- name: Assert all lv in testvg are active
loop: "{{ activate_partial_lv_status_result.stdout_lines }}"
assert:
that:
- "'active' == '{{ item }}'"
- name: Deactive volume group in check mode
lvg:
state: inactive
vg: testvg
register: check_mode_vg_deactivate_result
check_mode: true
- name: Collect all lv active status in testvg
shell: vgs -olv_active --noheadings testvg | xargs -n1
register: check_mode_deactivate_lv_status_result
- name: Verify check mode vg deactivation changed
assert:
that:
- check_mode_vg_deactivate_result is changed
- name: Assert all lv in testvg are still active
loop: "{{ check_mode_deactivate_lv_status_result.stdout_lines }}"
assert:
that:
- "'active' == '{{ item }}'"

View file

@ -0,0 +1,71 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Collect vgcreate help
command: "vgcreate --help"
register: vgcreate_help_result
- when: "'--setautoactivation' in vgcreate_help_result.stdout"
block:
- name: Create autoactivated volume group on disk device
lvg:
state: active
vg: vg_autoact_test
pvs: "{{ loop_device2 }}"
- name: Collect vg autoactivation status for vg_autoact_test
shell: vgs -oautoactivation --noheadings vg_autoact_test | xargs -n1
register: active_vg_autoact_status_result
- name: Assert vg autoactivation is set for vg_autoact_test
assert:
that: "'enabled' == active_vg_autoact_status_result.stdout"
- name: Remove vg_autoact_test for the next test
lvg:
state: absent
vg: vg_autoact_test
force: true
- name: Create auttoactivation disabled volume group on disk device
lvg:
state: inactive
vg: vg_autoact_test
pvs: "{{ loop_device2 }}"
- name: Collect vg autoactivation status for vg_autoact_test
shell: vgs -oautoactivation --noheadings vg_autoact_test | xargs -n1
register: inactive_vg_autoact_status_result
- name: Assert vg autoactivation disabled for vg_autoact_test
assert:
that: "inactive_vg_autoact_status_result.stdout | length == 0"
- name: Remove vg_autoact_test for the next test
lvg:
state: absent
vg: vg_autoact_test
force: true
- name: Create auttoactivation disabled by option volume group on disk device
lvg:
state: active
vg: vg_autoact_test
vg_options: "--setautoactivation n"
pvs: "{{ loop_device2 }}"
- name: Collect vg autoactivation status for vg_autoact_test
shell: vgs -oautoactivation --noheadings vg_autoact_test | xargs -n1
register: inactive_by_option_vg_autoact_status_result
- name: Assert vg autoactivation disabled by option for vg_autoact_test
assert:
that: "inactive_by_option_vg_autoact_status_result.stdout | length == 0"
always:
- name: Cleanup vg_autoact_test
lvg:
state: absent
vg: vg_autoact_test
force: true

View file

@ -0,0 +1,107 @@
---
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
- name: Create volume group on disk device
lvg:
vg: testvg
pvs: "{{ loop_device1 }}"
- name: Save testvg uuid
shell: vgs -ouuid --noheadings testvg | xargs -n1
register: orig_vg_uuid_cmd_result
- name: Save pv uuid
shell: "pvs -ouuid --noheadings {{ loop_device1 }} | xargs -n1"
register: orig_pv_uuid_cmd_result
- name: Deactivate and reset vg/pv uuid
lvg:
state: inactive
vg: testvg
pvs: "{{ loop_device1 }}"
reset_vg_uuid: true
reset_pv_uuid: true
register: vg_uuid_reset
- name: Save testvg uuid
shell: vgs -ouuid --noheadings testvg | xargs -n1
register: new_vg_uuid_cmd_result
- name: Save pv uuid
shell: "pvs -ouuid --noheadings {{ loop_device1 }} | xargs -n1"
register: new_pv_uuid_cmd_result
- name: Do all assertions to verify expected results
assert:
that:
- vg_uuid_reset is changed
- orig_vg_uuid_cmd_result.stdout != new_vg_uuid_cmd_result.stdout
- orig_pv_uuid_cmd_result.stdout != new_pv_uuid_cmd_result.stdout
- name: Reset vg uuid again to verify non-idempotence
lvg:
vg: testvg
reset_vg_uuid: true
register: repeat_vg_uuid_reset
- name: Reset pv uuid again to verify non-idempotence
lvg:
vg: testvg
reset_pv_uuid: true
pvs: "{{ loop_device1 }}"
register: repeat_pv_uuid_reset
- name: Save testvg uuid
shell: vgs -ouuid --noheadings testvg | xargs -n1
register: repeat_vg_uuid_cmd_result
- name: Save pv uuid
shell: "pvs -ouuid --noheadings {{ loop_device1 }} | xargs -n1"
register: repeat_pv_uuid_cmd_result
- name: Do all assertions to verify expected results
assert:
that:
- repeat_vg_uuid_reset is changed
- repeat_pv_uuid_reset is changed
- new_vg_uuid_cmd_result.stdout != repeat_vg_uuid_cmd_result.stdout
- new_pv_uuid_cmd_result.stdout != repeat_pv_uuid_cmd_result.stdout
- name: Reset vg uuid in check mode
lvg:
vg: testvg
reset_vg_uuid: true
register: check_mode_vg_uuid_reset
check_mode: true
- name: Reset pv uuid in check mode
lvg:
vg: testvg
reset_pv_uuid: true
pvs: "{{ loop_device1 }}"
register: check_mode_pv_uuid_reset
check_mode: true
- name: Save testvg uuid
shell: vgs -ouuid --noheadings testvg | xargs -n1
register: check_mode_vg_uuid_cmd_result
- name: Save pv uuid
shell: "pvs -ouuid --noheadings {{ loop_device1 }} | xargs -n1"
register: check_mode_pv_uuid_cmd_result
- name: Do all assertions to verify expected results
assert:
that:
- check_mode_vg_uuid_reset is changed
- check_mode_pv_uuid_reset is changed
- check_mode_vg_uuid_cmd_result.stdout == repeat_vg_uuid_cmd_result.stdout
- check_mode_pv_uuid_cmd_result.stdout == repeat_pv_uuid_cmd_result.stdout
- name: Activate volume group
lvg:
state: active
vg: testvg
register: vg_activate