#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. # # # image_install is used when installing a zone in a p2v or v2v scenario. # This script is invoked by pkgcreatezone due to the use of the -a or -d # option to zoneadm install. # # For both p2v and v2v, data is transferred into the zone's dataset # hierarchy - either from an archive or a directory. In the case of # p2v, additional processing is performed to convert the global zone # image into a non-global zone image. This additional processing is # performed by the brand's p2v script. # . /usr/lib/brand/solaris/common.ksh # Allows developer to override some things like PATH and PYTHONPATH . /usr/lib/brand/solaris/developerenv.ksh m_usage=$(gettext "\n install {-a archive|-d path} {-p|-u} [-s|-v] [-c profile.xml | dir]") # If not doing p2v, m_postnote3 is cleared. m_postnote3=$(gettext " Make any other adjustments, such as disabling SMF services\n that are no longer needed.") media_missing=\ $(gettext "%s: you must specify an installation source using '-a' or '-d'.") cfgchoice_missing=\ $(gettext "you must specify -u (configure) or -p (preserve identity).") both_kinds=$(gettext "Only one of -a and/or -d options may be used.") # Clean up on interrupt trap_cleanup() { log "$m_interrupt" trap_exit } # If the install failed then clean up the ZFS datasets we created. trap_exit() { # trap_cleanup calls trap_exit. Don't make multiple passes. trap - INT EXIT if [[ -n $BRAND_SKIP_CLEANUP ]]; then vlog "Exiting with exit code $EXIT_CODE (skipping cleanup)" finish_log zone exit $EXIT_CODE fi # umount any mounted file systems [[ -n "$fstmpfile" ]] && umnt_fs if (( $EXIT_CODE != $ZONE_SUBPROC_OK )); then delete_unpinned_datasets "${zone.path.ds}" # # If cleanup completed, don't force the use of zoneadm # uninstall, as it will have no work to do. # if (( $? == 0 && $EXIT_CODE == $ZONE_SUBPROC_FATAL )); then EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN fi unpin_datasets "${zone.path.ds}" || error "$f_unpin" fi vlog "Exiting with exit code $EXIT_CODE" finish_log zone exit $EXIT_CODE } # # The main body of the script starts here. # # This script should never be called directly by a user but rather should # only be called by pkgcreatezone to install an OpenSolaris system image into # a zone. # # # Exit code to return if install is interrupted or exit code is otherwise # unspecified. # EXIT_CODE=$ZONE_SUBPROC_USAGE # Used by start_log set -A save_args "$0" "$@" # If we weren't passed at least two arguments, exit now. (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE init_zone zone "$1" "$2" eval $(bind_legacy_zone_globals zone) shift; shift # remove zonename and zonepath from arguments array unset inst_type unset msg unset silent_mode unset verbose_mode sc_config= allow_update=min # This lists the valid -x options typeset -A zone.xopts=([cert]= [ca-cert]= [key]=) # # It is worth noting here that we require the end user to pick one of # -u (configure) or -p (preserve config). This is because we can't # really know in advance which option makes a better default. Forcing # the user to pick one or the other means that they will consider their # choice and hopefully not be surprised or disappointed with the result. # unset unconfig_zone unset preserve_zone unset archived_zone # # If extracting an archive that contains multiple BEs, it is possible that # we won't be able to automatically select which BE to set as the active # zbe. In such a case, discover_active_be() will suggest the use of this # command. It may be augmented in getopts processing. # set -A ATTACH_Z_COMMAND zoneadm -z "${zone.name}" attach -z "" -u while getopts "a:c:d:psuUvx:z:" opt do case "$opt" in a) if [[ -n "$inst_type" ]]; then fatal "$both_kinds" "zoneadm install" fi if [[ $OPTARG != @(http://|https://|file:/)* ]]; then # [[ -f ... ]] does not trigger the automounter ls "$OPTARG" >/dev/null 2>&1 [[ -f $OPTARG ]] || fatal "$f_arg_not_file" "$OPTARG" fi inst_type="archive" install_media="$OPTARG" ;; c) sc_config=$OPTARG a_push ATTACH_Z_COMMAND "-c" "$OPTARG" ;; d) if [[ -n "$inst_type" ]]; then fatal "$both_kinds" "zoneadm install" fi # [[ -d ... ]] does not trigger the automounter ls "$OPTARG" >/dev/null 2>&1 [[ -d $OPTARG ]] || fatal "$f_arg_not_dir" "$OPTARG" inst_type="directory" install_media="$OPTARG" ;; p) preserve_zone="-p";; s) silent_mode=1;; u) unconfig_zone="-u" # # attach doesn't have an "unconfigure" option, so if # attach -z will be needed, provide an appropriate # option for a sysconfig profile that will do the # unconfigure. # a_push ATTACH_Z_COMMAND "-c" \ /usr/share/auto_install/sc_profiles/enable_sci.xml ;; U) allow_update=all ;; v) verbose_mode="-v" a_push ATTACH_Z_COMMAND "-v" ;; x) # May call fail_usage process_xopt zone.xopts "$OPTARG" ;; z) archived_zone=$OPTARG ;; *) fail_usage "" ;; esac done shift OPTIND-1 # The install can't be both verbose AND silent... [[ -n $silent_mode && -n $verbose_mode ]] && fail_usage "$f_incompat_options" "-s" "-v" # Cannot preserve the config and apply a config. [[ -n $preserve_zone && -n $sc_config ]] && fail_usage "$f_incompat_options" "-p" "-c" [[ -z $install_media ]] && fail_usage "$media_missing" "zoneadm install" # The install can't both preserve and unconfigure [[ -n $unconfig_zone && -n $preserve_zone ]] && fail_usage "$f_incompat_options" "-u" "-p" # Must pick one or the other, unless it is a unified archive. if [[ -z $unconfig_zone && -z $preserve_zone ]]; then # If it's not an archive, it's not a unified archive. [[ $inst_type == archive ]] || fail_usage "$cfgchoice_missing" # If this fails, it must be a legacy archive. typeset -A uar_props read_uar_info "$install_media" zone.xopts uar_props >/dev/null 2>&1 || fail_usage "$cfgchoice_missing" # Recovery archives default to -p, others default to -u. key=${!uar_props[archive][*]} if [[ ${uar_props[archive][$key][recovery]} == Yes ]]; then if [[ -n $sc_config ]]; then unconfig_zone=-u else preserve_zone=-p fi else unconfig_zone=-u fi fi # # From here on out, an unspecified exit or interrupt should exit with # ZONE_SUBPROC_FATAL, meaning a user will need to do an uninstall before # attempting another install, as we've modified the directories we were going # to install to in some way. Note, however, that this is influenced by # pin_datasets() and trap_exit(). # start_log zone install "${save_args[@]}" vlog "Starting pre-installation tasks." pin_datasets "${zone.path.ds}" || fatal "$f_pin" trap trap_cleanup INT trap trap_exit EXIT EXIT_CODE=$ZONE_SUBPROC_FATAL # # Create the ZBE and transfer data to it. # zone.ua_archived_zone=${archived_zone:-} vlog "Installation started for zone \"%s\"" "${zone.name}" attach_datasets -t "$inst_type" -m "$install_media" zone || exit $EXIT_CODE log "$m_active_zbe" "${zone.active_ds}" set -- $(pkg -R "${zone.root}" variant -H variant.opensolaris.zone) if [[ $2 == nonglobal ]]; then # Disable this message - it is only relevant for p2v. m_postnote3= fi # We've made it far enough that attach can fix it. EXIT_CODE=$ZONE_SUBPROC_UNAVAILABLE enable_zones_services 1 || exit $EXIT_CODE # Attach the image, perhaps with updates. attach_image zone "$allow_update" # Be sure that shared data that shouldn't be in in the ZBE isn't in the ZBE. migrate_export zone migrate_rpool zone # # Unconfigure or reconfigure the zone. # [[ -n $unconfig_zone ]] && reconfigure_zone "$sc_config" EXIT_CODE=$ZONE_SUBPROC_OK # Do not leave the BE mounted for labeled zones. [[ ${zone.brand} == labeled ]] && unmount_be zone unpin_datasets "${zone.path.ds}" || error "$f_unpin" log "\n$m_complete_seconds" ${SECONDS} printf "$m_postnote\n" printf "$m_postnote2\n" [[ -n $m_postnote3 ]] && printf "$m_postnote3\n" finish_log zone logfile trap - EXIT exit $ZONE_SUBPROC_OK