From 7aa5c9dc1becd685e5319063bcf27f563bdba44b Mon Sep 17 00:00:00 2001 From: Jose Date: Sat, 15 Nov 2025 09:51:38 +0100 Subject: [PATCH] =?UTF-8?q?feat=20=E2=9C=A8:=20Added=20new=20feature=20to?= =?UTF-8?q?=20generate=20Debian=20VM=20templates=20and=20deploy=20clones?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces a new feature that allows users to create Debian VM templates and deploy clones. The feature includes options for customizing the template, such as making it a template or creating clones from it. --- defaults/main.yml | 53 ++++++++++ tasks/main.yml | 140 +++++++++++++++++++++++++++ templates/cloudinit_userdata.yaml.j2 | 24 +++++ templates/cloudinit_vendor.yaml.j2 | 14 +++ 4 files changed, 231 insertions(+) create mode 100644 defaults/main.yml create mode 100644 tasks/main.yml create mode 100644 templates/cloudinit_userdata.yaml.j2 create mode 100644 templates/cloudinit_vendor.yaml.j2 diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..904cbd7 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,53 @@ +vm_id: 150 +hostname: debian-template-base + +memory: 4096 +cores: 4 +bridge: vmbr0 +storage: local-lvm +cpu_type: host +mac_address: "DE:AD:BE:EF:44:55" + +# Networking for template VM +ip_mode: dhcp +ipconfig0: "ip=dhcp" + +packages: + - qemu-guest-agent + - curl + - htop + +ci_user: debian +ci_password: "SecurePass123" +ssh_key_path: "~/.ssh/id_rsa.pub" + +resize_disk: true +resize_size: "16G" + +gpu_passthrough: false +gpu_device: "0000:01:00.0" +virtio_gpu: false + +enable_tpm: false + +########################## +# NEW OPTIONS +########################## + +# Convert VM to template? +make_template: true + +# Create clones from the template? +create_clones: true + +# List of clones to generate +clones: + - id: 301 + hostname: app01 + ip: "192.168.1.81/24" + gateway: "192.168.1.1" + + - id: 302 + hostname: app02 + ip: "192.168.1.82/24" + gateway: "192.168.1.1" diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..3171061 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,140 @@ +--- +- name: Create a Debian VM template and optionally deploy clones + hosts: localhost + become: true + + tasks: + + ################################################################## + # 1. Ensure Debian GenericCloud Image Exists + ################################################################## + - name: Check for Debian image + ansible.builtin.stat: + path: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2" + register: debian_img + + - name: Download GenericCloud qcow2 + ansible.builtin.get_url: + url: "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2" + dest: "/var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2" + mode: "0644" + when: not debian_img.stat.exists + + ################################################################## + # 2. Create Base VM + ################################################################## + - name: Create VM + ansible.builtin.command: > + qm create {{ vm_id }} + --name {{ hostname }} + --memory {{ memory }} + --cores {{ cores }} + --cpu {{ cpu_type }} + --net0 virtio,bridge={{ bridge }},macaddr={{ mac_address }} + args: + creates: "/etc/pve/qemu-server/{{ vm_id }}.conf" + + ################################################################## + # 3. Optional UEFI + Secure Boot + TPM 2.0 + ################################################################## + - name: Enable UEFI + Secure Boot + TPM (optional) + ansible.builtin.command: > + qm set {{ vm_id }} + --bios ovmf + --efidisk0 {{ storage }}:1,pre-enrolled-keys=1 + --tpmstate0 {{ storage }}:1,size=4M,version=v2.0 + when: enable_tpm | default(false) + + ################################################################## + # 4. Disk Import + ################################################################## + - name: Import qcow2 disk + ansible.builtin.command: > + qm importdisk {{ vm_id }} + /var/lib/vz/template/qemu/debian-genericcloud-amd64.qcow2 + {{ storage }} + + - name: Attach imported disk + ansible.builtin.command: > + qm set {{ vm_id }} + --scsihw virtio-scsi-pci + --scsi0 {{ storage }}:vm-{{ vm_id }}-disk-0 + + ################################################################## + # 5. Optional Disk Resize + ################################################################## + - name: Resize disk + ansible.builtin.command: > + qm resize {{ vm_id }} scsi0 {{ resize_size }} + when: resize_disk | default(false) + + ################################################################## + # 6. Optional GPU Passthrough + ################################################################## + - name: PCI GPU passthrough + ansible.builtin.command: > + qm set {{ vm_id }} --hostpci0 {{ gpu_device }} + when: gpu_passthrough | default(false) + + - name: VirtIO GPU passthrough + ansible.builtin.command: > + qm set {{ vm_id }} --vga virtio + when: virtio_gpu | default(false) + + ################################################################## + # 7. Cloud-Init Templates + ################################################################## + - name: Create Cloud-Init vendor-data + ansible.builtin.template: + src: cloudinit_vendor.yaml.j2 + dest: "/var/lib/vz/snippets/{{ vm_id }}-vendor.yaml" + + - name: Create Cloud-Init user-data + ansible.builtin.template: + src: cloudinit_userdata.yaml.j2 + dest: "/var/lib/vz/snippets/{{ vm_id }}-user.yaml" + + ################################################################## + # 8. Apply Cloud-Init + ################################################################## + - name: Apply Cloud-Init config + ansible.builtin.command: > + qm set {{ vm_id }} + --ciuser {{ ci_user }} + --cipassword '{{ ci_password }}' + --sshkeys "{{ lookup('file', ssh_key_path) }}" + --hostname {{ hostname }} + --citype nocloud + --cicustom "user=local:snippets/{{ vm_id }}-user.yaml,vendor=local:snippets/{{ vm_id }}-vendor.yaml" + --ipconfig0 {{ ipconfig0 }} + + ################################################################## + # 9. Optional Convert Base VM to Template + ################################################################## + - name: Convert VM to template + ansible.builtin.command: qm template {{ vm_id }} + when: make_template | default(false) + + ################################################################## + # 10. Optionally Create Cloud-Init Clones from Template + ################################################################## + - name: Create clones from template (optional) + when: create_clones | default(false) + loop: "{{ clones }}" + loop_control: + loop_var: clone + + block: + + - name: Clone VM from template + ansible.builtin.command: > + qm clone {{ vm_id }} {{ clone.id }} --name {{ clone.hostname }} + + - name: Apply cloud-init settings for clone + ansible.builtin.command: > + qm set {{ clone.id }} + --hostname {{ clone.hostname }} + --ipconfig0 ip={{ clone.ip }},gw={{ clone.gateway }} + + - name: Start clone VM + ansible.builtin.command: qm start {{ clone.id }} diff --git a/templates/cloudinit_userdata.yaml.j2 b/templates/cloudinit_userdata.yaml.j2 new file mode 100644 index 0000000..4950d3a --- /dev/null +++ b/templates/cloudinit_userdata.yaml.j2 @@ -0,0 +1,24 @@ +#cloud-config + +users: + - name: {{ ci_user }} + sudo: ALL=(ALL) NOPASSWD:ALL + groups: users, admin, sudo + shell: /bin/bash + lock_passwd: false + passwd: {{ ci_password | password_hash('sha512') }} + ssh_authorized_keys: + - {{ lookup('file', ssh_key_path) }} + +chpasswd: + expire: false + +ssh_pwauth: true + +timezone: "{{ timezone | default('UTC') }}" + +package_update: true +package_upgrade: false + +runcmd: + - echo "Cloud-init user-data executed for {{ hostname }}" diff --git a/templates/cloudinit_vendor.yaml.j2 b/templates/cloudinit_vendor.yaml.j2 new file mode 100644 index 0000000..a4232c2 --- /dev/null +++ b/templates/cloudinit_vendor.yaml.j2 @@ -0,0 +1,14 @@ +#cloud-config +packages: +{% for pkg in packages %} + - {{ pkg }} +{% endfor %} + +{% if dns %} +manage_resolve_conf: true +resolv_conf: + nameservers: + {% for ns in dns %} + - {{ ns }} + {% endfor %} +{% endif %}