blob: 9f18d0ec16a996d07ea074b7644a9e6e1aabea06 (
plain) (
blame)
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
###########################################################
# Include: Setup dnbd for image access, nfs/cifs fallback #
###########################################################
# This will currently make sure that the variable
# VM_DISKFILE_RO is set which will contain the
# absolute path to the disk image to use for the vm
# session.
# When using DNBD3 this will differ from SRC_IMG_ABSOLUTE,
# otherwise it will be identical.
# In the future DNBD3 (or something else) might provide
# a CoW layer so we don't need snapshots etc. anymore.
# This include should set VM_DISKFILE_RW in that case to
# indicate to the virt plugin that it doesn't need to
# handle creating a temporary CoW layer itself.
# Helper to cleanup the image mounted with dnbd3-fuse
cleanup_dnbd3() {
if ! isset DNBD3_MOUNT_POINT; then
writelog "'DNBD3_MOUNT_POINT' is not set! Aborting DNBD3 cleanup."
return 1
fi
# try to umount it now
for timeout in 1 1 1 2 2 3 FAIL; do
fs_path_ismountpoint "${DNBD3_MOUNT_POINT}" || break
fusermount -u "${DNBD3_MOUNT_POINT}" && break
writelog "dnbd3 still busy...."
[ "$timeout" = "FAIL" ] && break
sleep "$timeout"
done
}
setup_dnbd3_proxy () {
[ -d "/mnt/dnbd3/images" ] || return 1
writelog "Trying to access via dnbd3-server-fuse"
echo "${SRC_IMG_RELATIVE}:0" > "/mnt/dnbd3/control" || return 1
VM_DISKFILE_REVISION=0
VM_DISKFILE_RO="/mnt/dnbd3/images/${SRC_IMG_RELATIVE}:0"
writelog "Success."
return 0
}
setup_dnbd3 () {
local dnbd3_tmplog="${TMPDIR}/dnbd3fuse.log"
local dnbd3_diskfile=
setup_dnbd3_common
if isempty dnbd3_diskfile; then
slxlog "virt-dnbd3" "No dnbd3 server for ${SRC_IMG_RELATIVE} found, trying NFS/CIFS..." "$dnbd3_tmplog"
writelog "No working dnbd3 server found :-("
return 1
fi
VM_DISKFILE_RO="$dnbd3_diskfile"
return 0
}
setup_dnbd3_cow () {
local dnbd3_tmplog="${TMPDIR}/dnbd3fuse.log"
local dnbd3_diskfile=
mkdir "${TMPDIR}/cow"
setup_dnbd3_common -c "${TMPDIR}/cow" -C "${SLX_VMCHOOSER_BASE_URL//"/vmchooser/"/"/cow/"}" --upload-uuid "$DMSD_COW_SESSION" --cow-stats-file --merge
if isempty dnbd3_diskfile; then
slxlog "virt-dnbd3" "Failed to setup dnbd3-fuse with copy-on-write" "$dnbd3_tmplog"
writelog "Error setting up CoW"
cleanexit 1
fi
VM_DISKFILE_RW="$dnbd3_diskfile"
}
setup_dnbd3_common () {
# Mount path for images mounted with dnbd3-fuse
declare -rg DNBD3_MOUNT_POINT="${TMPDIR}/dnbd3fuse.mnt"
mkdir -p "${DNBD3_MOUNT_POINT}"
# start dnbd3-fuse in subshell
local DNBD3_EXITFLAG="${TMPDIR}/dnbd3exit$RANDOM"
local TIMEOUT VM_DISKFILE_REVISION
rm -f -- "${DNBD3_EXITFLAG}"
(
trap 'writelog "[dnbd3-fuse] Received TERM"; kill $dnbd3pid; exit' SIGTERM
trap 'writelog "[dnbd3-fuse] Received QUIT"; kill -SIGQUIT $dnbd3pid' SIGQUIT
startup="$( date +%s )"
while [ "$( date +%s )" -lt "$(( startup + 4 ))" ]; do
dnbd3-fuse -f -o allow_other,max_readahead=262144 -h "${SLX_DNBD3_SERVERS}" -i "${SRC_IMG_RELATIVE}" "$@" "${DNBD3_MOUNT_POINT}" &> "${dnbd3_tmplog}" &
dnbd3pid=$!
wait "$dnbd3pid"
RET=$?
done
touch "${DNBD3_EXITFLAG}"
if [ "$RET" != "0" ]; then
writelog "dnbd3-fuse stopped working (Exit code $RET)"
slxlog "virt-dnbd3-fuse" "dnbd3-fuse stopped/refused serving '${SRC_IMG_RELATIVE}' from '${SLX_DNBD3_SERVERS}' with error code: $RET" "${dnbd3_tmplog}"
fi
) &
declare -rg DNBD3_PID=$!
# give it a bit of time
usleep 250000
# check if we have the image
for TIMEOUT in 0.5 1 1 1 1 2 OUT; do
if [ -r "${DNBD3_MOUNT_POINT}/img" ]; then
VM_DISKFILE_REVISION="$(grep -m 1 "^Revision:" "${DNBD3_MOUNT_POINT}/status" | cut -d" " -f2)"
dnbd3_diskfile="${DNBD3_MOUNT_POINT}/img"
writelog "DNBD3: ${SRC_IMG_RELATIVE} on ${dnbd3_diskfile} with rid ${VM_DISKFILE_REVISION}"
add_cleanup "cleanup_dnbd3"
break
fi
if [ "$TIMEOUT" = "OUT" ] || [ -e "$DNBD3_EXITFLAG" ]; then
break
fi
sleep "$TIMEOUT"
done
}
setup_fallback() {
# Maybe we're reading a dnbd3 directory with RIDs encoded into the filename - use latest one
unset VM_DISKFILE_REVISION
local VM_DISKFILE_REVISION=$(ls -1 "${SRC_IMG_ABSOLUTE}.r"* | grep -E -o '\.r[0-9]+$' | grep -o -E '[0-9]+$' | sort -n | tail -n 1)
if notempty VM_DISKFILE_REVISION; then
# found
VM_DISKFILE_RO="${SRC_IMG_ABSOLUTE}.r${VM_DISKFILE_REVISION}"
elif [ -e "${SRC_IMG_ABSOLUTE}" ]; then
# try name we got from xml in the first place
VM_DISKFILE_RO="${SRC_IMG_ABSOLUTE}"
fi
}
## MAIN PART / Sanity checks ##
setup_image_access() {
writelog "Setting up virtual hard disk access for virtualizer/emulator ..."
unset VM_DISKFILE_RO VM_DISKFILE_RW
declare -g VM_DISKFILE_RO VM_DISKFILE_RW
run_hooks "image-access"
if [ -n "$VM_DISKFILE_RW" ]; then
writelog "A hook in setup_image_access supplied a writable diskfile. Not running default setup."
elif [ -n "$VM_DISKFILE_RO" ]; then
writelog "A hook in setup_image_access supplied a read-only diskfile. Not running default setup."
else
setup_image_access_default
fi
readonly VM_DISKFILE_RO VM_DISKFILE_RW
if [ -n "$VM_DISKFILE_RW" ]; then
writelog "\tVM disk file (RW):\t\t$VM_DISKFILE_RW"
if ! [ -s "$VM_DISKFILE_RW" ]; then
writelog ".... not found!"
EXIT_TYPE="user" EXIT_REASON="Schreibbare VM nicht gefunden. Adminmodus fehlgeschlagen." cleanexit 1
fi
if ! [ -w "$VM_DISKFILE_RW" ]; then
writelog ".... not writable!"
EXIT_TYPE="user" EXIT_REASON="VM-Image auf schreibbarem VM-Speicher nicht schreibbar. Adminmodus fehlgeschlagen." cleanexit 1
fi
elif [ -n "$VM_DISKFILE_RO" ]; then
writelog "\tVM disk file (RO):\t\t$VM_DISKFILE_RO"
if ! [ -s "$VM_DISKFILE_RO" ]; then
writelog ".... not found!"
EXIT_TYPE="user" EXIT_REASON="VM-Image nicht gefunden." cleanexit 1
fi
if ! [ -r "$VM_DISKFILE_RO" ]; then
writelog ".... not readable!"
EXIT_TYPE="user" EXIT_REASON="VM-Image nicht lesbar." cleanexit 1
fi
else
EXIT_TYPE="user" EXIT_REASON="Kein VM-Image Dateiname angegeben/gefunden." cleanexit 1
fi
}
setup_image_access_default() {
# See if we should setup dnbd3 image access at all
if ! isset SRC_IMG_RELATIVE; then
writelog "\tCan't use dnbd3 as SRC_IMG_RELATIVE is not set"
elif isempty SLX_DNBD3_SERVERS || [ "x${SLX_VM_DNBD3}" != "xyes" ]; then
writelog "\tCan't use dnbd3 as no servers are given in config, or SLX_VM_DNBD3 is not set to yes"
elif [ -n "$DMSD_COW_SESSION" ]; then
writelog "Setting up DNBD3 CoW session"
setup_dnbd3_cow
elif setup_dnbd3_proxy; then
writelog "\tImage setup done."
elif ! check_dep dnbd3-fuse fusermount; then
writelog "\tCan't use dnbd3 as dnbd3-fuse/fusermount binaries are not in PATH"
else
# register setup_dnbd3 as start hook after sourcing this include
writelog "Trying image access via DNBD3..."
setup_dnbd3
fi
# VM_DISKFILE_RO will be empty if dnbd3 is not used or failed to connect.
if isempty VM_DISKFILE_RO; then
# try to fallback to access the image via NFS/CIFS filesystem
writelog "Trying fallback image access via NFS/CIFS..."
setup_fallback
fi
}
call_post_source setup_image_access
|