ff3a40e573217e4b9c52029d633d30aa16e1b23e
[grml-terminalserver.git] / grml-terminalserver-config
1 #!/bin/bash
2 # Filename:      terminalserver-config
3 # Purpose:       configuration program for grml-terminalserver
4 # Authors:       grml-team (grml.org), (c) Michael Gebetsroither <gebi@grml.org>
5 # Bug-Reports:   see http://grml.org/bugs/
6 # License:       This file is licensed under the GPL v2.
7 ################################################################################
8
9
10 ###
11 ### __INCLUDES
12 ###
13 . /etc/grml/sh-lib
14 #. /etc/grml/sysexits-sh
15
16
17
18 ###
19 ### __VARIABLES
20 ###
21
22 verbose_=0
23
24 # this file holds all variable definitions
25 SHARED_PROG_VARS_="/usr/share/grml-terminalserver/shared_prog_vars"
26 isExistent $SHARED_PROG_VARS_ die
27 . $SHARED_PROG_VARS_
28
29 # variables used in the config file for grml-terminalserver
30 INTERFACE_=""
31 IP_=""
32 NETMASK_=""
33 GW_=""
34 NAMESERVERS_=""
35 IPRANGE_FROM_=""
36 IPRANGE_TO_=""
37 NETWORK_=""
38 OPTIONS_=""
39 BOOT_ARGS_=""
40 NAT_INTERFACE_=""
41
42
43 ###
44 ### __FUNCTIONS
45 ###
46
47 function printUsage
48 {
49   cat <<EOT
50 Usage: "$PROG_NAME__" [OPTIONS] <command>
51
52 $PROG_NAME__ is the config program for the terminalserver coming with grml.
53
54 COMMANDS:
55
56    help             This help text
57    interactive      Interactive Configuration of the grml-terminalserver
58    initrd           Only create the initrd
59    clean            Remove all configfiles created during user configuration
60    <default>        interactive mode
61
62 OPTIONS:
63    -v               verbose (show what is going on, v++)
64    -h               this help text
65
66 EOT
67 }
68
69
70 function writeConfig
71 {
72   local date_=""
73
74   if [ -f $CONF_FILE_ ]; then
75     mv -fb $CONF_FILE_ ${CONF_FILE_}-old
76   fi
77
78   date_=`date`
79   cat <<EOT > $CONF_FILE_
80 # GRML TERMINAL-SERVER CONFIG
81 # created on "$date_"
82 INTERFACE_="$INTERFACE_"
83 IP_="$IP_"
84 NETWORK_="$NETWORK_"
85 NETMASK_="$NETMASK_"
86 GW_="$GW_"
87 NAMESERVERS_="$NAMESERVERS_"
88 IPRANGE_FROM_="$IPRANGE_FROM_"
89 IPRANGE_TO_="$IPRANGE_TO_"
90 OPTIONS_="$OPTIONS_"
91 BOOT_ARGS_="$BOOT_ARGS_"
92 NAT_INTERFACE_="$NAT_INTERFACE_"
93
94 EOT
95   notice "config successfully safed to \"$CONF_FILE_\""
96 }
97
98
99 # AUTOMATIC CONFIGURATION  {{{
100 function checkParamArg
101 {
102   local param_name="$1"
103   local arg="$2"
104
105   #eval "echo $`echo $test`"
106   echo $arg |grep "^[-|+]" &>/dev/null || return
107
108   die "Argument from $param_name looks like another parameter \"$arg\"" 1
109 }
110
111 function actionAutoconf
112 {
113   checkParamArg "-i" "$interface_"
114 }
115 # }}}
116
117
118 # INITRD {{{
119 function actionMkInitrd
120 {
121   echo
122   echo "Creating initrd $PATH_/minirt26.gz:"
123   if isExistent "$PATH_/minirt26.gz" ; then
124      echo
125      echo "$PATH_/minirt26.gz exists already, skipping initrd creation"
126      return 0
127   fi
128
129   mkInitrd
130
131   echo '... done'
132 }
133
134 function mkInitrd
135 {
136   # we do not want to include persistent configuration files
137   # from udev in the initrd
138   udev_tmp_=$(mktemp -d terminalserver__udev.XXXXXX)
139   persistent=false
140   if ls /etc/udev/rules.d/*persistent* >/dev/null 2>&1 ; then
141     persistent_files=true
142     for f in /etc/udev/rules.d/*persistent* ; do
143       mv "$f" "${udev_tmp_}/"
144     done
145   fi
146
147   set -e
148   local cfg_="/etc/initramfs-tools/initramfs.conf"
149   local tmp_="`mktemp -t terminalserver__initramfsbk.XXXXXX`"
150   cp $cfg_ $tmp_
151   sed -i 's/^MODULES=.*/MODULES=netboot/' $cfg_
152   update-initramfs -u -t 1>/dev/null
153   mv $tmp_ $cfg_
154
155   local initrd_="/boot/initrd.img-$KERNEL_VERSION_"
156   mv $initrd_ $PATH_/minirt26.gz
157   mv ${initrd_}.bak $initrd_
158   set +e
159
160   # restore udev configuration files
161   if $persistent_files ; then
162     mv ${udev_tmp_}/* /etc/udev/rules.d/
163     rmdir "${udev_tmp_}"
164   fi
165 }
166 # }}}
167
168
169 # INTERACTIVE CONFIGURATION  {{{
170
171 function actionInteractive
172 {
173   local i=""
174
175   dprint "running in interactive mode"
176
177   local card_title_="Choose network device connected to client network"
178   local card_message_="Available network devices:"
179   local iprange_title_="IP Address range for clients"
180 local iprange_message_="
181 Please enter the desired IP-Range of addresses that should be allocated by clients, separated by a single space.
182
183 Example:
184           192.168.0.101 192.168.0.200
185
186 for addresses from 192.168.0.101 to (and including) 192.168.0.200.
187
188 "
189   local runconfig_title_="Networkcard config"
190   local runconfig_message_="Would you like to configure your interfaces now?"
191
192   # on witch interfaces should we listen
193   local netdevices_="$(grep -ve 'lo:' -ve 'Inter-|' -ve 'face |bytes' /proc/net/dev | awk -F: '{print $1}')"
194   local device_list_=""
195   for INTERFACE_ in $netdevices_; do device_list_="$device_list_ ${INTERFACE_} Networkcard_${INTERFACE_##eth}"; done
196     echo -n "" >"$TMP_"
197     $DIALOG_ --backtitle "$BACK_TITLE_" --title "$card_title_" --menu "$card_message_" \
198       0 0 18 $device_list_ 2>"$TMP_" || warn "could not get network-interface"
199   INTERFACE_="$(<$TMP_)" ; echo -n "" >"$TMP_"
200
201   while true; do
202     IP_=`netGetIp "$INTERFACE_" warn`
203     NETMASK_=`netGetNetmask "$INTERFACE_" warn`
204     netValidIp "$IP_" warn && break
205     $DIALOG_ --backtitle "$BACK_TITLE_" --title "$runconfig_title_" --yesno "$runconfig_message_" 18 45 && \
206       netcardconfig || die "Could not get interface" $?
207   done
208
209   IPRANGE_FROM_=`execute "ipcalc -nb $IP_/$NETMASK_" warn |awk '/HostMin/{print $2}'`
210   IPRANGE_TO_=`execute "ipcalc -nb $IP_/$NETMASK_" warn |awk '/HostMax/{print $2}'`
211   NETWORK_=`execute "ipcalc -nb $IP_/$NETMASK_" warn |awk '/Network:/{print $2}'`
212   NETWORK_=${NETWORK_%/*}
213   local iprange_=""
214   while [ -z "$IPRANGE_FROM_" -o -z "$IPRANGE_TO_" -o -z "$iprange_" ]; do
215     iprange_="$IPRANGE_FROM_ $IPRANGE_TO_"
216     echo -n "" >"$TMP_"
217     $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$iprange_title_ ($INTERFACE_=$IP_/$NETMASK_)" \
218       --inputbox "$iprange_message_" 18 75 "$iprange_" 2>"$TMP_" || die "problems getting network range" $?
219
220     iprange_="$(<$TMP_)"
221     IPRANGE_FROM_="${iprange_%% *}"
222     IPRANGE_TO_="${iprange_##* }"
223
224     for i in "$IPRANGE_FROM_" "$IPRANGE_TO_"; do
225       netValidIp "$i" warn || iprange_=""
226     done
227   done
228
229   NAMESERVERS_=`netGetNameservers warn`
230   GW_=`netGetDefaultGateway warn`
231   GW_DEV_=`/sbin/ip route get "$GW_" | awk '{ print $3; exit; }'`
232   if [ "$GW_DEV_" != "$INTERFACE_" ] && [ "$GW_DEV_" != "" ]; then
233     # GW_DEV_ of server is not the same device as the one serviced by dhcpd
234     # so it doesn't make sense to provide the GW_ address to the clients
235     local do_nat_="YES"
236     local do_nat_title_="Network Address Translation"
237     local do_nat_message_="
238 Do you want to set up NAT so that clients booting from this
239 grml-terminalserver can use this machine also as gateway to
240 the internet?"
241
242     $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$do_nat_title_" --yesno "$do_nat_message_" 15 75 || \
243       do_nat_="NO"
244     if [ "$do_nat_" = "YES" ]; then
245       # user wants NAT, we give the clients the server address as
246       # gateway as well
247       GW_="$IP_"
248       NAT_INTERFACE_="$GW_DEV_"
249     else
250       # no NAT, no sensible gateway
251       GW_=""
252       NAT_INTERFACE_=""
253     fi
254   fi
255
256   # get options
257   #local OPT_IPTABLES_="yes"
258   #local OPT_SSH_="yes"
259   #local OPT_DISTCC_="yes"
260   #local OPT_SQUID_=""
261
262   local OPTIONS_TITLE_="Options"
263   local OPTIONS_MESSAGE_="Please give the appropriate options you want the clients to use:
264
265 grml2hd   - Make a non-interactive remote installation
266
267
268
269 "
270 #  local OPTIONS_MESSAGE_="Please give the appropriate options you want the clients to use:
271 #
272 #iptables  - Only the server should be able to access the clients
273 #ssh       - A ssh-key will be created on the server and distributed to the clients
274 #distcc    - You want to use the clients as compile-farm (ssh options recommned)
275 #
276 #"
277
278   local OPT_IPTABLES_DESC_="Start iptables on the clients"
279   local OPT_SSH_DESC_="Start ssh on the clients"
280   local OPT_DISTCC_DESC_="Start distcc on the clients"
281   local OPT_GRML2HD_DESC_="Remote install grml on the network clients"
282   # dialog options (enable if implemented)
283   #iptables "$OPT_IPTABLES_DESC_" off \
284   #ssh "$OPT_SSH_DESC_" off \
285   #distcc "$OPT_DISTCC_DESC_" off \
286   echo -n "" >"$TMP_"
287   $DIALOG_ --clear --separate-output --backtitle "$BACK_TITLE_" --title "$OPTIONS_TITLE_" --checklist "$OPTIONS_MESSAGE_" 25 80 10 \
288   grml2hd "$OPT_GRML2HD_DESC_" off \
289     2>$TMP_ || die "could not get terminalserver options" $?
290   while read tmp_option_; do
291     OPTIONS_="$OPTIONS_ $tmp_option_"
292   done <$TMP_
293
294   # parse options
295   for i in $OPTIONS_; do
296     case "$i" in
297       grml2hd)  optGrml2Hd || return 1 ;;
298     esac
299   done
300
301   echo -n "" >"$TMP_"
302   local OPTIONS_BOOTARG_MESSAGE_="Here you can add additional boot arguments for the clients seperated by spaces:
303
304 Quite usefull examples:
305
306 ssh=<pw>              - Start ssh server and set password of user grml to pw
307 services=<1,2,3>      - Execute /etc/init.d/{1,2,3} start
308 console=ttyS0,9600n8  - Initialise serial console
309 startx                - Boot into X
310
311
312 "
313   $DIALOG_ --clear --no-collapse --backtitle "$BACK_TITLE_" --title "$OPTIONS_TITLE_" --inputbox "$OPTIONS_BOOTARG_MESSAGE_" 0 0\
314     2>$TMP_ || die "problems getting additional boot arguments"
315   BOOT_ARGS_="$BOOT_ARGS_ $(<$TMP_)"
316
317   writeConfig
318   actionMkInitrd
319   notice "GRML terminalserver successfully configured"
320 }
321 # }}}
322
323 # OPTIONS GETTING DIALOG {{{
324 function optGrml2Hd
325 {
326   local GRML2HD_TITLE_='Grml2hd options dialog'
327   local tmp_=''
328   local options_='BOOT_IMAGE=grml2hd'
329
330   # get partition to install grml2hd on
331   OPTIONS_PARTITION_MSG_='Please specify the target partition where to install grml'
332   PARTITION_TITLE_='Partition selection'
333   echo -n "" >"$TMP_"
334   $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$PARTITION_TITLE_" --inputbox \
335     "$OPTIONS_PARTITION_MSG_" 0 75 '/dev/hda1' 2>$TMP_ || die "problems getting partition"
336   tmp_="partition=$(<$TMP_)"
337   options_="$options_ $tmp_"
338
339   # get filesystem type
340   OPTION_FS_TYPE_='Please specify the filesystem type'
341   FS_TITLE_='Filesystem selection'
342   echo -n "" >"$TMP_"
343   $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$FS_TITLE_" --inputbox \
344   "$OPTION_FS_TYPE_" 0 75 'ext3' 2>$TMP_ || die "problems getting filesystem type"
345   tmp_="filesystem=$(<$TMP_)"
346   options_="$options_ $tmp_"
347
348   # get where to save mbr
349   OPTION_MBR_='Please specify the location where to save the mbr'
350   MBR_TITLE_='Select location of mbr'
351   echo -n "" >"$TMP_"
352   $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$MBR_TITLE_" --inputbox \
353     "$OPTION_MBR_" 0 75 '/dev/hda' 2>$TMP_ || die "problems getting location where to write mbr"
354   tmp_="mbr=$(<$TMP_)"
355   options_="$options_ $tmp_"
356
357   # get first user
358   OPTION_USER_='Who should be the first user on the system'
359   USER_TITLE_='User selection'
360   echo -n "" >"$TMP_"
361   $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "$USER_TITLE_" --inputbox \
362     "$OPTION_USER_" 0 75 'grml' 2>$TMP_ || die "problems getting first user of system"
363   tmp_="user=$(<$TMP_)"
364   options_="$options_ $tmp_"
365
366   BOOT_ARGS_="$options_"
367 }
368 #}}}
369
370
371 function removeTmpFiles
372 {
373   execute "rm -f $TMP_" warn
374 }
375
376 function actionClean
377 {
378   for i in dhcpd.conf minirt26.gz; do
379     execute "rm -f $PATH_/$i*"
380   done
381
382   for i in $CARDS_DETECTED_BY_DISCOVER $CONF_FILE_; do
383     execute "rm -f $i"
384   done
385
386 }
387
388
389 ###
390 ### __MAIN
391 ###
392
393 while getopts "i:hv" opt; do
394   case "$opt" in
395     i) interface_=$OPTARG ;;
396     h) printUsage; exit ;;
397     v) let verbose_=$verbose_+1 ;;
398     ?) printUsage; exit 64 ;;
399   esac
400 done
401 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
402 setVerbose $verbose_
403
404 case "$1" in
405   help)   printUsage; exit 0 ;;
406 esac
407
408 checkRoot die 'You have to be root to use this program'
409 disableSyslog
410
411 execute "mkdir -p $PATH_" die
412
413 TMP_=`mktemp -t grml-terminalserver-config.XXXXXX` || die "Could not create tmpfile" $?
414 setExitFunction 'removeTmpFiles'
415
416
417 . $DEFAULT_CONFIG_
418 . $CONFIG_
419 # used config vars:
420 # MODULES_PATH_
421 # MODULES_PATH_ROOT_DIFF_
422 # KERNEL_VERSION_
423 # ORIGINAL_INITRD_
424 if [[ $MODULES_PATH_ == "" || $KERNEL_VERSION_ == "" || $ORIGINAL_INITRD_ == "" ]]; then
425   warn "MODULES_PATH_=\"$MODULES_PATH_\" \
426 KERNEL_VERSION_=\"$KERNEL_VERSION_\" \
427 ORIGINAL_INITRD_=\"$ORIGINAL_INITRD_\""
428   die "False configuration, please update $CONFIG_"
429 fi
430
431
432 case "$1" in
433   interactive)  actionInteractive ;;
434   initrd) actionMkInitrd ;;
435   clean)  actionClean ;;
436   *)    actionInteractive ;;
437 esac
438
439 removeTmpFiles
440 # END OF FILE
441 ################################################################################
442 # vim:foldmethod=marker tabstop=2 expandtab shiftwidth=2