1 #!/usr/bin/bash 2 # 3 # CDDL HEADER START 4 # 5 # The contents of this file are subject to the terms of the 6 # Common Development and Distribution License (the "License"). 7 # You may not use this file except in compliance with the License. 8 # 9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 # or http://www.opensolaris.org/os/licensing. 11 # See the License for the specific language governing permissions 12 # and limitations under the License. 13 # 14 # When distributing Covered Code, include this CDDL HEADER in each 15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 # If applicable, add the following below this CDDL HEADER, with the 17 # fields enclosed by brackets "[]" replaced with your own identifying 18 # information: Portions Copyright [yyyy] [name of copyright owner] 19 # 20 # CDDL HEADER END 21 # 22 # Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 # Use is subject to license terms. 24 # 25 # Script to install minimal OpenSolaris over network 26 # by Alexander R. Eremin <eremin (at] milax.org> 27 28 PATH=/sbin:/usr/sbin:/usr/bin:$PATH 29 export PATH 30 31 PART=/tmp/part.$$ 32 SETACT=/tmp/setact.$$ 33 NUMSECT=/tmp/numsect.$$ 34 MINIMAL_SIZE=1024 35 ROOT_POOL=rpool 36 ROOT_FILESYSTEM=opensolaris 37 ZFSROOT=/zfsroot 38 TIMEZONE=TZ=US/Eastern 39 HOSTNAME=opensolaris 40 declare -a DISKLIST 41 42 # preparing partition 43 preparepart() { 44 45 dev=$1 46 dsk=$2 47 acyls=$(prtvtoc $dsk | awk '/accessible/{print $2 }') 48 cyls=$((acyls - 1)) 49 format $dev >/dev/null <<EOF 50 partition 51 0 52 root 53 wm 54 55 ${cyls}e 56 label 57 58 y 59 EOF 60 61 } 62 63 # get partition info 64 getpart() { 65 66 fdisk -W "$PART" /dev/rdsk/$1 67 cat "$PART"|grep -v '^*'|grep '[0-9]' 68 rm -f "$PART" 69 } 70 71 # check Solaris2 partition 72 checkpart() { 73 74 disk=$1 75 exist=1 76 for item in $(getpart $disk | awk '{print $1}') 77 do 78 if [[ "$item" == 191 ]]; then 79 exist=0 80 fi 81 done 82 return $exist 83 84 } 85 86 # creating ZFS pool, installing packages and configuring system 87 zfsinstall() { 88 89 dev=$1 90 dsk=/dev/dsk/$dev 91 rdsk=/dev/rdsk/$dev 92 preparepart $dev $dsk 93 94 scdev=$(echo $dsk|sed -e 's/p0/s0/') 95 sbdev=$(echo $rdsk|sed -e 's/p0/s0/') 96 97 # Ensure we have things unmounted 98 umount -f $scdev 2>/dev/null >/dev/null 99 100 if [[ -z "${ROOT_FS}" ]] 101 then 102 # make our root pool and file system 103 GOT_ROOT=$( zpool list | grep $ROOT_POOL ) 104 if [[ -z "${GOT_ROOT}" ]] 105 then 106 zpool create -f "${ROOT_POOL}" $scdev 107 if [[ $? != 0 ]] 108 then 109 echo "Sorry, unable to create root pool with zpool options $scdev. Exiting now." 110 exit 1 111 fi 112 else 113 echo "Sorry ZFS pool \"${ROOT_POOL}\" already exists. Recreate it? [Yes|No]" 114 while read answer 115 do 116 case "$answer" in 117 Yes|yes|Y) 118 sleep 2 119 # removing old pool 120 zpool destroy -f "${ROOT_POOL}" 121 # creating new pool 122 zpool create -f "${ROOT_POOL}" $scdev 123 if [[ $? != 0 ]] 124 then 125 echo "Sorry, unable to create root pool with zpool options $scdev. Exiting now." 126 exit 1 127 fi 128 break 129 ;; 130 No|no|N) 131 echo "ZFS pool "${ROOT_POOL}" exists.You must destroy it before installing" 132 exit 1 133 ;; 134 *) 135 echo "Choices are Yes, No" 136 continue 137 ;; 138 esac 139 done 140 141 fi 142 # creating zfs filesystem 143 zfs set compression=on "$ROOT_POOL" 144 zfs create -p "${ROOT_POOL}/ROOT/${ROOT_FILESYSTEM}" 145 ROOT_FS="${ROOT_POOL}/ROOT/${ROOT_FILESYSTEM}" 146 fi 147 148 149 zfs set mountpoint=legacy "$ROOT_FS" 150 151 # making install directory 152 rm -rf "$ZFSROOT" 153 if [[ ! -d "$ZFSROOT" ]] 154 then 155 mkdir "$ZFSROOT" 156 else 157 echo "Sorry "$ZFSROOT" already exists : exiting now in case we overwrite data" 158 exit 1 159 fi 160 mount -F zfs "$ROOT_FS" "$ZFSROOT" 161 if [[ $? != 0 ]] 162 then 163 echo "Unable to mount ZFS root filesystem on "$ZFSROOT". Exiting now." 164 exit 1 165 fi 166 167 # pkg work here. Using dev repo due some errors with grub-0.95 168 pkg image-create -f -F -a opensolaris.org=http://pkg.opensolaris.org/dev/ "$ZFSROOT" 2>/dev/null >/dev/null 169 cd "$ZFSROOT" 170 pkg refresh 2>/dev/null >/dev/null 171 172 # minimal packages list 173 local PKGS 174 PKGS=" 175 SUNWcsd 176 SUNWcs 177 SUNWcar 178 SUNWcakr 179 SUNWkvm 180 SUNWos86r 181 SUNWrmodr 182 SUNWpsdcr 183 SUNWpsdir 184 SUNWcnetr 185 SUNWesu 186 SUNWkey 187 SUNWnfsckr 188 SUNWnfsc 189 SUNWgss 190 SUNWgssc 191 SUNWbip 192 SUNWbash 193 SUNWloc 194 SUNWsshcu 195 SUNWsshd 196 SUNWssh 197 SUNWtoo 198 SUNWzfskr 199 SUNWipf 200 SUNWipkg 201 SUNWadmr 202 SUNWadmap 203 SUNWPython 204 SUNWperl584core 205 SUNWgrub 206 entire 207 " 208 # recognizing network card 209 IFACE=$(dladm show-link|sed -n '2p'|awk '{print $1}'|sed 's/0//') 210 211 for pkg in ${PKGS} 212 do 213 tput ed 214 echo "Installing ${pkg}" 215 pkg install --no-index --no-refresh $pkg 2>/dev/null >/dev/null 216 tput dl1 217 tput cuu1 218 done 219 220 # seed the initial smf repository 221 cp "$ZFSROOT"/lib/svc/seed/global.db "$ZFSROOT"/etc/svc/repository.db 222 chmod 0600 "$ZFSROOT"/etc/svc/repository.db 223 chown root:sys "$ZFSROOT"/etc/svc/repository.db 224 225 # set timezone and nodename 226 echo "$TIMEZONE" > "$ZFSROOT"/etc/TIMEZONE 227 echo "$HOSTNAME" > "$ZFSROOT"/etc/nodename 228 229 # setup smf profiles 230 ln -s ns_files.xml "$ZFSROOT"/var/svc/profile/name_service.xml 231 ln -s generic_limited_net.xml "$ZFSROOT"/var/svc/profile/generic.xml 232 ln -s inetd_generic.xml "$ZFSROOT"/var/svc/profile/inetd_services.xml 233 ln -s platform_none.xml "$ZFSROOT"/var/svc/profile/platform.xml 234 235 # Set the environment variables for svccfg. 236 SVCCFG_DTD="${ZFSROOT}"/usr/share/lib/xml/dtd/service_bundle.dtd.1 237 SVCCFG_REPOSITORY="${ZFSROOT}"/etc/svc/repository.db 238 SVCCFG=svccfg 239 export SVCCFG_DTD SVCCFG_REPOSITORY SVCCFG 240 "${SVCCFG}" import "${ZFSROOT}"/var/svc/manifest/milestone/sysconfig.xml 241 "${SVCCFG}" -s network/physical:default setprop general/enabled=false 242 "${SVCCFG}" -s network/physical:nwam setprop general/enabled=true 243 244 # mark the new system image as uninstalled 245 sysidconfig -b "$ZFSROOT" -a /lib/svc/method/sshd 246 touch "$ZFSROOT"/etc/.UNCONFIGURED 247 248 # configure our new /etc/vfstab 249 printf "${ROOT_FS}\t-\t/\tzfs\t-\tno\t-\n" >> "$ZFSROOT"/etc/vfstab 250 chmod a+r "$ZFSROOT"/etc/vfstab 251 252 # turn off root as a role 253 printf "/^root::::type=role;\ns/^root::::type=role;/root::::/\nw" | ed -s "$ZFSROOT"/etc/user_attr 2>/dev/null >/dev/null 254 255 # delete the "jack" user 256 printf "/^jack:/d\nw" | ed -s "$ZFSROOT"/etc/passwd 2>/dev/null >/dev/null 257 chmod u+w "$ZFSROOT"/etc/shadow 258 printf "/^jack:/d\nw" | ed -s "$ZFSROOT"/etc/shadow 2>/dev/null >/dev/null 259 chmod u-w "$ZFSROOT"/etc/shadow 260 261 # generate sshd keys 262 ssh-keygen -t dsa -f "$ZFSROOT"/etc/ssh/ssh_host_dsa_key -N '' 2>/dev/null >/dev/null 263 ssh-keygen -t rsa -f "$ZFSROOT"/etc/ssh/ssh_host_rsa_key -N '' 2>/dev/null >/dev/null 264 265 # configure /dev in the new image 266 devfsadm -r "$ZFSROOT" 267 ln -s ../devices/pseudo/sysmsg@0:msglog "$ZFSROOT"/dev/msglog 2>/dev/null >/dev/null 268 269 mkdir -p /"$ROOT_POOL"/boot/grub 270 271 # create the new real grub menu 272 cat <<-EOF > /rpool/boot/grub/menu.lst 273 default 0 274 timeout 10 275 276 title OpenSolaris minimal 2008.11 277 bootfs rpool/ROOT/opensolaris 278 kernel\$ /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS-BOOTFS 279 module\$ /platform/i86pc/\$ISADIR/boot_archive 280 281 EOF 282 283 # make the grub menu files readable by everyone. 284 chmod a+r "$ZFSROOT"/boot/grub/menu.lst 285 chmod a+r /"$ROOT_POOL"/boot/grub/menu.lst 286 287 echo "etc/zfs/zpool.cache" >> "$ZFSROOT"/boot/solaris/filelist.ramdisk 288 zpool set bootfs="$ROOT_FS" "$ROOT_POOL" 289 290 mkdir -p /"$ROOT_POOL"/boot/grub 291 292 # setup /etc/bootsign so that grub can find this zpool 293 mkdir -p /"$ROOT_POOL"/etc 294 echo pool_rpool > /"$ROOT_POOL"/etc/bootsign 295 296 echo "Creating boot_archive" 297 bootadm update-archive -R "$ZFSROOT" 298 299 # grub installation 300 echo "Installing grub on $sbdev" 301 installgrub "$ZFSROOT"/boot/grub/stage1 "$ZFSROOT"/boot/grub/stage2 $sbdev 302 303 umount -f "$ZFSROOT" 304 305 # all done 306 echo "Minimal OpenSolaris installation is complete." 307 308 } 309 310 # main procedure 311 main() { 312 313 clear 314 echo "Starting OSinstall script which installs minimal OpenSolaris over network" 315 echo 316 317 # checking disks 318 HAVEDISK=$(echo q |format 2>&1 | egrep "[0-9]") 319 if [[ -z "$HAVEDISK" ]]; then 320 echo "No hard disk found." 321 exit 1 322 fi 323 324 # find target disk 325 echo "Found the following disks:" 326 i=0 327 for item in $(echo q | format -e 2>&1 | egrep "c[0-9]+" | nawk '{ print $2 }') 328 do 329 disk=/dev/rdsk/${item}p0 330 DISKLIST[$i]=$item 331 ((i++)) 332 fdisk -G $disk | tail -1 | nawk '{ 333 n=" '$i'" 334 disk="'$disk'" 335 ncyl=$2 336 nhead=$5 337 nsect=$6 338 secsz=$7 339 sectors=ncyl*nhead*nsect; 340 bytes=sectors/(1024/secsz); 341 printf("%d %7d MB %s\n",n, bytes/1024, disk); 342 }' 343 done 344 345 while read -p "On which disk do you want to install system: " choice 346 do 347 if [[ -z "${choice}" ]]; then 348 continue 349 fi 350 if [[ $choice -eq 0 ]] || [[ $choice -gt $i ]]; then 351 echo "$i Invalid choice" 352 continue 353 fi 354 break 355 done 356 357 i=0 358 for item in "${DISKLIST[@]}" 359 do 360 ((i++)) 361 if [[ $choice -eq $i ]]; then 362 dev=${item}p0 363 fi 364 done 365 366 if [[ ! -n "$dev" ]]; then 367 echo "Sorry, no disks selected" 368 exit 1 369 fi 370 371 # check and create Solaris2 partition 372 if ! checkpart $dev; then 373 echo "No solaris partition found on $dev" 374 echo "Use entire disk? (All data will be lost) [Yes|No]" 375 while read answer 376 do 377 case "$answer" in 378 Yes|yes|Y) 379 fdisk -B /dev/rdsk/$disk 380 break 381 ;; 382 No|no|N) 383 echo "You must create solaris partition manually" 384 echo "Press any key to run fdisk" 385 read 386 fdisk /dev/rdsk/$disk 387 break 388 ;; 389 *) 390 echo "Choices are Yes, No" 391 continue 392 ;; 393 esac 394 done 395 fi 396 397 # no partition 398 if ! checkpart $dev; then 399 echo "No solaris partition found on $dev, exiting" 400 exit 1 401 fi 402 403 # check active partition 404 partn=0 405 getpart $disk | while read Id Act Bhead Bsect Bcyl Ehead Esect Ecyl Rsect Numsect 406 do 407 let partn=$partn+1 408 if [[ $Id == 191 ]]; then 409 echo $Numsect > "$NUMSECT" 410 if [ $Act != 128 ]; then 411 echo 2 > "$SETACT" 412 echo $partn >> "$SETACT" 413 echo 5 >> "$SETACT" 414 fi 415 fi 416 done 417 418 # check partition size 419 numsect=$(cat "$NUMSECT") 420 rm -f "$NUMSECT" 421 psize=$(fdisk -G /dev/rdsk/$disk| tail -1 | awk "{print \$7*$numsect}") 422 let psize=$psize/1024/1024 423 if [[ "$psize" -lt "$MINIMAL_SIZE" ]];then 424 echo "$psize Not enough free space. At least 1GB required" 425 fi 426 427 if [[ -f "$SETACT" ]]; then 428 echo "Partition is not active. Activate? [Yes|No]" 429 while read answer 430 do 431 case "$answer" in 432 Yes|yes|Y] ) 433 cat "$SETACT" | fdisk /dev/rdsk/$dev 2>&1 >/dev/null 434 rm -f "$SETACT" 435 break 436 ;; 437 No|no|N] ) 438 echo "You must activate partition before reboot" 439 break 440 ;; 441 *) 442 echo "Choices are Yes, No" 443 continue 444 ;; 445 esac 446 done 447 fi 448 rm -f "$SETACT" 449 450 echo "System will be installed on $dev. Continue? [Yes|No]" 451 while read answer 452 do 453 case "$answer" in 454 Yes|yes|Y ) 455 zfsinstall $dev 456 break 457 ;; 458 No|no|N) 459 echo "Bye!" 460 exit 0 461 ;; 462 *) 463 echo "Choices are Yes, No" 464 continue 465 ;; 466 esac 467 done 468 exit 0 469 } 470 471 # call main procedure 472 main 473
