summaryrefslogtreecommitdiffstats
path: root/data/openslx-install
blob: 1c943efa421f92523add1ec5ae9259be5201706c (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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#!/bin/bash

function print ()
{
	echo -e "\033[01;29m$@\033[00m"
}

function error ()
{
	echo -e "\033[01;31m$@\033[00m"
	exit 1
}

function getinput ()
{
	[ $# -ne 2 ] && error "getinput called with wrong parameter count ($@)"
	CURRENT_VAR="$2"
	echo -n -e "\033[01;29m$1 [${!CURRENT_VAR}]:\033[00m "
	read RETVAL
	[ -z "$RETVAL" ] && RETVAL="${!CURRENT_VAR}"
}

function accept ()
{
	[ -z "$CURRENT_VAR" ] && error "accept called when CURRENT_VAR is empty"
	eval "$CURRENT_VAR='$RETVAL'"
	CURRENT_VAR=""
	break
}

function deny ()
{
	print "Ungültige Eingabe: '$RETVAL'"
}

function yesno ()
{
	while true; do
		echo -n -e "\033[01;29m$@ [J/n] "
		read KEYPRESS
		[ -z "$KEYPRESS" ] && return 0
		[[ "$KEYPRESS" == J* || "$KEYPRESS" == j* ]] && return 0
		[[ "$KEYPRESS" == N* || "$KEYPRESS" == n* ]] && return 1
		print "Bitte mit J oder N antworten"
	done
}

function save_defaults ()
{
	echo -e "# OpenSLX-NG defaults for this server - saved from a previous run of openslx-install\n# Delete this file if you want to start from scratch" > "$DEFAULTS_FILE"
        for VARNAME in ${!SLX_*}; do
                echo "$VARNAME='${!VARNAME}'" >> "$DEFAULTS_FILE"
        done
}

function check_password ()
{
	[ $# -lt 1 ] && error "No user given to check_password"
	[ $# -lt 2 ] && error "No password given to check_password"
	[ ! -r /etc/shadow ] && return 1
	local correct=$(< /etc/shadow awk -v "user=$1" -F : 'user == $1 {print $2}')
	local prefix=${correct%"${correct#\$*\$*\$}"}
	local supplied="$(perl -e "print crypt('$2', '$prefix')")" # el cheapo: do not pass a password containing a single quote ( ' )
	[ "x$supplied" = "x$correct" ] && return 0
	return 1
}

# Load "Factory defaults" first
FACTORY_DEFAULTS_FILE="/opt/openslx/server-factory-defaults"
if [ -s "$FACTORY_DEFAULTS_FILE" ]; then
	. "$FACTORY_DEFAULTS_FILE" || error "Factory defaults konnten nicht geladen werden. ($FACTORY_DEFAULTS_FILE)"
fi
# Load presets/previously given replies
DEFAULTS_FILE="/opt/openslx/server-defaults"
if [ -s "$DEFAULTS_FILE" ]; then
	. "$DEFAULTS_FILE" || error "Voreinstellungen aus vorherigem Skriptdurchlauf konnten nicht geladen werden. Bitte die Datei $DEFAULTS_FILE überprüfen und reparieren oder ggf. löschen."
	print " *** Voreinstellungen aus vorherigem Skiptaufruf ($SLX_LAST_INVOCATION) gefunden"
	print " *** Diese Einstellungen werden als Standard-Antwort auf alle Fragen"
	print "     angenommen. Um dieses Setup mit den ursprünglichen Standardantworten"
	print "     auszuführen, die Datei $DEFAULTS_FILE löschen."
	print " *** Das Setup kann mit Strg+C abgebrochen werden."
	print ""
fi

print "OpenSLX-NG Server Preview: Setup"
print ""
print "Zum erfolgreichen Aufsetzen eines OpenSLX-NG Servers müssen"
print "einige Fragen beantwortet werden."
print ""

#
# ---- Ask if the private key of Uni Freiburg should be accepted for root logins
#
if [ ! -s "/root/.ssh/authorized_keys" ] || ! grep "openslx-admin@uni-freiburg.de" "/root/.ssh/authorized_keys" > /dev/null; then
	print ""
	print "Soll der Private Key der bwLehrpool-Abteilung in Freiburg für root-Logins auf"
	print "diesem Server zugelassen werden? Dadurch ist es für die Entwickler aus Freiburg"
	print "möglich, sich ohne Kenntnis des Passworts als root auf diesem Server einzuloggen."
	if yesno "Dies vereinfacht die Fernwartung, Fehlerdiagnose und -behebung."; then
		if mkdir -p "/root/.ssh" \
		&& chmod 0700 "/root/.ssh" \
		&& echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC667v6bIksFcwE6DMFs65ySfjySSn9V44GoN7qzIOUok/fgOsiotq2HJby/cgQxGVKogVmGUDRUqK3lKSqYnDmEigP3aQdleP1NFx6ex/zhEUoHp4VfqfQncSZT1zYE5IGQ9YNERrsDEI0YOZ5Cr+/I3p0bJAbXZM9dk/1Y6VOyMt1ZHXam5VvC6EJnJQzW9uAS69JSezprRsDYH+3NGd/XV/INkOsPIvkLc8rp5rtcdHrq/7NPNqtTCUdChv5F5lNMMHyXlhaM9FjG/DOZ0teKzh8MMe3oUXg/VibqEPZK4zVBKypATlWdv6zODiMrbi4n/Vm9IMA5i/71NW2GOdH openslx-admin@uni-freiburg.de" >> "/root/.ssh/authorized_keys" \
		&& chmod 0600 "/root/.ssh/authorized_keys"; then
			print "Key erfolgreich hinzugefügt"
		else
			error "Fehler beim Hinzufügen des Keys!"
		fi
	fi
fi

#
# ---- Haupt-Adresse (zwecks iPXE) ----
#
print ""
print "Zum Einrichten der iPXE-Funktionalität muss die IP-Adresse des Servers"
print "festgelegt werden. Alle Clients werden über diese Adresse bedient."
print "WICHTIG: Sollte sich die Adresse des Servers ändern, muss dieses Setup"
print "erneut ausgeführt werden."
print "Erkannte lokale Adressen:"

LOCAL_ADDRS="$(ip a | grep -E -o '^\s*inet\s+[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')"
echo "$LOCAL_ADDRS"

if [ -z "$SLX_LOCAL_ADDR" ] || [[ $LOCAL_ADDRS != *$SLX_LOCAL_ADDR* ]]; then
	SLX_LOCAL_ADDR=""
	for ADDR in $LOCAL_ADDRS; do
		[[ "$ADDR" == 127.* ]] && continue
		LAN_IP=$ADDR
		[[ "$ADDR" == 192.168.* ]] && continue
		[[ "$ADDR" == 10.* ]] && continue
		[[ "$ADDR" == 172.* ]] && continue
		SLX_LOCAL_ADDR=$ADDR
	done
	[ -z "$SLX_LOCAL_ADDR" ] && SLX_LOCAL_ADDR=$LAN_IP
fi

while true; do
	getinput "Primäre IP-Adresse des Servers" SLX_LOCAL_ADDR
	# syntax check
	echo "$RETVAL" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' > /dev/null || continue
	if ! ip a | grep -E "^\s*inet\s+$RETVAL/" > /dev/null; then
		print "Dieser Server scheint kein Interface zu besitzen, welches auf"
		print "die Adresse $RETVAL konfiguriert ist."
		yesno "Trotzdem diese Adresse verwenden?" || continue
	fi
	accept
done

#
# ---- NFS Share
#
# Is it a local one?
print ""
print "Bereitstellung der VMWare-Images"
print "Die Clients booten die VMWare-Images von einem NFS-Share. Dieses kann"
print "entweder auf diesem Server oder auf einem externen Server mit NFS-Zugang liegen."
print "Sofern die Images von diesem Server ausgeliefert werden sollen, wird ein"
print "zusätzlicher SMB-Server installiert, um das Aufspielen neuer Images"
print "von einem Windows-PC aus zu erleichtern."

while true; do
	getinput "Welches Setup ist erwünscht? L = Lokal, E = Extern" SLX_VM_NFS_TYPE
	# Local Server
	if [[ "$RETVAL" == L* || "$RETVAL" == l* ]]; then
		while true; do
			getinput "Lokaler Speicherort für VM-Images" SLX_VM_PATH
			if [[ "$RETVAL" != /* ]]; then
				print "FEHLER: Der Pfad muss absolut sein (mit einem / beginnen)"
				continue
			fi
			mkdir -p "$RETVAL"
			[ -w "$RETVAL" ] && accept
			print "FEHLER: Verzeichnis '$RETVAL' nicht beschreibbar."
		done
		SLX_VM_NFS="$SLX_LOCAL_ADDR:$SLX_VM_PATH"
		print "Lokaler VM-NFS-Share erreichbar unter $SLX_VM_NFS"
		SLX_VM_NFS_TYPE=L
		break # No accept here as it cannot be nested
	fi
	# External Server
	if [[ "$RETVAL" == E* || "$RETVAL" == e* ]]; then
		while true; do
			getinput "Adresse und Pfad des externen NFS-Shares für VM-Images im Format Adresse:Pfad" SLX_VM_NFS
			echo "$RETVAL" | grep -E '^\S+:\S+$' > /dev/null && accept
			print "FEHLER: Ungültiges NFS-Share-Format: $RETVAL"
		done
		print "Externer VM-NFS-Share erreichbar unter $SLX_VM_NFS"
		SLX_VM_NFS_TYPE=E
		break # No accept
	fi
	print "Ungültige Auswahl '$RETVAL'"
done # Done setting up VM NFS Server type


getinput "Adresse oder IP des NTP-Servers, mit dem die Zeit synchronisiert werden soll" SLX_NTP_SERVER
SLX_NTP_SERVER="$RETVAL"

#
# ---- Safety first: make user change root password if it is still the default ----
#
if [ "x$1" != "x--test" ] && check_password "root" "openslx-ng"; then
	print ""
	print "Aus Sicherheitsgründen sollte das root-Passwort dieses Servers geändert werden."
	while check_password "root" "openslx-ng" && yesno "Passwort jetzt ändern?"; do
		passwd
	done
fi

if yesno "Soll die aktuellste stabile Version des MiniLinux nach der Einrichtung automatisch heruntergeladen werden?"; then
	DOWNLOAD_ML=yes
else
	DOWNLOAD_ML=no
fi

print ""
print "Beginne Installation"

#
# ---- Compile iPXE ----
#
print ""
print "Erstelle iPXE Binary..."
sleep 3
cd /opt/openslx/ipxe || error "cd /opt/openslx/ipxe failed"
cat > ipxelinux.ipxe << HEREEND
#!ipxe
set use-cached 1
dhcp net0
set net0.dhcp/next-server $SLX_LOCAL_ADDR
set net0.dhcp/filename ipxelinux.0
imgload pxelinux.0
boot pxelinux.0
HEREEND
cd src || error "cd src failed"
[ -e "bin/undionly.kkkpxe" ] && unlink "bin/undionly.kkkpxe"
make bin/undionly.kkkpxe EMBED=../ipxelinux.ipxe,../pxelinux.0
[ ! -e "bin/undionly.kkkpxe" -o "$(stat -c %s "bin/undionly.kkkpxe")" -lt 80000 ] && error "Error compiling ipxelinux.0"
cp "bin/undionly.kkkpxe" "/srv/openslx/tftp/ipxelinux.0" || error "Could not write to /srv/openslx/tftp/ipxelinux.0"

#
#
#
if [[ "$SLX_VM_NFS_TYPE" == "L" ]]; then
	# Write SMB Config
cat > "/etc/samba/smb.conf" << HEREEND
[global]

workgroup = WORKGROUP
server string = OpenSLX-NG Test-Server

wins support = no
dns proxy = no
name resolve order = host

log file = /var/log/samba/log.%m
max log size = 100
syslog only = no
syslog = 0

panic action = /usr/share/samba/panic-action %d

security = user
encrypt passwords = true
passdb backend = tdbsam
obey pam restrictions = yes

domain master = no

[images]
   comment = Directory where all the VMWare Images go
   writeable = yes
   locking = no
   path = $SLX_VM_PATH
   guest ok = no
   valid users = vmware
HEREEND
	# End SMB Config
	chown -R vmware "$SLX_VM_PATH"
	# NFS Config
	echo "$SLX_VM_PATH	*(ro,async,insecure,no_root_squash,no_subtree_check)" > "/etc/exports"
	# End NFS Config
	update-rc.d samba defaults
	update-rc.d nfs-kernel-server defaults
	service samba restart
	service nfs-kernel-server restart
else # external NFS Server for VM Images is used. Disable NFS + Samba
	service samba stop
	service nfs-kernel-server stop
	for LEVEL in S 0 1 2 3 4 5; do
		update-rc.d samba disable "$LEVEL"
		update-rc.d nfs-kernel-server disable "$LEVEL"
	done
fi
print "Dienste konfiguriert."

[ ! -e "/srv/openslx/www/config.tgz" ] && openslx-settings

#
# ---- Create boottime system config ----
#
print ""
print "Schreibe Bootzeit-Konfiguration für MiniLinux"
cat > "/opt/openslx/client-config" << HEREEND
SLX_VM_NFS='$SLX_VM_NFS'
SLX_HTTP_ADDR='http://$SLX_LOCAL_ADDR'
SLX_NTP_SERVER='$SLX_NTP_SERVER'
SLX_BIOS_CLOCK='local'
HEREEND

SLX_LAST_INVOCATION="$(date)"
save_defaults

if [[ "$DOWNLOAD_ML" == yes ]]; then
	print ""
	print "Lade aktuellste Version des MiniLinux herunter"
	openslx-update
fi
print ""
print "Das MiniLinux kann jederzeit manuell durch den Befehl openslx-update aktualisiert werden."

print ""
print "Einrichtung abgeschlossen."