diff --git a/library/cluster_vm.py b/library/cluster_vm.py
index dfbc17085..116a3d689 100644
--- a/library/cluster_vm.py
+++ b/library/cluster_vm.py
@@ -201,6 +201,13 @@
- Optional parameter relevant only if I(command) is C(clone)
type: bool
default: false
+ additional_disks:
+ description:
+ - List of qcow2 file paths for additional disks
+ - Device names (vdb, vdc, ...) are assigned automatically
+ - Optional parameter relevant only if I(command) is C(create)
+ type: list
+ default: []
disk_bus:
description:
- Disk bus type to use for the VM's disk (virtio, scsi, ide, etc.)
@@ -311,6 +318,16 @@
cpu: 4
memory: 2048
+# Create a VM with additional disks
+- name: Create guest0 with an extra data disk
+ cluster_vm:
+ name: guest0
+ command: create
+ system_image: my_disk.qcow2
+ xml: "{{ lookup('template', 'my_vm_config.xml.j2') }}"
+ additional_disks:
+ - additional_data.qcow2
+
# Remove a VM
- name: Remove guest0
cluster_vm:
@@ -548,7 +565,7 @@ def check_parameters(parameters, commands_list):
command=dict(type="str", required=True, choices=commands_list),
name=dict(type="str", required=False, aliases=["guest"]),
xml=dict(type="str", required=False),
- data_disk=dict(type="str", required=False),
+ additional_disks=dict(type="list", required=False, default=[]),
force=dict(type="bool", required=False, default=False),
enable=dict(type="bool", required=False, default=True),
system_image=dict(type="str", required=False),
@@ -668,6 +685,7 @@ def check_parameters(parameters, commands_list):
"clear_pacemaker_utilization", False
)
disk_bus = args.get("disk_bus", "virtio")
+ additional_disks = args.get("additional_disks", [])
vm_name_command_list = commands_list.copy()
vm_name_command_list.remove("list_vms")
@@ -689,6 +707,13 @@ def check_parameters(parameters, commands_list):
module.fail_json(
msg="`system_image` doesn't exist or is not a file`"
)
+ for i, filepath in enumerate(additional_disks):
+ if not os.path.isfile(filepath):
+ module.fail_json(
+ msg="additional_disks[{}] '{}' doesn't exist or is not a file".format(
+ i, filepath
+ )
+ )
vm_options = {
"name": vm_name,
"base_xml": vm_config,
@@ -710,6 +735,7 @@ def check_parameters(parameters, commands_list):
"pacemaker_params": pacemaker_params,
"pacemaker_utilization": pacemaker_utilization,
"disk_bus": disk_bus,
+ "additional_disks": additional_disks,
}
vm_manager.create(vm_options)
elif command == "clone":
diff --git a/roles/deploy_vm_manager/files/vm_manager b/roles/deploy_vm_manager/files/vm_manager
index 80ab2ac02..bdd5209cc 160000
--- a/roles/deploy_vm_manager/files/vm_manager
+++ b/roles/deploy_vm_manager/files/vm_manager
@@ -1 +1 @@
-Subproject commit 80ab2ac02241ffde1988ab42fa6fff8023dfff23
+Subproject commit bdd5209ccac8d11fd4b849b2b25c7a0f5de8dfba
diff --git a/roles/deploy_vms_cluster/README.md b/roles/deploy_vms_cluster/README.md
index 8f9c1714b..a8e475aa1 100644
--- a/roles/deploy_vms_cluster/README.md
+++ b/roles/deploy_vms_cluster/README.md
@@ -66,38 +66,38 @@ This templated XML file offers default behaviors and configurations to launch VM
It can be a good starting point if you plan to deploy your VM on SEAPATH, however, for any production setup, it is recommended to create your own XML file.
Below is a list of the VMs member variables that can be used with this XML file. None of these variables are required.
-| Member variable | Derived variable | Type | Default | Comments |
-|-----------------|------------------|-----------------|-----------|-----------------------------------------------------------------------------------------------------------------------------|
-| uuid | | Integer | random | Libvirt UUID of the VM |
-| description | | String | Test VM | Libvirt description of the VM |
-| memory | | Integer | 2048 | RAM of the VM in MiB |
-| additional_disk | | List of strings | | Additional disks to give to the VM. The main disk is given by the vm_disk variable |
-| vm_features | | List of strings | | List of vm features to enable. Possible values are "rt", "isolated", "secure-boot", "dpdk", "memballoon", "graphic-console" |
-| | rt | | | Enable real time tweaks (priority, cgroup, scheduler, etc ...). Depends on `cpuset` |
-| | isolated | | | Pin vCPU to hypervisor CPUs. Depends on `cpuset` |
-| | secure-boot | | | Enable secure boot |
-| | dpdk | | | Connect the VM to a DPDK OVS bridge port. Depends on `dpdk` |
-| | memballoon | | | Enable memory ballooning for the VM. |
-| | graphic-console | | | Add a graphic console (VNC) with video and tablet input to the VM |
-| graphics_listen | | String | 127.0.0.1 | Address on which the VNC server listens. Depends on `graphic-console` in `vm_features` |
-| cpuset | | List of int | | List of hypervisor CPU cores to use in the case of an isolated/RT VM |
-| emulatorpin | | Integer | | Hypervisor CPU on which to pin the QEMU thread running the VM. If not set, the thread is not pinned. |
-| nb_cpu | | Integer | 1 | Number of vCPU for the VM. Fallback to `cpuset` size if defined. |
-| sriov | | List of strings | | List of SRIOV pools to use. |
-| pci_passthrough | | List of dict | | List of dictionaries defining devices to passthrough to the VM. Each entry must contain: |
-| | domain | Integer | | PCI domain of the device |
-| | bus | Integer | | PCI bus of the device |
-| | slot | Integer | | PCI slot of the device |
-| | function | Integer | | PCI function of the device |
-| bridges | | List of dicts | | List of Linux bridges to use. Each entry must define: |
-| | name | String | | Name of the bridge to connect to |
-| | mac_address | String | | Mac address of the virtual NIC of the VM on this bridge |
-| ovs | | List of dicts | | List of OVS ports to use. Each element must contain: |
-| | ovs_port | String | | OVS port to use for this interface |
-| | mad_address | String | | Mac address of this interface |
-| dpdk | | List of dicts | | List of Open vSwitch ports on which to enable dpdk. Depends on `dpdk` in `vm_features`. Each element must contain: |
-| | ovs_port | | | OVS port on which to enable DPDK |
-| | cpu_nb | | | Hypervisor CPU to use for this port (100% of the cpu time will be used) |
+| Member variable | Derived variable | Type | Default | Comments |
+|-----------------|------------------|-----------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------|
+| uuid | | Integer | random | Libvirt UUID of the VM |
+| description | | String | Test VM | Libvirt description of the VM |
+| memory | | Integer | 2048 | RAM of the VM in MiB |
+| additional_disk | | List of strings | | Additional disks to give to the VM. Each entry is a path to a qcow2 disk image. Device names (vdb, vdc, ...) are assigned automatically. |
+| vm_features | | List of strings | | List of vm features to enable. Possible values are "rt", "isolated", "secure-boot", "dpdk", "memballoon", "graphic-console" |
+| | rt | | | Enable real time tweaks (priority, cgroup, scheduler, etc ...). Depends on `cpuset` |
+| | isolated | | | Pin vCPU to hypervisor CPUs. Depends on `cpuset` |
+| | secure-boot | | | Enable secure boot |
+| | dpdk | | | Connect the VM to a DPDK OVS bridge port. Depends on `dpdk` |
+| | memballoon | | | Enable memory ballooning for the VM. |
+| | graphic-console | | | Add a graphic console (VNC) with video and tablet input to the VM |
+| graphics_listen | | String | 127.0.0.1 | Address on which the VNC server listens. Depends on `graphic-console` in `vm_features` |
+| cpuset | | List of int | | List of hypervisor CPU cores to use in the case of an isolated/RT VM |
+| emulatorpin | | Integer | | Hypervisor CPU on which to pin the QEMU thread running the VM. If not set, the thread is not pinned. |
+| nb_cpu | | Integer | 1 | Number of vCPU for the VM. Fallback to `cpuset` size if defined. |
+| sriov | | List of strings | | List of SRIOV pools to use. |
+| pci_passthrough | | List of dict | | List of dictionaries defining devices to passthrough to the VM. Each entry must contain: |
+| | domain | Integer | | PCI domain of the device |
+| | bus | Integer | | PCI bus of the device |
+| | slot | Integer | | PCI slot of the device |
+| | function | Integer | | PCI function of the device |
+| bridges | | List of dicts | | List of Linux bridges to use. Each entry must define: |
+| | name | String | | Name of the bridge to connect to |
+| | mac_address | String | | Mac address of the virtual NIC of the VM on this bridge |
+| ovs | | List of dicts | | List of OVS ports to use. Each element must contain: |
+| | ovs_port | String | | OVS port to use for this interface |
+| | mad_address | String | | Mac address of this interface |
+| dpdk | | List of dicts | | List of Open vSwitch ports on which to enable dpdk. Depends on `dpdk` in `vm_features`. Each element must contain: |
+| | ovs_port | | | OVS port on which to enable DPDK |
+| | cpu_nb | | | Hypervisor CPU to use for this port (100% of the cpu time will be used) |
## Example Playbook
diff --git a/roles/deploy_vms_cluster/tasks/main.yml b/roles/deploy_vms_cluster/tasks/main.yml
index d58e9eda1..ca760ebc3 100644
--- a/roles/deploy_vms_cluster/tasks/main.yml
+++ b/roles/deploy_vms_cluster/tasks/main.yml
@@ -69,6 +69,18 @@
vars:
ansible_remote_tmp: "{{ deploy_vms_cluster_qcow2tmpuploadfolder | default(omit) }}"
when: deploy_vms_cluster_disk_copy | bool
+ - name: "Copy additional disk on target for {{ item }}"
+ ansible.builtin.copy:
+ src: "{{ add_disk }}"
+ dest: "{{ deploy_vms_cluster_qcow2tmpuploadfolder }}/additional_{{ add_disk_idx }}.qcow2"
+ mode: "0644"
+ vars:
+ ansible_remote_tmp: "{{ deploy_vms_cluster_qcow2tmpuploadfolder | default(omit) }}"
+ loop: "{{ hostvars[item].additional_disk | default([]) }}"
+ loop_control:
+ loop_var: add_disk
+ index_var: add_disk_idx
+ when: deploy_vms_cluster_disk_copy | bool
- name: "Create {{ item }}"
cluster_vm:
name: "{{ item }}"
@@ -86,6 +98,7 @@
preferred_host: "{{ hostvars[item].preferred_host | default(omit) }}"
crm_config_cmd: "{{ hostvars[item].crm_config_cmd | default(omit) }}"
disk_bus: "{{ hostvars[item].disk_bus | default(omit) }}"
+ additional_disks: "{{ range(hostvars[item].additional_disk | default([]) | length) | map('string') | map('regex_replace', '^(.+)$', deploy_vms_cluster_qcow2tmpuploadfolder ~ '/additional_\\1.qcow2') | list }}"
xml: >-
{{ lookup('file', hostvars[item].xml_path)
if hostvars[item].xml_path is defined
@@ -93,10 +106,18 @@
if hostvars[item].vm_template is defined
else lookup('file',deploy_vms_cluster_vms_disks_directory + '/' + item + '.xml')
| replace('\n', '') }}
- - name: Remove temporary file
+ - name: Remove temporary system disk file
ansible.builtin.file:
path: "{{ vm_file_dest }}"
state: absent
+ - name: "Remove temporary additional disk files for {{ item }}"
+ ansible.builtin.file:
+ path: "{{ deploy_vms_cluster_qcow2tmpuploadfolder }}/additional_{{ add_disk_idx }}.qcow2"
+ state: absent
+ loop: "{{ hostvars[item].additional_disk | default([]) }}"
+ loop_control:
+ loop_var: add_disk
+ index_var: add_disk_idx
- name: Wait for VM connections
ansible.builtin.wait_for_connection:
delegate_to: "{{ item }}"
diff --git a/roles/deploy_vms_standalone/README.md b/roles/deploy_vms_standalone/README.md
index 5beaa613c..88ef80509 100644
--- a/roles/deploy_vms_standalone/README.md
+++ b/roles/deploy_vms_standalone/README.md
@@ -50,39 +50,39 @@ This templated XML file offers default behaviors and configurations to launch VM
It can be a good starting point if you plan to deploy your VM on SEAPATH, however, for any production setup, it is recommended to create your own XML file.
Below is a list of the VMs member variables that can be used with this XML file. None of these variables are required.
-| Member variable | Derived variable | Type | Default | Comments |
-|-----------------|------------------|-----------------|-----------|-----------------------------------------------------------------------------------------------------------------------------|
-| uuid | | Integer | random | Libvirt UUID of the VM |
-| description | | String | Test VM | Libvirt description of the VM |
-| autostart | | Bool | true | Set the VM to autostart on hypervisor boot |
-| memory | | Integer | 2048 | RAM of the VM in MiB |
-| additional_disk | | List of strings | | Additional disks to give to the VM. The main disk is given by the vm_disk variable |
-| vm_features | | List of strings | | List of vm features to enable. Possible values are "rt", "isolated", "secure-boot", "dpdk", "memballoon", "graphic-console" |
-| | rt | | | Enable real time tweaks (priority, cgroup, scheduler, etc ...). Depends on `cpuset` |
-| | isolated | | | Pin vCPU to hypervisor CPUs. Depends on `cpuset` |
-| | secure-boot | | | Enable secure boot |
-| | dpdk | | | Connect the VM to a DPDK OVS bridge port. Depends on `dpdk` |
-| | memballoon | | | Enable memory ballooning for the VM. |
-| | graphic-console | | | Add a graphic console (VNC) with video and tablet input to the VM |
-| graphics_listen | | String | 127.0.0.1 | Address on which the VNC server listens. Depends on `graphic-console` in `vm_features` |
-| cpuset | | List of int | | List of hypervisor CPU cores to use in the case of an isolated/RT VM |
-| emulatorpin | | Integer | | Hypervisor CPU on which to pin the QEMU thread running the VM. If not set, the thread is not pinned. |
-| nb_cpu | | Integer | 1 | Number of vCPU for the VM. Fallback to `cpuset` size if defined. |
-| sriov | | List of strings | | List of SRIOV pools to use. |
-| pci_passthrough | | List of dict | | List of dictionaries defining devices to passthrough to the VM. Each entry must contain: |
-| | domain | Integer | | PCI domain of the device |
-| | bus | Integer | | PCI bus of the device |
-| | slot | Integer | | PCI slot of the device |
-| | function | Integer | | PCI function of the device |
-| bridges | | List of dicts | | List of Linux bridges to use. Each entry must define: |
-| | name | String | | Name of the bridge to connect to |
-| | mac_address | String | | Mac address of the virtual NIC of the VM on this bridge |
-| ovs | | List of dicts | | List of OVS ports to use. Each element must contain: |
-| | ovs_port | String | | OVS port to use for this interface |
-| | mad_address | String | | Mac address of this interface |
-| dpdk | | List of dicts | | List of Open vSwitch ports on which to enable dpdk. Depends on `dpdk` in `vm_features`. Each element must contain: |
-| | ovs_port | | | OVS port on which to enable DPDK |
-| | cpu_nb | | | Hypervisor CPU to use for this port (100% of the cpu time will be used) |
+| Member variable | Derived variable | Type | Default | Comments |
+|-----------------|------------------|-----------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------|
+| uuid | | Integer | random | Libvirt UUID of the VM |
+| description | | String | Test VM | Libvirt description of the VM |
+| autostart | | Bool | true | Set the VM to autostart on hypervisor boot |
+| memory | | Integer | 2048 | RAM of the VM in MiB |
+| additional_disk | | List of strings | | Additional disks to give to the VM. Each entry is a path to a qcow2 disk image. Device names (vdb, vdc, ...) are assigned automatically. |
+| vm_features | | List of strings | | List of vm features to enable. Possible values are "rt", "isolated", "secure-boot", "dpdk", "memballoon", "graphic-console" |
+| | rt | | | Enable real time tweaks (priority, cgroup, scheduler, etc ...). Depends on `cpuset` |
+| | isolated | | | Pin vCPU to hypervisor CPUs. Depends on `cpuset` |
+| | secure-boot | | | Enable secure boot |
+| | dpdk | | | Connect the VM to a DPDK OVS bridge port. Depends on `dpdk` |
+| | memballoon | | | Enable memory ballooning for the VM. |
+| | graphic-console | | | Add a graphic console (VNC) with video and tablet input to the VM |
+| graphics_listen | | String | 127.0.0.1 | Address on which the VNC server listens. Depends on `graphic-console` in `vm_features` |
+| cpuset | | List of int | | List of hypervisor CPU cores to use in the case of an isolated/RT VM |
+| emulatorpin | | Integer | | Hypervisor CPU on which to pin the QEMU thread running the VM. If not set, the thread is not pinned. |
+| nb_cpu | | Integer | 1 | Number of vCPU for the VM. Fallback to `cpuset` size if defined. |
+| sriov | | List of strings | | List of SRIOV pools to use. |
+| pci_passthrough | | List of dict | | List of dictionaries defining devices to passthrough to the VM. Each entry must contain: |
+| | domain | Integer | | PCI domain of the device |
+| | bus | Integer | | PCI bus of the device |
+| | slot | Integer | | PCI slot of the device |
+| | function | Integer | | PCI function of the device |
+| bridges | | List of dicts | | List of Linux bridges to use. Each entry must define: |
+| | name | String | | Name of the bridge to connect to |
+| | mac_address | String | | Mac address of the virtual NIC of the VM on this bridge |
+| ovs | | List of dicts | | List of OVS ports to use. Each element must contain: |
+| | ovs_port | String | | OVS port to use for this interface |
+| | mad_address | String | | Mac address of this interface |
+| dpdk | | List of dicts | | List of Open vSwitch ports on which to enable dpdk. Depends on `dpdk` in `vm_features`. Each element must contain: |
+| | ovs_port | | | OVS port on which to enable DPDK |
+| | cpu_nb | | | Hypervisor CPU to use for this port (100% of the cpu time will be used) |
## Example Playbook
diff --git a/roles/deploy_vms_standalone/tasks/copy_additional_disk.yml b/roles/deploy_vms_standalone/tasks/copy_additional_disk.yml
new file mode 100644
index 000000000..af6194954
--- /dev/null
+++ b/roles/deploy_vms_standalone/tasks/copy_additional_disk.yml
@@ -0,0 +1,15 @@
+# Copyright (C) 2024 RTE
+# SPDX-License-Identifier: Apache-2.0
+
+---
+- name: "Copy additional disk {{ _vm_name ~ ' - ' ~ (add_disk | basename) }}"
+ ansible.builtin.copy:
+ src: "{{ add_disk }}"
+ dest: "{{ deploy_vms_standalone_disk_pool }}/{{ add_disk | basename }}"
+ mode: "0644"
+ vars:
+ ansible_remote_tmp: "{{ deploy_vms_standalone_qcow2tmpuploadfolder | default(omit) }}"
+ loop: "{{ hostvars[_vm_name].additional_disk }}"
+ loop_control:
+ loop_var: add_disk
+ label: "{{ _vm_name }} - {{ add_disk | basename }}"
diff --git a/roles/deploy_vms_standalone/tasks/main.yml b/roles/deploy_vms_standalone/tasks/main.yml
index 0f95cf292..8893da93c 100644
--- a/roles/deploy_vms_standalone/tasks/main.yml
+++ b/roles/deploy_vms_standalone/tasks/main.yml
@@ -77,6 +77,16 @@
- item not in deploy_vms_standalone_all_vms.list_vms or (item in deploy_vms_standalone_all_vms.list_vms and hostvars[item].force is defined and hostvars[item].force)
loop: "{{ groups['VMs'] }}"
+- name: Copy additional disks on target
+ ansible.builtin.include_tasks: copy_additional_disk.yml
+ vars:
+ _vm_name: "{{ item }}"
+ loop: "{{ groups['VMs'] }}"
+ when:
+ - hostvars[item].additional_disk is defined
+ - deploy_vms_standalone_disk_copy | bool
+ - item not in deploy_vms_standalone_all_vms.list_vms or (item in deploy_vms_standalone_all_vms.list_vms and hostvars[item].force is defined and hostvars[item].force)
+
- name: Add main disk to disk list
# This is only done in standalone because the disk is handled by vm-manager in the cluster
ansible.builtin.set_fact:
diff --git a/templates/vm/guest.xml.j2 b/templates/vm/guest.xml.j2
index 878cd02f1..27ce0c6bf 100644
--- a/templates/vm/guest.xml.j2
+++ b/templates/vm/guest.xml.j2
@@ -116,17 +116,17 @@
{% endif %}
{% if vm.standalone_main_disk is defined %}
-
+
{% endif %}
-{% if vm.additional_disk is defined %}
-{% for disk in vm.additional_disk %}
+{% if vm.additional_disk is defined and vm.standalone_main_disk is defined %}
+{% for file in vm.additional_disk %}
-
-
-
+
+
+
{% endfor %}
{% endif %}