Skip to content

Commit baba356

Browse files
authored
Merge pull request #1 from w-miller/vm_list2
Allow specification of multiple VMs
2 parents 33f5f72 + 4f92ba8 commit baba356

File tree

9 files changed

+229
-99
lines changed

9 files changed

+229
-99
lines changed

README.md

Lines changed: 82 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Libvirt VM
22
==========
33

4-
This role configures an creates (or destroys) a VM on a KVM hypervisor.
4+
This role configures and creates (or destroys) VMs on a KVM hypervisor.
55

66
Requirements
77
------------
@@ -12,45 +12,70 @@ be preconfigured with libvirt/KVM.
1212
Role Variables
1313
--------------
1414

15-
`libvirt_vm_state`: set to `present` to create or `absent` to destroy the VM.
16-
Defaults to `present`.
15+
- `libvirt_vm_default_console_log_dir`: The default directory in which to store
16+
VM console logs, if a VM-specific log file path is not given. Default is
17+
"/var/log/libvirt/qemu/".
1718

18-
`libvirt_vm_name`: the name to assign to the VM.
19+
- `libvirt_image_cache_path`: The directory in which to cache downloaded
20+
images. Default is "/tmp/".
1921

20-
`libvirt_vm_memory_mb`: the memory to assign to the VM, in megabytes.
22+
- `libvirt_vm_engine`: virtualisation engine. If not set, the role will attempt
23+
to auto-detect the optimal engine to use.
2124

22-
`libvirt_vm_vcpus`: the number of VCPU cores to assign to the VM.
25+
- `libvirt_vm_emulator`: path to emulator binary. If not set, the role will
26+
attempt to auto-detect the correct emulator to use.
2327

24-
`libvirt_vm_engine`: virtualisation engine. If not set, the role will attempt
25-
to auto-detect the optimal engine to use.
28+
- `libvirt_vm_arch`: CPU architecture, default is `x86_64`.
2629

27-
`libvirt_vm_emulator`: path to emulator binary. If not set, the role will
28-
attempt to auto-detect the correct emulator to use.
30+
- `libvirt_vms`: list of VMs to be created/destroyed. Each one may have the
31+
following attributes:
2932

30-
`libvirt_vm_arch`: CPU architecture, default is `x86_64`.
33+
- `state`: set to `present` to create or `absent` to destroy the VM.
34+
Defaults to `present`.
3135

32-
`libvirt_vm_machine`: Virtual machine type. Default is `None` if
33-
`libvirt_vm_engine` is `kvm`, otherwise `pc-1.0`.
36+
- `name`: the name to assign to the VM.
3437

35-
`libvirt_vm_cpu_mode`: Virtual machine CPU mode. Default is `host-passthrough`
36-
if `libvirt_vm_engine` is `kvm`, otherwise `host-model`.
38+
- `memory_mb`: the memory to assign to the VM, in megabytes.
3739

38-
`libvirt_vm_volumes`: a list of volumes to attach to the VM. Each volume is
39-
defined with the following dict:
40-
- `name`: Name to associate with the volume being created.
41-
- `device`: `disk`
42-
- `format`: options include `raw`, `qcow2`, `vmdk`. See `man virsh` for the
43-
full range. Default is `qcow2`
44-
- `capacity`: volume capacity (can be suffixed with M,G,T or MB,GB,TB, etc)
45-
- `image`: (optional) a URL to an image with which the volume is initalised.
46-
- `pool`: Name or UUID of the storage pool from which the volume should be
47-
allocated.
40+
- `vcpus`: the number of VCPU cores to assign to the VM.
4841

49-
`libvirt_vm_interfaces`: a list of network interfaces to attach to the VM.
50-
Each network interface is defined with the following dict:
51-
- `network`: Name of the network to which an interface should be attached.
42+
- `machine`: Virtual machine type. Default is `None` if
43+
`libvirt_vm_engine` is `kvm`, otherwise `pc-1.0`.
5244

53-
`libvirt_vm_image_cache_path`: path to cache downloaded images.
45+
- `cpu_mode`: Virtual machine CPU mode. Default is `host-passthrough` if
46+
`libvirt_vm_engine` is `kvm`, otherwise `host-model`.
47+
48+
- `volumes`: a list of volumes to attach to the VM. Each volume is
49+
defined with the following dict:
50+
- `name`: Name to associate with the volume being created.
51+
- `device`: `disk`
52+
- `format`: options include `raw`, `qcow2`, `vmdk`. See `man virsh` for the
53+
full range. Default is `qcow2`
54+
- `capacity`: volume capacity (can be suffixed with M,G,T or MB,GB,TB, etc)
55+
- `image`: (optional) a URL to an image with which the volume is initalised.
56+
- `pool`: Name or UUID of the storage pool from which the volume should be
57+
allocated.
58+
59+
- `interfaces`: a list of network interfaces to attach to the VM.
60+
Each network interface is defined with the following dict:
61+
- `network`: Name of the network to which an interface should be attached.
62+
63+
- `console_log_enabled`: if `true`, log console output to a file at the
64+
path specified by `console_log_path`, **instead of** to a PTY. If
65+
`false`, direct terminal output to a PTY at serial port 0. Default is
66+
`false`.
67+
68+
- `console_log_path`: Path to console log file. Default is
69+
`{{ libvirt_vm_default_console_log_dir }}/{{ name }}-console.log`.
70+
71+
72+
N.B. the following variables are deprecated: `libvirt_vm_state`,
73+
`libvirt_vm_name`, `libvirt_vm_memory_mb`, `libvirt_vm_vcpus`,
74+
`libvirt_vm_engine`, `libvirt_vm_machine`, `libvirt_vm_cpu_mode`,
75+
`libvirt_vm_volumes`, `libvirt_vm_interfaces` and
76+
`libvirt_vm_console_log_path`. If the variable `libvirt_vms` is left unset, its
77+
default value will be a singleton list containing a VM specification using
78+
these deprecated variables.
5479

5580
Dependencies
5681
------------
@@ -61,22 +86,37 @@ Example Playbook
6186
----------------
6287

6388
---
64-
- name: Create a VM
89+
- name: Create VMs
6590
hosts: hypervisor
6691
roles:
6792
- role: stackhpc.libvirt-vm
68-
libvirt_vm_state: present
69-
libvirt_vm_name: 'my-vm'
70-
libvirt_vm_memory_mb: 512
71-
libvirt_vm_vcpus: 2
72-
libvirt_vm_volumes:
73-
- name: 'data'
74-
device: 'disk'
75-
format: 'qcow2'
76-
capacity: '400GB'
77-
pool: 'my-pool'
78-
libvirt_vm_interfaces:
79-
- network: 'br-datacentre'
93+
libvirt_vms:
94+
- state: present
95+
name: 'vm1'
96+
memory_mb: 512
97+
vcpus: 2
98+
volumes:
99+
- name: 'data1'
100+
device: 'disk'
101+
format: 'qcow2'
102+
capacity: '400GB'
103+
pool: 'my-pool'
104+
interfaces:
105+
- network: 'br-datacentre'
106+
107+
- state: present
108+
name: 'vm2'
109+
memory_mb: 1024
110+
vcpus: 1
111+
volumes:
112+
- name: 'data2'
113+
device: 'disk'
114+
format: 'qcow2'
115+
capacity: '200GB'
116+
pool: 'my-pool'
117+
interfaces:
118+
- network: 'br-datacentre'
119+
80120

81121
Author Information
82122
------------------

defaults/main.yml

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
---
2-
# State of the VM. May be 'present' or 'absent'.
3-
libvirt_vm_state: present
42

5-
# Name of the VM.
6-
libvirt_vm_name:
3+
# The default directory in which to store VM console logs, if a VM-specific log
4+
# file path is not given.
5+
libvirt_vm_default_console_log_dir: "/var/log/libvirt-consoles/"
76

8-
# Memory in MB.
9-
libvirt_vm_memory_mb:
7+
# Path to cache downloaded images.
8+
libvirt_image_cache_path: "/tmp/"
109

11-
# Number of vCPUs.
12-
libvirt_vm_vcpus:
10+
# CPU architecture.
11+
libvirt_vm_arch: x86_64
1312

1413
# Virtualisation engine. If not set, the role will attempt to auto-detect the
1514
# optimal engine to use.
@@ -19,23 +18,50 @@ libvirt_vm_engine:
1918
# correct emulator to use.
2019
libvirt_vm_emulator:
2120

22-
# CPU architecture.
23-
libvirt_vm_arch: x86_64
21+
# A list of specifications of VMs to be created.
22+
# For backwards compatibility, libvirt_vms defaults to a singleton list using
23+
# the values of the deprecated variables below.
24+
# See README.md or tasks/main.yml for these attributes' defaults.
25+
libvirt_vms:
26+
# State of the VM. May be 'present' or 'absent'.
27+
- state: "{{ libvirt_vm_state }}"
2428

25-
# Virtual machine type.
26-
libvirt_vm_machine: "{{ None if libvirt_vm_engine == 'kvm' else 'pc-1.0' }}"
29+
# Name of the VM.
30+
name: "{{ libvirt_vm_name }}"
2731

28-
# Virtual machine CPU mode.
29-
libvirt_vm_cpu_mode: "{{ 'host-passthrough' if libvirt_vm_engine == 'kvm' else 'host-model' }}"
32+
# Memory in MB.
33+
memory_mb: "{{ libvirt_vm_memory_mb }}"
3034

31-
# List of volumes.
32-
libvirt_vm_volumes: []
35+
# Number of vCPUs.
36+
vcpus: "{{ libvirt_vm_vcpus }}"
3337

34-
# List of network interfaces.
35-
libvirt_vm_interfaces: []
38+
# Virtual machine type.
39+
machine: "{{ libvirt_vm_machine }}"
3640

37-
# Path to cache downloaded images.
38-
libvirt_vm_image_cache_path:
41+
# Virtual machine CPU mode.
42+
cpu_mode: "{{ libvirt_vm_cpu_mode }}"
43+
44+
# List of volumes.
45+
volumes: "{{ libvirt_vm_volumes }}"
46+
47+
# List of network interfaces.
48+
interfaces: "{{ libvirt_vm_interfaces }}"
49+
50+
# Path to console log file.
51+
console_log_path: "{{ libvirt_vm_console_log_path }}"
52+
53+
54+
### DEPRECATED ###
55+
# Use the above settings for each item within `libvirt_vms`, instead of the
56+
# below deprecated variables.
3957

40-
# List of authorized SSH public keys.
41-
#libvirt_vm_public_keys: []
58+
libvirt_vm_state:
59+
libvirt_vm_machine:
60+
libvirt_vm_cpu_mode:
61+
libvirt_vm_volumes:
62+
libvirt_vm_interfaces:
63+
libvirt_vm_console_log_path:
64+
# Required, so we should fail if not set.
65+
#libvirt_vm_name:
66+
#libvirt_vm_memory_mb:
67+
#libvirt_vm_vcpus:

meta/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
galaxy_info:
33
author: Mark Goddard
44
description: >
5-
Role to configure and create a VM on a Libvirt/KVM hypervisor
5+
Role to configure and create VMs on a Libvirt/KVM hypervisor
66
company: StackHPC Ltd
77
license: Apache2
88
min_ansible_version: 2.0

tasks/destroy-vm.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@
33
# exists before destroying it.
44
- name: Check the VM's status
55
virt:
6-
name: "{{ libvirt_vm_name }}"
6+
name: "{{ vm.name }}"
77
command: list_vms
88
register: result
9+
become: yes
910

1011
- block:
1112
- name: Ensure the VM is absent
1213
virt:
13-
name: "{{ libvirt_vm_name }}"
14+
name: "{{ vm.name }}"
1415
state: destroyed
16+
become: yes
1517

1618
- name: Ensure the VM is undefined
1719
virt:
18-
name: "{{ libvirt_vm_name }}"
20+
name: "{{ vm.name }}"
1921
command: undefine
20-
when: libvirt_vm_name in result.list_vms
22+
become: yes
23+
when: vm.name in result.list_vms

tasks/destroy-volumes.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
destroy_virt_volume.sh
55
{{ item.name }}
66
{{ item.pool }}
7-
with_items: "{{ libvirt_vm_volumes }}"
7+
with_items: "{{ volumes }}"
88
register: volume_result
99
changed_when:
10-
- volume_result | success
10+
- volume_result is success
1111
- (volume_result.stdout | from_json).changed | default(True)
12+
become: yes

tasks/main.yml

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
11
---
2-
- block:
3-
- include: autodetect.yml
4-
- include: volumes.yml
5-
- include: vm.yml
6-
when: libvirt_vm_state == 'present'
7-
8-
- block:
9-
- include: destroy-volumes.yml
10-
- include: destroy-vm.yml
11-
when: libvirt_vm_state == 'absent'
2+
- include_tasks: autodetect.yml
3+
# We need to know the engine and emulator if we're creating any new VMs.
4+
when: libvirt_vms | rejectattr('state', 'eq', 'absent') | list
5+
6+
- include_tasks: volumes.yml
7+
vars:
8+
volumes: "{{ vm.volumes | default([], true) }}"
9+
with_items: "{{ libvirt_vms }}"
10+
loop_control:
11+
loop_var: vm
12+
when: (vm.state | default('present', true)) == 'present'
13+
14+
- include_tasks: vm.yml
15+
vars:
16+
console_log_enabled: "{{ vm.console_log_enabled | default(false) }}"
17+
console_log_path: "{{ vm.console_log_path | default(libvirt_vm_default_console_log_dir + '/' + vm.name + '-console.log', true) }}"
18+
machine_default: "{{ none if libvirt_vm_engine == 'kvm' else 'pc-1.0' }}"
19+
machine: "{{ vm.machine | default(machine_default, true) }}"
20+
cpu_mode_default: "{{ 'host-passthrough' if libvirt_vm_engine == 'kvm' else 'host-model' }}"
21+
cpu_mode: "{{ vm.cpu_mode | default(cpu_mode_default, true) }}"
22+
volumes: "{{ vm.volumes | default([], true) }}"
23+
interfaces: "{{ vm.interfaces | default([], true) }}"
24+
with_items: "{{ libvirt_vms }}"
25+
loop_control:
26+
loop_var: vm
27+
when: (vm.state | default('present', true)) == 'present'
28+
29+
- include_tasks: destroy-volumes.yml
30+
vars:
31+
volumes: "{{ vm.volumes | default([], true) }}"
32+
with_items: "{{ libvirt_vms }}"
33+
loop_control:
34+
loop_var: vm
35+
when: (vm.state | default('present', true)) == 'absent'
36+
37+
- include_tasks: destroy-vm.yml
38+
with_items: "{{ libvirt_vms }}"
39+
loop_control:
40+
loop_var: vm
41+
when: (vm.state | default('present', true)) == 'absent'

tasks/vm.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
11
---
2+
- name: Ensure the VM console log directory exists
3+
file:
4+
path: "{{ console_log_path | dirname }}"
5+
state: directory
6+
owner: qemu
7+
group: qemu
8+
recurse: true
9+
mode: 0770
10+
when: console_log_enabled | bool
11+
become: true
12+
213
- name: Ensure the VM is defined
314
virt:
4-
name: "{{ libvirt_vm_name }}"
15+
name: "{{ vm.name }}"
516
command: define
617
xml: "{{ lookup('template', 'vm.xml.j2') }}"
18+
become: true
719

820
- name: Ensure the VM is running and started at boot
921
virt:
10-
name: "{{ libvirt_vm_name }}"
22+
name: "{{ vm.name }}"
1123
autostart: true
1224
state: running
25+
become: true

0 commit comments

Comments
 (0)