Commit | Line | Data |
---|---|---|
a816ce8e AHJ |
1 | #!/bin/sh |
2 | # | |
3 | # This script takes in account a disk list to make a lvm(8) stripe | |
4 | # which will contain a hammer filesystem and the swap partition. | |
5 | # | |
6 | # Be aware that this is just to provide _basic_ installation | |
7 | # functionalities and it may need actions from the sysadmin to | |
8 | # properly install and get a consistent installed system. | |
9 | ||
10 | # set -x | |
11 | ||
12 | export LVM_SUPPRESS_FD_WARNINGS=1 | |
13 | ||
14 | disklist="da0 da1" | |
15 | bootdisk="" | |
16 | logfile="/tmp/hammer_lvm_stripe.log" | |
17 | ||
18 | # | |
19 | # err exitval message | |
20 | # Display an error and exit | |
21 | # | |
22 | err() | |
23 | { | |
24 | exitval=$1 | |
25 | shift | |
26 | ||
27 | echo 1>&2 "$0: ERROR: $*" | |
28 | exit $exitval | |
29 | } | |
30 | ||
31 | # | |
32 | # cktmpdir | |
33 | # | |
34 | # Checks whether /tmp is writeable. | |
35 | # Exit if not | |
36 | # | |
37 | cktmpdir() | |
38 | { | |
39 | mktemp "/tmp/XXX" >> ${logfile} 2>&1 | |
40 | ||
41 | if [ $? -ne 0 ]; then | |
42 | err 1 "/tmp directory must be writeable" | |
43 | fi | |
44 | } | |
45 | ||
46 | # | |
47 | # ckpreinstall | |
48 | # | |
49 | # Checks whether lv nodes exist which would may | |
50 | # indicate an installation already succeeded or | |
51 | # a previous failed one. | |
52 | # | |
53 | ckpreinstall() | |
54 | { | |
55 | ||
56 | # Try to activate the volume first | |
57 | vgchange -a y main >> ${logfile} 2>&1 | |
58 | ||
59 | if [ -c /dev/mapper/main-lv_root -o -c /dev/mapper/main-lv_swap ]; then | |
60 | echo " ERROR: Either a previous installation failed or your installation" | |
61 | echo " is already done. If the former, please follow instructions below." | |
62 | echo "" | |
63 | ||
64 | lvmexit | |
65 | fi | |
66 | } | |
67 | ||
68 | ||
69 | # | |
70 | # ckstatus status progname | |
71 | # | |
72 | # Checks exit status of programs and if it fails | |
73 | # it exists with a message | |
74 | # | |
75 | ckstatus() | |
76 | { | |
77 | local st=$1 | |
78 | local prog=$2 | |
79 | ||
80 | if [ ${st} -ne 0 ]; then | |
81 | err 1 "Failed to run $2. Check ${logfile}" | |
82 | fi | |
83 | } | |
84 | ||
85 | # | |
86 | # ckloadmod modname | |
87 | # | |
88 | # Checks if a module is loaded, if not | |
89 | # it tries to load it. In case of failure | |
90 | # it exits | |
91 | # | |
92 | ckloadmod() | |
93 | { | |
94 | local mod=$1 | |
95 | ||
96 | if ! kldstat -q -m ${mod}; then | |
97 | kldload $1 >> ${logfile} 2>&1 | |
98 | ||
99 | if [ $? -ne 0 ]; then | |
100 | err 1 "Could not load ${mod}" | |
101 | fi | |
102 | fi | |
103 | } | |
104 | ||
105 | # | |
106 | # prepdisk disk | |
107 | # | |
108 | # Clears the first sectors of the disk | |
109 | # and then prepares the disk for disklabel. | |
110 | # It also installs bootblocks in the first | |
111 | # disk of the list. | |
112 | # | |
113 | prepdisk() | |
114 | { | |
115 | local disk=$1 | |
116 | ||
117 | # Hey don't shoot yourself in the foot | |
118 | if [ ! "$disk" = "" ]; then | |
119 | mount | fgrep ${disk} >> ${logfile} 2>&1 | |
120 | ||
121 | if [ $? -ne 1 ]; then | |
122 | err 1 "${disk} is already being used, aborting" | |
123 | fi | |
124 | fi | |
125 | ||
126 | if [ "${bootdisk}" = "" ]; then | |
127 | bootdisk=${disk} | |
128 | fi | |
129 | ||
130 | dd if=/dev/zero of=/dev/${disk} bs=32k count=16 >> ${logfile} 2>&1 | |
131 | ckstatus $? "dd" | |
132 | ||
133 | fdisk -IB ${disk} >> ${logfile} 2>&1 | |
134 | ckstatus $? "fdisk" | |
135 | ||
0a319615 | 136 | disklabel -r -w ${disk}s1 >> ${logfile} 2>&1 |
a816ce8e AHJ |
137 | ckstatus $? "disklabel" |
138 | ||
139 | if [ ! "${bootdisk}" = "" ]; then | |
140 | disklabel -B ${disk}s1 >> ${logfile} 2>&1 | |
141 | ckstatus $? "disklabel" | |
142 | fi | |
143 | } | |
144 | ||
145 | # | |
146 | # mklabel disk | |
147 | # | |
148 | # Create same labels for every disk | |
149 | # except for the disk that will contain | |
150 | # /boot partition | |
151 | # | |
152 | mklabel() | |
153 | { | |
154 | local disk=$1 | |
155 | ||
156 | disklabel ${disk}s1 > /tmp/label | |
157 | ckstatus $? "disklabel" | |
158 | ||
159 | if [ "${disk}" = "${bootdisk}" ]; then | |
160 | cat >> /tmp/label <<EOF | |
161 | a: 768m 0 4.2BSD | |
162 | d: * * unknown | |
163 | EOF | |
164 | else | |
165 | cat >> /tmp/label <<EOF | |
166 | d: * * unknown | |
167 | EOF | |
168 | ||
169 | fi | |
170 | ||
171 | disklabel -R ${disk}s1 /tmp/label >> ${logfile} 2>&1 | |
172 | ckstatus $? "disklabel" | |
173 | } | |
174 | ||
175 | ||
176 | # | |
177 | # lvmexit | |
178 | # | |
179 | # lvm exit message | |
180 | lvmexit() | |
181 | { | |
182 | local status=$1 | |
183 | ||
184 | if [ $# -ne 0 ]; then | |
185 | if [ ${status} -eq 0 ]; then | |
186 | return | |
187 | fi | |
188 | fi | |
189 | ||
190 | echo " There was an error during or after LVM operations for this" | |
191 | echo " installation and those operations done cannot be reverted" | |
192 | echo " by the script itself. Please revert them manually:" | |
193 | echo "" | |
194 | echo " Basically you need to perform these steps:" | |
195 | echo " 1. Remove all logical volumes in VG main (lv_swap, lv_root)" | |
196 | echo " 2. Remove main volume group" | |
197 | echo " 3. Remove all the physical volumes. PVs are all in [disk]1d" | |
198 | echo " For example, if you have 2 disks, you need to remove:" | |
199 | echo " /sbin/pvremove /dev/da0s1d" | |
200 | echo " /sbin/pvremove /dev/da1s1d" | |
201 | echo "" | |
202 | exit 1 | |
203 | } | |
204 | ||
205 | # | |
206 | # rev_lvmops | |
207 | # | |
208 | # Revert all lvmops | |
209 | # | |
210 | rev_lvmops() | |
211 | { | |
212 | ||
213 | vgchange -a n main >> ${logfile} 2>&1 | |
214 | ||
215 | lvremove --force lv_swap main >> ${logfile} 2>&1 | |
216 | if [ $? -ne 0 ]; then | |
217 | lvmexit | |
218 | fi | |
219 | ||
220 | lvremove --force lv_root main >> ${logfile} 2>&1 | |
221 | if [ $? -ne 0 ]; then | |
222 | lvmexit | |
223 | fi | |
224 | ||
225 | vgremove --force main >> ${logfile} 2>&1 | |
226 | if [ $? -ne 0 ]; then | |
227 | lvmexit | |
228 | fi | |
229 | ||
230 | for disk in ${disklist} | |
231 | do | |
232 | pvremove /dev/${disk}s1d >> ${logfile} 2>&1 | |
233 | done | |
234 | } | |
235 | ||
236 | # | |
237 | # lvmops | |
238 | # | |
239 | # Create physical volumes, volume group 'main' and | |
240 | # the ROOT hammer filesystem where everything will | |
241 | # be installed. swap is also created as a log. volume. | |
242 | # | |
243 | lvmops() | |
244 | { | |
245 | local lst="" | |
246 | local tmp="" | |
247 | ||
248 | for disk in ${disklist} | |
249 | do | |
250 | pvcreate /dev/${disk}s1d >> ${logfile} 2>&1 | |
251 | if [ $? -ne 0 ]; then | |
252 | rev_lvmops | |
253 | fi | |
254 | tmp=${lst} | |
255 | lst="${tmp} /dev/${disk}s1d" | |
256 | ||
257 | # Be safe | |
258 | sync | |
259 | sleep 1 | |
260 | done | |
261 | ||
262 | # Do a full scan in the hope the lvm | |
263 | # cache is rebuilt | |
264 | pvscan >> ${logfile} 2>&1 | |
265 | ||
266 | vgcreate main ${lst} >> ${logfile} 2>&1 | |
267 | if [ $? -ne 0 ]; then | |
268 | rev_lvmops | |
269 | fi | |
270 | ||
271 | # We need to sync and wait for some secs to settle | |
272 | # Otherwise /dev/main won't appear | |
273 | echo " Settling LVM operations (5 secs)" | |
274 | sync | |
275 | sleep 5 | |
276 | vgscan >> ${logfile} 2>&1 | |
277 | ||
278 | lvcreate -Z n -n lv_swap -L ${memtotal} main >> ${logfile} 2>&1 | |
279 | if [ $? -ne 0 ]; then | |
280 | rev_lvmops | |
281 | fi | |
282 | ||
283 | # We sync in every lvm operation | |
284 | sync | |
285 | lvscan >> ${logfile} 2>&1 | |
286 | sleep 1 | |
287 | ||
288 | lvcreate -Z n -n lv_root -l 100%FREE main >> ${logfile} 2>&1 | |
289 | if [ $? -ne 0 ]; then | |
290 | rev_lvmops | |
291 | fi | |
292 | ||
293 | } | |
294 | ||
295 | echo "ALL DATA IN DISKS ${disklist} WILL BE LOST!" | |
296 | echo "Press ^C to abort." | |
297 | for n in 10 9 8 7 6 5 4 3 2 1 | |
298 | do | |
299 | echo -n " ${n}" | |
300 | sleep 1 | |
301 | done | |
302 | echo "" | |
303 | ||
304 | # /tmp has to be writeable | |
305 | echo "* Checking /tmp is writeable" | |
306 | cktmpdir | |
307 | ||
308 | rm "${logfile}" >> ${logfile} 2>&1 | |
309 | echo "* Output to ${logfile}" | |
310 | ||
311 | # calculate memory | |
312 | tmp=`sysctl hw.physmem | cut -w -f 2` | |
313 | memtotal=`expr ${tmp} / 1024 / 1024` | |
314 | ||
315 | # kldload needed modules and start udevd | |
316 | echo "* Loading modules" | |
317 | ckloadmod dm_target_striped >> ${logfile} 2>&1 | |
318 | ckloadmod dm_target_linear >> ${logfile} 2>&1 | |
319 | /sbin/udevd >> ${logfile} 2>&1 | |
320 | ||
321 | # check previous installations | |
322 | ckpreinstall | |
323 | ||
324 | # Unmount any prior mounts on /mnt, reverse order to unwind | |
325 | # sub-directory mounts. | |
326 | # | |
327 | for mount in `df | fgrep /mnt | awk '{ print $6; }' | tail -r` | |
328 | do | |
329 | echo " Umounting ${mount}" | |
330 | umount ${mount} >> ${logfile} 2>&1 | |
331 | done | |
332 | ||
333 | # Prepare the disks in the list | |
334 | for disk in ${disklist} | |
335 | do | |
336 | echo "* Preparing disk ${disk}" | |
337 | prepdisk ${disk} | |
338 | mklabel ${disk} | |
339 | pvscan >> ${logfile} 2>&1 | |
340 | done | |
341 | ||
342 | # lvm(8) operations in the disks | |
343 | echo "* Performing LVM operations" | |
344 | lvmops | |
345 | ||
346 | # Format the volumes | |
785fe344 | 347 | echo "* Formatting ${bootdisk} and LVs lv_root" |
a816ce8e AHJ |
348 | newfs /dev/${bootdisk}s1a >> ${logfile} 2>&1 |
349 | lvmexit $? | |
350 | ||
351 | newfs_hammer -f -L ROOT /dev/main/lv_root >> ${logfile} 2>&1 | |
352 | lvmexit $? | |
353 | ||
354 | # Mount it | |
355 | # | |
356 | echo "* Mounting everything" | |
357 | mount_hammer /dev/main/lv_root /mnt >> ${logfile} 2>&1 | |
358 | lvmexit $? | |
359 | ||
360 | mkdir /mnt/boot | |
361 | ||
362 | mount /dev/${bootdisk}s1a /mnt/boot >> ${logfile} 2>&1 | |
363 | lvmexit $? | |
364 | ||
365 | # Create PFS mount points for nullfs. | |
366 | pfslist="usr usr.obj var var.crash var.tmp tmp home" | |
367 | ||
368 | mkdir /mnt/pfs | |
369 | ||
370 | for pfs in ${pfslist} | |
371 | do | |
372 | hammer pfs-master /mnt/pfs/$pfs >> ${logfile} 2>&1 | |
373 | lvmexit $? | |
374 | done | |
375 | ||
376 | # Mount /usr and /var so that you can add subdirs | |
377 | mkdir /mnt/usr >> ${logfile} 2>&1 | |
378 | mkdir /mnt/var >> ${logfile} 2>&1 | |
379 | mount_null /mnt/pfs/usr /mnt/usr >> ${logfile} 2>&1 | |
380 | lvmexit $? | |
381 | ||
382 | mount_null /mnt/pfs/var /mnt/var >> ${logfile} 2>&1 | |
383 | lvmexit $? | |
384 | ||
385 | mkdir /mnt/usr/obj >> ${logfile} 2>&1 | |
386 | mkdir /mnt/var/tmp >> ${logfile} 2>&1 | |
387 | mkdir /mnt/var/crash >> ${logfile} 2>&1 | |
388 | ||
389 | mkdir /mnt/tmp >> ${logfile} 2>&1 | |
390 | mkdir /mnt/home >> ${logfile} 2>&1 | |
391 | ||
392 | mount_null /mnt/pfs/tmp /mnt/tmp >> ${logfile} 2>&1 | |
393 | lvmexit $? | |
394 | ||
395 | mount_null /mnt/pfs/home /mnt/home >> ${logfile} 2>&1 | |
396 | lvmexit $? | |
397 | ||
398 | mount_null /mnt/pfs/var.tmp /mnt/var/tmp >> ${logfile} 2>&1 | |
399 | lvmexit $? | |
400 | ||
401 | mount_null /mnt/pfs/var.crash /mnt/var/crash >> ${logfile} 2>&1 | |
402 | lvmexit $? | |
403 | ||
404 | mount_null /mnt/pfs/usr.obj /mnt/usr/obj >> ${logfile} 2>&1 | |
405 | lvmexit $? | |
406 | ||
407 | chmod 1777 /mnt/tmp >> ${logfile} 2>&1 | |
408 | chmod 1777 /mnt/var/tmp >> ${logfile} 2>&1 | |
409 | ||
410 | # Install the system from the live CD | |
411 | # | |
412 | echo "* Starting file copy" | |
413 | cpdup -vv -o / /mnt >> ${logfile} 2>&1 | |
414 | lvmexit $? | |
415 | ||
416 | cpdup -vv -o /boot /mnt/boot >> ${logfile} 2>&1 | |
417 | lvmexit $? | |
418 | ||
419 | cpdup -vv -o /usr /mnt/usr >> ${logfile} 2>&1 | |
420 | lvmexit $? | |
421 | ||
422 | cpdup -vv -o /var /mnt/var >> ${logfile} 2>&1 | |
423 | lvmexit $? | |
424 | ||
425 | cpdup -vv -i0 /etc.hdd /mnt/etc >> ${logfile} 2>&1 | |
426 | lvmexit $? | |
427 | ||
428 | chflags -R nohistory /mnt/tmp >> ${logfile} 2>&1 | |
429 | chflags -R nohistory /mnt/var/tmp >> ${logfile} 2>&1 | |
430 | chflags -R nohistory /mnt/var/crash >> ${logfile} 2>&1 | |
431 | chflags -R nohistory /mnt/usr/obj >> ${logfile} 2>&1 | |
432 | ||
433 | echo "* Adapting fstab and loader.conf" | |
434 | cat > /mnt/etc/fstab << EOF | |
435 | # Device Mountpoint FStype Options Dump Pass# | |
436 | /dev/main/lv_root / hammer rw 1 1 | |
437 | /dev/${bootdisk}s1a /boot ufs rw 1 1 | |
438 | /dev/main/lv_swap none swap sw 0 0 | |
439 | /pfs/usr /usr null rw 0 0 | |
440 | /pfs/var /var null rw 0 0 | |
441 | /pfs/tmp /tmp null rw 0 0 | |
442 | /pfs/home /home null rw 0 0 | |
443 | /pfs/var.tmp /var/tmp null rw 0 0 | |
444 | /pfs/usr.obj /usr/obj null rw 0 0 | |
445 | /pfs/var.crash /var/crash null rw 0 0 | |
446 | proc /proc procfs rw 0 0 | |
447 | EOF | |
448 | ||
449 | # Because root is not on the boot partition we have to tell the loader | |
450 | # to tell the kernel where root is. | |
451 | # | |
452 | cat > /mnt/boot/loader.conf << EOF | |
453 | dm_target_striped_load="YES" | |
454 | dm_target_linear_load="YES" | |
455 | initrd.img_load="YES" | |
456 | initrd.img_type="md_image" | |
457 | vfs.root.mountfrom="ufs:md0s0" | |
458 | vfs.root.realroot="local:hammer:/dev/main/lv_root" | |
459 | EOF | |
460 | ||
461 | # Setup interface, configuration, sshd | |
462 | # | |
463 | echo "* iface setup" | |
464 | ifc=`route -n get default | fgrep interface | awk '{ print $2; }'` | |
465 | ip=`ifconfig $ifc | fgrep inet | fgrep -v inet6 | awk '{ print $2; }'` | |
466 | lip=`echo $ip | awk -F . '{ print $4; }'` | |
467 | ||
468 | echo -n "ifconfig_$ifc=" >> /mnt/etc/rc.conf | |
469 | echo '"DHCP"' >> /mnt/etc/rc.conf | |
470 | cat >> /mnt/etc/rc.conf << EOF | |
471 | sshd_enable="YES" | |
472 | dntpd_enable="YES" | |
473 | hostname="test$lip.MYDOMAIN.XXX" | |
474 | dumpdev="/dev/main/lv_swap" | |
475 | EOF | |
476 | ||
477 | # Misc sysctls | |
478 | # | |
479 | cat >> /mnt/etc/sysctl.conf << EOF | |
480 | #net.inet.ip.portrange.first=4000 | |
481 | EOF | |
482 | ||
a816ce8e AHJ |
483 | # mkinitd image |
484 | echo "* Preparing initrd image" | |
485 | /sbin/mkinitrd -b /mnt/boot >> ${logfile} 2>&1 | |
486 | ||
487 | # Warn about ssh | |
488 | echo "" | |
489 | echo "Warning:" | |
490 | echo "chroot now to /mnt and change root password and also edit" | |
491 | echo "/mnt/etc/ssh/sshd_config to allow root login and authentication" | |
492 | echo "using passwords. Alternatively, you can also just copy your" | |
493 | echo "~/.ssh/authorized_keys file to allow login using your ssh keys." | |
494 | ||
495 | echo "Installation finished successfully." | |
496 | ||
497 | ||
498 | # take CD out and reboot | |
499 | # |