diff --git a/.github/workflows/molecule.yml b/.github/workflows/molecule.yml index ec9d923..ccea32e 100644 --- a/.github/workflows/molecule.yml +++ b/.github/workflows/molecule.yml @@ -39,6 +39,8 @@ jobs: release: jammy - scenario: debian release: bullseye + - scenario: debian + release: bookworm steps: - name: Check out the codebase. diff --git a/.talismanrc b/.talismanrc index 8446c83..db366b9 100644 --- a/.talismanrc +++ b/.talismanrc @@ -3,10 +3,14 @@ fileignoreconfig: ignore_detectors: [filecontent] - filename: tasks/lvm.yml ignore_detectors: [filecontent] +- filename: tasks/metadata/storage.yml + ignore_detectors: [filecontent] - filename: molecule/ubuntu/molecule.yml ignore_detectors: [filecontent] - filename: molecule/debian/molecule.yml ignore_detectors: [filecontent] +- filename: molecule/common/inventory.yml + ignore_detectors: [filecontent] - filename: molecule/common/create.yml ignore_detectors: [filecontent] - filename: molecule/common/converge.yml diff --git a/Makefile b/Makefile index 114122a..22ade8b 100644 --- a/Makefile +++ b/Makefile @@ -18,25 +18,28 @@ UBUNTU_ISO=${UBUNTU_MIRROR}/${UBUNTU_BASENAME} REQUIREMENTS = requirements.yml ifeq (${MOLECULE_SCENARIO}, ubuntu) +MOLECULE_DISTRO=${UBUNTU_DISTRO} MOLECULE_ISO=${UBUNTU_ISO} else ifeq (${MOLECULE_SCENARIO}, debian) +MOLECULE_DISTRO=${DEBIAN_DISTRO} MOLECULE_ISO=${DEBIAN_ISO} endif all: install version lint test test: lint - MOLECULE_ISO=${MOLECULE_ISO} poetry run molecule $@ -s ${MOLECULE_SCENARIO} + MOLECULE_DISTRO=${MOLECULE_DISTRO} \ + MOLECULE_ISO=${MOLECULE_ISO} \ + poetry run molecule $@ -s ${MOLECULE_SCENARIO} install: @type poetry >/dev/null || pip3 install poetry @sudo apt-get install -y libvirt-dev - @poetry install + @poetry install --no-root lint: install poetry run yamllint . poetry run ansible-lint . - poetry run molecule syntax roles: [ -f ${REQUIREMENTS} ] && yq '.$@[] | .name' -r < ${REQUIREMENTS} \ @@ -49,7 +52,9 @@ collections: requirements: roles collections dependency create prepare converge idempotence side-effect verify destroy login reset: - MOLECULE_ISO=${MOLECULE_ISO} poetry run molecule $@ -s ${MOLECULE_SCENARIO} + MOLECULE_DISTRO=${MOLECULE_DISTRO} \ + MOLECULE_ISO=${MOLECULE_ISO} \ + poetry run molecule $@ -s ${MOLECULE_SCENARIO} ignore: poetry run ansible-lint --generate-ignore diff --git a/README.md b/README.md index 7a97c1e..15b39af 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,12 @@ An opinionated [ansible role](https://galaxy.ansible.com/nephelaiio/growfs) to grow filesystems for linux systems +## Dependencies + +Role execution requires filters defined in [nephelaiio.plugins](https://galaxy.ansible.com/ui/repo/published/nephelaiio/plugins/) collection + ## Use case + The main use case for the role is to automatically grow partitions/filesystems on systems installed using [nephelaiio.centos_installer](https://galaxy.ansible.com/nephelaiio/centos_installer) and [nephelaiio.ubuntu_installer](https://galaxy.ansible.com/nephelaiio/ubuntu_installer) ## Logic diff --git a/meta/main.yml b/meta/main.yml index d955231..d11c0be 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -20,5 +20,4 @@ galaxy_info: - stretch galaxy_tags: ['growfs'] -dependencies: - - nephelaiio.plugins +dependencies: [] diff --git a/molecule/common/create.yml b/molecule/common/create.yml index f5972b1..fb616a2 100644 --- a/molecule/common/create.yml +++ b/molecule/common/create.yml @@ -6,53 +6,38 @@ - name: Spawn KVM guests hosts: localhost become: true + vars_files: + - vars.yml pre_tasks: - - name: Install disk utils ansible.builtin.apt: name: - parted - lvm2 - tasks: - - - name: Query KVM guest info - community.libvirt.virt: - command: info - register: libvirt_info - - - name: Filter uninitialized KVM guests - ansible.builtin.set_fact: - guest_info: "{{ _guest_info }}" - vars: - _guest_names: "{{ libvirt_info.keys() }}" - _target_names: "{{ guests | map(attribute='installer_hostname') | list }}" - _target_create: "{{ _target_names | difference(_guest_names) }}" - _guest_info: "{{ guests | selectattr('installer_hostname', 'in', _target_create) }}" - - name: Cache installer iso ansible.builtin.get_url: - url: "{{ iso_installer.url }}" - dest: "{{ iso_installer.dest | urlsplit('path') }}" + url: "{{ molecule_installer_url }}" + dest: "{{ molecule_installer_dest | urlsplit('path') }}" - name: Build ubuntu installer isos ansible.builtin.include_role: name: nephelaiio.ubuntu_installer vars: ubuntu_installer_interface_name: enp1s0 - ubuntu_installer_target_dir: "{{ cache_dir }}" - ubuntu_installer_image_url: "{{ iso_installer.dest }}" + ubuntu_installer_target_dir: "{{ molecule_libvirt_path }}" + ubuntu_installer_image_url: "{{ molecule_installer_dest }}" ubuntu_installer_hostname: "{{ guest.installer_hostname }}" ubuntu_installer_username: molecule ubuntu_installer_password: "{{ 'molecule' | password_hash('sha512') }}" ubuntu_installer_sshkey: - - "{{ lookup('file', kvm_keypair + '.pub') }}" + - "{{ lookup('file', molecule_kvm_keypair + '.pub') }}" ubuntu_installer_interface: "{{ guest.installer_interface }}" ubuntu_installer_partman_method: "{{ guest.installer_partitioning_method }}" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" when: molecule_scenario == "ubuntu" - name: Build debian installer isos @@ -60,46 +45,77 @@ name: nephelaiio.debian_installer vars: debian_installer_interface_name: enp1s0 - debian_installer_target_dir: "{{ cache_dir }}" - debian_installer_image_url: "{{ iso_installer.dest }}" + debian_installer_target_dir: "{{ molecule_libvirt_path }}" + debian_installer_image_url: "{{ debian_installer_dest }}" debian_installer_hostname: "{{ guest.installer_hostname }}" debian_installer_username: molecule debian_installer_password: "{{ 'molecule' | password_hash('sha512') }}" debian_installer_sshkey: - - "{{ lookup('file', kvm_keypair + '.pub') }}" + - "{{ lookup('file', molecule_kvm_keypair + '.pub') }}" debian_installer_interface: "{{ guest.installer_interface }}" debian_installer_partman_method: "{{ guest.installer_partitioning_method }}" debian_installer_preseed_include: "{{ guest.installer_preseed_include | default('') }}" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" when: molecule_scenario == "debian" + - name: Destroy KVM guest + community.libvirt.virt: + state: destroyed + name: "{{ guest.installer_hostname }}" + loop_control: + loop_var: guest + label: "{{ guest.installer_hostname }}" + loop: "{{ molecule_kvm_guests }}" + failed_when: false + + - name: Undefine KVM guest + community.libvirt.virt: + command: undefine + name: "{{ guest.installer_hostname }}" + loop_control: + loop_var: guest + label: "{{ guest.installer_hostname }}" + loop: "{{ molecule_kvm_guests }}" + failed_when: false + + - name: Destroy KVM guest disks + ansible.builtin.file: + path: "{{ guest_disk }}" + state: absent + vars: + guest_disk: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" + loop_control: + loop_var: guest + label: "{{ guest.installer_hostname }}" + loop: "{{ molecule_kvm_guests }}" + - name: Create KVM guest disks ansible.builtin.command: "qemu-img create {{ guest_disk }} {{ guest_disk_size }}" args: creates: "{{ guest_disk }}" vars: - guest_disk: "{{ cache_dir }}/{{ guest.installer_hostname }}.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" guest_disk_size: "{{ guest.installer_disk_size }}" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" - name: Manage permissions for KVM guest disks ansible.builtin.file: path: "{{ guest_disk }}" owner: libvirt-qemu group: kvm - mode: 0640 + mode: 0666 vars: - guest_disk: "{{ cache_dir }}/{{ guest.installer_hostname }}.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" - name: Create KVM guest community.libvirt.virt: @@ -107,16 +123,16 @@ command: define vars: guest_hostname: "{{ guest.installer_hostname }}" - guest_bridge: "{{ bridge_name }}" - guest_iso: "{{ cache_dir }}/{{ guest_hostname }}.iso" - guest_disk_path: "{{ cache_dir }}/{{ guest.installer_hostname }}.img" + guest_network: "{{ molecule_libvirt_network }}" + guest_iso: "{{ molecule_libvirt_path }}/{{ guest_hostname }}.iso" + guest_disk_path: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" guest_mac: "{{ '52:54:00' | random_mac(seed=guest_hostname) }}" guest_disk_format: raw xml_template: "{{ lookup('template', 'vm.xml.j2') }}" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" - name: Start KVM guest community.libvirt.virt: @@ -127,4 +143,4 @@ loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guest_info }}" + loop: "{{ molecule_kvm_guests }}" diff --git a/molecule/common/cleanup.yml b/molecule/common/destroy.yml similarity index 50% rename from molecule/common/cleanup.yml rename to molecule/common/destroy.yml index 76a6b3c..6148f70 100644 --- a/molecule/common/cleanup.yml +++ b/molecule/common/destroy.yml @@ -3,7 +3,6 @@ hosts: localhost become: true tasks: - - name: Destroy KVM guest community.libvirt.virt: state: destroyed @@ -11,7 +10,7 @@ loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guests }}" + loop: "{{ molecule_kvm_guests }}" failed_when: false - name: Undefine KVM guest @@ -21,7 +20,7 @@ loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guests }}" + loop: "{{ molecule_kvm_guests }}" failed_when: false - name: Destroy KVM guest disks @@ -29,31 +28,38 @@ path: "{{ guest_disk }}" state: absent vars: - guest_disk: "{{ cache_dir }}/{{ guest.installer_hostname }}.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" loop_control: loop_var: guest label: "{{ guest.installer_hostname }}" - loop: "{{ guests }}" + loop: "{{ molecule_kvm_guests }}" - - name: Destroy KVM extra disks - ansible.builtin.file: - path: "{{ guest_disk }}" - state: absent - vars: - guest_disk: "{{ cache_dir }}/{{ guest.installer_hostname }}.add.img" - loop_control: - loop_var: guest - label: "{{ guest.installer_hostname }}" - loop: "{{ guests }}" - - name: Destroy dummy bridge - ansible.builtin.command: "nmcli con del {{ bridge_name }}" +- name: Destroy libvirt network and storage + hosts: localhost + become: true + vars_files: + - vars.yml + tasks: + - name: Stop libvirt network + community.libvirt.virt_net: + command: destroy + name: "{{ _libvirt_network }}" + when: _libvirt_network != "default" failed_when: false - - name: Destroy dummy interface - ansible.builtin.command: "ip link del {{ bridge_iface }}" - failed_when: false + - name: Delete libvirt network + community.libvirt.virt_net: + command: undefine + name: "{{ _libvirt_network }}" + when: _libvirt_network != "default" - - name: Destroy dummy bridge - ansible.builtin.command: "ip link del {{ bridge_name }} type bridge" - failed_when: false + - name: Undefine libvirt pool + community.libvirt.virt_pool: + state: undefined + name: "{{ _libvirt_pool }}" + + - name: Destroy libvirt pool + ansible.builtin.file: + path: "{{ _libvirt_pool }}" + state: absent diff --git a/molecule/common/inventory.yml b/molecule/common/inventory.yml index d0dbd11..e6580fc 100644 --- a/molecule/common/inventory.yml +++ b/molecule/common/inventory.yml @@ -12,18 +12,17 @@ ansible_user: molecule ansible_host: "{{ guest_address }}" ansible_port: "{{ guest_port }}" - ansible_ssh_private_key_file: "{{ kvm_keypair }}" + ansible_ssh_private_key_file: "{{ molecule_kvm_keypair }}" partitioning_method: "{{ guest.installer_partitioning_method }}" - disk_location: "{{ cache_dir }}/{{ guest.installer_hostname }}.img" + disk_location: "{{ molecule_libvirt_path }}/{{ guest.installer_hostname }}.img" disk_size: "{{ guest.installer_disk_size }}" disk_index: "{{ disk_index }}" vars: guest_hostname: "{{ guest.installer_hostname }}" - bridge_address: "{{ guest.installer_interface.ipaddress }}" - guest_address: "{{ bridge_address }}" + guest_address: "{{ guest.installer_interface.ipaddress }}" guest_port: 22 loop_control: loop_var: guest index_var: disk_index label: "{{ guest.installer_hostname }}" - loop: "{{ guests }}" + loop: "{{ molecule_kvm_guests }}" diff --git a/molecule/common/kvm.yml b/molecule/common/kvm.yml index b7ca9da..c7fbc62 100644 --- a/molecule/common/kvm.yml +++ b/molecule/common/kvm.yml @@ -1,80 +1,72 @@ --- -- name: Prepare host networking +- name: Configure KVM host hosts: localhost become: true + vars_files: + - vars.yml tasks: + - name: Install package requirements + ansible.builtin.package: + name: + - qemu-kvm + - qemu-efi + - libvirt-clients + - libvirt-daemon-system + - libvirt-daemon-system-systemd + - python3-libvirt + become: true - - name: Update apt package cache - ansible.builtin.apt: - update_cache: true - when: ansible_os_family == 'Debian' + - name: Query libvirt pools + community.libvirt.virt_pool: + command: list_pools + register: _pools - - name: Create molecule cache dir + - name: Create libvirt path ansible.builtin.file: - path: "{{ cache_dir }}" + path: "{{ _libvirt_path }}" state: directory - mode: 0777 - become: false - - - name: Create KVM keypair - ansible.builtin.command: - cmd: "ssh-keygen -t rsa -f {{ kvm_keypair }} -q -P '' -C ''" - creates: "{{ kvm_keypair }}" - become: false - - - name: Create dummy bridge - ansible.builtin.command: "ip link add {{ bridge_name }} type bridge" - failed_when: false - - - name: Create dummy interface - ansible.builtin.command: "ip link add {{ bridge_iface }} type dummy" - failed_when: false + owner: libvirt-qemu + group: kvm + mode: 0755 + become: true - - name: Create dummy bridge slave - ansible.builtin.command: "ip link set {{ bridge_iface }} master {{ bridge_name }}" - failed_when: false + - name: Define libvirt pool + community.libvirt.virt_pool: + command: define + name: "{{ _libvirt_pool }}" + xml: "{{ lookup('ansible.builtin.template', 'pool.j2.xml') }}" + vars: + _pool: "{{ _libvirt_pool }}" + _path: "{{ _libvirt_path }}" - - name: Set bridge interface ip address - ansible.builtin.command: "ip addr add {{ bridge_host }}/{{ bridge_prefix }} dev {{ bridge_name }}" - failed_when: false + - name: Activate libvirt pool + community.libvirt.virt_pool: + state: active + name: "{{ _libvirt_pool }}" - - name: Start bridge interface - ansible.builtin.command: "ip link set dev {{ bridge_name }} up" - failed_when: false + - name: Add libvirt network + community.libvirt.virt_net: + command: define + name: "{{ _libvirt_network }}" + xml: "{{ lookup('ansible.builtin.template', 'network.j2.xml') }}" + vars: + _network: "{{ _libvirt_network }}" + _address: "{{ _libvirt_address }}" + _dhcp: "{{ _libvirt_dhcp }}" + _net_address: "{{ _address | ansible.utils.ipaddr('1') | ansible.utils.ipaddr('address') }}" + _net_mask: "{{ _address | ansible.utils.ipaddr('netmask') }}" + _net_dhcp_start: "{{ _dhcp | ansible.utils.ipaddr('2') | ansible.utils.ipaddr('address') }}" + _net_dhcp_end: "{{ _dhcp | ansible.utils.ipaddr('-2') | ansible.utils.ipaddr('address') }}" + when: _libvirt_network != "default" - - name: Masquerade bridge - ansible.builtin.iptables: - table: nat - chain: POSTROUTING - out_interface: "{{ ansible_default_ipv4.interface }}" - source: "{{ bridge_net }}" - destination: 0.0.0.0/0 - jump: MASQUERADE - protocol: all - state: present + - name: Start libvirt network + community.libvirt.virt_net: + command: create + name: "{{ _libvirt_network }}" + when: _libvirt_network != "default" - - name: Enable ipv4 forwarding - ansible.posix.sysctl: - name: net.ipv4.ip_forward - value: '1' - state: present - reload: True - - - name: Install Debian packages - when: ansible_os_family == 'Debian' - block: - - - name: Install libvirt packages - ansible.builtin.apt: - name: - - libvirt-clients - - libvirt-daemon-system - - libvirt-daemon-system-systemd - - python3-libvirt - - - name: Install qemu packages - ansible.builtin.apt: - name: - - qemu-efi - - qemu-system-x86 - - qemu-utils + - name: Create KVM keypair + ansible.builtin.command: + cmd: "ssh-keygen -t rsa -f {{ molecule_kvm_keypair }} -q -P '' -C ''" + creates: "{{ molecule_kvm_keypair }}" + become: false diff --git a/molecule/common/prepare.yml b/molecule/common/prepare.yml index 18fd212..18b03c2 100644 --- a/molecule/common/prepare.yml +++ b/molecule/common/prepare.yml @@ -8,10 +8,8 @@ gather_facts: false become: true pre_tasks: - - name: Recofigure guest storage block: - - name: Query KVM guest info community.libvirt.virt: command: info @@ -24,7 +22,6 @@ - inventory_hostname in libvirt_info - libvirt_info[inventory_hostname].state == "running" block: - - name: Wait for connection ansible.builtin.wait_for_connection: timeout: 1200 @@ -50,10 +47,9 @@ - name: Reconfigure guest disks delegate_to: localhost block: - - name: Stat kvm base disk ansible.builtin.stat: - path: "{{ cache_dir }}/{{ inventory_hostname }}.img" + path: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.img" register: guest_disk_query - name: Debug base disk info @@ -63,13 +59,13 @@ - name: Resize kvm base disks ansible.builtin.command: "qemu-img resize -f raw {{ guest_disk }} {{ guest_disk_size }}" vars: - guest_disk: "{{ cache_dir }}/{{ inventory_hostname }}.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.img" guest_disk_size: "{{ 2 * (disk_size | int) }}" when: (guest_disk_size | int) > (guest_disk_query.stat.size | int) - name: Stat additional kvm disk ansible.builtin.stat: - path: "{{ cache_dir }}/{{ inventory_hostname }}.add.img" + path: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.add.img" register: guest_addisk_query - name: Create additional kvm disk for lvm instances @@ -77,7 +73,7 @@ args: creates: "{{ guest_disk }}" vars: - guest_disk: "{{ cache_dir }}/{{ inventory_hostname }}.add.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.add.img" guest_disk_size: "{{ 2 * (disk_size | int) }}" when: - not guest_addisk_query.stat.exists @@ -91,7 +87,7 @@ group: kvm mode: 0660 vars: - guest_disk: "{{ cache_dir }}/{{ inventory_hostname }}.add.img" + guest_disk: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.add.img" when: partitioning_method == 'lvm' - name: Flush handlers @@ -111,18 +107,17 @@ tags: always always: - - name: Set debug facts ansible.builtin.set_fact: debug_disk: "{{ disk_location }}.debug" debug_hostdir: "{{ _hostdir }}" debug_logfile: "{{ _logfile }}" debug_crashdir: "{{ _crashdir }}" - debug_output_dir: "{{ output_dir }}" - debug_output_curtin: "{{ output_dir }}/{{ inventory_hostname }}.curtin.log" - debug_output_screenshot: "{{ output_dir }}/{{ inventory_hostname }}.png" + debug_output_dir: "{{ molecule_install_dir }}" + debug_output_curtin: "{{ molecule_install_dir }}/{{ inventory_hostname }}.curtin.log" + debug_output_screenshot: "{{ molecule_install_dir }}/{{ inventory_hostname }}.png" vars: - _hostdir: "{{ cache_dir }}/{{ inventory_hostname }}" + _hostdir: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}" _logfile: "{{ _hostdir }}/var/log/installer/curtin-install.log" _crashdir: "{{ _hostdir }}/var/crash/" @@ -136,11 +131,9 @@ - name: Take guest screenshot ansible.builtin.command: "virsh screenshot {{ inventory_hostname }} {{ debug_output_screenshot }}" delegate_to: localhost - when: molecule_debug become: true handlers: - - name: Create definition for additional kvm guest disk ansible.builtin.template: src: disk.xml.j2 @@ -150,9 +143,9 @@ mode: 0660 vars: guest_hostname: "{{ inventory_hostname }}" - guest_disk_extra_path: "{{ cache_dir }}/{{ inventory_hostname }}.add.img" + guest_disk_extra_path: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}.add.img" guest_disk_format: raw - guest_disk_xml: "{{ cache_dir }}/{{ guest_hostname }}.disk.xml" + guest_disk_xml: "{{ molecule_libvirt_path }}/{{ guest_hostname }}.disk.xml" delegate_to: localhost listen: attach kvm guest disk @@ -160,6 +153,6 @@ ansible.builtin.command: "virsh attach-device {{ guest_hostname }} --file {{ guest_disk_xml }} --config" vars: guest_hostname: "{{ inventory_hostname }}" - guest_disk_xml: "{{ cache_dir }}/{{ guest_hostname }}.disk.xml" + guest_disk_xml: "{{ molecule_libvirt_path }}/{{ guest_hostname }}.disk.xml" delegate_to: localhost listen: attach kvm guest disk diff --git a/molecule/common/templates/meta-data.yml.j2 b/molecule/common/templates/meta-data.yml.j2 new file mode 100644 index 0000000..d2a729f --- /dev/null +++ b/molecule/common/templates/meta-data.yml.j2 @@ -0,0 +1,2 @@ +instance-id: {{ inventory_hostname }} +local-hostname: {{ inventory_hostname }} diff --git a/molecule/common/templates/network.j2.xml b/molecule/common/templates/network.j2.xml new file mode 100644 index 0000000..be95b60 --- /dev/null +++ b/molecule/common/templates/network.j2.xml @@ -0,0 +1,14 @@ + + {{ _network }} + + + + + + + + + + + + diff --git a/molecule/common/templates/pool.j2.xml b/molecule/common/templates/pool.j2.xml new file mode 100644 index 0000000..03109ed --- /dev/null +++ b/molecule/common/templates/pool.j2.xml @@ -0,0 +1,11 @@ + + {{ _pool }} + + {{ _path }} + + 0711 + 0 + 0 + + + diff --git a/molecule/common/templates/user-data.yml.j2 b/molecule/common/templates/user-data.yml.j2 new file mode 100644 index 0000000..954bde0 --- /dev/null +++ b/molecule/common/templates/user-data.yml.j2 @@ -0,0 +1,8 @@ +#cloud-config +users: + - name: {{ guest_user }} + ssh_authorized_keys: + - {{ guest_key }} + sudo: "ALL=(ALL) NOPASSWD:ALL" + groups: sudo + shell: /bin/bash diff --git a/molecule/common/templates/vm.xml.j2 b/molecule/common/templates/vm.xml.j2 index db89e4f..a2b10f5 100644 --- a/molecule/common/templates/vm.xml.j2 +++ b/molecule/common/templates/vm.xml.j2 @@ -1,4 +1,4 @@ - + {{ guest_hostname }} 4194304 4194304 @@ -146,9 +146,10 @@
- - + +
+ diff --git a/molecule/common/vars.yml b/molecule/common/vars.yml new file mode 100644 index 0000000..208bdf4 --- /dev/null +++ b/molecule/common/vars.yml @@ -0,0 +1,7 @@ +--- +_libvirt_network: "{{ molecule_libvirt_network | default('rke') }}" +_libvirt_address: "{{ molecule_libvirt_address | default('172.31.255.1/24') }}" +_libvirt_dhcp: "{{ molecule_libvirt_dhcp | default(_libvirt_address) }}" +_libvirt_user: "{{ molecule_libvirt_user | default('molecule') }}" +_libvirt_pool: "{{ molecule_libvirt_pool | default('molecule') }}" +_libvirt_path: "{{ molecule_libvirt_path | default('/var/lib/libvirt/molecule') }}" diff --git a/molecule/common/verify.yml b/molecule/common/verify.yml index 6d1d41f..c7d04e0 100644 --- a/molecule/common/verify.yml +++ b/molecule/common/verify.yml @@ -95,11 +95,11 @@ debug_hostdir: "{{ _hostdir }}" debug_logfile: "{{ _logfile }}" debug_crashdir: "{{ _crashdir }}" - debug_output_dir: "{{ output_dir }}" - debug_output_curtin: "{{ output_dir }}/{{ inventory_hostname }}.curtin.log" - debug_output_screenshot: "{{ output_dir }}/{{ inventory_hostname }}.png" + debug_output_dir: "{{ molecule_install_dir }}" + debug_output_curtin: "{{ molecule_install_dir }}/{{ inventory_hostname }}.curtin.log" + debug_output_screenshot: "{{ molecule_install_dir }}/{{ inventory_hostname }}.png" vars: - _hostdir: "{{ cache_dir }}/{{ inventory_hostname }}" + _hostdir: "{{ molecule_libvirt_path }}/{{ inventory_hostname }}" _logfile: "{{ _hostdir }}/var/log/installer/curtin-install.log" _crashdir: "{{ _hostdir }}/var/crash/" @@ -113,7 +113,6 @@ - name: Take guest screenshot ansible.builtin.command: "virsh screenshot {{ inventory_hostname }} {{ debug_output_screenshot }}" delegate_to: localhost - when: molecule_debug become: true - name: End play for lvm guests diff --git a/molecule/debian/molecule.yml b/molecule/debian/molecule.yml index 832f0e5..3d5b03e 100644 --- a/molecule/debian/molecule.yml +++ b/molecule/debian/molecule.yml @@ -27,43 +27,37 @@ provisioner: create: ../common/create.yml converge: ../common/converge.yml verify: ../common/verify.yml - cleanup: ../common/cleanup.yml + destroy: ../common/destroy.yml side_effect: ../common/reboot.yml inventory: hosts: all: vars: - growfs_device_filter: "vd.*" - molecule_scenario: "${MOLECULE_SCENARIO_NAME}" - molecule_distro: "{{ lookup('env', 'MOLECULE_DISTRO', default='bookworm') }}" - molecule_iso: "{{ lookup('env', 'MOLECULE_ISO') }}" - molecule_debug: "{{ lookup('env', 'GITHUB_ACTIONS', default='false') | bool }}" - cache_dir: "/tmp/{{ molecule_distro }}" - output_dir: "{{ lookup('env', 'MOLECULE_OUTPUT_DIR', default='/tmp/logs') }}" - - molecule_net: "{{ lookup('env', 'MOLECULE_NET', default='192.168.254.0/24') }}" - bridge_net: "{{ molecule_net | ansible.utils.ipv4('network/prefix') }}" - bridge_host: "{{ bridge_net | ansible.utils.nthhost(1) }}" - bridge_prefix: "{{ bridge_net | ansible.utils.ipaddr('prefix') }}" - bridge_name: "{{ molecule_distro }}br1" - bridge_iface: "{{ molecule_distro }}0" - - kvm_keypair: "{{ cache_dir }}/kvm_key" ansible_ssh_common_args: '-o StrictHostKeyChecking=no' - iso_installer: - dest: "file://{{ cache_dir }}/{{ molecule_distro }}.iso" - url: "{{ molecule_iso }}" + growfs_device_filter: "vd.*" - guests: + molecule_scenario: "${MOLECULE_SCENARIO_NAME}" + molecule_distro: "{{ lookup('env', 'MOLECULE_DISTRO') }}" + molecule_iso: "{{ lookup('env', 'MOLECULE_ISO') }}" + molecule_installer_url: "{{ molecule_iso }}" + molecule_installer_dest: "file://{{ molecule_libvirt_path }}/{{ molecule_distro }}.iso" + molecule_libvirt_netaddr: "{{ lookup('env', 'MOLECULE_NET', default='192.168.247.0/24') | ansible.utils.ipv4('network/prefix') }}" + molecule_libvirt_netsize: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('prefix') }}" + molecule_libvirt_address: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(1) }}/{{ molecule_libvirt_netsize }}" + molecule_libvirt_network: "molecule" + molecule_libvirt_path: "/var/lib/libvirt/growfs" + molecule_install_dir: "{{ lookup('env', 'MOLECULE_OUTPUT_DIR', default='/tmp/logs') }}" + molecule_kvm_keypair: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/kvm_key" + molecule_kvm_guests: - installer_hostname: "{{ molecule_distro }}-lvm-10g" installer_disk_size: "{{ 10*(1024**3) }}" installer_interface: static: true - ipaddress: "{{ bridge_net | ansible.utils.nthhost(2) }}" - network: "{{ bridge_net | ansible.utils.ipaddr('network') }}" - netmask: "{{ bridge_net | ansible.utils.ipaddr('netmask') }}" - gateway: "{{ bridge_host }}" + ipaddress: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(2) }}" + network: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('network') }}" + netmask: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('netmask') }}" + gateway: "{{ molecule_libvirt_address | ansible.utils.ipaddr('address') }}" nameservers: - 1.1.1.1 - 8.8.8.8 @@ -73,10 +67,10 @@ provisioner: installer_disk_size: "{{ 10*(1024**3) }}" installer_interface: static: true - ipaddress: "{{ bridge_net | ansible.utils.nthhost(3) }}" - network: "{{ bridge_net | ansible.utils.ipaddr('network') }}" - netmask: "{{ bridge_net | ansible.utils.ipaddr('netmask') }}" - gateway: "{{ bridge_host }}" + ipaddress: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(3) }}" + network: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('network') }}" + netmask: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('netmask') }}" + gateway: "{{ molecule_libvirt_address | ansible.utils.ipaddr('address') }}" nameservers: - 1.1.1.1 - 8.8.8.8 @@ -92,4 +86,3 @@ scenario: - converge - side_effect - verify - - cleanup diff --git a/molecule/ubuntu/molecule.yml b/molecule/ubuntu/molecule.yml index b20ba4b..1475f23 100644 --- a/molecule/ubuntu/molecule.yml +++ b/molecule/ubuntu/molecule.yml @@ -27,43 +27,37 @@ provisioner: create: ../common/create.yml converge: ../common/converge.yml verify: ../common/verify.yml - cleanup: ../common/cleanup.yml + destroy: ../common/destroy.yml side_effect: ../common/reboot.yml inventory: hosts: all: vars: - growfs_device_filter: "vd.*" - molecule_scenario: "${MOLECULE_SCENARIO_NAME}" - molecule_distro: "{{ lookup('env', 'MOLECULE_DISTRO', default='jammy') }}" - molecule_iso: "{{ lookup('env', 'MOLECULE_ISO') }}" - molecule_debug: "{{ lookup('env', 'GITHUB_ACTIONS', default='false') | bool }}" - cache_dir: "/tmp/{{ molecule_distro }}" - output_dir: "{{ lookup('env', 'MOLECULE_OUTPUT_DIR', default='/tmp/logs') }}" - - molecule_net: "{{ lookup('env', 'MOLECULE_NET', default='192.168.255.0/24') }}" - bridge_net: "{{ molecule_net | ansible.utils.ipv4('network/prefix') }}" - bridge_host: "{{ bridge_net | ansible.utils.nthhost(1) }}" - bridge_prefix: "{{ bridge_net | ansible.utils.ipaddr('prefix') }}" - bridge_name: "{{ molecule_distro }}br1" - bridge_iface: "{{ molecule_distro }}0" - - kvm_keypair: "{{ cache_dir }}/kvm_key" ansible_ssh_common_args: '-o StrictHostKeyChecking=no' - iso_installer: - dest: "file://{{ cache_dir }}/{{ molecule_distro }}.iso" - url: "{{ molecule_iso }}" + growfs_device_filter: "vd.*" - guests: + molecule_scenario: "${MOLECULE_SCENARIO_NAME}" + molecule_distro: "{{ lookup('env', 'MOLECULE_DISTRO') }}" + molecule_iso: "{{ lookup('env', 'MOLECULE_ISO') }}" + molecule_installer_url: "{{ molecule_iso }}" + molecule_installer_dest: "file://{{ molecule_libvirt_path }}/{{ molecule_distro }}.iso" + molecule_libvirt_netaddr: "{{ lookup('env', 'MOLECULE_NET', default='192.168.248.0/24') | ansible.utils.ipv4('network/prefix') }}" + molecule_libvirt_netsize: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('prefix') }}" + molecule_libvirt_address: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(1) }}/{{ molecule_libvirt_netsize }}" + molecule_libvirt_network: "growfs" + molecule_libvirt_path: "/var/lib/libvirt/growfs" + molecule_install_dir: "{{ lookup('env', 'MOLECULE_OUTPUT_DIR', default='/tmp/logs') }}" + molecule_kvm_keypair: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/kvm_key" + molecule_kvm_guests: - installer_hostname: "{{ molecule_distro }}-lvm-10g" installer_disk_size: "{{ 10*(1024**3) }}" installer_interface: static: true - ipaddress: "{{ bridge_net | ansible.utils.nthhost(2) }}" - network: "{{ bridge_net | ansible.utils.ipaddr('network') }}" - netmask: "{{ bridge_net | ansible.utils.ipaddr('netmask') }}" - gateway: "{{ bridge_host }}" + ipaddress: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(2) }}" + network: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('network') }}" + netmask: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('netmask') }}" + gateway: "{{ molecule_libvirt_address | ansible.utils.ipaddr('address') }}" nameservers: - 1.1.1.1 - 8.8.8.8 @@ -73,10 +67,10 @@ provisioner: installer_disk_size: "{{ 10*(1024**3) }}" installer_interface: static: true - ipaddress: "{{ bridge_net | ansible.utils.nthhost(3) }}" - network: "{{ bridge_net | ansible.utils.ipaddr('network') }}" - netmask: "{{ bridge_net | ansible.utils.ipaddr('netmask') }}" - gateway: "{{ bridge_host }}" + ipaddress: "{{ molecule_libvirt_netaddr | ansible.utils.nthhost(3) }}" + network: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('network') }}" + netmask: "{{ molecule_libvirt_netaddr | ansible.utils.ipaddr('netmask') }}" + gateway: "{{ molecule_libvirt_address | ansible.utils.ipaddr('address') }}" nameservers: - 1.1.1.1 - 8.8.8.8 @@ -92,4 +86,3 @@ scenario: - converge - side_effect - verify - - cleanup diff --git a/poetry.lock b/poetry.lock index 611b6a7..d6f3bdd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -56,13 +56,13 @@ resolvelib = ">=0.5.3,<1.1.0" [[package]] name = "ansible-lint" -version = "6.22.2" +version = "24.2.0" description = "Checks playbooks for practices and behavior that could potentially be improved" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "ansible-lint-6.22.2.tar.gz", hash = "sha256:2f409fe98efada61da9f8ab7cdf34a5b67de43e1338cee0619f5d51f4f8b15dd"}, - {file = "ansible_lint-6.22.2-py3-none-any.whl", hash = "sha256:d28a7c1ceaf043b77aebeb0a20475e647565270356c23f4790a9c01e67bf815d"}, + {file = "ansible-lint-24.2.0.tar.gz", hash = "sha256:6bc5d6273f33711ec6d370dfe5fdbe97a64b4c36c2a7a19a249401326eb03616"}, + {file = "ansible_lint-24.2.0-py3-none-any.whl", hash = "sha256:755f369c6baf601b09c4931a4e6bd0df3d79c54eb519f093e5db6ab52ad03e0c"}, ] [package.dependencies] @@ -82,7 +82,6 @@ yamllint = ">=1.30.0" [package.extras] docs = ["mkdocs-ansible (>=0.2.0)", "pipdeptree (>=2.7.1)"] -lock = ["ansible-compat (==4.1.11)", "ansible-core (==2.16.2)", "attrs (==23.2.0)", "black (==23.12.1)", "bracex (==2.4)", "certifi (==2023.11.17)", "cffi (==1.16.0)", "charset-normalizer (==3.3.2)", "click (==8.1.7)", "cryptography (==41.0.7)", "filelock (==3.13.1)", "idna (==3.6)", "jinja2 (==3.1.3)", "jsonschema (==4.20.0)", "jsonschema-specifications (==2023.12.1)", "markdown-it-py (==3.0.0)", "markupsafe (==2.1.3)", "mdurl (==0.1.2)", "mypy-extensions (==1.0.0)", "packaging (==23.2)", "pathspec (==0.12.1)", "platformdirs (==4.1.0)", "pycparser (==2.21)", "pygments (==2.17.2)", "pyyaml (==6.0.1)", "referencing (==0.32.1)", "requests (==2.31.0)", "rich (==13.7.0)", "rpds-py (==0.17.1)", "ruamel-yaml (==0.18.5)", "subprocess-tee (==0.4.1)", "tomli (==2.0.1)", "typing-extensions (==4.9.0)", "urllib3 (==2.1.0)", "wcmatch (==8.5)", "yamllint (==1.33.0)"] test = ["black", "coverage-enable-subprocess", "coverage[toml] (>=6.4.4)", "jmespath", "license-expression (>=30.1.1)", "mypy", "netaddr", "psutil", "pylint", "pytest (>=7.2.2)", "pytest-mock", "pytest-plus (>=0.6)", "pytest-xdist (>=2.1.0)", "ruamel-yaml-clib", "ruamel.yaml (>=0.17.31)", "types-jsonschema", "types-pyyaml"] [[package]] @@ -701,25 +700,6 @@ docs = ["linkchecker (==10.2.1)", "mkdocs-ansible[lock] (>=0.2.0)", "pipdeptree test = ["ansi2html (>=1.8.0)", "ansible-lint (>=6.12.1)", "check-jsonschema", "coverage (>=7.0.3)", "filelock (>=3.9.0)", "pexpect (>=4.8.0,<5)", "pytest (>=7.2.0)", "pytest-mock (>=3.10.0)", "pytest-plus (>=0.4.0)", "pytest-xdist (>=3.1.0)"] testinfra = ["pytest-testinfra (>=8.1.0)"] -[[package]] -name = "molecule-ec2" -version = "0.4" -description = "EC2 Molecule Plugin :: run molecule tests using AWS EC2" -optional = false -python-versions = ">=3.6" -files = [ - {file = "molecule-ec2-0.4.tar.gz", hash = "sha256:e7524a6c4a4e3d384fa63be4275dbcda41eb24b130a08714428deb30f1a014b5"}, - {file = "molecule_ec2-0.4-py3-none-any.whl", hash = "sha256:768ac602009f8d454a2cc2ba4afc7079d7ac1a945b01d9011a6150d74a6ba83e"}, -] - -[package.dependencies] -boto3 = {version = "*", markers = "platform_system == \"Windows\""} -molecule = ">=3.2" -pyyaml = ">=5.1" - -[package.extras] -test = ["molecule[test]"] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -1222,4 +1202,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "021b4bc4b98d28ed09409fef9e82a59f2d1b0b79d1cdfde64c9f08aa5db6e0fb" +content-hash = "7c0ee4e905a738cdc40f2a408698d8fb799a3f36d32478ad79d40282805041ca" diff --git a/pyproject.toml b/pyproject.toml index bde20a5..c6103aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,14 +8,13 @@ authors = ["Ted Cook "] python = "^3.11" [tool.poetry.group.dev.dependencies] +ansible-lint = { version = "^24.2.0", markers = "platform_system != 'Windows'" } ansible = "^8.4.0" molecule = "^6.0.2" -molecule-ec2 = "^0.4" boto = "^2.49.0" boto3 = "^1.28.60" netaddr = "^0.9.0" yamllint = "^1.32.0" -ansible-lint = { version = "^6.20.3", markers = "platform_system != 'Windows'" } libvirt-python = "^9.8.0" lxml = "^5.1.0" diff --git a/requirements.yml b/requirements.yml index 4de3224..3e83f0a 100644 --- a/requirements.yml +++ b/requirements.yml @@ -3,7 +3,7 @@ roles: - name: nephelaiio.ubuntu_installer - name: nephelaiio.debian_installer - name: nephelaiio.centos_installer - - name: nephelaiio.plugins collections: - community.aws - community.general + - nephelaiio.plugins diff --git a/tasks/lvm.yml b/tasks/lvm.yml index 6ee2fed..21fac8d 100644 --- a/tasks/lvm.yml +++ b/tasks/lvm.yml @@ -59,6 +59,7 @@ label: "{{ partition_target.name }}" loop: "{{ __growfs_target_devices }}" when: (item.used_sectors | int) < ((item.sectors | int) * (growfs_resize_threshold | int)/100) + tags: skip_ansible_lint - name: Resize filesystems (ansible < 2.10) community.general.filesystem: @@ -119,7 +120,7 @@ partition_data: "{{ item.1 }}" partition_uuids: "{{ partition_data['links']['uuids'] }}" partition_device: "/dev/{{ partition_data.name }}" - device_dict: "{{ __growfs_target_devices | list_to_dict('name') }}" + device_dict: "{{ __growfs_target_devices | nephelaiio.plugins.list_to_dict('name') }}" device_data: "{{ device_dict[partition_disk.name] }}" loop_control: label: "{{ partition_device }}" @@ -155,7 +156,6 @@ - name: Select lvs target when: growfs_lvs_name is undefined block: - - name: Ensure target lvs is unambiguous ansible.builtin.fail: msg: "multiple logical volumes present ({{ __growfs_target_lvs.join(', ') }}) and growfs_lvs_name is unset" @@ -174,7 +174,6 @@ - name: Extend logical volume when: growfs_lvs_name != '' block: - - name: Manage logical volume community.general.lvol: vg: "{{ _vg_name }}" @@ -198,11 +197,11 @@ - name: Manage volume mount when: growfs_lvs_mount is defined block: - - name: Manage mount directory ansible.builtin.file: path: "{{ growfs_lvs_mount }}" state: directory + mode: 0755 - name: Manage lvs mount ansible.posix.mount: diff --git a/tasks/main.yml b/tasks/main.yml index 6b7e8e3..a29d4ec 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,8 +1,8 @@ --- - name: Set variable overrides ansible.builtin.set_fact: - _growfs_packages: "{{ growfs_packages | default(growfs_packages_default | sorted_get(overrides)) }}" - _growfs_lvs_fs: "{{ growfs_fs | default(growfs_fs_default) | sorted_get(overrides) }}" + _growfs_packages: "{{ growfs_packages | default(growfs_packages_default | nephelaiio.plugins.sorted_get(overrides)) }}" + _growfs_lvs_fs: "{{ growfs_fs | default(growfs_fs_default) | nephelaiio.plugins.sorted_get(overrides) }}" vars: overrides: - "{{ ansible_distribution | lower }}-{{ ansible_distribution_release | lower }}" diff --git a/tasks/metadata/storage.yml b/tasks/metadata/storage.yml index 2546c13..ba737df 100644 --- a/tasks/metadata/storage.yml +++ b/tasks/metadata/storage.yml @@ -5,14 +5,14 @@ - name: Initialize storage device metadata ansible.builtin.set_fact: __growfs_target_devices: [] - __growfs_mountpoints: "{{ ansible_mounts | list_to_dict('device', remove_key=False) }}" + __growfs_mountpoints: "{{ ansible_mounts | nephelaiio.plugins.list_to_dict('device', remove_key=False) }}" - name: Filter storage device names ansible.builtin.set_fact: __growfs_target_devices: "{{ __growfs_target_devices + [target_device] }}" vars: target_device: "{{ item.value | combine(target_device_extra) }}" - target_device_partitions: "{{ (item.value.partitions | default({})) | dict_to_list('name') | list }}" + target_device_partitions: "{{ (item.value.partitions | default({})) | nephelaiio.plugins.dict_to_list('name') | list }}" target_device_extra: name: "{{ item.key }}" used_sectors: "{{ target_device_partitions | selectattr('sectors', 'defined') | map(attribute='sectors') | map('int') | sum }}" @@ -22,8 +22,8 @@ loop: "{{ ansible_devices | dict2items }}" when: - item.key is search(growfs_device_filter) - - ((growfs_model_filter is defined) and ('model' in item.value) and (item.value.model is search(growfs_model_filter))) or (growfs_model_filter is not defined) - - ((growfs_vendor_filter is defined) and ('vendor' in item.value) and (item.value.vendor is search(growfs_vendor_filter))) or (growfs_vendor_filter is not defined) + - (growfs_model_filter is not defined) or (('model' in item.value) and (item.value.model is search(growfs_model_filter))) + - (growfs_vendor_filter is not defined) or (('vendor' in item.value) and (item.value.vendor is search(growfs_vendor_filter))) - name: Debug target storage devices ansible.builtin.debug: diff --git a/tasks/static.yml b/tasks/static.yml index 7e91619..cfcc5a7 100644 --- a/tasks/static.yml +++ b/tasks/static.yml @@ -12,6 +12,7 @@ label: "{{ partition_target.name }}" loop: "{{ __growfs_target_devices }}" when: (item.used_sectors | int) < ((item.sectors | int) * (growfs_resize_threshold | int)/100) + tags: skip_ansible_lint - name: Resize filesystems (ansible < 2.10) community.general.filesystem: