summaryrefslogtreecommitdiffstats
path: root/scripts/mount-store
blob: cc6766d409ebbf7b2e5e0653b70e4d2e8d1d0fb1 (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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/bin/bash

if [ $# -lt 2 ]; then
	echo "Bad call to $0." >&2
	echo "Expected: $0 images <source>" >&2
	echo "TM_USERNAME and TM_PASSWORD are expected environment variables for CIFS" >&2
	echo "TM_MOUNT_OPTIONS can be supplied in both cases to override automatic guessing" >&2
	exit 1
fi

USERNAME="$TM_USERNAME"
PASSWORD="$TM_PASSWORD"
MOUNT_OPTIONS="$TM_MOUNT_OPTIONS"
unset TM_PASSWORD

declare -rg CIFS_OPTS="/opt/openslx/cifs.opts"
declare -rg NFS_OPTS="/opt/openslx/nfs.opts"

WHAT="$1"
SOURCE="$2"
[ -n "$3" ] && USERNAME="$3"
[ -n "$4" ] && PASSWORD="$4"

# Currently WHAT can only be images (the central store for all images),
# but maybe there will be other storage types in the future.
case "$WHAT" in
images)
	DEST="/srv/openslx/nfs"
	;;
*)
	echo "Invalid/Unknown mount type: '$WHAT'." >&2
	exit 1
	;;
esac

FLAG="${DEST}/.notmounted"
SUBDIR="${DEST}/bwlehrpool_store"

storage_test () {
	rm -f -- "${FLAG}"
	if [ -e "${FLAG}" ]; then
		echo "Error: File '.notmounted' exists on remote storage and could not be deleted." >&2
		echo "Error: Make sure the share is writable." >&2
		return 5
	fi
	chgrp images "${DEST}" 2>/dev/null
	mkdir -p "${SUBDIR}"
	if [ ! -d "${SUBDIR}" ]; then
		echo "Error: Could not create directory $(basename "${SUBDIR}")! Storage not writable!" >&2
		return 6
	fi
	echo "Applying group..."
	find "${SUBDIR}" -type d -exec chgrp images {} \; 2>/dev/null
	echo "Applying permissions..."
	find "${SUBDIR}" -type d -exec chmod ug+rwx {} \; 2>/dev/null
	echo "Creating test file..."
	local TEST="${SUBDIR}/.deleteme-$RANDOM-$RANDOM"
	sudo -n -u dmsd touch "$TEST"
	local RET=$?
	if [ -e "$TEST" ]; then
		sudo -n -u dmsd rm -f -- "$TEST"
	else
		[ "$RET" = "0" ] && RET=127
		echo "Error: Mounted share is not writable." >&2
		ls -al "${DEST}" "${SUBDIR}" >&2
	fi
	return $RET
}

systemctl stop dnbd3-server.service

# Already mounted?
TRIES=0
while awk '{print $2}' "/proc/mounts" | grep -Fxq "${DEST}"; do
	echo "Trying to unmount '$DEST'..."
	if [ "$TRIES" -gt 5 ]; then
		cat >&2 <<-HEREDOC
			Error: Cannot unmount '$DEST'!
			Storage might be in use (running VM upload etc.)
			Try stopping DMSD first

			If the problem persists, try rebooting the server.

			Possible troublemaker(s):
		HEREDOC
		lsof -n | grep "$DEST" >&2
		exit 99 # marker that nothing changed
	elif [ "$TRIES" -gt 3 ]; then
		umount -v -f "$DEST"
		RET=$?
	else
		umount -v "$DEST"
		RET=$?
	fi
	[ "$RET" = 0 ] && break
	sleep 1
	TRIES=$(( TRIES + 1 ))
done

# Sanity checks: Destination exists?
if [ ! -d "$DEST" ]; then
	mkdir -p "$DEST"
	chown root:images "$DEST"
	chmod 0775 "$DEST"
fi

# Still a no?
if [ ! -d "$DEST" ]; then
	echo "Mount point '$DEST' does not exist and could not be created!" >&2
	echo "This should not happen and means this server is severely messed up. :(" >&2
	exit 1
fi

# Unmount and not requested to mount (local mode)
if [[ "${SOURCE}" == "null" ]]; then
	rm -f -- "${FLAG}"
	echo "Success. Now using internal storage."
	systemctl --no-block start dnbd3-server.service
	exit 0
fi

touch "${FLAG}"

if [[ "${SOURCE}" == "unknown" ]]; then
	echo "Storage type not configured, doing nothing."
	exit 0
fi

# Mount!

# exec_mount <type> <options> <source> <dest>
exec_mount () {
	local fstype="$1"
	local mntopts="$2"
	local SOURCE="$3"
	local DEST="$4"
	echo " * Trying ${fstype} with ${mntopts}..."
	mount -v -t "$fstype" -o "$mntopts" "$SOURCE" "$DEST"
	RET=$?
	[ "$RET" -ne "0" ] && return "$RET"
	echo "Mount succeeded, checking write permissions...."
	storage_test
	RET=$?
	[ "$RET" -eq "0" ] && return 0
	umount -v "$DEST" || umount -v -f -l "$DEST"
	return "$RET"
}

remove_option () {
	local opt
	while [ $# -gt 0 ]; do
		opt=$1
		shift
		[[ "$MOUNT_OPTIONS" =~ (^|,)$opt($|,|=) ]] || continue
		MOUNT_OPTIONS=$( echo "$MOUNT_OPTIONS" | sed -r "s/(^|,)$opt(|=[^,]*)(,|$)/\\1/g;s/,$//" )
	done
}

main () {
	local RET=999
	if grep -E -q '^[^/].+:.+' <<<$SOURCE; then
		# seems to be NFS
		if [ "$RET" != 0 ] && [ -n "$MOUNT_OPTIONS" ]; then
			remove_option bg retry ro
			MOUNT_OPTIONS="$MOUNT_OPTIONS,fg,retry=0,rw"
			exec_mount "nfs" "$MOUNT_OPTIONS" "$SOURCE" "$DEST"
			return $?
		fi
		OPTSTR=
		if [ -f "$NFS_OPTS" ]; then
			OPTSTR=$(cat "$NFS_OPTS")
		fi
		if [ "$RET" != 0 ] && [ -n "$OPTSTR" ]; then
			echo " * Trying last successful mount options..."
			exec_mount "nfs" "$OPTSTR" "$SOURCE" "$DEST"
			RET=$?
		fi
		if [ "$RET" != 0 ]; then
			for opt in "#" "vers=4" "vers=3"; do
				OPTSTR="rw,noatime,noexec,nodev,async,nolock,fg,ac,retry=0,timeo=200,sec=sys"
				[ "$opt" != "#" ] && OPTSTR="$OPTSTR,$opt"
				exec_mount "nfs" "$OPTSTR" "$SOURCE" "$DEST"
				RET=$?
				[ "$RET" = 0 ] && break
			done
			if [ "$RET" = 0 ] && [ -n "$OPTSTR" ]; then
				echo "$OPTSTR" > "$NFS_OPTS"
			fi
		fi
	elif grep -E -q '^//' <<<$SOURCE; then
		# seems to be SMB
		export USER="$USERNAME"
		export PASSWD="$PASSWORD"
		if [ "$RET" != 0 ] && [ -n "$MOUNT_OPTIONS" ]; then
			remove_option uid gid file_mode dir_mode umask ro
			MOUNT_OPTIONS="$MOUNT_OPTIONS,uid=0,gid=12345,forceuid,forcegid,file_mode=0664,dir_mode=0775,rw"
			exec_mount "cifs" "$MOUNT_OPTIONS" "$SOURCE" "$DEST"
			return $?
		fi
		OPTSTR=
		if [ -f "$CIFS_OPTS" ]; then
			OPTSTR=$(cat "$CIFS_OPTS")
		fi
		if [ "$RET" != 0 ] && [ -n "$OPTSTR" ]; then
			echo " * Trying last successful mount options..."
			exec_mount "cifs" "$OPTSTR" "$SOURCE" "$DEST"
			RET=$?
		fi
		if [ "$RET" != 0 ]; then
			for vers in "" "3.0" "2.1" "2.0" "1.0"; do
				[ -n "$vers" ] && vers=",vers=${vers}"
				for sec in "" "ntlmssp" "ntlmv2" "ntlm"; do
					[ -n "$sec" ] && sec=",sec=${sec}"
					OPTSTR="rw,uid=0,gid=12345,forceuid,forcegid,nounix,file_mode=0664,dir_mode=0775$vers$sec"
					exec_mount "cifs" "$OPTSTR" "$SOURCE" "$DEST"
					RET=$?
					[ "$RET" = 0 ] && break 2
				done
			done
			if [ "$RET" = 0 ] && [ -n "$OPTSTR" ]; then
				echo "$OPTSTR" > "$CIFS_OPTS"
			fi
		fi
		unset USER PASSWD
	else
		echo "Unknown mount type: $SOURCE"
		RET=1
	fi
	return "$RET"
}

main
RET=$?

echo ""

if [ "$RET" = "0" ]; then
	echo "----------------------------------"
	echo "-- Share mounted successfully!  --"
	echo "----------------------------------"
	systemctl --no-block start dnbd3-server.service
fi

exit "$RET"