diff --git a/README.md b/README.md index 303a561..9ae83e4 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ all: username: root@pam password: !vault | $ANSIBLE_VAULT... - host: pve01 + node: pve01 storage: local-lvm children: @@ -268,7 +268,7 @@ The first user's credentials are prompted interactively via `vars_prompt` unless | `url` | string | -- | API host (Proxmox/VMware) | | `username` | string | -- | API username | | `password` | string | -- | API password | -| `host` | string | -- | Proxmox node name | +| `node` | string | -- | Target compute node (Proxmox node / VMware ESXi host; mutually exclusive with `cluster` on VMware) | | `storage` | string | -- | Storage identifier (Proxmox/VMware) | | `datacenter` | string | -- | VMware datacenter | | `cluster` | string | -- | VMware cluster | diff --git a/inventory_example.yml b/inventory_example.yml index c17a9d2..944cd4a 100644 --- a/inventory_example.yml +++ b/inventory_example.yml @@ -6,7 +6,7 @@ all: url: "pve01.example.com" username: "root@pam" password: "CHANGE_ME" - host: "pve01" + node: "pve01" storage: "local-lvm" boot_iso: "local:iso/archlinux-x86_64.iso" children: diff --git a/roles/global_defaults/defaults/main.yml b/roles/global_defaults/defaults/main.yml index 2cb2cf8..317001d 100644 --- a/roles/global_defaults/defaults/main.yml +++ b/roles/global_defaults/defaults/main.yml @@ -46,7 +46,7 @@ hypervisor_defaults: url: "" username: "" password: "" - host: "" + node: "" storage: "" datacenter: "" cluster: "" @@ -136,10 +136,10 @@ system_defaults: # All virtual types additionally require network bridge or interfaces. hypervisor_required_fields: proxmox: - hypervisor: [url, username, password, host, storage] + hypervisor: [url, username, password, node, storage] system: [id] vmware: - hypervisor: [url, username, password, datacenter, cluster, storage] + hypervisor: [url, username, password, datacenter, storage] system: [] xen: hypervisor: [] diff --git a/roles/global_defaults/tasks/_normalize_system.yml b/roles/global_defaults/tasks/_normalize_system.yml index b8e12e6..b96f076 100644 --- a/roles/global_defaults/tasks/_normalize_system.yml +++ b/roles/global_defaults/tasks/_normalize_system.yml @@ -77,7 +77,12 @@ if (system_raw.mirror | default('') | string | trim | length) > 0 else _mirror_defaults[system_raw.os | default('') | string | lower] | default('') }} - path: "{{ system_raw.path | default('') | string }}" + path: >- + {{ + (system_raw.path | default('') | string) + if (system_raw.path | default('') | string | length > 0) + else (hypervisor_cfg.folder | default('') | string) + }} packages: >- {{ ( diff --git a/roles/global_defaults/tasks/main.yml b/roles/global_defaults/tasks/main.yml index 1bcf33f..bba32b0 100644 --- a/roles/global_defaults/tasks/main.yml +++ b/roles/global_defaults/tasks/main.yml @@ -32,12 +32,19 @@ api_host: "{{ hypervisor_cfg.url }}" api_user: "{{ hypervisor_cfg.username }}" api_password: "{{ hypervisor_cfg.password }}" - node: "{{ hypervisor_cfg.host }}" + node: "{{ hypervisor_cfg.node }}" no_log: true - name: Normalize system inputs ansible.builtin.include_tasks: system.yml +- name: Inherit folder from hypervisor when system path is empty + when: + - system_cfg.path | default('') | string | length == 0 + - hypervisor_cfg.folder | default('') | string | length > 0 + ansible.builtin.set_fact: + system_cfg: "{{ system_cfg | combine({'path': hypervisor_cfg.folder | string}, recursive=True) }}" + - name: Validate variables ansible.builtin.include_tasks: validation.yml @@ -85,3 +92,12 @@ when: hypervisor_type == "vmware" ansible.builtin.set_fact: ansible_connection: vmware_tools + ansible_vmware_host: "{{ hypervisor_cfg.url }}" + ansible_vmware_port: 443 + ansible_vmware_user: "{{ hypervisor_cfg.username }}" + ansible_vmware_password: "{{ hypervisor_cfg.password }}" + ansible_vmware_guest_path: "/{{ hypervisor_cfg.datacenter }}/vm{{ system_cfg.path }}/{{ hostname }}" + ansible_vmware_validate_certs: "{{ hypervisor_cfg.certs | bool }}" + ansible_vmware_tools_user: root + ansible_vmware_tools_password: "{{ system_cfg.root.password }}" + no_log: true diff --git a/roles/global_defaults/tasks/validation.yml b/roles/global_defaults/tasks/validation.yml index 5994378..eda9916 100644 --- a/roles/global_defaults/tasks/validation.yml +++ b/roles/global_defaults/tasks/validation.yml @@ -166,6 +166,23 @@ label: "hypervisor.{{ item }}" no_log: true +- name: Validate VMware placement (cluster or node required, mutually exclusive) + when: + - system_cfg.type == "virtual" + - hypervisor_type == "vmware" + ansible.builtin.assert: + that: + - >- + (hypervisor_cfg.cluster | default('') | string | length > 0) + or (hypervisor_cfg.node | default('') | string | length > 0) + - >- + (hypervisor_cfg.cluster | default('') | string | length == 0) + or (hypervisor_cfg.node | default('') | string | length == 0) + fail_msg: >- + VMware requires either hypervisor.cluster or hypervisor.node (mutually exclusive). + cluster targets a vSphere cluster; node targets a specific ESXi host. + quiet: true + - name: Validate hypervisor-specific required system fields when: - system_cfg.type == "virtual" @@ -293,8 +310,8 @@ system_disk_mounts: >- {{ (system_cfg.disks | default([])) - | map(attribute='mount') - | map(attribute='path') + | map(attribute='mount', default={}) + | map(attribute='path', default='') | map('string') | map('trim') | reject('equalto', '') diff --git a/roles/system_check/tasks/main.yml b/roles/system_check/tasks/main.yml index 5b205e5..b55b107 100644 --- a/roles/system_check/tasks/main.yml +++ b/roles/system_check/tasks/main.yml @@ -45,7 +45,7 @@ block: - name: Query Proxmox for existing VM community.proxmox.proxmox_vm_info: - node: "{{ hypervisor_cfg.host }}" + node: "{{ hypervisor_cfg.node }}" vmid: "{{ system_cfg.id }}" name: "{{ hostname }}" type: qemu @@ -66,6 +66,7 @@ - name: Check VM existence in vCenter when: hypervisor_type == "vmware" delegate_to: localhost + become: false module_defaults: community.vmware.vmware_guest_info: hostname: "{{ hypervisor_cfg.url }}" @@ -106,6 +107,7 @@ - name: Check if VM already exists on Xen when: hypervisor_type == "xen" delegate_to: localhost + become: false ansible.builtin.command: argv: - xl diff --git a/roles/virtualization/tasks/vmware.yml b/roles/virtualization/tasks/vmware.yml index 0bc89af..88d6d8f 100644 --- a/roles/virtualization/tasks/vmware.yml +++ b/roles/virtualization/tasks/vmware.yml @@ -32,7 +32,8 @@ {%- endfor -%} {{ ns.out }} community.vmware.vmware_guest: - cluster: "{{ hypervisor_cfg.cluster }}" + cluster: "{{ hypervisor_cfg.cluster if (hypervisor_cfg.node | default('') | length == 0) else omit }}" + esxi_hostname: "{{ hypervisor_cfg.node if (hypervisor_cfg.node | default('') | length > 0) else omit }}" folder: "{{ system_cfg.path if system_cfg.path | string | length > 0 else omit }}" name: "{{ hostname }}" # Generic guest ID — VMware auto-detects OS post-install diff --git a/vars_example.yml b/vars_example.yml index 59c3871..ee5aa02 100644 --- a/vars_example.yml +++ b/vars_example.yml @@ -7,7 +7,7 @@ hypervisor: url: "pve01.example.com" username: "root@pam" password: "CHANGE_ME" - host: "pve01" + node: "pve01" storage: "local-lvm" datacenter: "dc01" cluster: "cluster01"