--- - name: Update system hosts: all tasks: - name: Ensure aptitude installed apt: name: "aptitude" state: present tags: - apt become: true - name: Ensure OS upgraded apt: upgrade: dist tags: - apt - update - os become: true - name: Check if reboot is necessary register: reboot_required_file stat: path: /var/run/reboot-required get_checksum: false tags: - os - reboot notify: reboot host - name: All packages updated apt: name: "*" state: latest # noqa 403 tags: - apt - update - packages become: true handlers: - name: Reboot host reboot: msg: "Reboot initiated by Ansible" connect_timeout: 5 reboot_timeout: 600 pre_reboot_delay: 0 post_reboot_delay: 30 test_command: whoami become: true when: reboot_required_file.stat.exists - name: Incus - Add package repository (apt) hosts: all gather_facts: true gather_subset: - "distribution_release" vars: task_release: "{{ incus_release | default('stable') }}" task_roles: "{{ incus_roles | default(['standalone', 'ui']) }}" any_errors_fatal: true tasks: - name: Check if distribution is supported meta: end_play when: 'ansible_distribution not in ("Ubuntu", "Debian")' - name: Create apt keyring path file: path: /etc/apt/keyrings/ mode: 0755 state: directory when: 'task_roles|length > 0 and task_release != "distro"' - name: Add Zabbly repository key copy: src: files/zabbly-key.asc dest: /etc/apt/keyrings/ansible-zabbly.asc notify: Update apt become: true when: 'task_roles|length > 0 and task_release != "distro"' - name: Get DPKG architecture shell: dpkg --print-architecture register: dpkg_architecture changed_when: false check_mode: no when: 'task_roles|length > 0 and task_release != "distro"' - name: Add Zabbly package source template: src: files/incus.sources.tpl dest: /etc/apt/sources.list.d/ansible-zabbly-incus-{{ task_release }}.sources notify: Update apt become: true when: 'task_roles|length > 0 and task_release != "distro"' handlers: - name: Update apt apt: force_apt_get: yes update_cache: yes cache_valid_time: 0 become: true - name: Incus - Install packages and bootstrap hosts: all gather_facts: true gather_subset: - "default_ipv4" - "default_ipv6" - "distribution_release" vars: task_init: "{{ incus_init | default('{}') }}" task_ip_address: "{{ incus_ip_address | default(ansible_default_ipv6['address'] | default(ansible_default_ipv4['address'])) }}" task_name: "{{ incus_name | default('') }}" task_roles: "{{ incus_roles | default(['ui', 'standalone']) }}" task_ovn_northbound: "{{ lookup('template', '../files/ovn/ovn-central.servers.tpl') | from_yaml | map('regex_replace', '^(.*)$', 'ssl:[\\1]:6641') | join(',') }}" task_servers: "{{ lookup('template', 'files/incus.servers.tpl') | from_yaml | sort }}" any_errors_fatal: true become: true tasks: - name: Install the Incus package (deb) apt: name: - incus install_recommends: no state: present register: install_deb when: 'ansible_distribution in ("Debian", "Ubuntu") and task_roles | length > 0' - name: Install the Incus package (rpm) ansible.builtin.package: name: - incus state: present register: install_rpm when: 'ansible_distribution == "CentOS" and task_roles | length > 0' - name: Install the Incus UI package (deb) apt: name: - incus-ui-canonical install_recommends: no state: present when: 'ansible_distribution in ("Debian", "Ubuntu") and "ui" in task_roles' # - name: Install btrfs tools # ansible.builtin.package: # name: # - btrfs-progs # state: present # when: "task_roles | length > 0 and 'btrfs' in task_init['storage'] | dict2items | json_query('[].value.driver')" # # - name: Install ceph tools # ansible.builtin.package: # name: # - ceph-common # state: present # when: "task_roles | length > 0 and 'ceph' in task_init['storage'] | dict2items | json_query('[].value.driver')" # # - name: Install LVM tools # ansible.builtin.package: # name: # - lvm2 # state: present # when: "task_roles | length > 0 and 'lvm' in task_init['storage'] | dict2items | json_query('[].value.driver')" # # - name: Install ZFS dependencies # ansible.builtin.package: # name: # - zfs-dkms # state: present # when: "task_roles | length > 0 and 'zfs' in task_init['storage'] | dict2items | json_query('[].value.driver') and ansible_distribution == 'Debian'" # # - name: Install ZFS tools # ansible.builtin.package: # name: # - zfsutils-linux # state: present # when: "task_roles | length > 0 and 'zfs' in task_init['storage'] | dict2items | json_query('[].value.driver')" - name: Set uid allocation shell: cmd: "usermod root --add-subuids 10000000-1009999999" when: '(install_deb.changed or install_rpm.changed) and ansible_distribution == "CentOS"' - name: Set gid allocation shell: cmd: "usermod root --add-subgids 10000000-1009999999" when: '(install_deb.changed or install_rpm.changed) and ansible_distribution == "CentOS"' - name: Enable incus socket unit systemd: enabled: true name: incus.socket state: started when: 'install_deb.changed or install_rpm.changed' - name: Enable incus service unit systemd: enabled: true name: incus.service state: started when: 'install_deb.changed or install_rpm.changed' - name: Enable incus startup unit systemd: enabled: true name: incus-startup.service state: started when: 'install_deb.changed or install_rpm.changed' - name: Set client listen address shell: cmd: "incus --force-local config set core.https_address {{ task_ip_address }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Set cluster listen address shell: cmd: "incus --force-local config set cluster.https_address {{ task_ip_address }}" when: '(install_deb.changed or install_rpm.changed) and "cluster" in task_roles and task_servers[0] == inventory_hostname' # - name: Set OVN NorthBound database # shell: # cmd: "incus --force-local config set network.ovn.northbound_connection={{ task_ovn_northbound }} network.ovn.client_cert=\"{{ lookup('file', '../data/ovn/'+ovn_name+'/'+inventory_hostname+'.crt') }}\" network.ovn.client_key=\"{{ lookup('file', '../data/ovn/'+ovn_name+'/'+inventory_hostname+'.key') }}\" network.ovn.ca_cert=\"{{ lookup('file', '../data/ovn/'+ovn_name+'/ca.crt') }}\"" # notify: Restart Incus # when: '(install_deb.changed or install_rpm.changed) and task_ovn_northbound and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Add networks shell: cmd: "incus network create {{ item.key }} --type={{ item.value.type }}{% for k in item.value.local_config | default([]) %} {{ k }}={{ item.value.local_config[k] }}{% endfor %}{% for k in item.value.config | default([]) %} {{ k }}={{ item.value.config[k] }}{% endfor %}" loop: "{{ task_init['network'] | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Set network description shell: cmd: "incus network set --property {{ item.key }} description=\"{{ item.value.description }}\"" loop: "{{ task_init['network'] | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname)) and item.value.description | default(None)' - name: Add storage pools shell: cmd: "incus storage create {{ item.key }} {{ item.value.driver }}{% for k in item.value.local_config | default([]) %} {{ k }}={{ item.value.local_config[k] }}{% endfor %}{% for k in item.value.config | default([]) %} {{ k }}={{ item.value.config[k] }}{% endfor %}" loop: "{{ task_init['storage'] | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Set storage pool description shell: cmd: "incus storage set --property {{ item.key }} description=\"{{ item.value.description }}\"" loop: "{{ task_init['storage'] | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname)) and item.value.description | default(None)' - name: Add storage pool to default profile shell: cmd: "incus profile device add default root disk path=/ pool={{ item }}" loop: "{{ task_init['storage'] | dict2items | json_query('[?value.default].key') }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Add network to default profile shell: cmd: "incus profile device add default eth0 nic network={{ item }} name=eth0" loop: "{{ task_init['network'] | dict2items | json_query('[?value.default].key') }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Bootstrap the cluster shell: cmd: "incus --force-local cluster enable {{ inventory_hostname }}" when: '(install_deb.changed or install_rpm.changed) and "cluster" in task_roles and task_servers[0] == inventory_hostname' - name: Create join tokens delegate_to: "{{ task_servers[0] }}" shell: cmd: "incus --force-local --quiet cluster add {{ inventory_hostname }}" register: cluster_add when: '(install_deb.changed or install_rpm.changed) and "cluster" in task_roles and task_servers[0] != inventory_hostname' - name: Wait 5s to avoid token use before valid ansible.builtin.wait_for: timeout: 5 delegate_to: localhost when: 'cluster_add.changed' - name: Join the cluster throttle: 1 shell: cmd: "incus --force-local admin init --preseed" stdin: |- cluster: enabled: true cluster_address: "{{ task_ip_address }}" cluster_token: "{{ cluster_add.stdout }}" server_address: "{{ task_ip_address }}" member_config: {% for pool in task_init.storage %}{% for key in task_init.storage[pool].local_config | default([]) %} - entity: storage-pool name: {{ pool }} key: {{ key }} value: {{ task_init.storage[pool].local_config[key] }}{% endfor %}{% endfor %}{% for network in task_init.network %}{% for key in task_init.network[network].local_config | default([]) %} - entity: network name: {{ network }} key: {{ key }} value: {{ task_init.network[network].local_config[key] }}{% endfor %}{% endfor %} when: 'cluster_add.changed' - name: Apply additional configuration shell: cmd: "incus config set {{ item.key }}=\"{{ item.value }}\"" loop: "{{ task_init['config'] | default({}) | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' - name: Load client certificates shell: cmd: "incus config trust add-certificate --name \"{{ item.key }}\" --type={{ item.value.type | default('client') }} -" stdin: "{{ item.value.certificate }}" loop: "{{ task_init['clients'] | default({}) | dict2items }}" when: '(install_deb.changed or install_rpm.changed) and ("standalone" in task_roles or ("cluster" in task_roles and task_servers[0] == inventory_hostname))' handlers: - name: Restart Incus systemd: name: incus.service state: restarted