refactor ♻️: Refactored the Debian VM template and cloning tasks for improved readability and maintainability.

Improved the structure and organization of the tasks to make it easier to understand and modify. Added comments and whitespace to enhance readability.
This commit is contained in:
2025-11-15 12:59:20 +01:00
parent e4dc0f3265
commit 0a1981194b
2 changed files with 101 additions and 48 deletions

View File

@@ -1,3 +1,4 @@
---
vm_id: 150 vm_id: 150
hostname: debian-template-base hostname: debian-template-base
@@ -6,48 +7,73 @@ cores: 4
bridge: vmbr0 bridge: vmbr0
storage: local-lvm storage: local-lvm
cpu_type: host cpu_type: host
mac_address: "DE:AD:BE:EF:44:55"
# Networking for template VM # Default MAC generator: avoids collisions
ip_mode: dhcp mac_base: "DE:AD:BE"
ipconfig0: "ip=dhcp" mac_suffix: "{{ '%02X:%02X' | format((vm_id // 256) % 256, vm_id % 256) }}"
mac_address: "{{ mac_base }}:{{ mac_suffix }}"
###############
# Networking
###############
ip_mode: dhcp # or static
ip_address: "192.168.1.60/24"
gateway: "192.168.1.1"
dns:
- "1.1.1.1"
- "8.8.8.8"
ipconfig0: "{{ 'ip=dhcp' if ip_mode == 'dhcp' else 'ip=' + ip_address + ',gw=' + gateway }}"
###############
# Packages
###############
packages: packages:
- qemu-guest-agent - qemu-guest-agent
- curl - curl
- htop - htop
###############
# Cloud-Init user + SSH + password
###############
ci_user: debian ci_user: debian
ci_password: "SecurePass123" ci_password: "SecurePass123" # consider vault
ssh_key_path: "~/.ssh/id_rsa.pub" ssh_key_path: "~/.ssh/id_rsa.pub"
timezone: "Europe/Berlin"
###############
# Optional Disk Resize
###############
resize_disk: true resize_disk: true
resize_size: "16G" resize_size: "16G"
###############
# GPU Options
###############
gpu_passthrough: false gpu_passthrough: false
gpu_device: "0000:01:00.0" gpu_device: "0000:01:00.0"
virtio_gpu: false virtio_gpu: false
###############
# TPM + Secure Boot
###############
enable_tpm: false enable_tpm: false
##########################
# NEW OPTIONS
##########################
# Convert VM to template? # Convert VM to template?
make_template: true make_template: true
# Create clones from the template? # Create clones from the template?
create_clones: true create_clones: true
# List of clones to generate # List of clones
clones: clones:
- id: 301 - id: 301
hostname: app01 hostname: app01
ip: "192.168.1.81/24" ip: "192.168.1.81/24"
gateway: "192.168.1.1" gateway: "192.168.1.1"
full: 1
- id: 302 - id: 302
hostname: app02 hostname: app02
ip: "192.168.1.82/24" ip: "192.168.1.82/24"
gateway: "192.168.1.1" gateway: "192.168.1.1"
full: 0

View File

@@ -1,7 +1,8 @@
--- ---
- name: Create a Debian VM template and optionally deploy clones - name: "Create a Debian VM template and optionally deploy clones"
hosts: localhost hosts: localhost
become: true become: true
gather_facts: false
tasks: tasks:
@@ -9,132 +10,158 @@
# 1. Ensure Debian GenericCloud Image Exists # 1. Ensure Debian GenericCloud Image Exists
################################################################## ##################################################################
- name: Check for Debian image - name: Check for Debian image
ansible.builtin.stat: stat:
path: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2" path: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2"
register: debian_img register: debian_img
- name: Download GenericCloud qcow2 - name: Download GenericCloud qcow2
ansible.builtin.get_url: get_url:
url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2" url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
dest: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2" dest: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2"
mode: "0644" mode: "0644"
when: not debian_img.stat.exists when: not debian_img.stat.exists
################################################################## ##################################################################
# 2. Create Base VM # 2. Create Base VM (if not exists)
################################################################## ##################################################################
- name: Check if VM exists
stat:
path: "/etc/pve/qemu-server/{{ vm_id }}.conf"
register: vm_conf
- name: Create VM - name: Create VM
ansible.builtin.command: > command: >
qm create {{ vm_id }} qm create {{ vm_id }}
--name {{ hostname }} --name {{ hostname }}
--memory {{ memory }} --memory {{ memory }}
--cores {{ cores }} --cores {{ cores }}
--cpu {{ cpu_type }} --cpu {{ cpu_type }}
--net0 virtio,bridge={{ bridge }},macaddr={{ mac_address }} --net0 virtio,bridge={{ bridge }},macaddr={{ mac_address }}
args: --agent 1
creates: "/etc/pve/qemu-server/{{ vm_id }}.conf" when: not vm_conf.stat.exists
################################################################## ##################################################################
# 3. Optional UEFI + Secure Boot + TPM 2.0 # 3. Optional UEFI + Secure Boot + TPM
################################################################## ##################################################################
- name: Enable UEFI + Secure Boot + TPM (optional) - name: Enable UEFI + TPM
ansible.builtin.command: > command: >
qm set {{ vm_id }} qm set {{ vm_id }}
--bios ovmf --bios ovmf
--efidisk0 {{ storage }}:1,pre-enrolled-keys=1 --efidisk0 {{ storage }}:0,pre-enrolled-keys=1
--tpmstate0 {{ storage }}:1,size=4M,version=v2.0 --tpmstate0 {{ storage }}:1,size=4M,version=v2.0
when: enable_tpm | default(false) when: enable_tpm | default(false)
################################################################## ##################################################################
# 4. Disk Import # 4. Disk Import & Attach
################################################################## ##################################################################
- name: Check if disk already exists
stat:
path: "/var/lib/vz/images/{{ vm_id }}/vm-{{ vm_id }}-disk-0.qcow2"
register: disk_exists
- name: Import qcow2 disk - name: Import qcow2 disk
ansible.builtin.command: > command: >
qm importdisk {{ vm_id }} qm importdisk {{ vm_id }}
/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2 /var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2
{{ storage }} {{ storage }}
when: not disk_exists.stat.exists
- name: Attach imported disk - name: Attach imported disk
ansible.builtin.command: > command: >
qm set {{ vm_id }} qm set {{ vm_id }}
--scsihw virtio-scsi-pci --scsihw virtio-scsi-pci
--scsi0 {{ storage }}:vm-{{ vm_id }}-disk-0 --scsi0 {{ storage }}:vm-{{ vm_id }}-disk-0
when: not disk_exists.stat.exists
- name: Enable serial console + boot disk
command: >
qm set {{ vm_id }}
--serial0 socket
--boot order=scsi0
################################################################## ##################################################################
# 5. Optional Disk Resize # 5. Optional Disk Resize
################################################################## ##################################################################
- name: Resize disk - name: Resize disk
ansible.builtin.command: > command: qm resize {{ vm_id }} scsi0 {{ resize_size }}
qm resize {{ vm_id }} scsi0 {{ resize_size }}
when: resize_disk | default(false) when: resize_disk | default(false)
################################################################## ##################################################################
# 6. Optional GPU Passthrough # 6. Optional GPU
################################################################## ##################################################################
- name: PCI GPU passthrough - name: PCI GPU passthrough
ansible.builtin.command: > command: qm set {{ vm_id }} --hostpci0 {{ gpu_device }}
qm set {{ vm_id }} --hostpci0 {{ gpu_device }}
when: gpu_passthrough | default(false) when: gpu_passthrough | default(false)
- name: VirtIO GPU passthrough - name: VirtIO GPU
ansible.builtin.command: > command: qm set {{ vm_id }} --vga virtio
qm set {{ vm_id }} --vga virtio
when: virtio_gpu | default(false) when: virtio_gpu | default(false)
################################################################## ##################################################################
# 7. Cloud-Init Templates # 7. Cloud-Init Snippets
################################################################## ##################################################################
- name: Create Cloud-Init vendor-data - name: Create Cloud-Init vendor-data
ansible.builtin.template: template:
src: cloudinit_vendor.yaml.j2 src: cloudinit_vendor.yaml.j2
dest: "/var/lib/vz/snippets/{{ vm_id }}-vendor.yaml" dest: "/var/lib/vz/snippets/{{ vm_id }}-vendor.yaml"
- name: Create Cloud-Init user-data - name: Create Cloud-Init user-data
ansible.builtin.template: template:
src: cloudinit_userdata.yaml.j2 src: cloudinit_userdata.yaml.j2
dest: "/var/lib/vz/snippets/{{ vm_id }}-user.yaml" dest: "/var/lib/vz/snippets/{{ vm_id }}-user.yaml"
- name: Write SSH key snippet
copy:
content: "{{ lookup('file', ssh_key_path) }}"
dest: "/var/lib/vz/snippets/{{ vm_id }}-sshkey.pub"
################################################################## ##################################################################
# 8. Apply Cloud-Init # 8. Apply Cloud-Init
################################################################## ##################################################################
- name: Apply Cloud-Init config - name: Apply Cloud-Init config
ansible.builtin.command: > command: >
qm set {{ vm_id }} qm set {{ vm_id }}
--ciuser {{ ci_user }} --ciuser {{ ci_user }}
--cipassword '{{ ci_password }}' --sshkeys local:snippets/{{ vm_id }}-sshkey.pub
--sshkeys "{{ lookup('file', ssh_key_path) }}"
--hostname {{ hostname }} --hostname {{ hostname }}
--citype nocloud --citype nocloud
--cicustom "user=local:snippets/{{ vm_id }}-user.yaml,vendor=local:snippets/{{ vm_id }}-vendor.yaml" --cicustom "user=local:snippets/{{ vm_id }}-user.yaml,vendor=local:snippets/{{ vm_id }}-vendor.yaml"
--ipconfig0 {{ ipconfig0 }} --ipconfig0 {{ ipconfig0 }}
################################################################## ##################################################################
# 9. Optional Convert Base VM to Template # 9. Convert VM to Template
################################################################## ##################################################################
- name: Convert VM to template - name: Convert VM to template
ansible.builtin.command: qm template {{ vm_id }} command: qm template {{ vm_id }}
when: make_template | default(false) when: make_template | default(false)
args:
creates: "/etc/pve/qemu-server/{{ vm_id }}.conf.lock"
################################################################## ##################################################################
# 10. Optionally Create Cloud-Init Clones from Template # 10. Create Clones (if enabled)
################################################################## ##################################################################
- name: Create clones from template (optional) - name: Create clones from template
when: create_clones | default(false) when: create_clones | default(false)
loop: "{{ clones }}" loop: "{{ clones }}"
loop_control: loop_control:
loop_var: clone loop_var: clone
block: block:
- name: Check if clone exists
stat:
path: "/etc/pve/qemu-server/{{ clone.id }}.conf"
register: clone_conf
- name: Clone VM from template - name: Clone VM from template
ansible.builtin.command: > command: >
qm clone {{ vm_id }} {{ clone.id }} --name {{ clone.hostname }} qm clone {{ vm_id }} {{ clone.id }} --name {{ clone.hostname }} --full {{ clone.full }}
when: not clone_conf.stat.exists
- name: Apply cloud-init settings for clone - name: Apply Cloud-Init settings for clone
ansible.builtin.command: > command: >
qm set {{ clone.id }} qm set {{ clone.id }}
--hostname {{ clone.hostname }} --hostname {{ clone.hostname }}
--ipconfig0 ip={{ clone.ip }},gw={{ clone.gateway }} --ipconfig0 ip={{ clone.ip }},gw={{ clone.gateway }}
- name: Start clone VM - name: Start clone VM
ansible.builtin.command: qm start {{ clone.id }} command: qm start {{ clone.id }}