1 | #!/bin/sh |
---|
2 | # $Id: update_ws.sh,v 1.68 2004-05-05 18:39:52 ghudson Exp $ |
---|
3 | |
---|
4 | # Copyright 1996 by the Massachusetts Institute of Technology. |
---|
5 | # |
---|
6 | # Permission to use, copy, modify, and distribute this |
---|
7 | # software and its documentation for any purpose and without |
---|
8 | # fee is hereby granted, provided that the above copyright |
---|
9 | # notice appear in all copies and that both that copyright |
---|
10 | # notice and this permission notice appear in supporting |
---|
11 | # documentation, and that the name of M.I.T. not be used in |
---|
12 | # advertising or publicity pertaining to distribution of the |
---|
13 | # software without specific, written prior permission. |
---|
14 | # M.I.T. makes no representations about the suitability of |
---|
15 | # this software for any purpose. It is provided "as is" |
---|
16 | # without express or implied warranty. |
---|
17 | |
---|
18 | # update_ws (also known as auto_update) |
---|
19 | # |
---|
20 | # Check that an update is needed, and make sure the conditions necessary |
---|
21 | # for a successful update are met. Then prepare the machine for update, |
---|
22 | # and run do-update. |
---|
23 | |
---|
24 | # "tee" doesn't work reliably across OS versions (since it's not local on |
---|
25 | # Solaris), so emulate it in the shell. |
---|
26 | shelltee() { |
---|
27 | exec 3>$1 |
---|
28 | while IFS="" read line; do |
---|
29 | echo "$line" |
---|
30 | echo "$line" 1>&3 |
---|
31 | done |
---|
32 | } |
---|
33 | |
---|
34 | trap "" 1 15 |
---|
35 | |
---|
36 | export CONFDIR LIBDIR PATH HOSTTYPE |
---|
37 | CONFDIR=/etc/athena |
---|
38 | LIBDIR=/srvd/usr/athena/lib/update |
---|
39 | PATH=/bin:/etc:/usr/bin:/usr/ucb:/usr/bsd:/os/bin:/os/etc:/etc/athena:/bin/athena:/os/usr/bin:/usr/athena/sbin:/os/usr/ucb:/os/usr/bsd:/usr/sbin:$LIBDIR |
---|
40 | HOSTTYPE=`/bin/athena/machtype` |
---|
41 | |
---|
42 | case $0 in |
---|
43 | *auto_update) |
---|
44 | method=Auto |
---|
45 | why=$1 |
---|
46 | ;; |
---|
47 | *) |
---|
48 | method=Manual |
---|
49 | ;; |
---|
50 | esac |
---|
51 | |
---|
52 | # The -a option specifies that the update is automatic (run by the |
---|
53 | # boot script or reactivate). The -r option specifies that the update |
---|
54 | # is remote and that we shouldn't give the user a shell after the |
---|
55 | # reboot. |
---|
56 | while getopts a:r opt; do |
---|
57 | case $opt in |
---|
58 | a) |
---|
59 | method=Auto |
---|
60 | why=$OPTARG |
---|
61 | ;; |
---|
62 | r) |
---|
63 | method=Remote |
---|
64 | ;; |
---|
65 | \?) |
---|
66 | echo "$0 [-r] [-a reactivate|rc]" 1>&2 |
---|
67 | exit 1 |
---|
68 | ;; |
---|
69 | esac |
---|
70 | done |
---|
71 | shift `expr $OPTIND - 1` |
---|
72 | |
---|
73 | case `id` in |
---|
74 | "uid=0("*) |
---|
75 | ;; |
---|
76 | *) |
---|
77 | echo "You are not root. This update script must be run as root." |
---|
78 | exit 1 |
---|
79 | ;; |
---|
80 | esac |
---|
81 | |
---|
82 | # If /srvd is not mounted, quit. |
---|
83 | if [ ! -d /srvd/bin ]; then |
---|
84 | exit 1 |
---|
85 | fi |
---|
86 | |
---|
87 | if [ ! -f "$CONFDIR/version" ]; then |
---|
88 | echo "Athena Update (???) Version 0.0A Mon Jan 1 00:00:00 EDT 0000" \ |
---|
89 | > "$CONFDIR/version" |
---|
90 | fi |
---|
91 | |
---|
92 | newvers=`awk '{a=$5}; END{print a}' /srvd/.rvdinfo` |
---|
93 | version=`awk '$0 != "" {a=$5}; END{print a}' "$CONFDIR/version"` |
---|
94 | |
---|
95 | if [ -f "$CONFDIR/rc.conf" ]; then |
---|
96 | . "$CONFDIR/rc.conf" |
---|
97 | else |
---|
98 | export PUBLIC AUTOUPDATE HOST |
---|
99 | PUBLIC=true |
---|
100 | AUTOUPDATE=true |
---|
101 | HOST=`hostname` |
---|
102 | fi |
---|
103 | |
---|
104 | # Make sure /var/athena exists (it was introduced in 8.1.0) so we have a |
---|
105 | # place to put the temporary clusterinfo file and the desync state file |
---|
106 | # and the update log. |
---|
107 | if [ ! -d /var/athena ]; then |
---|
108 | mkdir -m 755 /var/athena |
---|
109 | fi |
---|
110 | |
---|
111 | # Get and read cluster information, to set one or both of |
---|
112 | # NEW_TESTING_RELEASE and NEW_PRODUCTION_RELEASE if there are new |
---|
113 | # releases available. |
---|
114 | /etc/athena/save_cluster_info |
---|
115 | if [ -f /var/athena/clusterinfo.bsh ]; then |
---|
116 | . /var/athena/clusterinfo.bsh |
---|
117 | fi |
---|
118 | |
---|
119 | # Check if we're already in the middle of an update. |
---|
120 | case $version in |
---|
121 | [0-9]*) |
---|
122 | # If this field starts with a digit, we're running a proper |
---|
123 | # release. Otherwise... |
---|
124 | ;; |
---|
125 | *) |
---|
126 | if [ ! -f /var/tmp/update.check ]; then |
---|
127 | logger -t $HOST -p user.notice at revision $version |
---|
128 | touch /var/tmp/update.check |
---|
129 | fi |
---|
130 | |
---|
131 | echo "This system is in the middle of an update. Please contact" |
---|
132 | echo "Athena Cluster Services at x3-1410. Thank you. -Athena Operations" |
---|
133 | exit 1 |
---|
134 | ;; |
---|
135 | esac |
---|
136 | |
---|
137 | # Find out if the version in /srvd/.rvdinfo is newer than |
---|
138 | # /etc/athena/version. Distinguish between major, minor, and patch |
---|
139 | # releases so that we can desynchronize patch releases. |
---|
140 | packsnewer=`echo "$newvers $version" | awk '{ |
---|
141 | split($1, v1, "."); |
---|
142 | split($2, v2, "."); |
---|
143 | if (v1[1] + 0 > v2[1] + 0) |
---|
144 | print "major"; |
---|
145 | else if (v1[1] + 0 == v2[1] + 0 && v1[2] + 0 > v2[2] + 0) |
---|
146 | print "minor"; |
---|
147 | else if (v1[1] == v2[1] && v1[2] == v2[2] && v1[3] + 0 > v2[3] + 0) |
---|
148 | print "patch"; }'` |
---|
149 | |
---|
150 | # If the packs aren't any newer, print an appropriate message and exit. |
---|
151 | if [ -z "$packsnewer" ]; then |
---|
152 | if [ Auto != "$method" ]; then |
---|
153 | # User ran update_ws; display something appropriate. |
---|
154 | if [ -n "$NEW_PRODUCTION_RELEASE" -o \ |
---|
155 | -n "$NEW_TESTING_RELEASE" ]; then |
---|
156 | echo "Your workstation software already matches the version on the" |
---|
157 | echo "system packs. You must manually attach a newer version of the" |
---|
158 | echo "system packs to update beyond this point." |
---|
159 | else |
---|
160 | echo "It appears you already have this update." |
---|
161 | fi |
---|
162 | else |
---|
163 | # System ran auto_update; point out new releases if available. |
---|
164 | if [ -n "$NEW_PRODUCTION_RELEASE" ]; then |
---|
165 | ver=$NEW_PRODUCTION_RELEASE |
---|
166 | echo "A new Athena release ($ver) is available. Since it may be" |
---|
167 | echo "incompatible with your workstation software, your workstation is" |
---|
168 | echo "still using the old system packs. Please contact Athena Cluster" |
---|
169 | echo "Services (x3-1410) to have your workstation updated." |
---|
170 | fi |
---|
171 | if [ -n "$NEW_TESTING_RELEASE" ]; then |
---|
172 | ver=$NEW_TESTING_RELEASE |
---|
173 | echo "A new Athena release ($ver) is now in testing. You are" |
---|
174 | echo "theoretically interested in this phase of testing, but because" |
---|
175 | echo "there may be bugs which would inconvenience your work, you must" |
---|
176 | echo "update to this release manually. Please contact Athena Cluster" |
---|
177 | echo "Services (x3-1410) if you have not received instructions on how" |
---|
178 | echo "to do so." |
---|
179 | fi |
---|
180 | fi |
---|
181 | exit 0 |
---|
182 | fi |
---|
183 | |
---|
184 | # The packs are newer, but if we were run as auto_update, we don't want to do |
---|
185 | # an update unless the machine is autoupdate (or public). |
---|
186 | if [ Auto = "$method" -a true != "$AUTOUPDATE" -a true != "$PUBLIC" ]; then |
---|
187 | echo "A new version of Athena software is now available. Please contact" |
---|
188 | echo "Athena Cluster Services (x3-1410) to get more information on how to" |
---|
189 | echo "update your workstation yourself, or to schedule us to do it for you." |
---|
190 | echo "Thank you. -Athena Operations" |
---|
191 | if [ ! -f /var/tmp/update.check ]; then |
---|
192 | logger -t "$HOST" -p user.notice at revision $version |
---|
193 | cp /dev/null /var/tmp/update.check |
---|
194 | fi |
---|
195 | exit 1 |
---|
196 | fi |
---|
197 | |
---|
198 | if [ Auto = "$method" -a patch = "$packsnewer" ]; then |
---|
199 | # There is a patch release available and we want to take the update, |
---|
200 | # but not necessarily right now. Use desync to stagger the update |
---|
201 | # over a four-hour period. (Use the version from /srvd for now to |
---|
202 | # make sure the -t option works, since that option was not |
---|
203 | # introduced until 8.1.) Note that we only do desynchronization |
---|
204 | # here for patch releases. Desynchronization for major or minor |
---|
205 | # releases is handled in getcluster, since we don't want the |
---|
206 | # workstation to run with a new, possibly incompatible version of |
---|
207 | # the packs. |
---|
208 | |
---|
209 | /srvd/etc/athena/desync -t /var/athena/update.desync 14400 |
---|
210 | if [ $? -ne 0 ]; then |
---|
211 | exit 0 |
---|
212 | fi |
---|
213 | fi |
---|
214 | |
---|
215 | # Beyond this point, if the update fails, it's probably due to a full |
---|
216 | # release which we can't take for some reason. A machine with new |
---|
217 | # system packs attached won't function properly in this state, so we |
---|
218 | # should attempt to reattach the old system packs before exiting if |
---|
219 | # this was an automatic update attempt. This function takes care of |
---|
220 | # reattaching the old system packs and exiting with an error status. |
---|
221 | failupdate() { |
---|
222 | if [ Auto = "$method" ]; then |
---|
223 | echo "Attempting to reattach old system packs" |
---|
224 | detach "$SYSLIB" |
---|
225 | AUTOUPDATE=false getcluster -b -l /etc/athena/cluster.local \ |
---|
226 | "$HOST" "$version" > /var/athena/cluster.oldrel |
---|
227 | if [ -s /var/athena/cluster.oldrel ]; then |
---|
228 | . /var/athena/cluster.oldrel |
---|
229 | fi |
---|
230 | attach -O "$SYSLIB" |
---|
231 | fi |
---|
232 | exit 1 |
---|
233 | } |
---|
234 | |
---|
235 | # This check needs to be updated for each full release. It verifies |
---|
236 | # that people aren't updating across two full releases, which |
---|
237 | # generally doesn't work. |
---|
238 | case "$version" in |
---|
239 | 9.2.*|9.3.*) |
---|
240 | ;; |
---|
241 | *) |
---|
242 | echo "You must update by only one full release at a time." |
---|
243 | failupdate |
---|
244 | ;; |
---|
245 | esac |
---|
246 | |
---|
247 | case "$HOSTTYPE" in |
---|
248 | sun4) |
---|
249 | # Don't allow the update on multi-partition Suns. |
---|
250 | if [ "`df /usr | awk '{print $1}'`" = /usr ]; then |
---|
251 | echo "This machine has a separate /usr partition from the root partition," |
---|
252 | echo "which is not supported by Athena release 9.3. You must reinstall" |
---|
253 | echo "in order to take this update. (If you have a 4GB or smaller disk," |
---|
254 | echo "you cannot take this update at all.)" |
---|
255 | logger -t "$HOST" -p user.notice multi-partition sun failed to update |
---|
256 | failupdate |
---|
257 | fi |
---|
258 | |
---|
259 | # Set required filesystem size for the 9.3 release, and required |
---|
260 | # filesystem space for the 9.3 update. Filesystem overhead consumes |
---|
261 | # about 7% of a partition, so we check for a filesystem size 10% |
---|
262 | # less than the partition size we want. We get some extra margin |
---|
263 | # from minfree, but we don't deliberately rely on that. |
---|
264 | reqsize=4718592 # 5GB partition; measured use 3447108K |
---|
265 | reqspace=2621440 # 2.5GB; measured space increase 2257525K |
---|
266 | |
---|
267 | # Check filesystem size. |
---|
268 | rootsize=`df -k / | awk '{ x = $2; } END { print x; }'` |
---|
269 | if [ "$reqsize" -gt "$rootsize" ]; then |
---|
270 | echo "Your root filesystem is not big enough for Athena release 9.3" |
---|
271 | echo "and higher. You cannot take this update." |
---|
272 | logger -t "$HOST" -p user.notice / too small to take update |
---|
273 | failupdate |
---|
274 | fi |
---|
275 | |
---|
276 | # Check free space if this is a full update to 9.3. |
---|
277 | case $version in |
---|
278 | 9.2.*) |
---|
279 | rootspace=`df -k / | awk '{ x = $4; } END { print x; }'` |
---|
280 | if [ "$reqspace" -gt "$rootspace" ]; then |
---|
281 | echo "The / partition must have ${reqspace}K free for this update." |
---|
282 | echo "Please reinstall or clean local files off the / partition." |
---|
283 | logger -t "$HOST" -p user.notice / too full to take update |
---|
284 | failupdate |
---|
285 | fi |
---|
286 | ;; |
---|
287 | esac |
---|
288 | |
---|
289 | ;; |
---|
290 | esac |
---|
291 | |
---|
292 | # If this is a private workstation, make sure we can recreate the mkserv |
---|
293 | # state of the machine after the update. |
---|
294 | if [ -d /var/server ] ; then |
---|
295 | /srvd/usr/athena/bin/mkserv updatetest |
---|
296 | if [ $? -ne 0 ]; then |
---|
297 | echo "mkserv services cannot be found for all services. Update cannot be" |
---|
298 | echo "performed." |
---|
299 | logger -t "$HOST" -p user.notice missing mkserv services, unable to take update |
---|
300 | failupdate |
---|
301 | fi |
---|
302 | fi |
---|
303 | |
---|
304 | # Tell dm to shut down everything and sleep forever during the update. |
---|
305 | if [ Auto = "$method" -a reactivate = "$why" ]; then |
---|
306 | if [ -f /var/athena/dm.pid ]; then |
---|
307 | kill -FPE `cat /var/athena/dm.pid` |
---|
308 | fi |
---|
309 | # 8.0 and prior machines still have /etc/athena/dm.pid. |
---|
310 | if [ -f /etc/athena/dm.pid ]; then |
---|
311 | kill -FPE `cat /etc/athena/dm.pid` |
---|
312 | fi |
---|
313 | |
---|
314 | if [ -f /etc/init.d/axdm ]; then |
---|
315 | /etc/init.d/axdm stop |
---|
316 | fi |
---|
317 | |
---|
318 | sleep 2 |
---|
319 | fi |
---|
320 | |
---|
321 | # Everything is all set; do the actual update. |
---|
322 | rm -f /var/athena/update.log |
---|
323 | if [ Auto = "$method" ]; then |
---|
324 | echo |
---|
325 | echo "THIS WORKSTATION IS ABOUT TO UNDERGO AN AUTOMATIC SOFTWARE UPDATE." |
---|
326 | echo "THIS PROCEDURE MAY TAKE SOME TIME." |
---|
327 | echo |
---|
328 | echo "PLEASE DO NOT DISTURB IT WHILE THIS IS IN PROGRESS." |
---|
329 | echo |
---|
330 | exec sh "$LIBDIR/do-update" "$method" "$version" "$newvers" \ |
---|
331 | < /dev/null 2>&1 | shelltee /var/athena/update.log |
---|
332 | else |
---|
333 | exec sh "$LIBDIR/do-update" "$method" "$version" "$newvers" \ |
---|
334 | 2>&1 | shelltee /var/athena/update.log |
---|
335 | fi |
---|