1 #!/bin/ksh -p 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 # ident "%Z%%M% %I% %E% SMI" 26 # 27 28 # 29 # This script contains various routines used to post-process a zone for use 30 # with BrandZ after it has been installed from RPM media or a tar image. 31 # 32 # Briefly, there are three main jobs we need to do: 33 # 34 # 1) Create any needed directories and symlinks BrandZ needs but that the 35 # Linux install may not create 36 # 37 # 2) Modify rc scripts to shut off services that don't apply to a zone 38 # or that wish to access hardware directly 39 # 40 # 3) Modify various Linux system files for use within a zone environment 41 # 42 43 # 44 # Restrict executables to /bin and /usr/bin 45 # 46 PATH=/bin:/usr/bin 47 export PATH 48 49 # 50 # Sends output to a log file via redirection of stderr. 51 # 52 # This script assumes its caller has already performed the redirection to the 53 # logfile. 54 # 55 log() 56 { 57 echo "$@" >&2 58 } 59 60 # 61 # Setup i18n output 62 # 63 TEXTDOMAIN="SUNW_OST_OSCMD" 64 export TEXTDOMAIN 65 66 cmd_failed=$(gettext "%s failed! Aborting installation...") 67 cmd2_failed=$(gettext "%s of '%s' to '%s' failed!") 68 create_failed=$(gettext "Could not create new file '%s'!") 69 disable_failed=$(gettext "Attempt to disable entries in '%s' failed!") 70 install_aborted=$(gettext "Aborting installation...") 71 install_noroot=$(gettext "Installation root directory '%s' does not exist.") 72 ln_fail=$(gettext "Unable to symlink '%s' to '%s'!") 73 mkdir_fail=$(gettext "Unable to create the directory '%s'") 74 mod_failed=$(gettext -n "Attempt to modify entries in '%s' failed!") 75 76 usage=$(gettext "usage: %s <install_root> [mini]") 77 78 # 79 # Output an internationalized string followed by a carriage return 80 # 81 i18n_echo() 82 { 83 typeset fmt="$1" 84 shift 85 86 printf "$fmt\n" "$@" 87 } 88 89 # 90 # Routine to make a full path out of a supplied path 91 # 92 fullpath() 93 { 94 typeset path="$1" 95 96 echo $path | egrep -s "^/" || path="${PWD:=$(pwd)}/$path" 97 echo $path 98 } 99 100 # 101 # Routine to create directories and handle errors 102 # 103 makedir() 104 { 105 typeset dirname=$(fullpath "$1") 106 typeset mode="" 107 108 [[ $# -eq 2 ]] && mode="-m $2" 109 110 [[ -d "$dirname" ]] && return 111 112 if ! mkdir $mode -p "$dirname"; then 113 log "Unable to create the directory \"$dirname\"!" 114 i18n_echo "$mkdir_fail" "$dirname" 115 echo $(gettext "Aborting installation...") 116 exit 1 117 fi 118 } 119 120 # 121 # Routine to create initial symlinks and handle errors 122 # 123 symlink() 124 { 125 typeset src="$1" 126 typeset dst=$(fullpath "$2") 127 128 [[ -e "$dst" || -h "$dst" ]] && rm -f "$dst" 129 130 if ! ln -s "$src" "$dst"; then 131 log "Unable to symlink \"$src\" to \"$dst\"!" 132 i18n_echo "$ln_fail" "$src" "$dst" 133 echo $(gettext "Aborting installation...") 134 exit 1 135 fi 136 } 137 138 # 139 # Install a file using "ln -s" 140 # 141 # Returns 0 on success, 1 on failure. 142 # 143 install_ln() 144 { 145 typeset source="$1" 146 typeset target=$(fullpath "$2") 147 148 log " Installing \"$target\"" 149 150 mv -f "$target" "$target.$tag" 2>/dev/null 151 152 if ! ln -s "$source" "$target"; then 153 log "" 154 log "Attempt to install $target FAILED." 155 return 1 156 fi 157 158 return 0 159 } 160 161 162 # 163 # Enable NFS servers and the NFS lock daemon for a particular zone. 164 # 165 enable_nfs_services() 166 { 167 log "Non-miniroot install; enabing NFS servers and NFS lock daemon" 168 169 # 170 # Setup files required for NFS: 171 # 172 # /native/etc/netconfig 173 # /native/etc/default/nfs 174 # 175 # These two files are treated as read-only in lx branded zones. 176 # To enfore this restriction we will read-only lofs mount them 177 # into the zone from the global zone. For these lofs mounts to 178 # work we'll need to create empty directories now that will serve 179 # as mount points later. 180 # 181 # /sbin/rpc.statd 182 # /sbin/rpc.lockd 183 # 184 # These files are symlinks to scripts supplied by the lx brand 185 # that will start up the solaris nfs daemons. 186 # 187 if { ! makedir native/etc/netconfig || 188 ! makedir native/etc/default/nfs ; }; then 189 log "Aborting NFS setup..." 190 log "" 191 return 192 fi 193 194 if { ! install_ln ../native/usr/lib/brand/lx/lx_lockd sbin/rpc.lockd || 195 ! install_ln ../native/usr/lib/brand/lx/lx_statd \ 196 sbin/rpc.statd ; }; then 197 log "Aborting NFS setup..." 198 log "" 199 return 200 fi 201 202 # 203 # update /etc/services for NFS 204 # 205 log "" 206 log "Adding lockd entry to \"$install_root/etc/services\"..." 207 208 cp -p $install_root/etc/services $install_root/etc/services.$tag 209 210 # 211 # Brackets in the sed script below contain a space followed by a tab 212 # 213 cat $install_root/etc/services.$tag | 214 sed 's:\(111\/..p[ ][ ]*\):\1rpcbind :' | 215 cat > $install_root/etc/services 216 217 cat >> $install_root/etc/services <<-EOF 218 lockd 4045/udp # NFS lock daemon/manager 219 lockd 4045/tcp # NFS lock daemon/manager 220 EOF 221 222 # 223 # Modify /etc/init.d/nfslock to enable the USERLAND_LOCKD option and to 224 # find some commands in alternate locations. 225 # 226 log "" 227 log "Modifying \"$install_root/etc/init.d/nfslock\"..." 228 cp -p etc/init.d/nfslock etc/init.d/nfslock.$tag 229 cat etc/init.d/nfslock.$tag | 230 sed ' 231 s/USERLAND_LOCKD=$/USERLAND_LOCKD="yes"/ 232 s/killproc rpc.statd/killproc statd/ 233 s/status rpc.statd/status statd/ 234 s/pidof rpc.statd/pidof statd/ 235 ' | 236 cat > etc/init.d/nfslock 237 } 238 239 # 240 # The main script starts here. 241 # 242 # The syntax is: 243 # 244 # lx_init_zone <rootdir> [mini] 245 # 246 # Where: 247 # <rootdir> is the root of the zone directory to be modified 248 # 249 # [mini] is an optional second argument that signifies whether this is 250 # to be a miniroot install; if it is, NFS services are not enabled 251 # in the processed zone 252 # 253 unset is_miniroot 254 unset install_root 255 256 install_root="$1" 257 258 tag="lxsave_$(date +%m.%d.%Y@%T)" 259 260 if (($# < 1 || $# > 2)); then 261 i18n_echo "$usage" "$0" 262 exit 1 263 fi 264 265 (($# == 2)) && is_miniroot=1 266 267 if [[ ! -d "$install_root" ]]; then 268 i18n_echo "$install_noroot" "$install_root" 269 echo $(gettext "** Installation aborted **") 270 exit 1 271 fi 272 273 cd "$install_root" 274 275 log "" 276 log "Initial lx_brand environment modification started `date`" 277 log "Making needed directories in \"$install_root\"." 278 echo $(gettext "Setting up the initial lx brand environment.") 279 280 # 281 # Make various directories in /native that are needed to boot an lx branded 282 # zone. 283 # 284 makedir native/dev 285 makedir native/etc/default 286 makedir native/etc/svc/volatile 287 makedir native/lib 288 makedir native/proc 289 makedir native/tmp 1777 290 makedir native/usr 291 makedir native/var 292 293 # 294 # Make various other directories needed for the lx brand 295 # 296 makedir mnt 297 makedir opt 298 makedir usr/local/bin 299 makedir usr/local/include 300 makedir usr/local/lib 301 makedir usr/local/sbin 302 makedir usr/local/share 303 makedir usr/local/src 304 305 makedir dev 0755 306 makedir tmp 1777 307 makedir proc 0555 308 makedir boot 0755 309 310 # 311 # zlogin requires that these utilities live in places other than their 312 # Linux defaults, so create appropriate links for them here. 313 # 314 # XX - The need for these links may go away in the future if zlogin is 315 # appropriately modified 316 # 317 symlink /bin/sh sbin/sh 318 symlink /bin/su usr/bin/su 319 symlink /native/usr/lib/ld.so.1 usr/lib/ld.so.1 320 321 libpam_so="$(echo lib/libpam.so.0.*)" 322 libpam_misc="$(echo lib/libpam_misc.so.0.*)" 323 libpamc_so="$(echo lib/libpamc.so.0.*)" 324 325 symlink "/$libpam_so" lib/libpam.so.0 326 symlink "/$libpam_misc" lib/libpam_misc.so.0 327 symlink "/$libpamc_so" lib/libpamc.so.0 328 329 log "" 330 log "Modifying system configuration in \"$install_root\"" 331 332 # 333 # Create a /var/ld/ld.config that will point to /native/lib for our Solaris 334 # libraries. 335 # 336 log "Creating \"$install_root/var/ld/ld.config\"..." 337 338 makedir var/ld 339 340 if ! crle -c var/ld/ld.config -l /native/lib:/native/usr/lib \ 341 -s /native/lib/secure:/native/usr/lib/secure; then 342 log "\tCreation of \"$install_root/var/ld/ld.config\" failed!" 343 i18n_echo "$cmd_failed" "crle" 344 exit 1 345 fi 346 347 log "" 348 log "Modifying \"$install_root/etc/fstab\"..." 349 350 mv -f etc/fstab etc/fstab.$tag 2>/dev/null 351 352 cat > etc/fstab <<- EOF 353 none / ufs defaults 1 1 354 none /proc proc defaults 0 0 355 EOF 356 357 if [[ $? -ne 0 ]]; then 358 log "Could not create new \"$install_root/etc/fstab\"!" 359 i18n_echo "$create_failed" "$install_root/etc/fstab" 360 exit 1 361 fi 362 363 # 364 # The default /etc/inittab spawns mingetty on each of the virtual consoles 365 # as well as xdm on the X console. Since we don't have virtual consoles nor 366 # an X console, spawn a single mingetty on /dev/console instead. 367 # 368 # Don't bother changing the file if it looks like we already did. 369 # 370 if ! egrep -s "Disabled by lx brand" etc/inittab; then 371 log "Modifying: \"$install_root/etc/inittab\"..." 372 373 tmpfile=/tmp/inittab.$$ 374 375 sed 's/^[1-6]:/# Disabled by lx brand: &/ 376 s/^id:5:initdefault:/id:3:initdefault: # Modified by lx brand: &/' \ 377 etc/inittab > $tmpfile 378 379 # 380 # Don't bother with further alterations if the sed above failed... 381 # 382 if [[ $? -eq 0 ]]; then 383 egrep -s "console login for lx brand" etc/inittab 384 if [[ $? -ne 0 ]]; then 385 cat >> $tmpfile <<- EOF 386 387 # 388 # console login for lx brand 389 # 390 1:2345:respawn:/sbin/mingetty console 391 EOF 392 393 # 394 # Only install the new inittab if the append 395 # above succeeded. 396 # 397 if [[ $? -eq 0 ]]; then 398 # 399 # Attempt to save off the original inittab 400 # before moving over the modified version. 401 # 402 mv -f etc/inittab etc/inittab.$tag 2>/dev/null 403 404 mv -f $tmpfile etc/inittab 405 406 if [[ $? -ne 0 ]]; then 407 log "mv of \"$tmpfile\" to" \ 408 "\"$installroot/etc/inittab\"" \ 409 "failed!" 410 i18n_echo "$cmd2_failed" "mv" \ 411 "$tmpfile" \ 412 "$installroot/etc/inittab" 413 i18n_echo "$install_aborted" 414 exit 1 415 else 416 chmod 644 etc/inittab 417 fi 418 fi 419 fi 420 421 else 422 log "Attempt to disable entries in" \ 423 "\"$install_root/etc/inittab\" failed!" 424 i18n_echo "$disable_failed" "$install_root/etc/inittab" 425 i18n_echo "$install_aborted" 426 exit 1 427 fi 428 fi 429 430 if [[ ! -e "$install_root/etc/hosts" ]]; then 431 log "" 432 log "Creating: \"$install_root/etc/hosts\"..." 433 434 cat > "$install_root/etc/hosts" <<-_EOF_ 435 127.0.0.1 localhost 436 _EOF_ 437 fi 438 439 # 440 # User must configure various brand-specific items to enable networking, so 441 # boot the system non-networked. 442 # 443 log "" 444 log "Modifying: \"$install_root/etc/sysconfig/network\"..." 445 446 mv -f etc/sysconfig/network etc/sysconfig/network.$tag 2>/dev/null 447 448 cat > etc/sysconfig/network <<- EOF 449 NETWORKING="no" 450 # 451 # To enable networking, change the "no" above to "yes" and 452 # uncomment and fill in the following parameters. 453 # 454 # If you are specifying a hostname by name rather than by IP address, 455 # be sure the system can resolve the name properly via the use of a 456 # name service and/or the proper name files, as specified by 457 # nsswitch.conf. See nsswitch.conf(5) for further details. 458 # 459 # HOSTNAME=your_hostname_here 460 # 461 EOF 462 463 if [[ $? -ne 0 ]]; then 464 log "Could not create new \"$install_root/etc/sysconfig/network\"!" 465 i18n_echo "$create_failed" "$install_root/etc/sysconfig/network" 466 i18n_echo "$install_aborted" 467 exit 1 468 fi 469 470 if [[ -a etc/sysconfig/syslog ]]; then 471 # 472 # By default, syslogd will attempt to create a socket in /dev/log, but 473 # /dev is not be writable. Instead, modify /etc/sysconfig/syslog to 474 # tell it to use /var/run/syslog instead, and make /dev/log a symlink 475 # to /var/run/syslog. 476 # 477 log "" 478 log "Modifying: \"$install_root/etc/sysconfig/syslog\"..." 479 480 tmpfile=/tmp/lx_sc.syslog.$$ 481 482 sed 's@\(SYSLOGD_OPTIONS="-m 0\)"@\1 -p /var/run/syslog"@' \ 483 etc/sysconfig/syslog > $tmpfile 484 485 # 486 # Only install the new sysconfig/syslog if the edit above succeeded. 487 # 488 if [[ $? -eq 0 ]]; then 489 # 490 # Attempt to save off the original syslog before moving over 491 # the modified version. 492 # 493 mv -f etc/sysconfig/syslog etc/sysconfig/syslog.$tag 2>/dev/null 494 495 if ! mv -f $tmpfile etc/sysconfig/syslog; then 496 log "mv of \"$tmpfile\" to" \ 497 "\"$installroot/etc/sysconfig/syslog\" failed!" 498 i18n_echo "$cmd2_failed" "mv" "$tmpfile" \ 499 "$installroot/etc/sysconfig/syslog" 500 i18n_echo "$install_aborted" 501 exit 1 502 else 503 chmod 755 etc/sysconfig/syslog 504 fi 505 else 506 log "Attempt to modify entries in" \ 507 "\"$install_root/sysconfig/syslog\" failed!" 508 i18n_echo "$mod_failed" "$install_root/sysconfig/syslog" 509 i18n_echo "$install_aborted" 510 exit 1 511 fi 512 fi 513 514 if [[ $? -ne 0 ]]; then 515 log "Could not create new \"$install_root/etc/sysconfig/syslog\"!" 516 i18n_echo "$create_failed" "$install_root/etc/sysconfig/syslog" 517 i18n_echo "$install_aborted" 518 exit 1 519 fi 520 521 # 522 # /etc/rc.d/init.d/keytable tries to load a physical keyboard map, which won't 523 # work in a zone. If we remove etc/sysconfig/keyboard, it won't try this at all. 524 # 525 mv -f etc/sysconfig/keyboard etc/sysconfig/keyboard.$tag 2>/dev/null 526 527 # 528 # /etc/rc.d/init.d/gpm tries to configure the console mouse for cut-and-paste 529 # text operations, which we don't support. Removing this file disables the 530 # mouse configuration. 531 # 532 mv -f etc/sysconfig/mouse etc/sysconfig/mouse.$tag 2>/dev/null 533 534 # 535 # The following scripts attempt to start services or otherwise configure 536 # the system in ways incompatible with zones, so don't execute them at boot 537 # time. 538 # 539 log "" 540 log "Modifying \"$install_root/etc/rc.d/init.d\" to disable any" 541 log " services not supported by BrandZ:" 542 unsupported_services=" 543 kudzu 544 microcode_ctl 545 network 546 random 547 pcmcia 548 isdn 549 iptables 550 ip6tables 551 iscsi 552 psacct 553 gpm 554 irda 555 smartd 556 rawdevices 557 netdump 558 hpoj 559 mdmonitor 560 mdmpd 561 irqbalance 562 " 563 564 for file in $unsupported_services; do 565 if [[ -a "etc/rc.d/init.d/$file" ]]; then 566 567 if mv -f "etc/rc.d/init.d/$file" "etc/rc.d/init.d/$file.$tag"; then 568 log " + Moved script \"etc/rc.d/init.d/$file\" to" 569 log " \"etc/rc.d/init.d/$file.$tag\"" 570 fi 571 fi 572 573 rc_files="$(echo etc/rc.d/rc[0-6].d/[SK]+([0-9])$file)" 574 575 if [[ "$rc_files" != "etc/rc.d/rc[0-6].d/[SK]+([0-9])$file" ]]; then 576 for file in $rc_files; do 577 if [[ -h "$file" ]]; then 578 rm -f "$file" && 579 log " + Removed symbolic link \"$file\"" 580 else 581 rm -f "$file" && 582 log " + Removed script \"$file\"" 583 fi 584 done 585 fi 586 done 587 588 # 589 # There is a lot of stuff in the standard halt and reboot scripts that we 590 # have no business running in a zone. Fortunately, the stuff we want to 591 # skip is all in one contiguous chunk. 592 # 593 # Don't bother to modify the file if it looks like we already did. 594 # 595 if ! egrep -s "Disabled by lx brand" etc/rc.d/init.d/halt; then 596 log "" 597 log "Modifying \"$install_root/etc/rc.d/init.d/halt\" for operation" 598 log " within a zone..." 599 awk 'BEGIN {skip = ""} 600 /^# Save mixer/ {skip = "# Disabled by lx brand: "} 601 /halt.local/ {skip = ""} 602 /./ {print skip $0}' etc/rc.d/init.d/halt > /tmp/halt.$$ 603 604 if [[ $? -eq 0 ]]; then 605 mv -f etc/rc.d/init.d/halt etc/rc.d/init.d/halt.$tag 2>/dev/null 606 mv -f /tmp/halt.$$ etc/rc.d/init.d/halt 607 chmod 755 etc/rc.d/init.d/halt 608 else 609 log "Attempt to modify \"$install_root/etc/rc.d/init.d/halt\"" \ 610 "FAILED" 611 log "Continuing with balance of zone setup..." 612 fi 613 fi 614 615 # 616 # Fix up /etc/rc.d/rc.sysinit: 617 # 618 # 1) /sbin/hwclock requires the iopl() system call, which BrandZ won't support. 619 # Since the hardware clock cannot be set from within a zone, we comment out 620 # the line. 621 # 622 # 2) Disable dmesg commands, since we don't implement klogctl 623 # 624 # 3) Disable initlog and the mount of /dev/pts 625 # 626 # 4) Don't touch /dev/tty* in order to start virtual terminals, as that won't 627 # work from within a zone. 628 # 629 # 5) Don't try to check the root filesystem (/) as there is no associated 630 # physical device, and any attempt to run fsck will fail. 631 # 632 # Don't modify the rc.sysinit file if it looks like we already did. 633 # 634 if ! egrep -s "Disabled by lx brand" etc/rc.d/rc.sysinit; then 635 log "" 636 log "Modifying: \"$install_root/etc/rc.d/rc.sysinit\"..." 637 log "" 638 639 tmpfile=/tmp/lx_rc.sysinit.$$ 640 641 sed 's@^/sbin/hwclock@# Disabled by lx brand: &@ 642 s@^HOSTTYPE=@HOSTTYPE=\"s390\" # Spoofed for lx brand: &@ 643 s@/bin/dmesg -n@: # Disabled by lx brand: &@ 644 s@^dmesg -s@# Disabled by lx brand: &@ 645 s@initlog -c \"fsck@: # Disabled by lx brand: &@ 646 s@^.*mount .* /dev/pts$@# Disabled by lx brand: &@' \ 647 etc/rc.d/rc.sysinit > $tmpfile 648 649 # 650 # Only install the new rc.sysinit if the edit above succeeded. 651 # 652 if [[ $? -eq 0 ]]; then 653 # 654 # Attempt to save off the original rc.sysinit 655 # before moving over the modified version. 656 # 657 mv -f etc/rc.d/rc.sysinit etc/rc.d/rc.sysinit.$tag 2>/dev/null 658 659 if ! mv -f $tmpfile etc/rc.d/rc.sysinit; then 660 log "mv of \"$tmpfile\" to" \ 661 "\"$installroot/etc/rc.d/rc.sysinit\" failed!" 662 i18n_echo "$cmd2_failed" "mv" "$tmpfile" \ 663 "$installroot/etc/rc.d/rc.sysinit" 664 i18n_echo "$install_aborted" 665 exit 1 666 else 667 chmod 755 etc/rc.d/rc.sysinit 668 fi 669 else 670 log "Attempt to modify entries in" \ 671 "\"$install_root/rc.d/rc.sysinit\" failed!" 672 i18n_echo "$mod_failed" "$install_root/rc.d/rc.sysinit" 673 i18n_echo "$install_aborted" 674 exit 1 675 fi 676 fi 677 678 if [[ -z $is_miniroot ]]; then 679 enable_nfs_services || log "NFS services were not properly enabled." 680 fi 681 682 log "" 683 log "System configuration modifications complete `date`" 684 log "" 685 i18n_echo "System configuration modifications complete." 686 exit 0