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 2009 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 #
  27 # image_install is used when installing a zone in a 'p2v' scenario.  In
  28 # this case the zone install hook will branch off to this script which
  29 # is responsible for setting up the physical system image in the zonepath
  30 # and performing the various modifications necessary to enable a physical
  31 # system image to run inside a zone.  This script sets up the image in the
  32 # zonepath then calls the p2v script to modify the image to run in a zone.
  33 #
  34 
  35 . /usr/lib/brand/ipkg/common.ksh
  36 
  37 m_usage=$(gettext "\n        install {-a archive|-d path} {-p|-u} [-s|-v]")
  38 install_log=$(gettext   "    Log File: %s")
  39 
  40 p2ving=$(gettext        "Postprocessing: This may take a while...")
  41 p2v_prog=$(gettext      "   Postprocess: ")
  42 p2v_done=$(gettext      "        Result: Postprocessing complete.")
  43 p2v_fail=$(gettext      "        Result: Postprocessing failed.")
  44 m_postnote3=$(gettext "              Make any other adjustments, such as disabling SMF services\n              that are no longer needed.")
  45 
  46 media_missing=\
  47 $(gettext "%s: you must specify an installation source using '-a' or '-d'.")
  48 cfgchoice_missing=\
  49 $(gettext "you must specify -u (sys-unconfig) or -p (preserve identity).")
  50 
  51 # Clean up on interrupt
  52 trap_cleanup()
  53 {
  54         msg=$(gettext "Installation cancelled due to interrupt.")
  55         log "$msg"
  56 
  57         trap_exit
  58 }
  59 
  60 # If the install failed then clean up the ZFS datasets we created.
  61 trap_exit()
  62 {
  63         # umount any mounted file systems
  64         [[ -n "$fstmpfile" ]] && umnt_fs
  65 
  66         if (( $zone_is_mounted != 0 )); then
  67                 error "$v_unmount"
  68                 zoneadm -z $ZONENAME unmount
  69                 zone_is_mounted=0
  70         fi
  71 
  72         if (( $EXIT_CODE != $ZONE_SUBPROC_OK )); then
  73                 /usr/lib/brand/ipkg/uninstall $ZONENAME $ZONEPATH -F
  74         fi
  75 
  76         exit $EXIT_CODE
  77 }
  78 
  79 #
  80 # The main body of the script starts here.
  81 #
  82 # This script should never be called directly by a user but rather should
  83 # only be called by pkgcreatezone to install an OpenSolaris system image into
  84 # a zone.
  85 #
  86 
  87 #
  88 # Exit code to return if install is interrupted or exit code is otherwise
  89 # unspecified.
  90 #
  91 EXIT_CODE=$ZONE_SUBPROC_USAGE
  92 
  93 zone_is_mounted=0
  94 trap trap_cleanup INT
  95 trap trap_exit EXIT
  96 
  97 # If we weren't passed at least two arguments, exit now.
  98 (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
  99 
 100 ZONENAME="$1"
 101 ZONEPATH="$2"
 102 # XXX shared/common script currently uses lower case zonename & zonepath
 103 zonename="$ZONENAME"
 104 zonepath="$ZONEPATH"
 105 
 106 ZONEROOT="$ZONEPATH/root"
 107 
 108 shift; shift    # remove zonename and zonepath from arguments array
 109 
 110 unset inst_type
 111 unset msg
 112 unset silent_mode
 113 unset verbose_mode
 114 
 115 #
 116 # It is worth noting here that we require the end user to pick one of
 117 # -u (sys-unconfig) or -p (preserve config).  This is because we can't
 118 # really know in advance which option makes a better default.  Forcing
 119 # the user to pick one or the other means that they will consider their
 120 # choice and hopefully not be surprised or disappointed with the result.
 121 #
 122 unset unconfig_zone
 123 unset preserve_zone
 124 
 125 while getopts "a:d:psuv" opt
 126 do
 127         case "$opt" in
 128                 a)
 129                         if [[ -n "$inst_type" ]]; then
 130                                 fatal "$both_kinds" "zoneadm install"
 131                         fi
 132                         inst_type="archive"
 133                         install_media="$OPTARG"
 134                         ;;
 135                 d)
 136                         if [[ -n "$inst_type" ]]; then
 137                                 fatal "$both_kinds" "zoneadm install"
 138                         fi
 139                         inst_type="directory"
 140                         install_media="$OPTARG"
 141                         ;;
 142                 p)      preserve_zone="-p";;
 143                 s)      silent_mode=1;;
 144                 u)      unconfig_zone="-u";;
 145                 v)      verbose_mode="-v";;
 146                 *)      exit $ZONE_SUBPROC_USAGE;;
 147         esac
 148 done
 149 shift OPTIND-1
 150 
 151 # The install can't be both verbose AND silent...
 152 [[ -n $silent_mode && -n $verbose_mode ]] && \
 153     fatal "$f_incompat_options" "-s" "-v"
 154 
 155 [[ -z $install_media ]] && fatal "$media_missing" "zoneadm install"
 156 
 157 # The install can't both preserve and unconfigure
 158 [[ -n $unconfig_zone && -n $preserve_zone ]] && \
 159     fatal "$f_incompat_options" "-u" "-p"
 160 
 161 # Must pick one or the other.
 162 [[ -z $unconfig_zone && -z $preserve_zone ]] && fail_usage "$cfgchoice_missing"
 163 
 164 LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $ZONENAME.install_log.XXXXXX)
 165 [[ -z "$LOGFILE" ]] && fatal "$e_tmpfile"
 166 exec 2>>"$LOGFILE"
 167 log "$install_log" "$LOGFILE"
 168 
 169 vlog "Starting pre-installation tasks."
 170 
 171 #
 172 # From here on out, an unspecified exit or interrupt should exit with
 173 # ZONE_SUBPROC_NOTCOMPLETE, meaning a user will need to do an uninstall before
 174 # attempting another install, as we've modified the directories we were going
 175 # to install to in some way.
 176 #
 177 EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
 178 
 179 # ZONEROOT was created by our caller (pkgcreatezone)
 180 
 181 vlog "Installation started for zone \"$ZONENAME\""
 182 install_image "$inst_type" "$install_media"
 183 
 184 #
 185 # Run p2v.
 186 #
 187 # Getting the output to the right places is a little tricky because what
 188 # we want is for p2v to output in the same way the installer does: verbose
 189 # messages to the log file always, and verbose messages printed to the
 190 # user if the user passes -v.  This rules out simple redirection.  And
 191 # we can't use tee or other tricks because they cause us to lose the
 192 # return value from the p2v script due to the way shell pipelines work.
 193 #
 194 # The simplest way to do this seems to be to hand off the management of
 195 # the log file to the p2v script.  So we run p2v with -l to tell it where
 196 # to find the log file and then reopen the log (O_APPEND) when p2v is done.
 197 #
 198 log "$p2ving"
 199 vlog "running: p2v $verbose_mode $unconfig_zone $ZONENAME $ZONEPATH"
 200 /usr/lib/brand/ipkg/p2v -l "$LOGFILE" $verbose_mode $unconfig_zone $ZONENAME \
 201     $ZONEPATH
 202 p2v_result=$?
 203 exec 2>>$LOGFILE
 204 
 205 if (( $p2v_result != 0 )); then
 206         log "$p2v_fail"
 207         log ""
 208         log "$install_fail"
 209         log "$install_log" "$LOGFILE"
 210         exit $ZONE_SUBPROC_FATAL
 211 fi
 212 vlog "$p2v_done"
 213 
 214 zone_is_mounted=1
 215 zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
 216 
 217 safe_copy $LOGFILE $ZONEPATH/lu/a/var/log/$ZONENAME.install$$.log
 218 
 219 zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
 220 zone_is_mounted=0
 221 
 222 trap - EXIT
 223 rm -f $LOGFILE
 224 
 225 # Mount active dataset on the root.
 226 is_brand_labeled
 227 (( $? == 0 )) && mount_active_ds
 228 
 229 log ""
 230 log "$m_complete" ${SECONDS}
 231 printf "$install_log\n" "$ZONEROOT/var/log/$ZONENAME.install$$.log"
 232 printf "$m_postnote\n"
 233 printf "$m_postnote2\n"
 234 printf "$m_postnote3\n"
 235 
 236 exit $ZONE_SUBPROC_OK