Skip to content

Commit 17d8100

Browse files
authored
Merge pull request #19 from JPvRiel/master
Support backing image and destroy VMs before volumes
2 parents 8d25fa8 + b53522a commit 17d8100

File tree

4 files changed

+85
-42
lines changed

4 files changed

+85
-42
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,16 @@ Role Variables
5353

5454
- `volumes`: a list of volumes to attach to the VM. Each volume is
5555
defined with the following dict:
56+
- `pool`: Name or UUID of the storage pool from which the volume should be
57+
allocated.
5658
- `name`: Name to associate with the volume being created.
59+
- `capacity`: volume capacity (can be suffixed with M,G,T or MB,GB,TB, etc)
5760
- `device`: `disk`
5861
- `format`: options include `raw`, `qcow2`, `vmdk`. See `man virsh` for the
5962
full range. Default is `qcow2`
60-
- `capacity`: volume capacity (can be suffixed with M,G,T or MB,GB,TB, etc)
61-
- `image`: (optional) a URL to an image with which the volume is initalised.
62-
- `pool`: Name or UUID of the storage pool from which the volume should be
63-
allocated.
63+
- `image`: (optional) a URL to an image with which the volume is initalised (full copy).
64+
- `backing_image`: (optional) name of the backing volume which is assumed to already be the same pool (copy-on-write).
65+
- `image` and `backing_image` are mutually exclusive options.
6466

6567
- `interfaces`: a list of network interfaces to attach to the VM.
6668
Each network interface is defined with the following dict:

files/virt_volume.sh

Lines changed: 67 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,82 +17,121 @@
1717
# Ensure that a libvirt volume exists, optionally uploading an image.
1818
# On success, output a JSON object with a 'changed' item.
1919

20-
if [[ $# -ne 4 ]] && [[ $# -ne 5 ]]; then
21-
echo "Usage: $0 <name> <pool> <capacity> <format> [<image>]"
20+
# Parse options
21+
OPTIND=1
22+
23+
while getopts ":n:p:c:f:i:b:" opt; do
24+
case ${opt} in
25+
n) NAME=$OPTARG;;
26+
p) POOL=$OPTARG;;
27+
c) CAPACITY=$OPTARG;;
28+
f) FORMAT=$OPTARG;;
29+
i) IMAGE=$OPTARG;;
30+
b) BACKING_IMAGE=$OPTARG;;
31+
\?)
32+
echo "Invalid option: -$OPTARG" >&2
33+
exit 1
34+
;;
35+
:)
36+
echo "Option -$OPTARG requires an argument." >&2
37+
exit 1
38+
;;
39+
esac
40+
done
41+
42+
# Check options
43+
if ! [[ -n $NAME && -n $POOL && -n $CAPACITY ]]; then
44+
echo "Missing manditory options" >&2
45+
echo "Usage: $0 -n <name> -p <pool> -c <capacity> [-f <format>] [-i <source image> | -b <backing image>]"
2246
exit 1
2347
fi
48+
if [[ -n $IMAGE && -n $BACKING_IMAGE ]]; then
49+
echo "Options -i and -b are mutually exclusive" >&2
50+
exit 1
51+
fi
52+
if [[ -z "$FORMAT" ]]; then
53+
FORMAT='qcow2'
54+
fi
2455

25-
NAME=$1
26-
POOL=$2
27-
CAPACITY=$3
28-
FORMAT=$4
29-
IMAGE=$5
3056

3157
# Check whether a volume with this name exists.
32-
output=$(virsh vol-info --pool $POOL --vol $NAME 2>&1)
58+
output=$(virsh vol-info --pool "$POOL" --vol "$NAME" 2>&1)
3359
result=$?
3460
if [[ $result -eq 0 ]]; then
3561
echo '{"changed": false}'
3662
exit 0
3763
elif ! echo "$output" | grep 'Storage volume not found' >/dev/null 2>&1; then
38-
echo "Unexpected error while getting volume info"
64+
echo "Unexpected error while getting volume info" >&2
3965
echo "$output"
4066
exit $result
4167
fi
4268

4369
# Create the volume.
44-
output=$(virsh vol-create-as --pool $POOL --name $NAME --capacity $CAPACITY --format $FORMAT 2>&1)
45-
result=$?
70+
if [[ -n $BACKING_IMAGE ]]; then
71+
if [[ "$FORMAT" != 'qcow2' ]]; then
72+
echo "qcow2 format assumed for backing images, but $FORMAT format was supplied."
73+
exit 1
74+
fi
75+
output=$(virsh vol-create-as --pool "$POOL" --name "$NAME" --capacity "$CAPACITY" --format "$FORMAT" --backing-vol "$BACKING_IMAGE" --backing-vol-format "$FORMAT" 2>&1)
76+
result=$?
77+
else
78+
output=$(virsh vol-create-as --pool "$POOL" --name "$NAME" --capacity "$CAPACITY" --format "$FORMAT" 2>&1)
79+
result=$?
80+
fi
4681
if [[ $result -ne 0 ]]; then
4782
echo "Failed to create volume"
4883
echo "$output"
4984
exit $result
5085
fi
5186

5287
# Determine the path to the volume file.
53-
output=$(virsh vol-key --pool $POOL --vol $NAME 2>&1)
88+
output=$(virsh vol-key --pool "$POOL" --vol "$NAME" 2>&1)
5489
result=$?
5590
if [[ $result -ne 0 ]]; then
5691
echo "Failed to get volume file path"
5792
echo "$output"
58-
virsh vol-delete --pool $POOL --vol $NAME
93+
virsh vol-delete --pool "$POOL" --vol "$NAME"
5994
exit $result
6095
fi
6196

6297
# Change the ownership of the volume to VOLUME_OWNER:VOLUME_GROUP if
6398
# these environmental variables are defined. Without doing this libvirt
6499
# cannot access the volume on RedHat based GNU/Linux distributions.
65-
existing_owner="$(stat --format '%U' "$output")"
66-
existing_group="$(stat --format '%G' "$output")"
67-
new_owner="${VOLUME_OWNER:-$existing_owner}"
68-
new_group="${VOLUME_GROUP:-$existing_group}"
69-
output=$(chown "$new_owner":"$new_group" $output 2>1)
70-
result=$?
71-
if [[ $result -ne 0 ]]; then
72-
echo "Failed to change ownership of the volume to $new_owner:$new_group"
73-
echo "$output"
74-
virsh vol-delete --pool $POOL --vol $NAME
75-
exit $result
100+
# Avoid attempting to change permissions on volumes that are not file or
101+
# directory based
102+
if [[ -f "$output" || -d "$output" ]]; then
103+
existing_owner="$(stat --format '%U' "$output")"
104+
existing_group="$(stat --format '%G' "$output")"
105+
new_owner="${VOLUME_OWNER:-$existing_owner}"
106+
new_group="${VOLUME_GROUP:-$existing_group}"
107+
output=$(chown "$new_owner":"$new_group" "$output" 2>1)
108+
result=$?
109+
if [[ $result -ne 0 ]]; then
110+
echo "Failed to change ownership of the volume to $new_owner:$new_group"
111+
echo "$output"
112+
virsh vol-delete --pool "$POOL" --vol "$NAME"
113+
exit $result
114+
fi
76115
fi
77116

78117
if [[ -n $IMAGE ]]; then
79118
# Upload an image to the volume.
80-
output=$(virsh vol-upload --pool $POOL --vol $NAME --file $IMAGE 2>&1)
119+
output=$(virsh vol-upload --pool "$POOL" --vol "$NAME" --file "$IMAGE" 2>&1)
81120
result=$?
82121
if [[ $result -ne 0 ]]; then
83122
echo "Failed to upload image $IMAGE to volume $NAME"
84123
echo "$output"
85-
virsh vol-delete --pool $POOL --vol $NAME
124+
virsh vol-delete --pool "$POOL" --vol "$NAME"
86125
exit $result
87126
fi
88127

89128
# Resize the volume to the requested capacity.
90-
output=$(virsh vol-resize --pool $POOL --vol $NAME --capacity $CAPACITY 2>&1)
129+
output=$(virsh vol-resize --pool "$POOL" --vol "$NAME" --capacity "$CAPACITY" 2>&1)
91130
result=$?
92131
if [[ $result -ne 0 ]]; then
93132
echo "Failed to resize volume $VOLUME to $CAPACITY"
94133
echo "$output"
95-
virsh vol-delete --pool $POOL --vol $NAME
134+
virsh vol-delete --pool "$POOL" --vol "$NAME"
96135
exit $result
97136
fi
98137
fi

tasks/main.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@
4242
loop_var: vm
4343
when: (vm.state | default('present', true)) == 'present'
4444

45-
- include_tasks: destroy-volumes.yml
46-
vars:
47-
volumes: "{{ vm.volumes | default([], true) }}"
45+
- include_tasks: destroy-vm.yml
4846
with_items: "{{ libvirt_vms }}"
4947
loop_control:
5048
loop_var: vm
5149
when: (vm.state | default('present', true)) == 'absent'
5250

53-
- include_tasks: destroy-vm.yml
51+
- include_tasks: destroy-volumes.yml
52+
vars:
53+
volumes: "{{ vm.volumes | default([], true) }}"
5454
with_items: "{{ libvirt_vms }}"
5555
loop_control:
5656
loop_var: vm
57-
when: (vm.state | default('present', true)) == 'absent'
57+
when: (vm.state | default('present', true)) == 'absent'

tasks/volumes.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
- name: Ensure the VM volumes exist
1717
script: >
1818
virt_volume.sh
19-
{{ item.name }}
20-
{{ item.pool }}
21-
{{ item.capacity }}
22-
{{ item.format | default(libvirt_volume_default_format) }}
19+
-n {{ item.name }}
20+
-p {{ item.pool }}
21+
-c {{ item.capacity }}
22+
-f {{ item.format | default(libvirt_volume_default_format) }}
2323
{% if item.image is defined %}
24-
{{ libvirt_vm_image_cache_path }}/{{ item.image | basename }}
24+
-i {{ libvirt_vm_image_cache_path }}/{{ item.image | basename }}
25+
{% elif item.backing_image is defined %}
26+
-b {{ item.backing_image }}
2527
{% endif %}
2628
with_items: "{{ volumes }}"
2729
environment: "{{ libvirt_vm_script_env }}"

0 commit comments

Comments
 (0)