test: add aio tests (#318)

* test: add aio tests

* ci: fix runs-on node

* ci: add tmate

* Tmate after converge

* Run destroy always

* Disable ipv6 in runner

* Fix permission for ipv6 disable

* disable ipv6 permanently

* Fix sysctl configuration

* Fix typo

* ci: test disable_ipv6

* ci: use focal node

* ci: add aio inside gha

* wip: aio

* ci: fix become for prepare

* ci: add ceph bootstrap

* ci: add ceph backend

* ci: fix ceph + use bigger node

* ci: fix ci for aio

* ci: increase number of cores

* Set virt_type as qemu

* Fix nic name in auto bridge add

* Disable auto bridge add in molecule aio

* ci: run full suite with eth1

* ci: fix molecule command

* ci: clean-up more values

* ci: use correct ip

* ci: use correct keepalived interface

* Fix glance_images

* fix ceph_mon_config_overrides keys and set mon_max_pg_per_osd as 500

* Enable fact gathering in tempest playbook

* Use other address for ceph_public_network and reduce image upload

- 10.0.0.0/22 is confused with cilium network. So mon ip is catched from cilium host nic in idempotence.

* fix(ceph-provisioners): stop depending on ceph-csi-rbd

* fix: allow for hci label adding

* fix: add ceph scenario

* ci: enable nested virt

* ci: final cleanup

---------

Co-authored-by: okozachenko1203 <okozachenko1203@users.noreply.github.com>
diff --git a/molecule/ceph/prepare.yml b/molecule/ceph/prepare.yml
new file mode 100644
index 0000000..f3337d9
--- /dev/null
+++ b/molecule/ceph/prepare.yml
@@ -0,0 +1,75 @@
+# Copyright (c) 2023 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- import_playbook: vexxhost.atmosphere.generate_workspace
+  vars:
+    workspace_path: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}"
+    domain_name: "{{ '{{' }} ansible_default_ipv4['address'].replace('.', '-') {{ '}}' }}.{{ lookup('env', 'ATMOSPHERE_DNS_SUFFIX_NAME') | default('nip.io', True) }}"
+
+- name: Prepare
+  hosts: all
+  become: true
+  pre_tasks:
+    - name: Wait for systemd to complete initialization
+      ansible.builtin.command: systemctl is-system-running
+      register: systemctl_status
+      until: >
+        'running' in systemctl_status.stdout or
+        'degraded' in systemctl_status.stdout
+      retries: 30
+      delay: 5
+      changed_when: false
+      failed_when: systemctl_status.rc > 1
+  tasks:
+    - name: Refresh cache & install "iptables"
+      ansible.builtin.package:
+        name: iptables
+        update_cache: true
+
+    # NOTE(mnaser): The base image installs Ansible using `pip` which breaks
+    #               the system Python, we uninstall all Python packages.
+    - name: Fix Python installation
+      block:
+        - name: Get all Python packages
+          ansible.builtin.command: pip freeze
+          register: pip_freeze
+
+        - name: Uninstall all Python packages
+          ansible.builtin.pip:
+            name: "{{ pip_freeze.stdout_lines }}"
+            state: absent
+
+- ansible.builtin.import_playbook: vexxhost.ceph.create_fake_devices
+
+- hosts: controllers
+  become: true
+  tasks:
+    - name: Overwrite existing osds.yml file
+      delegate_to: localhost
+      ansible.builtin.copy:
+        dest: "{{ lookup('env', 'MOLECULE_SCENARIO_DIRECTORY') }}/group_vars/cephs/osds.yml"
+        content: |
+          ceph_osd_devices:
+            - "/dev/ceph-{{ inventory_hostname_short }}-osd0/data"
+            - "/dev/ceph-{{ inventory_hostname_short }}-osd1/data"
+            - "/dev/ceph-{{ inventory_hostname_short }}-osd2/data"
+
+    - name: Set masquerade rule
+      become: yes
+      ansible.builtin.iptables:
+        table: nat
+        chain: POSTROUTING
+        source: 10.96.250.0/24
+        out_interface: "{{ ansible_default_ipv4.interface }}"
+        jump: MASQUERADE