# SPDX-License-Identifier: MIT
---
- name: Manage SBD
  when: ha_cluster_sbd_enabled
  block:
    - name: Configure SBD watchdog
      block:
        - name: Configure and unload watchdog kernel modules from blocklist
          block:
            - name: Configure watchdog kernel module blocklist
              ansible.builtin.lineinfile:
                path: "/etc/modprobe.d/{{ item }}.conf"
                create: true
                mode: '0644'
                # wokeignore:rule=blacklist
                regexp: "^(options|blacklist) {{ item }}"
                # wokeignore:rule=blacklist
                line: "blacklist {{ item }}"
                state: present
              loop: "{{ ha_cluster.sbd_watchdog_modules_blocklist | d([]) }}"

            - name: Unload watchdog kernel modules from blocklist
              community.general.modprobe:
                name: "{{ item }}"
                state: absent
              loop: "{{ ha_cluster.sbd_watchdog_modules_blocklist | d([]) }}"

        # Softdog is minimum that needs to be provided if /dev/watchdog is not present.
        # This ensures that SBD service does not fail due to missing /dev/watchdog.
        - name: Configure and load watchdog kernel module
          block:
            - name: Configure watchdog kernel modules
              ansible.builtin.lineinfile:
                path: "/etc/modules-load.d/{{ item }}.conf"
                create: true
                mode: '0644'
                regexp: "^{{ item }}"
                line: "{{ item }}"
                state: present
              loop: "{{ ha_cluster.sbd_watchdog_modules | d(['softdog']) }}"

            - name: Load watchdog kernel modules
              community.general.modprobe:
                name: "{{ item }}"
                state: present
              loop: "{{ ha_cluster.sbd_watchdog_modules | d(['softdog']) }}"


    - name: Manage SBD devices
      # Ideally, the block as a whole should run one node at a time. This does
      # not seem to be possible with Ansible yet. Instead, we at least make the
      # block's tasks run one by one. This way, we avoid possible issues caused
      # by initializing one device from multiple host at the same time. Devices
      # initialized before the role started will not be reinitialized. Devices
      # not initialized before the role started will be initialized as many
      # times as there are nodes. That, however, has no other side effect than
      # suboptimal performance of the role.
      throttle: 1
      block:
        - name: Probe SBD devices
          ansible.builtin.command:
            cmd: sbd -d {{ item | quote }} dump
          loop: "{{ ha_cluster.sbd_devices | d([]) }}"
          register: __ha_cluster_check_sbd_devices_result
          changed_when: false
          # return_code == 0 means the disk is initialized already
          # return_code != 0 means the disk is not initialized yet
          failed_when: false
          # This command doesn't do any changes and so can safely be executed
          # even in check_mode.
          check_mode: false

        - name: Initialize SBD devices
          ansible.builtin.command:
            cmd: sbd -d {{ item.item | quote }} -1 60 -4 120 create
          changed_when: true
          loop: "{{ __ha_cluster_check_sbd_devices_result.results }}"
          when: item.rc != 0

    - name: Distribute SBD config
      ansible.builtin.template:
        src: templates/sbd
        dest: /etc/sysconfig/sbd
        owner: root
        group: root
        mode: '0644'
      vars:
        options: "{{ ha_cluster_sbd_options | d([]) }}"
        node_name: "{{ __ha_cluster_node_name }}"
        node_watchdog: "{{ ha_cluster.sbd_watchdog | d('/dev/watchdog') }}"
        node_devices: "{{ ha_cluster.sbd_devices | d([]) }}"
      register: __ha_cluster_distribute_sbd_config

    - name: Configure systemd timeout for SBD
      vars:
        __sbd_delay_start: "{{ ha_cluster_sbd_options
          | selectattr('name', 'match', '^delay-start$')
          | map(attribute='value') | list }}"
      when:
        - __sbd_delay_start | length > 0
        - __sbd_delay_start | first | int > 0
      block:
        - name: Ensure /etc/systemd/system/sbd.service.d directory exists
          ansible.builtin.file:
            path: /etc/systemd/system/sbd.service.d
            state: directory
            owner: root
            group: root
            mode: '0755'

        - name: Override start timeout for SBD
          ansible.builtin.template:
            src: templates/override-timeout.conf
            dest: /etc/systemd/system/sbd.service.d/override-timeout.conf
            owner: root
            group: root
            mode: '0644'
          vars:
            # Make sure the timeout is at least the default 90 seconds.
            # The intent is to make the timeout longer if needed, not shorter.
            # yamllint disable rule:line-length
            timeout_value: "{{ [90,
              (__sbd_delay_start | first | float * 1.2) | round(0, 'ceil') |
               int] | max }}"
            # yamllint enable rule:line-length

        - name: Reload systemd service files
          ansible.builtin.systemd:
            daemon_reload: true
