troubleshooting early ssh access
[bootcd.git] / initscripts / pl_netinit
1 #!/bin/sh
2 #-*-shell-script-*-
3
4 set -x
5
6 # the name of the floppy based network configuration
7 # files (checked first). the name planet.cnf is kept
8 # for backward compatibility with old nodes, and only
9 # the floppy disk is searched for files with this name.
10 # new files are named plnode.txt and can be located on
11 # a floppy or usb device or on the cdrom
12 OLD_NODE_CONF_NAME=planet.cnf
13 NEW_NODE_CONF_NAME=plnode.txt
14
15 # one location of cd-based network configuration file
16 # (checked if floppy conf file missing and usb
17 # configuration file is missing)
18 CD_NET_CONF_BOOT=/usr/boot/$NEW_NODE_CONF_NAME
19
20 # the other location of cd-based network configuration file
21 CD_NET_CONF_ROOT=/usr/$NEW_NODE_CONF_NAME
22
23 # if all other network configuration file sources 
24 # don't exist, fall back to this one (always on the cd)
25 FALLBACK_NET_CONF=/usr/boot/default-node.txt
26
27 # a temporary place to hold the old configuration file
28 # off of the floppy disk if we find it (so we don't have
29 # to remount the floppy later)
30 TMP_OLD_FLOPPY_CONF_FILE=/tmp/oldfloppy_planet.cnf
31
32 # once a configuration file is found, save it in /tmp
33 # (may be used later by boot scripts)
34 USED_NET_CONF=/tmp/planet.cnf
35
36 # default device to use for contacting PLC if not specified
37 # in the configuration file
38 DEFAULT_NET_DEV=eth0
39
40 # where to store the temporary dhclient conf file
41 DHCLIENT_CONF_FILE=/tmp/dhclient.conf
42
43 # which fs types we support finding node configuration files on
44 # (will be based as a -t parameter to mount)
45 NODE_CONF_DEVICE_FS_TYPES="msdos,ext2"
46
47 # a temporary place to mount devices that might contain configuration
48 # files on
49 CONF_DEVICE_MOUNT_POINT=/mnt/confdevice
50 /bin/mkdir -p $CONF_DEVICE_MOUNT_POINT
51
52 # for some backwards compatibility, save the ifconfig <device>
53 # output to this file after everything is online
54 IFCONFIG_OUTPUT=/tmp/ifconfig
55
56 # set to 1 if the default network configuration was loaded off the cd
57 # (no other configuration file found)
58 DEFAULT_NET_CONF=0
59
60
61 function net_init_failed() {
62     echo
63     echo $(date "+%H:%M:%S") " pl_netinit: network initialization failed with interface $ETH_DEVICE"
64     echo
65     echo For forensics
66     echo
67     echo ========== lspci beg
68     /sbin/lspci -n | /bin/grep "Class 0200"    
69     echo ========== lspci end
70     echo
71     echo ========== ifconfig beg
72     /sbin/ifconfig
73     echo ========== ifconfig end
74     echo ========== ip address show beg
75     ip address show
76     echo ========== ip address show end
77     echo 
78     echo $(date "+%H:%M:%S") " pl_netinit: network initialization failed with interface $ETH_DEVICE"
79     echo $(date "+%H:%M:%S") " pl_netinit: shutting down machine in two hours"
80     /bin/sleep 2h
81     /sbin/shutdown -h now
82     exit 1
83 }
84
85 # Function for checking the IP address to see if its sensible.
86 function check_ip() {
87     case "$*" in
88         "" | *[!0-9.]* | *[!0-9]) return 1 ;;
89     esac
90     local IFS=.
91     set -- $*
92     [ $# -eq 4 ] &&
93     [ ${1:-666} -le 255 ] && [ ${2:-666} -le 255 ] &&
94     [ ${3:-666} -le 255 ] && [ ${4:-666} -le 255 ]
95 }
96
97 # find and parse a node network configuration file. return 0 if not found,
98 # return 1 if found and parsed. if this is the case, DEFAULT_NET_CONF will 
99 # be set to 1. For any found configuration file, $USED_NET_CONF will
100 # contain the validated contents
101 function find_node_config() {
102     /bin/rm -f $TMP_OLD_FLOPPY_CONF_FILE 2>&1 > /dev/null
103
104     echo $(date "+%H:%M:%S") " pl_netinit: looking for node configuration file on floppy"
105     
106     /bin/mount -o ro -t $NODE_CONF_DEVICE_FS_TYPES /dev/fd0 \
107         $CONF_DEVICE_MOUNT_POINT 2>&1 > /dev/null
108     if [[ $? -eq 0 ]]; then
109
110         # 1. check for new named file first on the floppy disk
111         if [ -r "$CONF_DEVICE_MOUNT_POINT/$NEW_NODE_CONF_NAME" ]; then
112             conf_file="$CONF_DEVICE_MOUNT_POINT/$NEW_NODE_CONF_NAME"
113             echo $(date "+%H:%M:%S") " pl_netinit: found node configuration file $conf_file"
114             /etc/init.d/pl_validateconf < $conf_file > $USED_NET_CONF
115             /bin/umount $CONF_DEVICE_MOUNT_POINT
116             return 1
117
118         # since we have the floppy mounted already, see if an old file
119         # exists there so we don't have to remount the floppy when we need
120         # to check for an old file on it (later in the order). if it does
121         # just copy it off to a special location
122         elif [ -r "$CONF_DEVICE_MOUNT_POINT/$OLD_NODE_CONF_NAME" ]; then
123             conf_file="$CONF_DEVICE_MOUNT_POINT/$OLD_NODE_CONF_NAME"
124             /bin/cp -f $conf_file $TMP_OLD_FLOPPY_CONF_FILE
125             echo $(date "+%H:%M:%S") " pl_netinit: found old named configuration file, checking later."
126         else
127             echo $(date "+%H:%M:%S") " pl_netinit: floppy mounted, but no configuration file."
128         fi
129
130         /bin/umount $CONF_DEVICE_MOUNT_POINT
131     else
132         echo $(date "+%H:%M:%S") " pl_netinit: no floppy could be mounted, continuing search."
133     fi
134
135     # 2. check for a new named file on removable flash devices (those 
136     # that start with sd*, because usb_storage emulates scsi devices).
137     # to prevent checking normal scsi disks, also make sure
138     # /sys/block/<dev>/removable is set to 1
139
140     echo $(date "+%H:%M:%S") " pl_netinit: looking for node configuration file on flash based devices"
141
142     # make the sd* hd* expansion fail to an empty string if there are no sd
143     # devices
144     shopt -s nullglob
145
146     for device in /sys/block/[hsv]d*; do
147         removable=$(cat $device/removable)
148         if [[ $removable -ne 1 ]]; then
149             continue
150         fi
151
152         partitions=$(/bin/awk "\$4 ~ /$(basename $device)[0-9]*/ { print \$4 }" /proc/partitions)
153         for partition in $partitions ; do
154             check_dev=/dev/$partition
155
156             echo $(date "+%H:%M:%S") " pl_netinit: looking for node configuration file on device $check_dev"
157             /bin/mount -o ro -t $NODE_CONF_DEVICE_FS_TYPES $check_dev \
158                 $CONF_DEVICE_MOUNT_POINT 2>&1 > /dev/null
159             if [[ $? -eq 0 ]]; then
160                 if [ -r "$CONF_DEVICE_MOUNT_POINT/$NEW_NODE_CONF_NAME" ]; then
161                     conf_file="$CONF_DEVICE_MOUNT_POINT/$NEW_NODE_CONF_NAME"
162                     echo $(date "+%H:%M:%S") " pl_netinit: found node configuration file $conf_file"
163                     /etc/init.d/pl_validateconf < $conf_file > $USED_NET_CONF
164                     echo $(date "+%H:%M:%S") " pl_netinit: found configuration"
165                     /bin/umount $CONF_DEVICE_MOUNT_POINT
166                     return 1
167                 fi
168                 
169                 echo $(date "+%H:%M:%S") " pl_netinit: not found"
170
171                 /bin/umount $CONF_DEVICE_MOUNT_POINT
172             fi
173         done
174     done
175
176     # normal filename expansion setting
177     shopt -u nullglob
178
179     # 3. see if there is an old file on the floppy disk. if there was,
180     # the file $TMP_OLD_FLOPPY_CONF_FILE will be readable.
181     if [ -r "$TMP_OLD_FLOPPY_CONF_FILE" ]; then
182         conf_file=$TMP_OLD_FLOPPY_CONF_FILE
183         echo $(date "+%H:%M:%S") " pl_netinit: found node configuration file $conf_file"
184         /etc/init.d/pl_validateconf < $conf_file > $USED_NET_CONF
185         return 1
186     fi
187
188
189     # 4. check for plnode.txt on the cd at /usr/boot
190     echo $(date "+%H:%M:%S") " pl_netinit: looking for network configuration on cd in /usr/boot"
191     if [ -r "$CD_NET_CONF_BOOT" ]; then
192         
193         echo $(date "+%H:%M:%S") " pl_netinit: found cd configuration file $CD_NET_BOOT_CONF"
194         /etc/init.d/pl_validateconf < $CD_NET_CONF_BOOT > $USED_NET_CONF
195         return 1
196     fi
197     
198
199     # 5. check for plnode.txt on the cd at /usr
200     echo $(date "+%H:%M:%S") " pl_netinit: looking for network configuration on cd in /usr"
201     if [ -r "$CD_NET_CONF_ROOT" ]; then
202         
203         echo $(date "+%H:%M:%S") " pl_netinit: found cd configuration file $CD_NET_CONF_ROOT"
204         /etc/init.d/pl_validateconf < $CD_NET_CONF_ROOT > $USED_NET_CONF
205         return 1
206     fi
207
208
209     # 6. no node configuration file could be found, fall back to
210     # builtin default. this can't be used to install a machine, but
211     # will at least let it download and run the boot manager, which
212     # can inform the users appropriately.
213     echo $(date "+%H:%M:%S") " pl_netinit: using default network configuration"
214     if [ -r "$FALLBACK_NET_CONF" ]; then
215         echo $(date "+%H:%M:%S") " pl_netinit: found cd default configuration file $FALLBACK_NET_CONF"
216         /etc/init.d/pl_validateconf < $FALLBACK_NET_CONF > $USED_NET_CONF
217         DEFAULT_NET_CONF=1
218         return 1
219     fi
220
221     return 0
222 }
223
224
225 echo $(date "+%H:%M:%S") " pl_netinit: bringing loopback network device up"
226 /sbin/ifconfig lo 127.0.0.1 up
227
228 find_node_config
229 if [ $? -eq 0 ]; then
230     # no network configuration file found. this should not happen as the
231     # default cd image has a backup one. halt.
232     echo $(date "+%H:%M:%S") " pl_netinit: unable to find even a default network configuration"
233     echo $(date "+%H:%M:%S") " pl_netinit: file, this cd may be corrupt."
234     net_init_failed
235 fi
236
237 # load the configuration file. if it was a default one (not user specified),
238 # then remove the saved copy from /tmp, but continue on. since a network 
239 # configuration file is required and boot scripts only know about this location
240 # they will fail (as they should) - but the network will be up if dhcp is
241 # available
242
243 echo $(date "+%H:%M:%S") " pl_netinit: loading network configuration"
244 . $USED_NET_CONF
245
246 if [[ $DEFAULT_NET_CONF -eq 1 ]]; then
247     /bin/rm -f $USED_NET_CONF
248 fi
249
250 # initialize IPMI device
251 if [[ -n "$IPMI_ADDRESS" ]] ; then
252     echo -n "pl_netinit: initializing IPMI: "
253     cmd="ipnmac -i $IPMI_ADDRESS"
254     if [[ -n "$IPMI_MAC" ]] ; then
255         cmd="$cmd -m $IPMI_MAC"
256     fi
257     echo $cmd
258     $cmd
259 fi
260
261 # now, we need to find which device to use (ie, eth0 or eth1). start out
262 # by defaulting to eth0, then see if the network configuration file specified
263 # either a mac address (in which case we will need to find the device), or
264 # the device itself
265
266 ETH_DEVICE=
267 if [[ -n "$NET_DEVICE" ]]; then
268     # the user specified a mac address we should use. find the network
269     # device for it.
270     NET_DEVICE=$(tr A-Z a-z <<< $NET_DEVICE)
271
272     pushd /sys/class/net
273     for device in *; do
274         dev_address=$(cat $device/address | tr A-Z a-z)
275         if [ "$device" == "$NET_DEVICE" -o "$dev_address" == "$NET_DEVICE" ]; then
276             ETH_DEVICE=$device
277             echo $(date "+%H:%M:%S") " pl_netinit: found device $ETH_DEVICE with mac address $dev_address"
278             break
279         fi
280     done
281     popd
282 fi
283
284 # if we didn't find a device yet, check which is the primary
285 if [[ -z "$ETH_DEVICE" ]]; then
286     pushd /etc/sysconfig/network-scripts > /dev/null
287     for conf in ifcfg-*; do
288         egrep -q '^PRIMARY=["'"'"']?[yY1t]' $conf || continue
289         ETH_DEVICE=${conf#ifcfg-}
290         break
291     done
292     popd > /dev/null
293 fi
294
295 # still nothing? fail the boot.
296 if [[ -z "$ETH_DEVICE" ]]; then
297     echo $(date "+%H:%M:%S") " pl_netinit: unable to find a usable device, check to make sure"
298     echo $(date "+%H:%M:%S") " pl_netinit: the NET_DEVICE field in the configuration file"
299     echo $(date "+%H:%M:%S") " pl_netinit: corresponds with a network adapter on this system"
300     net_init_failed
301 fi
302
303 # within a systemd-driven startup, we often see this stage
304 # triggered before the network interface is actually exposed
305 # by udev/kernel
306 # although of course we have network-online.target
307 # as a requirement; go figure what systemd actually does..
308
309 # in any case, let us try to work around that by allowing some delay
310 # here
311
312 # tmp: Thierry June 2015
313 # on fedora 21 nodes we see this running in a context where eth0 is not known to the system
314 # could be related to a dependency that we poorly describe to systemd
315 # I am increasing this timeout to 2 minutes in order to check that conjecture
316 ALLOW=60
317 COUNTER=0
318 while true; do
319     if /sbin/ifconfig $ETH_DEVICE >& /dev/null; then
320         echo $(date "+%H:%M:%S") " pl_netinit: device present $ETH_DEVICE, proceeding (${COUNTER}s/${ALLOW}s)"
321         break
322     fi
323     echo $(date "+%H:%M:%S") " pl_netinit: waiting for device $ETH_DEVICE - ${COUNTER}s/${ALLOW}s"
324     set -x
325     /sbin/ifconfig
326     journalctl -b | egrep 'eth|bnx|udev'
327     systemctl list-unit-files | grep -i network
328     set +x 
329     COUNTER=$(($COUNTER+1))
330     [ $COUNTER -ge $ALLOW ] && net_init_failed
331     sleep 1
332 done
333
334
335 # actually check to make sure ifconfig <device> succeeds
336
337 /sbin/ifconfig $ETH_DEVICE up 2>&1 > /dev/null || {
338     echo $(date "+%H:%M:%S") " pl_netinit: device $ETH_DEVICE does not exist, most likely"
339     echo $(date "+%H:%M:%S") " pl_netinit: this CD does not have hardware support for your"
340     echo $(date "+%H:%M:%S") " pl_netinit: network adapter. please send the following lines"
341     echo $(date "+%H:%M:%S") " pl_netinit: to your PlanetLab support for further assistance"
342     net_init_failed
343 }
344
345 echo $(date "+%H:%M:%S") " pl_netinit: attempting to start networking"
346 /sbin/service network start
347
348 # for backwards compatibility
349 /sbin/ifconfig $ETH_DEVICE > $IFCONFIG_OUTPUT
350
351 echo $(date "+%H:%M:%S") " pl_netinit: network online"
352
353 echo "BEG post pl_netinit forensics"
354
355 file=/root/.ssh/authorized_keys
356 echo "$file"
357 if ! [ -f "$file" ]; then
358     echo "!!!!!!!!!! missing $file"
359 else
360     echo "---------- $file"
361     cat $file
362 fi
363
364 file="/etc/ssh/sshd_config"    
365 if ! [ -f "$file" ]; then
366     echo "!!!!!!!!!! missing $file"
367 else
368     echo '---------- egrep Pass|Auth|PAM' $file
369     egrep 'Pass|Auth|PAM' $file
370 fi
371
372 echo "END post pl_netinit forensics"