--- # Create the OpenBao VM on the local libvirt host. Idempotent: if the domain already # exists it does nothing. Run on localhost with qemu:///system (become: true). - name: Resolve the SSH public key to inject ansible.builtin.set_fact: bao_vm_ssh_pubkey: "{{ lookup('file', bao_vm_ssh_pubkey_file | expanduser) }}" - name: Fail early if no usable public key ansible.builtin.assert: that: - bao_vm_ssh_pubkey is search('^ssh-') fail_msg: >- No SSH public key at {{ bao_vm_ssh_pubkey_file }}. Generate one (ssh-keygen -t ed25519) or set bao_vm_ssh_pubkey_file. - name: Check whether the libvirt domain already exists ansible.builtin.command: "virsh dominfo {{ bao_vm_name }}" register: bao_vm_dominfo changed_when: false failed_when: false - name: Create the VM when: bao_vm_dominfo.rc != 0 block: - name: Ensure image directories exist ansible.builtin.file: path: "{{ item }}" state: directory mode: "0711" loop: - "{{ bao_vm_images_dir }}" - "{{ bao_vm_images_dir }}/base" - name: Download the Ubuntu cloud image (once) ansible.builtin.get_url: url: "{{ bao_vm_image_url }}" dest: "{{ bao_vm_images_dir }}/base/{{ bao_vm_image_url | basename }}" mode: "0644" - name: Check whether the root-disk zvol already exists ansible.builtin.command: "zfs list -H -o name {{ bao_vm_zvol }}" register: bao_vm_zvol_check changed_when: false failed_when: false - name: Create the root-disk zvol ansible.builtin.command: cmd: >- zfs create {{ '-s ' if bao_vm_zvol_sparse else '' }}-V {{ bao_vm_disk_gb }}G -o volblocksize={{ bao_vm_zvol_volblocksize }} {{ bao_vm_zvol }} when: bao_vm_zvol_check.rc != 0 - name: Wait for the zvol device node to appear ansible.builtin.wait_for: path: "{{ bao_vm_zvol_dev }}" timeout: 30 when: bao_vm_zvol_check.rc != 0 - name: Write the cloud image into the zvol (raw) ansible.builtin.command: cmd: >- qemu-img convert -O raw {{ bao_vm_images_dir }}/base/{{ bao_vm_image_url | basename }} {{ bao_vm_zvol_dev }} when: bao_vm_zvol_check.rc != 0 # cloud-init growpart expands the rootfs to fill the zvol on first boot. - name: Render the cloud-init seed files ansible.builtin.template: src: "{{ item }}.j2" dest: "{{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed-{{ item }}" mode: "0644" loop: - user-data - meta-data - network-config - name: Build the NoCloud seed ISO ansible.builtin.command: cmd: >- genisoimage -output {{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed.iso -volid cidata -joliet -rock -graft-points user-data={{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed-user-data meta-data={{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed-meta-data network-config={{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed-network-config args: creates: "{{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed.iso" - name: Define and start the domain (cloud-init imports the disk) ansible.builtin.command: cmd: >- virt-install --name {{ bao_vm_name }} --memory {{ bao_vm_memory_mb }} --vcpus {{ bao_vm_vcpus }} --osinfo require=off,name={{ bao_vm_osinfo }} --disk path={{ bao_vm_zvol_dev }},format=raw,bus=virtio --disk path={{ bao_vm_images_dir }}/{{ bao_vm_name }}-seed.iso,device=cdrom --network bridge={{ bao_vm_bridge }},model=virtio --graphics none --noautoconsole --import register: virt_install changed_when: true - name: Wait for SSH on the new bao host ansible.builtin.wait_for: host: "{{ bao_vm_ip }}" port: 22 delay: 10 timeout: 300 when: bao_vm_dominfo.rc != 0