debops icon indicating copy to clipboard operation
debops copied to clipboard

[debops.swapfile] Swapfile is disabled after running this role

Open amedee opened this issue 5 months ago • 1 comments

Before running debops.swapfile:

# free
               total        used        free      shared  buff/cache   available
Mem:          980312      684304       91988       58712      204020       88916
Swap:        4194300           0     4194300

# swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   4G 9.3M   -2

After running debops.swapfile:

# free
               total        used        free      shared  buff/cache   available
Mem:          980312      686972       84020       58712      209320       83616
Swap:              0           0           0

@box:~# swapon --show

I have defined this variable in groups/all.yml:

swapfile__files:
  - path: /swapfile
    size: 4096
    state: present

The file /swapfile already exists as a swapfile and has a size of 4 GiB.

Expected result: no changes.

I think the culprit is in this code: https://github.com/debops/debops/blob/f66d7db9eea71ad5010010183ca0562ec14f00c4/ansible/roles/swapfile/tasks/main.yml#L8

- name: Disable swap files when requested
  ansible.builtin.shell: test -f {{ item.path | d(item) }} && swapoff {{ item.path | d(item) }} || true
  changed_when: False
  with_items: '{{ swapfile__files }}'
  when: (item.state | d("present") == 'absent' and
         ((ansible_system_capabilities_enforced | d()) | bool and
          "cap_sys_admin" in ansible_system_capabilities) or
         not (ansible_system_capabilities_enforced | d(True)) | bool)

I see in my logs that it's not skipped:

TASK [debops.debops.swapfile : Disable swap files when requested] **************
task path: /home/runner/.ansible/collections/ansible_collections/debops/debops/roles/swapfile/tasks/main.yml:7
ok: [********] => (item={'path': '/swapfile', 'size': 4096, 'state': 'present'}) => changed=false 
  ansible_loop_var: item
  cmd: test -f /swapfile && swapoff /swapfile || true
  delta: '0:00:01.480794'
  end: '2025-07-16 12:26:50.457782'
  item:
    path: /swapfile
    size: 4096
    state: present
  msg: ''
  rc: 0
  start: '2025-07-16 12:26:48.976988'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>
Wednesday 16 July 2025  10:26:50 +0000 (0:00:02.122)       0:00:10.138 ******** 
Wednesday 16 July 2025  10:26:50 +0000 (0:00:02.122)       0:00:10.136 ******** 

I would expect it to skip, because item.state == 'present'.

As a workaround, I am adding a post_task to hard enable swap with an unconditional swapon --all.

The host is Ubuntu 22.04.5 LTS. I am using Debops 3.2.4.

amedee avatar Jul 16 '25 10:07 amedee

I think there's something wrong with this when condition, but I can't figure out what.

  when: (item.state | d("present") == 'absent' and
         ((ansible_system_capabilities_enforced | d()) | bool and
          "cap_sys_admin" in ansible_system_capabilities) or
         not (ansible_system_capabilities_enforced | d(True)) | bool)

I added this pre_task:

    - name: Fake capabilities to prevent unwanted swapoff
      ansible.builtin.set_fact:
        ansible_system_capabilities_enforced: true
        ansible_system_capabilities: []

and I'm gathering facts right after running debops.swapfile to restore the original values:

- name: Refresh system facts to restore capability info
  ansible.builtin.setup:
    gather_subset:
      - '!all'
      - 'min'

After adding the pre_task with ansible_system_capabilities_enforced: true, disabling swap is properly skipped as expected.

amedee avatar Jul 16 '25 12:07 amedee