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:
@@ -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
|
||||||
|
|||||||
101
tasks/main.yml
101
tasks/main.yml
@@ -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 }}
|
||||||
|
|||||||
Reference in New Issue
Block a user