417a1839a678bb10a137c318024c8e35b4e2defc
[bootcd.git] / initscripts / pl_boot
1 #!/bin/bash
2
3 ### xxx tmp debug
4
5 set -x
6 echo pl_boot on console > /dev/console
7 exec 2>&1
8 exec > /dev/console
9 echo pl_boot plain
10
11 ###
12 . /etc/init.d/pl_functions
13
14 . /tmp/planet.cnf
15
16 # Run gpg once to create default options
17 GNUPGHOME=/root
18 export GNUPGHOME
19 /usr/bin/gpg --yes 2>/dev/null </dev/null
20
21 # if this file is present, cancel the boot (exit this script)
22 CANCEL_BOOT_FLAG=/tmp/CANCEL_BOOT
23
24 # how many times to fail in attempting to contact primary server
25 # before falling back to original. if the backup fails this many times
26 # too, then the process is repeated started with the primary server
27 ATTEMPTS_BEFORE_BACKUP=3
28
29 # where all the configuration files for contacting
30 # the boot server are stored
31 BOOT_DIR=/usr/boot/
32
33 # get the server we are going to be contacting
34 BOOT_SERVER=$(cat $BOOT_DIR/boot_server)
35 BOOT_SERVER_PORT=$(cat $BOOT_DIR/boot_server_port)
36
37 # the file to request from the boot server
38 BOOT_SERVER_PATH=$(cat $BOOT_DIR/boot_server_path)
39
40 # location of the cacert for this boot server
41 BOOT_SERVER_CACERT=$BOOT_DIR/cacert.pem
42
43 # location of the gpg key ring to verify scripts
44 BOOT_SERVER_GPG_KEYRING=$BOOT_DIR/pubring.gpg
45
46 # get the backup server we are going to be contacting
47 BACKUP_BOOT_SERVER=$(cat $BOOT_DIR/backup/boot_server)
48 BACKUP_BOOT_SERVER_PORT=$(cat $BOOT_DIR/backup/boot_server_port)
49
50 # the file to request from the backup boot server
51 BACKUP_BOOT_SERVER_PATH=$(cat $BOOT_DIR/backup/boot_server_path)
52
53 # location of the cacert for the backup boot server
54 BACKUP_BOOT_SERVER_CACERT=$BOOT_DIR/backup/cacert.pem
55
56 # location of the gpg key ring for backup server to verify scripts
57 BACKUP_BOOT_SERVER_GPG_KEYRING=$BOOT_DIR/backup/pubring.gpg
58
59 # location of a file containing this boot cd version
60 BOOT_VERSION_FILE=/pl_version
61
62 # the locations of the downloaded scripts
63 UNVERIFIED_SCRIPT=/tmp/bootscript.gpg
64 VERIFIED_SCRIPT=/tmp/bootscript
65
66
67 # --------------------------
68
69
70 # now, contact the boot server, run the script, and do it over again.
71 contact_count=0
72
73 # set to one when we are trying to contact backup server
74 on_backup_server=0
75
76 # start out contacting the primary servers
77 CONNECT_BOOT_SERVER=$BOOT_SERVER
78 CONNECT_BOOT_SERVER_PORT=$BOOT_SERVER_PORT
79 CONNECT_BOOT_SERVER_PATH=$BOOT_SERVER_PATH
80 CONNECT_BOOT_SERVER_GPG_KEYRING=$BOOT_SERVER_GPG_KEYRING
81 CONNECT_BOOT_SERVER_CACERT=$BOOT_SERVER_CACERT
82
83 while : ; do
84
85     if [[ -f $CANCEL_BOOT_FLAG ]]; then
86         echo $(date "+%H:%M:%S") " pl_boot: got request to cancel boot, exiting"
87         exit 0
88     fi
89     
90     if [[ $contact_count -ge $ATTEMPTS_BEFORE_BACKUP ]]; then
91
92         contact_count=0
93
94         if [[ $on_backup_server == 1 ]]; then
95             echo $(date "+%H:%M:%S") " pl_boot: failed to contact backup server, trying primary $BOOT_SERVER"
96
97             on_backup_server=0
98
99             CONNECT_BOOT_SERVER=$BOOT_SERVER
100             CONNECT_BOOT_SERVER_PORT=$BOOT_SERVER_PORT
101             CONNECT_BOOT_SERVER_PATH=$BOOT_SERVER_PATH
102             CONNECT_BOOT_SERVER_GPG_KEYRING=$BOOT_SERVER_GPG_KEYRING
103             CONNECT_BOOT_SERVER_CACERT=$BOOT_SERVER_CACERT
104         else
105             echo $(date "+%H:%M:%S") " pl_boot: failed to contact primary server, trying backup $BACKUP_BOOT_SERVER"
106
107             on_backup_server=1
108
109             CONNECT_BOOT_SERVER=$BACKUP_BOOT_SERVER
110             CONNECT_BOOT_SERVER_PORT=$BACKUP_BOOT_SERVER_PORT
111             CONNECT_BOOT_SERVER_PATH=$BACKUP_BOOT_SERVER_PATH
112             CONNECT_BOOT_SERVER_GPG_KEYRING=$BACKUP_BOOT_SERVER_GPG_KEYRING
113             CONNECT_BOOT_SERVER_CACERT=$BACKUP_BOOT_SERVER_CACERT
114         fi
115     fi
116
117     if [[ $contact_count != 0 ]]; then
118
119         echo $(date "+%H:%M:%S") " pl_boot: next attempt in 30s, to fetch script from server at $CONNECT_BOOT_SERVER"
120         /bin/sleep 30
121     fi
122
123     # assemble the curl transaction
124     CURL_CMD="/usr/bin/curl \
125         --connect-timeout 60 \
126         --max-time 600 \
127         --form version=<$BOOT_VERSION_FILE \
128         --form cmdline=</proc/cmdline \
129         --form uptime=</proc/uptime \
130         --form ifconfig=</tmp/ifconfig \
131         --form nonce=</tmp/nonce \
132         --location \
133         --output $UNVERIFIED_SCRIPT \
134         --sslv3  \
135         --silent \
136         --show-error \
137         --fail \
138         --stderr /tmp/curl_errors \
139         --cacert $CONNECT_BOOT_SERVER_CACERT \
140    https://$CONNECT_BOOT_SERVER:$CONNECT_BOOT_SERVER_PORT/$CONNECT_BOOT_SERVER_PATH"
141
142     # assemble the gpg command line
143     GPG_CMD="/usr/bin/gpg \
144         --no-default-keyring \
145         --keyring $CONNECT_BOOT_SERVER_GPG_KEYRING \
146         --output $VERIFIED_SCRIPT \
147         --always-trust \
148         --decrypt $UNVERIFIED_SCRIPT"
149
150     echo $(date "+%H:%M:%S") " pl_boot: generating new nonce"
151     /usr/bin/head --bytes=32 /dev/urandom | \
152     /usr/bin/od -tx1 -An --width=32 | \
153     /bin/sed 's/ //g' > /tmp/nonce
154
155     echo $(date "+%H:%M:%S") " pl_boot: fetching script from boot server $CONNECT_BOOT_SERVER"
156     ((contact_count++))
157     rm -f $UNVERIFIED_SCRIPT
158     $CURL_CMD
159     curl_err=$?
160     if [ $curl_err -ne 0 ]; then
161         echo $(date "+%H:%M:%S") " pl_boot: curl request failed with error $curl_err:"
162         cat /tmp/curl_errors
163         echo
164         if [ -n "$DISCONNECTED_OPERATION" ]; then
165             mkdir /tmp/boot-media
166             mount -U "$DISCONNECTED_OPERATION" /tmp/boot-media
167             cp /tmp/boot-media/bootscript.gpg $UNVERIFIED_SCRIPT
168             umount /tmp/boot-media
169             rmdir /tmp/boot-media
170         else
171             case $curl_err in
172                 6)
173                     echo $(date "+%H:%M:%S") " This error likely indicates a networking configuration error. "
174                     echo $(date "+%H:%M:%S") " Please, check whether you can ping this machine.  If you can, "
175                     echo $(date "+%H:%M:%S") " we recommend checking your DNS settings.  If you cannot, then "
176                     echo $(date "+%H:%M:%S") " please double check your network settings registered at PLC and "
177                     echo $(date "+%H:%M:%S") " stored on this Boot Image."
178                 ;;
179                 60)
180                     echo $(date "+%H:%M:%S") " This error likely indicates that the hardware clock is likely not set "
181                     echo $(date "+%H:%M:%S") " to GMT.  The result is that authentication between the local and "
182                     echo $(date "+%H:%M:%S") " remote site fails.  Please double check this machine's system "
183                     echo $(date "+%H:%M:%S") " clock, and set it to GMT in the BIOS. If after rebooting the same "
184                     echo $(date "+%H:%M:%S") " error occurs, please report the situation to support@planet-lab.org "
185                     echo $(date "+%H:%M:%S") " with as much detail as possible."
186                 ;;
187                 *)
188                     echo $(date "+%H:%M:%S") " The best-practice approach for handling this error is not yet "
189                     echo $(date "+%H:%M:%S") " documented.  Please report this error to support@planet-lab.org "
190                     echo $(date "+%H:%M:%S") " with as much detail as possible."
191                 ;;
192             esac
193             # in any case display as much info as we can (see pl_functions)
194             pl_network_sanity_checks
195             # retry
196             continue
197         fi
198     elif [ -n "$DISCONNECTED_OPERATION" ]; then
199         mkdir /tmp/boot-media
200         mount -U "$DISCONNECTED_OPERATION" /tmp/boot-media
201         cp $UNVERIFIED_SCRIPT /tmp/boot-media
202         umount /tmp/boot-media
203         rmdir /tmp/boot-media
204     fi 
205
206     echo $(date "+%H:%M:%S") " pl_boot: verifying downloaded script"
207     rm -f $VERIFIED_SCRIPT
208     $GPG_CMD 2> /tmp/gpg_errors
209     if [ $? -ne 0 ]; then
210         echo $(date "+%H:%M:%S") " pl_boot: failed to verify file:"
211         cat /tmp/gpg_errors
212         echo
213         continue
214     fi
215     echo $(date "+%H:%M:%S") " pl_boot: decrypted and verified script succesfully"
216
217     echo $(date "+%H:%M:%S") " pl_boot: handing control to download script"
218     rm -f $UNVERIFIED_SCRIPT
219     chmod +x $VERIFIED_SCRIPT
220     $VERIFIED_SCRIPT
221     
222     echo $(date "+%H:%M:%S") " pl_boot: downloaded script has returned"
223 done
224
225 echo $(date "+%H:%M:%S") " pl_boot: automatic boot process canceled by user"