-
Notifications
You must be signed in to change notification settings - Fork 8
/
sp-image-to-volume
executable file
·165 lines (137 loc) · 4.24 KB
/
sp-image-to-volume
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/bin/sh
# SPDX-FileCopyrightText: 2017 StorPool <[email protected]>
# SPDX-License-Identifier: Apache-2.0
set -e
usage() {
cat <<EOUSAGE
Usage: sp-image-to-volume [-v] [-c client-command] image-name volume-name
sp-image-to-volume -V | -h
-c specify the OpenStack client command to use (default: openstack)
-h display program usage information and exit
-V display program version information and exit
-v verbose operation; display diagnostic output
EOUSAGE
}
version() {
echo 'sp-volume-to-image 0.1.0'
}
debug() {
[ -z "$v" ] || echo "RDBG $*" 1>&2
}
unset hflag Vflag v
ocli='openstack'
while getopts 'c:hVv' o; do
case "$o" in
c)
ocli="$OPTARG"
;;
h)
hflag=1
;;
V)
Vflag=1
;;
v)
v='-v'
;;
*)
usage 1>&2
exit 1
;;
esac
done
[ -z "$Vflag" ] || version
[ -z "$hflag" ] || usage
[ -z "$Vflag$hflag" ] || exit 0
shift `expr "$OPTIND" - 1`
if [ "$#" -ne 2 ]; then
usage 1>&2
exit 1
fi
img_name="$1"
vol_name="$2"
# Get the image size and status
img_data="$($ocli image show -f json -- "$img_name" | jq -r '(.size | tostring) + ":" + .status')"
if [ -z "$img_data" ]; then
echo "The '$img_name' image does not seem to exist" 1>&2
exit 1
fi
img_size="${img_data%%:*}"
img_status="${img_data#*:}"
debug "got image size $img_size status $img_status"
if ! expr "x$img_size" : 'x[1-9][0-9]*$' > /dev/null; then
echo "Could not obtain a numeric image size for the '$img_name' image, got '$img_size'" 1>&2
exit 1
elif [ "$img_status" != 'active' ]; then
echo "The '$img_name' image is not in the 'active' state, '$img_status' instead" 1>&2
exit 1
fi
# Get the volume id and status
vol_data="$($ocli volume show -f json -- "$vol_name" | jq -r '.id + ":" + .status')"
if [ -z "$vol_data" ]; then
echo "The '$vol_name' volume does not seem to exist" 1>&2
exit 1
fi
vol_id="${vol_data%%:*}"
vol_status="${vol_data#*:}"
debug "got volume id $vol_id status $vol_status"
if [ "$vol_status" != 'available' ]; then
echo "The '$vol_name' image is not in the 'available' state, '$vol_status' instead" 1>&2
exit 1
fi
vol_sname="os--volume-$vol_id"
vol_ssize="$(storpool -Bj volume "$vol_sname" info | jq '.data.size')"
debug "got StorPool volume name $vol_sname size $vol_ssize"
if [ -z "$vol_ssize" ]; then
echo "Could not obtain the size for the StorPool volume '$vol_ssname' for the '$vol_name' volume" 1>&2
exit 1
elif ! expr "x$vol_ssize" : 'x[1-9][0-9]*$' > /dev/null; then
echo "Could not obtain a numeric volume size for the '$vol_name' volume, got '$vol_ssize'" 1>&2
fi
vol_local="/dev/storpool/$vol_sname"
if [ -e "$vol_local" ]; then
echo "The StorPool volume seems to be already attached here as $vol_local" 1>&2
exit 1
fi
if [ "$vol_ssize" -ge "$img_size" ]; then
debug "no need to resize the volume, it is big enough to hold the image"
else
vol_nsize="$(echo "($img_size + 1024 * 1024 * 1024 - 1) / (1024 * 1024 * 1024)" | bc)"
debug "resizing the volume to ${vol_nsize} GB"
$ocli volume set --size "$vol_nsize" -- "$vol_name"
fi
# Prepare for creating a temporary file... yes, shell trap handling is a bit weird
unset img_temp cleanup_err
cleanup() {
local res="$?"
local arg="$1"
if [ -n "$img_temp" ]; then
rm -f -- "$img_temp"
unset img_temp
fi
if [ "$arg" -eq 0 ] && [ -n "$res" ]; then
arg="$res"
fi
: "${cleanup_err:=$arg}"
exit $cleanup_err
}
trap 'cleanup 0' EXIT
trap 'cleanup 2' QUIT TERM INT HUP
# Create a temporary file and store the image
img_temp="$(mktemp -t sp-image-to-volume.XXXXXX)"
trap "rm -f $v -- '$img_temp'" EXIT HUP INT QUIT TERM
debug "using a temporary image file $img_temp"
$ocli image save --file "$img_temp" -- "$img_name"
img_tsize="$(stat -c '%s' -- "$img_temp")"
debug "stored $img_tsize bytes there"
if [ "$img_tsize" != "$img_size" ]; then
echo "Could not save the image to a temporary file, stored '$img_tsize' bytes, expected '$img_size' bytes" 1>&2
exit 1
fi
debug "about to attach the $vol_sname volume here"
storpool -B attach volume "$vol_sname" here
debug "about to run 'qemu-img dd' to write the image contents to it"
qemu-img dd -O raw bs=1M if="$img_temp" of="$vol_local"
debug "about to detach the $vol_sname volume"
storpool -B detach volume "$vol_sname" here
debug 'all done'