refactor(virt): adopt module_defaults for hypervisor credentials

This commit is contained in:
2026-02-20 21:16:33 +01:00
parent 5ca1c7f570
commit ba6be037ac
5 changed files with 273 additions and 261 deletions

View File

@@ -3,12 +3,20 @@
when: hypervisor_type == "proxmox"
delegate_to: localhost
become: false
module_defaults:
community.proxmox.proxmox_disk:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
community.proxmox.proxmox_kvm:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
node: "{{ hypervisor_cfg.host }}"
no_log: true
block:
- name: Cleanup Setup Disks
community.proxmox.proxmox_disk:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
name: "{{ hostname }}"
vmid: "{{ system_cfg.id }}"
disk: "{{ item }}"
@@ -17,14 +25,8 @@
- ide0
- ide2
failed_when: false
no_log: true
- name: Start the VM
community.proxmox.proxmox_kvm:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
node: "{{ hypervisor_cfg.host }}"
vmid: "{{ system_cfg.id }}"
state: restarted
no_log: true

View File

@@ -3,14 +3,23 @@
when: hypervisor_type == "vmware"
delegate_to: localhost
become: false
module_defaults:
community.vmware.vmware_guest:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
vmware.vmware.vm_powerstate:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
no_log: true
block:
- name: Remove CD-ROM from VM in vCenter
community.vmware.vmware_guest:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
name: "{{ hostname }}"
cdrom: >-
{{
@@ -40,15 +49,8 @@
)
}}
failed_when: false
no_log: true
- name: Start VM in vCenter
vmware.vmware.vm_powerstate:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
name: "{{ hostname }}"
state: powered-on
no_log: true

View File

@@ -33,70 +33,75 @@
Please choose a different hostname or remove the existing VM manually before proceeding.
quiet: true
- name: Check if VM already exists on Proxmox
- name: Check VM existence on Proxmox
when: hypervisor_type == "proxmox"
delegate_to: localhost
become: false
community.proxmox.proxmox_vm_info:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
node: "{{ hypervisor_cfg.host }}"
vmid: "{{ system_cfg.id }}"
name: "{{ hostname }}"
type: qemu
register: system_check_proxmox_check_result
changed_when: false
module_defaults:
community.proxmox.proxmox_vm_info:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
no_log: true
block:
- name: Query Proxmox for existing VM
community.proxmox.proxmox_vm_info:
node: "{{ hypervisor_cfg.host }}"
vmid: "{{ system_cfg.id }}"
name: "{{ hostname }}"
type: qemu
register: system_check_proxmox_check_result
changed_when: false
- name: Abort if VM already exists on Proxmox
when: hypervisor_type == "proxmox"
ansible.builtin.assert:
that:
- system_check_proxmox_check_result.proxmox_vms | default([]) | length == 0
fail_msg: |
VM {{ hostname }} (ID: {{ system_cfg.id }}) already exists on Proxmox hypervisor.
To avoid data loss, the playbook will not overwrite or delete existing VMs.
Please choose a different hostname or VM ID, or remove the existing VM manually before proceeding.
quiet: true
- name: Abort if VM already exists on Proxmox
ansible.builtin.assert:
that:
- system_check_proxmox_check_result.proxmox_vms | default([]) | length == 0
fail_msg: |
VM {{ hostname }} (ID: {{ system_cfg.id }}) already exists on Proxmox hypervisor.
To avoid data loss, the playbook will not overwrite or delete existing VMs.
Please choose a different hostname or VM ID, or remove the existing VM manually before proceeding.
quiet: true
- name: Check if VM already exists in vCenter
- name: Check VM existence in vCenter
when: hypervisor_type == "vmware"
delegate_to: localhost
community.vmware.vmware_guest_info:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
name: "{{ hostname }}"
folder: "{{ system_cfg.path if system_cfg.path | length > 0 else omit }}"
register: system_check_vmware_check_result
failed_when: false
changed_when: false
module_defaults:
community.vmware.vmware_guest_info:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
no_log: true
block:
- name: Query vCenter for existing VM
community.vmware.vmware_guest_info:
datacenter: "{{ hypervisor_cfg.datacenter }}"
name: "{{ hostname }}"
folder: "{{ system_cfg.path if system_cfg.path | length > 0 else omit }}"
register: system_check_vmware_check_result
failed_when: false
changed_when: false
- name: Fail if vCenter lookup failed unexpectedly
when: hypervisor_type == "vmware"
ansible.builtin.assert:
that:
- not system_check_vmware_check_result.failed
or (system_check_vmware_check_result.msg is search('non-existing VM'))
fail_msg: |
Unable to verify VM existence in vCenter.
{{ system_check_vmware_check_result.msg | default('Unknown error') }}
quiet: true
- name: Fail if vCenter lookup failed unexpectedly
ansible.builtin.assert:
that:
- not system_check_vmware_check_result.failed
or (system_check_vmware_check_result.msg is search('non-existing VM'))
fail_msg: |
Unable to verify VM existence in vCenter.
{{ system_check_vmware_check_result.msg | default('Unknown error') }}
quiet: true
- name: Abort if VM already exists in vCenter
when: hypervisor_type == "vmware"
ansible.builtin.assert:
that:
- system_check_vmware_check_result.instance is not defined
fail_msg: |
VM {{ hostname }} already exists in vCenter.
To avoid data loss, the playbook will not overwrite or delete existing VMs.
Please choose a different hostname or remove the existing VM manually before proceeding.
quiet: true
- name: Abort if VM already exists in vCenter
ansible.builtin.assert:
that:
- system_check_vmware_check_result.instance is not defined
fail_msg: |
VM {{ hostname }} already exists in vCenter.
To avoid data loss, the playbook will not overwrite or delete existing VMs.
Please choose a different hostname or remove the existing VM manually before proceeding.
quiet: true
- name: Check if VM already exists on Xen
when: hypervisor_type == "xen"

View File

@@ -1,95 +1,94 @@
---
- name: Deploy VM on Proxmox
delegate_to: localhost
vars:
virtualization_proxmox_scsi: >-
{%- set out = {} -%}
{%- for disk in system_cfg.disks -%}
{%- set _ = out.update({ 'scsi' ~ loop.index0: hypervisor_cfg.storage ~ ':' ~ (disk.size | int) }) -%}
{%- endfor -%}
{{ out }}
virtualization_proxmox_net: >-
{%- set out = {} -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- set val = 'virtio,bridge=' ~ iface.bridge -%}
{%- if iface.vlan | default('') | string | length > 0 -%}
{%- set val = val ~ ',tag=' ~ iface.vlan -%}
{%- endif -%}
{%- set _ = out.update({ 'net' ~ loop.index0: val }) -%}
{%- endfor -%}
{{ out }}
virtualization_proxmox_ipconfig: >-
{%- set out = {} -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- if iface.ip | default('') | string | length > 0 -%}
{%- set val = 'ip=' ~ iface.ip ~ '/' ~ iface.prefix
~ ((',gw=' ~ iface.gateway) if (iface.gateway | default('') | length > 0) else '') -%}
{%- else -%}
{%- set val = 'ip=dhcp' -%}
{%- endif -%}
{%- set _ = out.update({ 'ipconfig' ~ loop.index0: val }) -%}
{%- endfor -%}
{{ out }}
community.proxmox.proxmox_kvm:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
ciuser: "{{ system_cfg.users[0].name }}"
cipassword: "{{ system_cfg.users[0].password }}"
ciupgrade: false
node: "{{ hypervisor_cfg.host }}"
vmid: "{{ system_cfg.id }}"
name: "{{ hostname }}"
cpu: host
cores: "{{ system_cfg.cpus }}"
memory: "{{ system_cfg.memory }}"
balloon: "{{ system_cfg.balloon if system_cfg.balloon is defined and system_cfg.balloon | int > 0 else omit }}"
numa_enabled: true
hotplug: network,disk
update: "{{ virtualization_tpm2_enabled | bool }}"
update_unsafe: "{{ virtualization_tpm2_enabled | bool }}"
bios: ovmf
machine: "{{ 'q35' if virtualization_tpm2_enabled | bool else omit }}"
boot: ac
scsihw: virtio-scsi-single
scsi: "{{ virtualization_proxmox_scsi }}"
efidisk0:
efitype: 4m
format: raw
pre_enrolled_keys: false
storage: "{{ hypervisor_cfg.storage }}"
tpmstate0: >-
{{
{'storage': hypervisor_cfg.storage, 'version': '2.0'}
if virtualization_tpm2_enabled | bool
else omit
}}
ide:
ide0: "{{ boot_iso }},media=cdrom"
ide1: "{{ rhel_iso + ',media=cdrom' if rhel_iso is defined and rhel_iso | length > 0 else omit }}"
ide2: "{{ hypervisor_cfg.storage }}:cloudinit"
net: "{{ virtualization_proxmox_net }}"
ipconfig: "{{ virtualization_proxmox_ipconfig }}"
nameservers: "{{ system_cfg.network.dns.servers if system_cfg.network.dns.servers | length else omit }}"
searchdomains: "{{ system_cfg.network.dns.search if system_cfg.network.dns.search | length else omit }}"
onboot: true
state: present
no_log: true
module_defaults:
community.proxmox.proxmox_kvm:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
node: "{{ hypervisor_cfg.host }}"
block:
- name: Create VM on Proxmox
vars:
virtualization_proxmox_scsi: >-
{%- set out = {} -%}
{%- for disk in system_cfg.disks -%}
{%- set _ = out.update({ 'scsi' ~ loop.index0: hypervisor_cfg.storage ~ ':' ~ (disk.size | int) }) -%}
{%- endfor -%}
{{ out }}
virtualization_proxmox_net: >-
{%- set out = {} -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- set val = 'virtio,bridge=' ~ iface.bridge -%}
{%- if iface.vlan | default('') | string | length > 0 -%}
{%- set val = val ~ ',tag=' ~ iface.vlan -%}
{%- endif -%}
{%- set _ = out.update({ 'net' ~ loop.index0: val }) -%}
{%- endfor -%}
{{ out }}
virtualization_proxmox_ipconfig: >-
{%- set out = {} -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- if iface.ip | default('') | string | length > 0 -%}
{%- set val = 'ip=' ~ iface.ip ~ '/' ~ iface.prefix
~ ((',gw=' ~ iface.gateway) if (iface.gateway | default('') | length > 0) else '') -%}
{%- else -%}
{%- set val = 'ip=dhcp' -%}
{%- endif -%}
{%- set _ = out.update({ 'ipconfig' ~ loop.index0: val }) -%}
{%- endfor -%}
{{ out }}
community.proxmox.proxmox_kvm:
ciuser: "{{ system_cfg.users[0].name }}"
cipassword: "{{ system_cfg.users[0].password }}"
ciupgrade: false
vmid: "{{ system_cfg.id }}"
name: "{{ hostname }}"
cpu: host
cores: "{{ system_cfg.cpus }}"
memory: "{{ system_cfg.memory }}"
balloon: "{{ system_cfg.balloon if system_cfg.balloon is defined and system_cfg.balloon | int > 0 else omit }}"
numa_enabled: true
hotplug: network,disk
update: "{{ virtualization_tpm2_enabled | bool }}"
update_unsafe: "{{ virtualization_tpm2_enabled | bool }}"
bios: ovmf
machine: "{{ 'q35' if virtualization_tpm2_enabled | bool else omit }}"
boot: ac
scsihw: virtio-scsi-single
scsi: "{{ virtualization_proxmox_scsi }}"
efidisk0:
efitype: 4m
format: raw
pre_enrolled_keys: false
storage: "{{ hypervisor_cfg.storage }}"
tpmstate0: >-
{{
{'storage': hypervisor_cfg.storage, 'version': '2.0'}
if virtualization_tpm2_enabled | bool
else omit
}}
ide:
ide0: "{{ boot_iso }},media=cdrom"
ide1: "{{ rhel_iso + ',media=cdrom' if rhel_iso is defined and rhel_iso | length > 0 else omit }}"
ide2: "{{ hypervisor_cfg.storage }}:cloudinit"
net: "{{ virtualization_proxmox_net }}"
ipconfig: "{{ virtualization_proxmox_ipconfig }}"
nameservers: "{{ system_cfg.network.dns.servers if system_cfg.network.dns.servers | length else omit }}"
searchdomains: "{{ system_cfg.network.dns.search if system_cfg.network.dns.search | length else omit }}"
onboot: true
state: present
no_log: true
- name: Start VM on Proxmox
delegate_to: localhost
community.proxmox.proxmox_kvm:
api_host: "{{ hypervisor_cfg.url }}"
api_user: "{{ hypervisor_cfg.username }}"
api_password: "{{ hypervisor_cfg.password }}"
node: "{{ hypervisor_cfg.host }}"
name: "{{ hostname }}"
vmid: "{{ system_cfg.id }}"
state: started
no_log: true
register: virtualization_proxmox_start_result
- name: Start VM on Proxmox
community.proxmox.proxmox_kvm:
name: "{{ hostname }}"
vmid: "{{ system_cfg.id }}"
state: started
no_log: true
register: virtualization_proxmox_start_result
- name: Set VM created fact
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when: virtualization_proxmox_start_result is defined and virtualization_proxmox_start_result.changed | bool
- name: Set VM created fact
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when: virtualization_proxmox_start_result is defined and virtualization_proxmox_start_result.changed | bool

View File

@@ -11,105 +11,109 @@
loop_control:
label: "{{ item | to_json }}"
# community.vmware: full-featured guest management
- name: Create VM in vCenter
- name: Deploy VM in vCenter
delegate_to: localhost
vars:
virtualization_vmware_networks: >-
{%- set ns = namespace(out=[]) -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- set entry = {'name': iface.bridge, 'type': 'dhcp'} -%}
{%- if (iface.vlan | default('') | string | length) > 0 -%}
{%- set entry = entry | combine({'vlan': iface.vlan | int}) -%}
{%- endif -%}
{%- set ns.out = ns.out + [entry] -%}
{%- endfor -%}
{{ ns.out }}
community.vmware.vmware_guest:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
cluster: "{{ hypervisor_cfg.cluster }}"
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
name: "{{ hostname }}"
# Generic guest ID — VMware auto-detects OS post-install
guest_id: otherLinux64Guest
annotation: |
{{ note if note is defined else '' }}
state: "{{ 'poweredoff' if virtualization_tpm2_enabled | bool else 'poweredon' }}"
disk: "{{ virtualization_vmware_disks }}"
hardware:
memory_mb: "{{ system_cfg.memory }}"
num_cpus: "{{ system_cfg.cpus }}"
boot_firmware: efi
secure_boot: false
cdrom: >-
{{
[ {
"controller_number": 0,
"unit_number": 0,
"controller_type": "sata",
"state": "present",
"type": "iso",
"iso_path": boot_iso
} ]
+
( [ {
"controller_number": 0,
"unit_number": 1,
"controller_type": "sata",
"state": "present",
"type": "iso",
"iso_path": rhel_iso
} ] if rhel_iso is defined and rhel_iso | length > 0 else [] )
}}
networks: "{{ virtualization_vmware_networks }}"
no_log: true
register: virtualization_vmware_create_result
module_defaults:
community.vmware.vmware_guest:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
community.vmware.vmware_guest_tpm:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
vmware.vmware.vm_powerstate:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
block:
# community.vmware: full-featured guest management
- name: Create VM in vCenter
vars:
virtualization_vmware_networks: >-
{%- set ns = namespace(out=[]) -%}
{%- for iface in system_cfg.network.interfaces -%}
{%- set entry = {'name': iface.bridge, 'type': 'dhcp'} -%}
{%- if (iface.vlan | default('') | string | length) > 0 -%}
{%- set entry = entry | combine({'vlan': iface.vlan | int}) -%}
{%- endif -%}
{%- set ns.out = ns.out + [entry] -%}
{%- endfor -%}
{{ ns.out }}
community.vmware.vmware_guest:
cluster: "{{ hypervisor_cfg.cluster }}"
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
name: "{{ hostname }}"
# Generic guest ID — VMware auto-detects OS post-install
guest_id: otherLinux64Guest
annotation: |
{{ note if note is defined else '' }}
state: "{{ 'poweredoff' if virtualization_tpm2_enabled | bool else 'poweredon' }}"
disk: "{{ virtualization_vmware_disks }}"
hardware:
memory_mb: "{{ system_cfg.memory }}"
num_cpus: "{{ system_cfg.cpus }}"
boot_firmware: efi
secure_boot: false
cdrom: >-
{{
[ {
"controller_number": 0,
"unit_number": 0,
"controller_type": "sata",
"state": "present",
"type": "iso",
"iso_path": boot_iso
} ]
+
( [ {
"controller_number": 0,
"unit_number": 1,
"controller_type": "sata",
"state": "present",
"type": "iso",
"iso_path": rhel_iso
} ] if rhel_iso is defined and rhel_iso | length > 0 else [] )
}}
networks: "{{ virtualization_vmware_networks }}"
no_log: true
register: virtualization_vmware_create_result
- name: Set VM created fact when VM was powered on during creation
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when:
- virtualization_vmware_create_result is defined
- not virtualization_tpm2_enabled | bool
- virtualization_vmware_create_result.changed | bool
- name: Set VM created fact when VM was powered on during creation
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when:
- virtualization_vmware_create_result is defined
- not virtualization_tpm2_enabled | bool
- virtualization_vmware_create_result.changed | bool
- name: Ensure vTPM2 is enabled when required
when: virtualization_tpm2_enabled | bool
delegate_to: localhost
community.vmware.vmware_guest_tpm:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
name: "{{ hostname }}"
state: present
no_log: true
- name: Ensure vTPM2 is enabled when required
when: virtualization_tpm2_enabled | bool
community.vmware.vmware_guest_tpm:
folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}"
name: "{{ hostname }}"
state: present
no_log: true
# vmware.vmware: modern collection for power operations
- name: Start VM in vCenter
when: virtualization_tpm2_enabled | bool
delegate_to: localhost
vmware.vmware.vm_powerstate:
hostname: "{{ hypervisor_cfg.url }}"
username: "{{ hypervisor_cfg.username }}"
password: "{{ hypervisor_cfg.password }}"
validate_certs: "{{ hypervisor_cfg.certs | bool }}"
datacenter: "{{ hypervisor_cfg.datacenter }}"
name: "{{ hostname }}"
state: powered-on
no_log: true
register: virtualization_vmware_start_result
# vmware.vmware: modern collection for power operations
- name: Start VM in vCenter
when: virtualization_tpm2_enabled | bool
vmware.vmware.vm_powerstate:
name: "{{ hostname }}"
state: powered-on
no_log: true
register: virtualization_vmware_start_result
- name: Set VM created fact when VM was started separately (TPM2 case)
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when:
- virtualization_tpm2_enabled | bool
- virtualization_vmware_start_result is defined
- virtualization_vmware_start_result.changed | bool
- name: Set VM created fact when VM was started separately (TPM2 case)
ansible.builtin.set_fact:
virtualization_vm_created_in_run: true
when:
- virtualization_tpm2_enabled | bool
- virtualization_vmware_start_result is defined
- virtualization_vmware_start_result.changed | bool