Skip to content

Commit 8c5c487

Browse files
committed
Initial import from Kayobe master branch
0 parents  commit 8c5c487

File tree

9 files changed

+289
-0
lines changed

9 files changed

+289
-0
lines changed

defaults/main.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
# State of the VM. May be 'present' or 'absent'.
3+
libvirt_vm_state: present
4+
5+
# Name of the VM.
6+
libvirt_vm_name:
7+
8+
# Memory in MB.
9+
libvirt_vm_memory_mb:
10+
11+
# Number of vCPUs.
12+
libvirt_vm_vcpus:
13+
14+
# List of volumes.
15+
libvirt_vm_volumes: []
16+
17+
# List of network interfaces.
18+
libvirt_vm_interfaces: []
19+
20+
# Path to cache downloaded images.
21+
libvirt_vm_image_cache_path:
22+
23+
# List of authorized SSH public keys.
24+
#libvirt_vm_public_keys: []

files/destroy_virt_volume.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
# Copyright (c) 2017 StackHPC Ltd.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
# Ensure that a libvirt volume does not exists.
18+
# On success, output a JSON object with a 'changed' item.
19+
20+
if [[ $# -ne 2 ]]; then
21+
echo "Usage: $0 <name> <pool>"
22+
exit 1
23+
fi
24+
25+
NAME=$1
26+
POOL=$2
27+
28+
# Check whether a volume with this name exists.
29+
output=$(virsh vol-info --pool $POOL --vol $NAME 2>&1)
30+
result=$?
31+
if [[ $result -ne 0 ]]; then
32+
if echo "$output" | grep 'Storage volume not found' >/dev/null 2>&1; then
33+
echo '{"changed": false}'
34+
exit 0
35+
else
36+
echo "Unexpected error while getting volume info"
37+
echo "$output"
38+
exit $result
39+
fi
40+
fi
41+
42+
# Delete the volume.
43+
output=$(virsh vol-delete --pool $POOL --vol $NAME 2>&1)
44+
result=$?
45+
if [[ $result -ne 0 ]]; then
46+
echo "Failed to delete volume"
47+
echo "$output"
48+
exit $result
49+
fi
50+
51+
echo '{"changed": true}'
52+
exit 0

files/virt_volume.sh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/bin/bash
2+
3+
# Copyright (c) 2017 StackHPC Ltd.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
# Ensure that a libvirt volume exists, optionally uploading an image.
18+
# On success, output a JSON object with a 'changed' item.
19+
20+
if [[ $# -ne 4 ]] && [[ $# -ne 5 ]]; then
21+
echo "Usage: $0 <name> <pool> <capacity> <format> [<image>]"
22+
exit 1
23+
fi
24+
25+
NAME=$1
26+
POOL=$2
27+
CAPACITY=$3
28+
FORMAT=$4
29+
IMAGE=$5
30+
31+
# Check whether a volume with this name exists.
32+
output=$(virsh vol-info --pool $POOL --vol $NAME 2>&1)
33+
result=$?
34+
if [[ $result -eq 0 ]]; then
35+
echo '{"changed": false}'
36+
exit 0
37+
elif ! echo "$output" | grep 'Storage volume not found' >/dev/null 2>&1; then
38+
echo "Unexpected error while getting volume info"
39+
echo "$output"
40+
exit $result
41+
fi
42+
43+
# Create the volume.
44+
output=$(virsh vol-create-as --pool $POOL --name $NAME --capacity $CAPACITY --format $FORMAT 2>&1)
45+
result=$?
46+
if [[ $result -ne 0 ]]; then
47+
echo "Failed to create volume"
48+
echo "$output"
49+
exit $result
50+
fi
51+
52+
# Determine the path to the volume file.
53+
output=$(virsh vol-key --pool $POOL --vol $NAME 2>&1)
54+
result=$?
55+
if [[ $result -ne 0 ]]; then
56+
echo "Failed to get volume file path"
57+
echo "$output"
58+
virsh vol-delete --pool $POOL --vol $NAME
59+
exit $result
60+
fi
61+
62+
# Change the ownership of the volume to qemu. Without doing this libvirt cannot
63+
# access the volume.
64+
output=$(chown qemu:qemu $output 2>1)
65+
result=$?
66+
if [[ $result -ne 0 ]]; then
67+
echo "Failed to change ownership of the volume to qemu"
68+
echo "$output"
69+
virsh vol-delete --pool $POOL --vol $NAME
70+
exit $result
71+
fi
72+
73+
if [[ -n $IMAGE ]]; then
74+
# Upload an image to the volume.
75+
output=$(virsh vol-upload --pool $POOL --vol $NAME --file $IMAGE 2>&1)
76+
result=$?
77+
if [[ $result -ne 0 ]]; then
78+
echo "Failed to upload image $IMAGE to volume $NAME"
79+
echo "$output"
80+
virsh vol-delete --pool $POOL --vol $NAME
81+
exit $result
82+
fi
83+
84+
# Resize the volume to the requested capacity.
85+
output=$(virsh vol-resize --pool $POOL --vol $NAME --capacity $CAPACITY 2>&1)
86+
result=$?
87+
if [[ $result -ne 0 ]]; then
88+
echo "Failed to resize volume $VOLUME to $CAPACITY"
89+
echo "$output"
90+
virsh vol-delete --pool $POOL --vol $NAME
91+
exit $result
92+
fi
93+
fi
94+
95+
echo '{"changed": true}'
96+
exit 0

tasks/destroy-vm.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
# The destroyed state does not seem to be idempotent, so check whether the VM
3+
# exists before destroying it.
4+
- name: Check the VM's status
5+
virt:
6+
name: "{{ libvirt_vm_name }}"
7+
command: list_vms
8+
register: result
9+
10+
- block:
11+
- name: Ensure the VM is absent
12+
virt:
13+
name: "{{ libvirt_vm_name }}"
14+
state: destroyed
15+
16+
- name: Ensure the VM is undefined
17+
virt:
18+
name: "{{ libvirt_vm_name }}"
19+
command: undefine
20+
when: libvirt_vm_name in result.list_vms

tasks/destroy-volumes.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
- name: Ensure the VM volumes do not exist
3+
script: >
4+
destroy_virt_volume.sh
5+
{{ item.name }}
6+
{{ item.pool }}
7+
with_items: "{{ libvirt_vm_volumes }}"
8+
register: volume_result
9+
changed_when:
10+
- volume_result | success
11+
- (volume_result.stdout | from_json).changed | default(True)

tasks/main.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
- block:
3+
- include: volumes.yml
4+
- include: vm.yml
5+
when: libvirt_vm_state == 'present'
6+
7+
- block:
8+
- include: destroy-volumes.yml
9+
- include: destroy-vm.yml
10+
when: libvirt_vm_state == 'absent'

tasks/vm.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
- name: Ensure the VM is defined
3+
virt:
4+
name: "{{ libvirt_vm_name }}"
5+
command: define
6+
xml: "{{ lookup('template', 'vm.xml.j2') }}"
7+
8+
- name: Ensure the VM is running
9+
virt:
10+
name: "{{ libvirt_vm_name }}"
11+
state: running
12+
13+
- name: Ensure the VM is started at boot
14+
virt:
15+
name: "{{ libvirt_vm_name }}"
16+
command: autostart

tasks/volumes.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
- name: Ensure remote images are downloaded
3+
get_url:
4+
url: "{{ item }}"
5+
dest: "{{ libvirt_vm_image_cache_path }}/{{ item | basename }}"
6+
with_items: "{{ libvirt_vm_volumes | selectattr('image', 'defined') | map(attribute='image') | list }}"
7+
when: "'http' in item"
8+
9+
- name: Ensure local images are copied
10+
copy:
11+
src: "{{ item }}"
12+
dest: "{{ libvirt_vm_image_cache_path }}/{{ item | basename }}"
13+
with_items: "{{ libvirt_vm_volumes | selectattr('image', 'defined') | map(attribute='image') | list }}"
14+
when: "'http' not in item"
15+
16+
- name: Ensure the VM volumes exist
17+
script: >
18+
virt_volume.sh
19+
{{ item.name }}
20+
{{ item.pool }}
21+
{{ item.capacity }}
22+
{{ item.format | default('qcow2') }}
23+
{% if item.image is defined %}
24+
{{ libvirt_vm_image_cache_path }}/{{ item.image | basename }}
25+
{% endif %}
26+
with_items: "{{ libvirt_vm_volumes }}"
27+
register: volume_result
28+
changed_when:
29+
- volume_result | success
30+
- (volume_result.stdout | from_json).changed | default(True)

templates/vm.xml.j2

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<domain type='kvm'>
2+
<name>{{ libvirt_vm_name }}</name>
3+
<memory>{{ libvirt_vm_memory_mb | int * 1024 }}</memory>
4+
<vcpu>{{ libvirt_vm_vcpus }}</vcpu>
5+
<clock sync="localtime"/>
6+
<os>
7+
<type arch='x86_64'>hvm</type>
8+
</os>
9+
<devices>
10+
{% for volume in libvirt_vm_volumes %}
11+
<disk type='volume' device='{{ volume.device | default('disk') }}'>
12+
<driver name='qemu' type='{{ volume.format }}'/>
13+
<source pool='{{ volume.pool }}' volume='{{ volume.name }}'/>
14+
<target dev='vd{{ 'abcdefghijklmnopqrstuvwxyz'[loop.index] }}'/>
15+
</disk>
16+
{% endfor %}
17+
{% for interface in libvirt_vm_interfaces %}
18+
<interface type='network'>
19+
<source network='{{ interface.network }}'/>
20+
<model type='virtio'/>
21+
</interface>
22+
{% endfor %}
23+
<serial type='pty'>
24+
<target port='0'/>
25+
</serial>
26+
<console type='pty'>
27+
<target type='serial' port='0'/>
28+
</console>
29+
</devices>
30+
</domain>

0 commit comments

Comments
 (0)