Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions roles/deploy_vms_cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,26 @@ No requirement.
The role uses the "VMs" group of the inventory. All members of this group will be deployed according to member's variable described below.
The Ansible member inventory host name will be used as VM name.

| *item* variables | Required | Type | Default | Comments |
|--------------------|----------|-------------|---------------------------------------|-----------------------------------------------------------------------|
| vm_disk | No | String | vms_disks_directory + item + ".qcow2" | Path to the VM disk in `qcow2` format on the the Ansible machine |
| vm_template | No | String | | Path of the VM Libvirt XML templated file on the ansible machine |
| xml_path | No | String | vms_disks_directory + item + ".qcow2" | Path of the VM Libvirt XML file (non-template) on the ansible machine |
| force | No | Bool | false | Replace the VM if a VM with the same name is already deployed |
| enable | No | Bool | true | Enable and start the VM after creating it |
| nostart | No | Bool | false | Don't start the VM once deployed |
| live_migration | No | Bool | false | Set to true to enable livemigration support for this VM |
| migrate_to_timeout | No | Integer | | Maximum time given to a guest to live migrate (in seconds) |
| migration_downtime | No | Integer | | Allowed downtime when live migrating (in milliseconds) |
| priority | No | Integer | | Priority of resource in pacemaker |
| pinned_host | No | String | | Pin the VM on the given host. Fail if not possible |
| preferred_host | No | String | | Deploy the VM on the given host in priority if possible |
| crm_config_cmd | No | String list | | List of `crm config` to run when enabling this guest |
| colocated_vms | No | String list | | VM list to be be colocated with the new VM |
| strong_colocation | No | Bool | false | Enable strong colocation on colocated_vms. The VM will will not be started when the constraint is not fulfilled |
| disk_bus | No | String | | Disk bus type to use for the VM's disk (virtio, sata, scsi, ide, etc.) |
| *item* variables | Required | Type | Default | Comments |
|--------------------|----------|-------------|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| vm_disk | No | String | vms_disks_directory + item + ".qcow2" | Path to the VM disk in `qcow2` format on the the Ansible machine. Mutually exclusive with `vm_remote_disk`. |
| vm_remote_disk | No | String | | URL (`http`/`https`/`ftp`/`ftps`) of the VM disk, fetched directly on the target. Requires `vm_disk_checksum`. Mutually exclusive with `vm_disk`. |
| vm_disk_checksum | No | Dict | | Dict `{<algo>: <hex>, ...}` to verify the system disk after staging. Required for `vm_remote_disk`, optional for `vm_disk`. May list multiple algorithms; the strongest available is used (preference: `sha512` > `sha384` > `sha256`). |
| vm_template | No | String | | Path of the VM Libvirt XML templated file on the ansible machine |
| xml_path | No | String | vms_disks_directory + item + ".qcow2" | Path of the VM Libvirt XML file (non-template) on the ansible machine |
| force | No | Bool | false | Replace the VM if a VM with the same name is already deployed |
| enable | No | Bool | true | Enable and start the VM after creating it |
| nostart | No | Bool | false | Don't start the VM once deployed |
| live_migration | No | Bool | false | Set to true to enable livemigration support for this VM |
| migrate_to_timeout | No | Integer | | Maximum time given to a guest to live migrate (in seconds) |
| migration_downtime | No | Integer | | Allowed downtime when live migrating (in milliseconds) |
| priority | No | Integer | | Priority of resource in pacemaker |
| pinned_host | No | String | | Pin the VM on the given host. Fail if not possible |
| preferred_host | No | String | | Deploy the VM on the given host in priority if possible |
| crm_config_cmd | No | String list | | List of `crm config` to run when enabling this guest |
| colocated_vms | No | String list | | VM list to be be colocated with the new VM |
| strong_colocation | No | Bool | false | Enable strong colocation on colocated_vms. The VM will will not be started when the constraint is not fulfilled |
| disk_bus | No | String | | Disk bus type to use for the VM's disk (virtio, sata, scsi, ide, etc.) |

Here is an example of the structure for the VM inventory:

Expand Down
77 changes: 70 additions & 7 deletions roles/deploy_vms_cluster/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,79 @@
- name: Provision cluster VM (create if missing or forced)
when: deploy_vms_cluster_presencevm.status == "Undefined" or (hostvars[item].force is defined and hostvars[item].force)
vars:
vm_file: "{{ hostvars[item].vm_disk | default( deploy_vms_cluster_vms_disks_directory ~ '/' ~ item ~ '.qcow2') }}"
vm_local_disk: "{{ hostvars[item].vm_disk | default(deploy_vms_cluster_vms_disks_directory ~ '/' ~ item ~ '.qcow2') }}"
vm_remote_disk: "{{ hostvars[item].vm_remote_disk | default('') }}"
vm_file_dest: "{{ deploy_vms_cluster_qcow2tmpuploadfolder + '/os.qcow2' }}"
vm_disk_checksum: "{{ hostvars[item].vm_disk_checksum | default({}) }}"
vm_disk_checksum_preference: ['sha512', 'sha384', 'sha256']
vm_disk_checksum_unknown: "{{ (vm_disk_checksum.keys() | list) | difference(vm_disk_checksum_preference) }}"
vm_disk_checksum_algo: "{{ (vm_disk_checksum_preference | intersect(vm_disk_checksum.keys() | list)) | first | default('') }}"
vm_disk_checksum_hash: "{{ vm_disk_checksum[vm_disk_checksum_algo] | default('') }}"
vm_disk_checksum_present: "{{ (vm_disk_checksum_algo | length > 0) and (vm_disk_checksum_hash | length > 0) }}"
block:
- name: "Copy system disk on target for {{ item }}" # noqa: risky-file-permissions
ansible.builtin.copy:
src: "{{ vm_file }}"
dest: "{{ vm_file_dest }}"
vars:
ansible_remote_tmp: "{{ deploy_vms_cluster_qcow2tmpuploadfolder | default(omit) }}"
- name: "Validate VM disk source for {{ item }}"
ansible.builtin.fail:
msg: >-
For '{{ item }}', set either vm_disk (local path on control node) or
vm_remote_disk (URL fetched on target), not both.
when:
- hostvars[item].vm_disk is defined
- hostvars[item].vm_remote_disk is defined
- name: "Reject unsupported vm_disk_checksum keys for {{ item }}"
ansible.builtin.fail:
msg: >-
hostvars[{{ item }}].vm_disk_checksum contains unsupported keys: {{ vm_disk_checksum_unknown }}.
Supported algorithms: {{ vm_disk_checksum_preference | join(', ') }} (strongest used).
when: vm_disk_checksum_unknown | length > 0
- name: "Validate vm_disk_checksum shape for {{ item }}"
ansible.builtin.fail:
msg: >-
hostvars[{{ item }}].vm_disk_checksum must contain at least one supported
algorithm key ({{ vm_disk_checksum_preference | join(', ') }}) with a
non-empty hex digest. Got: {{ vm_disk_checksum }}.
when:
- vm_disk_checksum | length > 0
- not vm_disk_checksum_present
- name: "Stage system disk for {{ item }}"
when: deploy_vms_cluster_disk_copy | bool
block:
- name: "Require checksum for remote VM disk ({{ item }})"
ansible.builtin.fail:
msg: >-
hostvars[{{ item }}].vm_disk_checksum is required when using vm_remote_disk
(e.g. {sha256: '<hex>'}).
when:
- vm_remote_disk | length > 0
- not vm_disk_checksum_present
- name: "Download system disk from URL for {{ item }}"
ansible.builtin.get_url:
url: "{{ vm_remote_disk }}"
dest: "{{ vm_file_dest }}"
mode: "0644"
checksum: "{{ vm_disk_checksum_algo }}:{{ vm_disk_checksum_hash }}"
when: vm_remote_disk | length > 0
- name: "Copy system disk on target for {{ item }}" # noqa: risky-file-permissions
ansible.builtin.copy:
src: "{{ vm_local_disk }}"
dest: "{{ vm_file_dest }}"
vars:
ansible_remote_tmp: "{{ deploy_vms_cluster_qcow2tmpuploadfolder | default(omit) }}"
when: vm_remote_disk | length == 0
- name: "Stat system disk for checksum verification ({{ item }})"
ansible.builtin.stat:
path: "{{ vm_file_dest }}"
checksum_algorithm: "{{ vm_disk_checksum_algo }}"
get_checksum: true
register: deploy_vms_cluster_disk_stat
when: vm_disk_checksum_present
- name: "Verify system disk checksum for {{ item }}"
ansible.builtin.assert:
that: deploy_vms_cluster_disk_stat.stat.checksum == vm_disk_checksum_hash
fail_msg: >-
Checksum mismatch for {{ vm_file_dest }} on {{ inventory_hostname }}:
expected {{ vm_disk_checksum_algo }}:{{ vm_disk_checksum_hash }},
got {{ vm_disk_checksum_algo }}:{{ deploy_vms_cluster_disk_stat.stat.checksum | default('<none>') }}.
when: vm_disk_checksum_present
- name: "Create {{ item }}"
cluster_vm:
name: "{{ item }}"
Expand Down
Loading