Add orb and sun VMs with virtiofs swarm-common share
- Add orb (192.168.122.183) and sun (192.168.122.184) to inventory - Create host_vars for orb and sun (fresh install, brew_packages: []) - Add brew_packages to zap host_vars (gogcli, himalaya, kubernetes-cli, opencode) - customize.yml: parameterize brew_packages via host_vars, add /mnt/swarm-common virtiofs+bindfs mount for all VMs, install bindfs, fix Homebrew install - provision-vm.yml: remove become requirement; use virsh vol commands for all disk/image operations (no sudo needed) - roles/vm/tasks/main.yml: rewrite disk provisioning to use virsh vol-create-as and vol-upload; fix vol name quoting for names with spaces; use qcow2 backing - domain.xml.j2: always include swarm-common virtiofs share; make main share conditional on vm_virtiofs_source/tag Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
---
|
||||
# Provision a KVM/libvirt VM from an Ubuntu cloud image.
|
||||
# Runs on the hypervisor host (localhost).
|
||||
# Runs on the hypervisor host (localhost) without requiring sudo.
|
||||
# All writes to /var/lib/libvirt/images/ go through libvirtd (virsh vol-upload).
|
||||
|
||||
- name: Validate required variables
|
||||
ansible.builtin.assert:
|
||||
@@ -12,44 +13,71 @@
|
||||
- vm_ip | length > 0
|
||||
fail_msg: "vm_domain, vm_hostname, vm_disk_path, vm_mac, and vm_ip must all be set in host_vars"
|
||||
|
||||
- name: Install host dependencies
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- qemu-img
|
||||
- genisoimage
|
||||
- libvirt-utils
|
||||
state: present
|
||||
|
||||
# ── Cloud image ────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check if cloud image cache exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ vm_cloud_image_cache }}"
|
||||
register: cloud_image_stat
|
||||
- name: Check if cloud image volume exists in pool
|
||||
ansible.builtin.command:
|
||||
cmd: virsh -c {{ vm_libvirt_uri }} vol-info --pool default {{ vm_cloud_image_cache | basename }}
|
||||
register: cloud_image_vol_stat
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Download Ubuntu cloud image
|
||||
- name: Download Ubuntu cloud image to temp path
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ vm_cloud_image_url }}"
|
||||
dest: "{{ vm_cloud_image_cache }}"
|
||||
dest: "/tmp/{{ vm_cloud_image_cache | basename }}"
|
||||
mode: "0644"
|
||||
timeout: 300
|
||||
when: not cloud_image_stat.stat.exists
|
||||
timeout: 600
|
||||
when: cloud_image_vol_stat.rc != 0
|
||||
|
||||
- name: Create cloud image volume in pool
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
virsh -c {{ vm_libvirt_uri }} vol-create-as default
|
||||
'{{ vm_cloud_image_cache | basename }}' 4G --format raw
|
||||
register: cloud_vol_create
|
||||
failed_when:
|
||||
- cloud_vol_create.rc != 0
|
||||
- "'exists already' not in cloud_vol_create.stderr"
|
||||
changed_when: cloud_vol_create.rc == 0
|
||||
when: cloud_image_vol_stat.rc != 0
|
||||
|
||||
- name: Upload cloud image to pool
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
virsh -c {{ vm_libvirt_uri }} vol-upload
|
||||
--pool default '{{ vm_cloud_image_cache | basename }}'
|
||||
'/tmp/{{ vm_cloud_image_cache | basename }}'
|
||||
when: cloud_image_vol_stat.rc != 0 and (cloud_vol_create.rc | default(1)) == 0
|
||||
|
||||
- name: Remove temp cloud image download
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/{{ vm_cloud_image_cache | basename }}"
|
||||
state: absent
|
||||
when: cloud_image_vol_stat.rc != 0
|
||||
|
||||
# ── Disk image ─────────────────────────────────────────────────────────────
|
||||
|
||||
- name: Check if VM disk already exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ vm_disk_path }}"
|
||||
register: vm_disk_stat
|
||||
- name: Check if VM disk volume exists in pool
|
||||
ansible.builtin.shell:
|
||||
cmd: virsh -c {{ vm_libvirt_uri }} vol-info --pool default '{{ vm_disk_path | basename }}'
|
||||
register: vm_disk_vol_stat
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Create VM disk from cloud image
|
||||
ansible.builtin.command:
|
||||
- name: Create VM disk volume backed by cloud image
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
qemu-img create -f qcow2 -F qcow2
|
||||
-b {{ vm_cloud_image_cache }}
|
||||
{{ vm_disk_path }} {{ vm_disk_size }}
|
||||
creates: "{{ vm_disk_path }}"
|
||||
when: not vm_disk_stat.stat.exists
|
||||
virsh -c {{ vm_libvirt_uri }} vol-create-as default
|
||||
'{{ vm_disk_path | basename }}' {{ vm_disk_size }} --format qcow2
|
||||
--backing-vol '{{ vm_cloud_image_cache | basename }}'
|
||||
--backing-vol-format qcow2
|
||||
register: disk_vol_create
|
||||
failed_when:
|
||||
- disk_vol_create.rc != 0
|
||||
- "'exists already' not in disk_vol_create.stderr"
|
||||
changed_when: disk_vol_create.rc == 0
|
||||
when: vm_disk_vol_stat.rc != 0
|
||||
|
||||
# ── Cloud-init seed ISO ────────────────────────────────────────────────────
|
||||
|
||||
@@ -73,23 +101,46 @@
|
||||
dest: "{{ cloud_init_dir.path }}/meta-data"
|
||||
mode: "0644"
|
||||
|
||||
- name: Set seed ISO path fact
|
||||
- name: Set seed ISO facts
|
||||
ansible.builtin.set_fact:
|
||||
vm_seed_iso_name: "{{ vm_hostname }}-seed.iso"
|
||||
vm_seed_iso_tmp: "/tmp/{{ vm_hostname }}-seed.iso"
|
||||
vm_seed_iso: "/var/lib/libvirt/images/{{ vm_hostname }}-seed.iso"
|
||||
|
||||
- name: Create cloud-init seed ISO
|
||||
- name: Create cloud-init seed ISO in temp path
|
||||
ansible.builtin.command:
|
||||
cmd: >
|
||||
genisoimage -output {{ vm_seed_iso }}
|
||||
genisoimage -output {{ vm_seed_iso_tmp }}
|
||||
-volid cidata -joliet -rock
|
||||
{{ cloud_init_dir.path }}/user-data
|
||||
{{ cloud_init_dir.path }}/meta-data
|
||||
changed_when: true
|
||||
|
||||
- name: Clean up cloud-init temp directory
|
||||
- name: Create seed ISO volume in pool
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
virsh -c {{ vm_libvirt_uri }} vol-create-as default
|
||||
'{{ vm_seed_iso_name }}' 4M --format raw
|
||||
register: seed_vol_create
|
||||
failed_when:
|
||||
- seed_vol_create.rc != 0
|
||||
- "'exists already' not in seed_vol_create.stderr"
|
||||
changed_when: seed_vol_create.rc == 0
|
||||
|
||||
- name: Upload seed ISO to pool
|
||||
ansible.builtin.shell:
|
||||
cmd: >
|
||||
virsh -c {{ vm_libvirt_uri }} vol-upload
|
||||
--pool default '{{ vm_seed_iso_name }}' '{{ vm_seed_iso_tmp }}'
|
||||
changed_when: true
|
||||
|
||||
- name: Clean up cloud-init temp files
|
||||
ansible.builtin.file:
|
||||
path: "{{ cloud_init_dir.path }}"
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "{{ cloud_init_dir.path }}"
|
||||
- "{{ vm_seed_iso_tmp }}"
|
||||
|
||||
# ── VM definition ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -118,6 +169,7 @@
|
||||
register: dhcp_result
|
||||
failed_when:
|
||||
- dhcp_result.rc != 0
|
||||
- "'existing dhcp host entry' not in dhcp_result.stderr"
|
||||
- "'already exists' not in dhcp_result.stderr"
|
||||
changed_when: dhcp_result.rc == 0
|
||||
|
||||
@@ -140,7 +192,7 @@
|
||||
host: "{{ vm_ip }}"
|
||||
port: 22
|
||||
delay: 10
|
||||
timeout: 180
|
||||
timeout: 300
|
||||
state: started
|
||||
delegate_to: localhost
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<target type='virtio' name='org.qemu.guest_agent.0'/>
|
||||
</channel>
|
||||
|
||||
{% if vm_virtiofs_source and vm_virtiofs_tag %}
|
||||
{% if vm_virtiofs_source | default('') and vm_virtiofs_tag | default('') %}
|
||||
<!-- virtiofs host share -->
|
||||
<filesystem type='mount' accessmode='passthrough'>
|
||||
<driver type='virtiofs'/>
|
||||
@@ -93,6 +93,13 @@
|
||||
</filesystem>
|
||||
{% endif %}
|
||||
|
||||
<!-- virtiofs swarm-common share -->
|
||||
<filesystem type='mount' accessmode='passthrough'>
|
||||
<driver type='virtiofs'/>
|
||||
<source dir='/home/will/lab/swarm/swarm-common'/>
|
||||
<target dir='swarm-common'/>
|
||||
</filesystem>
|
||||
|
||||
<!-- TPM 2.0 -->
|
||||
<tpm model='tpm-crb'>
|
||||
<backend type='emulator' version='2.0'/>
|
||||
|
||||
Reference in New Issue
Block a user