---
- name: Test resize
  hosts: all
  become: true
  vars:
    storage_safe_mode: false
    mount_location: '/opt/test1'
    volume_group_size: '10g'
    volume_size_before: '5g'
    volume_size_after: '9g'
    invalid_size1: xyz GiB
    invalid_size2: none
    unused_disk_subfact: '{{ ansible_devices[unused_disks[0]] }}'
    too_large_size: '{{ unused_disk_subfact.sectors | int * 1.2 * 512 }}'
    acc_large_size: '{{ unused_disk_subfact.sectors | int * 1.015 * 512 }}'
    acc_small_size: '{{ unused_disk_subfact.sectors | int * 0.985 * 512 }}'
    disk_size: '{{ unused_disk_subfact.sectors | int * 512 }}'
  tags:
    - tests::lvm
  tasks:
    - name: Run the role
      include_role:
        name: linux-system-roles.storage

    - name: Mark tasks to be skipped
      set_fact:
        storage_skip_checks:
          - blivet_available
          - "{{ (lookup('env',
                        'SYSTEM_ROLES_REMOVE_CLOUD_INIT') in ['', 'false']) |
                ternary('packages_installed', '') }}"
          - service_facts

    - name: Get unused disks
      include_tasks: get_unused_disk.yml
      vars:
        min_size: "{{ volume_group_size }}"
        max_return: 1

    # For ext4 FS

    - name: Test ext4
      block:
        - name: >-
            Create one LVM logical volume under one volume group with size
            {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                disks: "{{ unused_disks }}"
                type: lvm
                volumes:
                  - name: test1
                    # resizing is currently supported only for ext2/3/4
                    fs_type: ext4
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume_size to {{ volume_size_after }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: 'ext4'
                    size: "{{ volume_size_after }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume size to {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext4
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Test for correct handling of too-large volume size
          include_tasks: verify-role-failed.yml
          vars:
            __storage_failed_regex: volume.+cannot be resized to.+
            __storage_failed_msg: >-
              Unexpected behavior w/ invalid volume size
            __storage_failed_params:
              storage_pools:
                - name: foo
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: ext4
                      size: "{{ too_large_size }}"
                      mount_point: "{{ mount_location }}"

        - name: Test for correct handling of volume size equal disk's size
          block:
            - name: >-
                Try to create LVM with volume size equal disk's size, resize to
                {{ disk_size }}
              include_role:
                name: linux-system-roles.storage
              vars:
                storage_pools:
                  - name: foo
                    disks: "{{ unused_disks }}"
                    volumes:
                      - name: test1
                        fs_type: ext4
                        size: "{{ disk_size }}"
                        mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Test for correct handling of acceptable size difference (slightly bigger than max)
          block:
            - name: >-
                Try to resize LVM volume size to disk size + 1.5 % (less than 2 % than
                maximum size should be tolerated)
              include_role:
                name: linux-system-roles.storage
              vars:
                storage_pools:
                  - name: foo
                    disks: "{{ unused_disks }}"
                    volumes:
                      - name: test1
                        fs_type: ext4
                        size: "{{ acc_large_size }}"
                        mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Test for correct handling of invalid size specification
          include_tasks: verify-role-failed.yml
          vars:
            __storage_failed_regex: invalid.+size
            __storage_failed_msg: >-
              Unexpected behavior w/ invalid volume size
            __storage_failed_params:
              storage_pools:
                - name: foo
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: ext4
                      size: "{{ invalid_size1 }}"
                      mount_point: "{{ mount_location }}"

        - name: Test for correct handling of invalid size specification
          include_tasks: verify-role-failed.yml
          vars:
            __storage_failed_regex: invalid.+size
            __storage_failed_msg: >-
              Unexpected behavior w/ invalid volume size
            __storage_failed_params:
              storage_pools:
                - name: foo
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: ext4
                      size: "{{ invalid_size2 }}"
                      mount_point: "{{ mount_location }}"

      always:
        - name: Clean up
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                disks: "{{ unused_disks }}"
                state: absent
                volumes:
                  - name: test1
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

    - name: Verify role results
      include_tasks: verify-role-results.yml

    # For ext3 FS

    - name: Test ext3
      block:
        - name: >-
            Create a LVM logical volume with for ext3 FS size
            {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext3
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume size to {{ volume_size_after }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext3
                    size: "{{ volume_size_after }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume size to {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext3
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

      always:
        - name: Clean up
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                disks: "{{ unused_disks }}"
                state: absent
                volumes:
                  - name: test1
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

    - name: Verify role results
      include_tasks: verify-role-results.yml

    # For ext2 FS

    - name: Test ext2
      block:
        - name: >-
            Create a LVM logical volume with for ext2 FS size
            {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext2
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume size to {{ volume_size_after }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext2
                    size: "{{ volume_size_after }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

        - name: Change volume size to {{ volume_size_before }}
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                type: lvm
                disks: "{{ unused_disks }}"
                volumes:
                  - name: test1
                    fs_type: ext2
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

      always:
        - name: Clean up
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                disks: "{{ unused_disks }}"
                state: absent
                volumes:
                  - name: test1
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

    - name: Verify role results
      include_tasks: verify-role-results.yml

    - name: Gather package facts
      package_facts:

    - name: Set blivet package name
      set_fact:
        blivet_pkg_name: "{{ ansible_facts.packages |
          select('search', 'blivet') | select('search', 'python') | list }}"

    - name: Set blivet package version
      set_fact:
        blivet_pkg_version: "{{
          ansible_facts.packages[blivet_pkg_name[0]][0]['version'] +
          '-' + ansible_facts.packages[blivet_pkg_name[0]][0]['release'] }}"

    - name: Set distribution version
      set_fact:
        is_rhel10: "{{ (ansible_facts['os_family'] == 'RedHat') and
                    ansible_facts.distribution_major_version == '10' }}"
        is_rhel9: "{{ (ansible_facts['os_family'] == 'RedHat') and
                    ansible_facts.distribution_major_version == '9' }}"
        is_rhel8: "{{ (ansible_facts['os_family'] == 'RedHat') and
                    ansible_facts.distribution_major_version == '8' }}"
        is_fedora: "{{ ansible_facts.distribution == 'Fedora' }}"

    # For ext4 FS -- online resize
    - name: Test ext4 online resize
      block:
      - name: Run test on supported platforms
        when: ((is_fedora and blivet_pkg_version is version("3.7.1-3", ">=")) or
              (is_rhel8 and blivet_pkg_version is version("3.6.0-6", ">=")) or
              (is_rhel9 and blivet_pkg_version is version("3.6.0-8", ">=")) or
              is_rhel10)
        block:
          - name: >-
              Create one LVM logical volume under one volume group with size
              {{ volume_size_before }}
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  disks: "{{ unused_disks }}"
                  type: lvm
                  volumes:
                    - name: test1
                      fs_type: ext4
                      size: "{{ volume_size_before }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

          - name: Change volume_size to {{ volume_size_after }}
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  type: lvm
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: ext4
                      size: "{{ volume_size_after }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

          - name: Test for correct handling of offline resize in safe mode
            include_tasks: verify-role-failed.yml
            vars:
              __storage_failed_regex: must be unmounted to be resized in safe mode
              __storage_failed_msg: >-
                Unexpected behavior w/ resize in safe mode
              __storage_failed_params:
                storage_safe_mode: true
                storage_pools:
                  - name: foo
                    disks: "{{ unused_disks }}"
                    volumes:
                      - name: test1
                        fs_type: ext4
                        size: "{{ volume_size_before }}"
                        mount_point: "{{ mount_location }}"

      always:
        - name: Clean up
          include_role:
            name: linux-system-roles.storage
          vars:
            storage_pools:
              - name: foo
                disks: "{{ unused_disks }}"
                state: absent
                volumes:
                  - name: test1
                    size: "{{ volume_size_before }}"
                    mount_point: "{{ mount_location }}"

        - name: Verify role results
          include_tasks: verify-role-results.yml

      # For XFS

    - name: Test xfs
      block:
      - name: Run test on supported platforms
        when: ((is_fedora and blivet_pkg_version is version("3.12.1-3", ">=")) or
              (is_rhel8 and blivet_pkg_version is version("3.4.0-1", ">=")) or
              is_rhel9 or is_rhel10)
        block:
          - name: >-
              Create a LVM logical volume with for XFS size
              {{ volume_size_before }}
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  type: lvm
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: xfs
                      size: "{{ volume_size_before }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

          - name: Change volume size to {{ volume_size_after }}
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  type: lvm
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: xfs
                      size: "{{ volume_size_after }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

          - name: Repeat for idempotency test
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  type: lvm
                  disks: "{{ unused_disks }}"
                  volumes:
                    - name: test1
                      fs_type: xfs
                      size: "{{ volume_size_after }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

          - name: Test for correct handling of shrinking (not supported by XFS)
            include_tasks: verify-role-failed.yml
            vars:
              __storage_failed_regex: volume.+cannot be resized.+
              __storage_failed_msg: >-
                Unexpected behavior w/ invalid volume size
              __storage_failed_params:
                storage_pools:
                  - name: foo
                    disks: "{{ unused_disks }}"
                    volumes:
                      - name: test1
                        fs_type: xfs
                        size: "{{ volume_size_before }}"
                        mount_point: "{{ mount_location }}"

          - name: Test for correct handling of acceptable size difference (slightly smaller than min)
            block:
              - name: >-
                  Try to resize LVM volume size to disk size - 1.5 % (less than 2 % than
                  minimum size should be tolerated)
                include_role:
                  name: linux-system-roles.storage
                vars:
                  storage_pools:
                    - name: foo
                      disks: "{{ unused_disks }}"
                      volumes:
                        - name: test1
                          fs_type: xfs
                          size: "{{ acc_small_size }}"
                          mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml

        always:
          - name: Clean up
            include_role:
              name: linux-system-roles.storage
            vars:
              storage_pools:
                - name: foo
                  disks: "{{ unused_disks }}"
                  state: absent
                  volumes:
                    - name: test1
                      size: "{{ volume_size_before }}"
                      mount_point: "{{ mount_location }}"

          - name: Verify role results
            include_tasks: verify-role-results.yml
