Skip to content

Commit 61a8d90

Browse files
committed
Support backing image and destroy VMs before volumes
1 parent e393f38 commit 61a8d90

File tree

4 files changed

+83
-42
lines changed

4 files changed

+83
-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: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,82 +17,119 @@
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+
if [[ $# -gt 4 ]] && [[ $# -lt 6 ]]; then
24+
echo "Usage: $0 -n <name> -p <pool> -c <capacity> -f <format> [-i <source image> | -b <backing image>]"
2225
exit 1
2326
fi
2427

25-
NAME=$1
26-
POOL=$2
27-
CAPACITY=$3
28-
FORMAT=$4
29-
IMAGE=$5
28+
while getopts ":n:p:c:f:i:b:" opt; do
29+
case ${opt} in
30+
n) NAME=$OPTARG;;
31+
p) POOL=$OPTARG;;
32+
c) CAPACITY=$OPTARG;;
33+
f) FORMAT=$OPTARG;;
34+
i) IMAGE=$OPTARG;;
35+
b) BACKING_IMAGE=$OPTARG;;
36+
\?)
37+
echo "Invalid option: -$OPTARG" >&2
38+
exit 1
39+
;;
40+
:)
41+
echo "Option -$OPTARG requires an argument." >&2
42+
exit 1
43+
;;
44+
esac
45+
done
46+
47+
if [[ -n $IMAGE && -n $BACKING_IMAGE ]]; then
48+
echo "Options -i and -b are mutually exclusive." >&2
49+
exit 1
50+
fi
3051

3152
# Check whether a volume with this name exists.
32-
output=$(virsh vol-info --pool $POOL --vol $NAME 2>&1)
53+
output=$(virsh vol-info --pool "$POOL" --vol "$NAME" 2>&1)
3354
result=$?
3455
if [[ $result -eq 0 ]]; then
3556
echo '{"changed": false}'
3657
exit 0
3758
elif ! echo "$output" | grep 'Storage volume not found' >/dev/null 2>&1; then
38-
echo "Unexpected error while getting volume info"
59+
echo "Unexpected error while getting volume info" >&2
3960
echo "$output"
4061
exit $result
4162
fi
4263

4364
# Create the volume.
44-
output=$(virsh vol-create-as --pool $POOL --name $NAME --capacity $CAPACITY --format $FORMAT 2>&1)
45-
result=$?
65+
if [[ -n $BACKING_IMAGE ]]; then
66+
if [[ "$FORMAT" -ne "qcow2" ]]; then
67+
echo "qcow2 format assumed for backing images, but $FORMAT format was supplied."
68+
exit 1
69+
fi
70+
output=$(virsh vol-create-as --pool "$POOL" --name "$NAME" --capacity "$CAPACITY" --format "$FORMAT" --backing-vol "$BACKING_IMAGE" --backing-vol-format "$FORMAT" 2>&1)
71+
result=$?
72+
else
73+
output=$(virsh vol-create-as --pool "$POOL" --name "$NAME" --capacity "$CAPACITY" --format "$FORMAT" 2>&1)
74+
result=$?
75+
fi
4676
if [[ $result -ne 0 ]]; then
4777
echo "Failed to create volume"
4878
echo "$output"
4979
exit $result
5080
fi
5181

5282
# Determine the path to the volume file.
53-
output=$(virsh vol-key --pool $POOL --vol $NAME 2>&1)
83+
output=$(virsh vol-key --pool "$POOL" --vol "$NAME" 2>&1)
5484
result=$?
5585
if [[ $result -ne 0 ]]; then
5686
echo "Failed to get volume file path"
5787
echo "$output"
58-
virsh vol-delete --pool $POOL --vol $NAME
88+
virsh vol-delete --pool "$POOL" --vol "$NAME"
5989
exit $result
6090
fi
6191

6292
# Change the ownership of the volume to VOLUME_OWNER:VOLUME_GROUP if
6393
# these environmental variables are defined. Without doing this libvirt
6494
# 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
95+
if [[ -z "$VOLUME_OWNER" || -z "$VOLUME_GROUP" ]]; then
96+
if [[ -f "$output" || -d "$output" ]]; then
97+
existing_owner="$(stat --format '%U' "$output")"
98+
existing_group="$(stat --format '%G' "$output")"
99+
new_owner="${VOLUME_OWNER:-$existing_owner}"
100+
new_group="${VOLUME_GROUP:-$existing_group}"
101+
output=$(chown "$new_owner":"$new_group" "$output" 2>1)
102+
result=$?
103+
if [[ $result -ne 0 ]]; then
104+
echo "Failed to change ownership of the volume to $new_owner:$new_group"
105+
echo "$output"
106+
virsh vol-delete --pool "$POOL" --vol "$NAME"
107+
exit $result
108+
fi
109+
else
110+
echo "Setting ownership on volumes not backed by a file or directory is not supported"
111+
exit 1
112+
fi
76113
fi
77114

78115
if [[ -n $IMAGE ]]; then
79116
# Upload an image to the volume.
80-
output=$(virsh vol-upload --pool $POOL --vol $NAME --file $IMAGE 2>&1)
117+
output=$(virsh vol-upload --pool "$POOL" --vol "$NAME" --file "$IMAGE" 2>&1)
81118
result=$?
82119
if [[ $result -ne 0 ]]; then
83120
echo "Failed to upload image $IMAGE to volume $NAME"
84121
echo "$output"
85-
virsh vol-delete --pool $POOL --vol $NAME
122+
virsh vol-delete --pool "$POOL" --vol "$NAME"
86123
exit $result
87124
fi
88125

89126
# Resize the volume to the requested capacity.
90-
output=$(virsh vol-resize --pool $POOL --vol $NAME --capacity $CAPACITY 2>&1)
127+
output=$(virsh vol-resize --pool "$POOL" --vol "$NAME" --capacity "$CAPACITY" 2>&1)
91128
result=$?
92129
if [[ $result -ne 0 ]]; then
93130
echo "Failed to resize volume $VOLUME to $CAPACITY"
94131
echo "$output"
95-
virsh vol-delete --pool $POOL --vol $NAME
132+
virsh vol-delete --pool "$POOL" --vol "$NAME"
96133
exit $result
97134
fi
98135
fi

tasks/main.yml

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

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

51-
- include_tasks: destroy-vm.yml
49+
- include_tasks: destroy-volumes.yml
50+
vars:
51+
volumes: "{{ vm.volumes | default([], true) }}"
5252
with_items: "{{ libvirt_vms }}"
5353
loop_control:
5454
loop_var: vm
55-
when: (vm.state | default('present', true)) == 'absent'
55+
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)