diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/brand/native/zone/common.ksh | 322 | ||||
-rw-r--r-- | usr/src/lib/brand/native/zone/image_install.ksh | 255 |
2 files changed, 349 insertions, 228 deletions
diff --git a/usr/src/lib/brand/native/zone/common.ksh b/usr/src/lib/brand/native/zone/common.ksh index 0007d8fcd4..8d31cfdf8f 100644 --- a/usr/src/lib/brand/native/zone/common.ksh +++ b/usr/src/lib/brand/native/zone/common.ksh @@ -267,7 +267,7 @@ install_flar() typeset archiver_command typeset archiver_arguments - vlog "cd $ZONEROOT && do_flar < \"$install_archive\"" + vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar" # Read cookie read -r input_line @@ -505,12 +505,332 @@ install_dir() return $result } +# +# This is a common function for laying down a zone image from a variety of +# different sources. This can be used to either install a fresh zone or as +# part of zone migration during attach. +# +# The first argument specifies the type of image: archive, directory or stdin. +# The second argument specifies the image itself. In the case of stdin, the +# second argument specifies the format of the stream (cpio, flar, etc.). +# Any validation or post-processing on the image is done elsewhere. +# +# This function calls a 'sanity_check' function which must be provided by +# the script which includes this code. +# +install_image() +{ + intype=$1 + insrc=$2 + + if [[ -z "$intype" || -z "$insrc" ]]; then + return 1 + fi + + filetype="unknown" + filetypename="unknown" + stage1="cat" + + if [[ "$intype" == "directory" ]]; then + if [[ "$insrc" == "-" ]]; then + # Indicates that the existing zonepath is prepopulated. + filetype="existing" + filetypename="existing" + else + if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then + fatal "$e_path_abs" "$insrc" + fi + + if [[ ! -e "$insrc" ]]; then + log "$e_not_found" "$insrc" + fatal "$e_install_abort" + fi + + if [[ ! -r "$insrc" ]]; then + log "$e_not_readable" "$insrc" + fatal "$e_install_abort" + fi + + if [[ ! -d "$insrc" ]]; then + log "$e_not_dir" + fatal "$e_install_abort" + fi + + sanity_check $insrc + + filetype="directory" + filetypename="directory" + fi + + else + # Common code for both archive and stdin stream. + + if [[ "$intype" == "archive" ]]; then + if [[ ! -f "$insrc" ]]; then + log "$e_unknown_archive" + fatal "$e_install_abort" + fi + ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)" + else + # For intype == stdin, the insrc parameter specifies + # the stream format coming on stdin. + ftype="$insrc" + insrc="-" + fi + + # Setup vars for the archive type we have. + case "$ftype" in + *cpio*) filetype="cpio" + filetypename="cpio archive" + ;; + *bzip2*) filetype="bzip2" + filetypename="bzipped cpio archive" + ;; + *gzip*) filetype="gzip" + filetypename="gzipped cpio archive" + ;; + *ufsdump*) filetype="ufsdump" + filetypename="ufsdump archive" + ;; + "flar") + filetype="flar" + filetypename="flash archive" + ;; + "flash") + filetype="flar" + filetypename="flash archive" + ;; + *Flash\ Archive*) + filetype="flar" + filetypename="flash archive" + ;; + "tar") + filetype="tar" + filetypename="tar archive" + ;; + *USTAR\ tar\ archive) + filetype="tar" + filetypename="tar archive" + ;; + "pax") + filetype="xustar" + filetypename="pax (xustar) archive" + ;; + *USTAR\ tar\ archive\ extended\ format*) + filetype="xustar" + filetypename="pax (xustar) archive" + ;; + "zfs") + filetype="zfs" + filetypename="ZFS send stream" + ;; + *ZFS\ snapshot\ stream*) + filetype="zfs" + filetypename="ZFS send stream" + ;; + *) log "$e_unknown_archive" + fatal "$e_install_abort" + ;; + esac + fi + + vlog "$filetypename" + + # Check for a non-empty root if no '-d -' option. + if [[ "$filetype" != "existing" ]]; then + cnt=$(ls $ZONEROOT | wc -l) + if (( $cnt != 0 )); then + fatal "$e_root_full" "$ZONEROOT" + fi + fi + + fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp) + if [[ -z "$fstmpfile" ]]; then + fatal "$e_tmpfile" + fi + + # Make sure we always have the files holding the directories to filter + # out when extracting from a CPIO or PAX archive. We'll add the fs + # entries to these files in get_fs_info() (there may be no IPDs for + # some brands but thats ok). + ipdcpiofile=$(/usr/bin/mktemp -t -p /var/tmp ipd.cpio.XXXXXX) + if [[ -z "$ipdcpiofile" ]]; then + rm -f $fstmpfile + fatal "$e_tmpfile" + fi + + # In addition to the IPDs, also filter out these directories. + echo 'dev/*' >>$ipdcpiofile + echo 'devices/*' >>$ipdcpiofile + echo 'devices' >>$ipdcpiofile + echo 'proc/*' >>$ipdcpiofile + echo 'tmp/*' >>$ipdcpiofile + echo 'var/run/*' >>$ipdcpiofile + echo 'system/contract/*' >>$ipdcpiofile + echo 'system/object/*' >>$ipdcpiofile + + ipdpaxfile=$(/usr/bin/mktemp -t -p /var/tmp ipd.pax.XXXXXX) + if [[ -z "$ipdpaxfile" ]]; then + rm -f $fstmpfile $ipdcpiofile + fatal "$e_tmpfile" + fi + + printf "%s " \ + "dev devices proc tmp var/run system/contract system/object" \ + >>$ipdpaxfile + + # Set up any fs mounts so the archive will install into the correct + # locations. + get_fs_info + mnt_fs + if (( $? != 0 )); then + umnt_fs >/dev/null 2>&1 + rm -f $fstmpfile $ipdcpiofile $ipdpaxfile + fatal "$mount_failed" + fi + + if [[ "$filetype" == "existing" ]]; then + log "$no_installing" + else + log "$installing" + fi + + # + # Install the image into the zonepath. + # + unpack_result=0 + stage1="cat" + if [[ "$filetype" == "gzip" ]]; then + stage1="gzcat" + filetype="cpio" + elif [[ "$filetype" == "bzip2" ]]; then + stage1="bzcat" + filetype="cpio" + fi + + if [[ "$filetype" == "cpio" ]]; then + install_cpio "$stage1" "$insrc" + unpack_result=$? + + elif [[ "$filetype" == "flar" ]]; then + ( cd "$ZONEROOT" && $stage1 $insrc | install_flar ) + unpack_result=$? + + elif [[ "$filetype" == "xustar" ]]; then + install_pax "$insrc" + unpack_result=$? + + elif [[ "$filetype" = "tar" ]]; then + vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\"" + ( cd "$ZONEROOT" && tar -xf "$insrc" ) + unpack_result=$? + post_unpack + + elif [[ "$filetype" == "ufsdump" ]]; then + install_ufsdump "$insrc" + unpack_result=$? + + elif [[ "$filetype" == "directory" ]]; then + install_dir "$insrc" + unpack_result=$? + + elif [[ "$filetype" == "zfs" ]]; then + # + # Given a 'zfs send' stream file, receive the snapshot into + # the zone's dataset. We're getting the original system's + # zonepath dataset. Destroy the existing dataset created + # above since this recreates it. + # + if [[ -z "$DATASET" ]]; then + fatal "$f_nodataset" + fi + /usr/sbin/zfs destroy "$DATASET" + if (( $? != 0 )); then + log "$f_zfsdestroy" "$DATASET" + fi + + vlog "$stage1 $insrc | zfs receive -F $DATASET" + ( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET ) + unpack_result=$? + fi + + vlog "$unpack_done" $unpack_result + + # Clean up any fs mounts used during unpacking. + umnt_fs + rm -f $fstmpfile $ipdcpiofile $ipdpaxfile + + # + # If the archive was of a zone then the archive might have been made + # of the zonepath (single dir), inside the zonepath (dev, root, etc., + # or just even just root) or inside the zonepath root (all the top + # level dirs). Try to normalize these possibilities. + # + dirsize=$(ls $ZONEROOT | wc -l) + if [[ -d $ZONEROOT/root && -d $ZONEROOT/root/etc && \ + -d $ZONEROOT/root/var ]]; then + # The archive was made of the zoneroot. + mkdir -m 0755 $ZONEPATH/.attach_root + mv $ZONEROOT/root/* $ZONEPATH/.attach_root + mv $ZONEROOT/root/.[a-zA-Z]* $ZONEPATH/.attach_root \ + >/dev/null 2>&1 + rm -rf $ZONEROOT + mv $ZONEPATH/.attach_root $ZONEROOT + + elif (( $dirsize == 1 )); then + # The archive was made of the the zonepath. + + dir=$(ls $ZONEROOT) + + if [[ -d $ZONEROOT/$dir/root ]]; then + mkdir -m 0755 $ZONEPATH/.attach_root + mv $ZONEROOT/$dir/root/* $ZONEPATH/.attach_root + mv $ZONEROOT/$dir/root/.[a-zA-Z]* \ + $ZONEPATH/.attach_root >/dev/null 2>&1 + rm -rf $ZONEROOT + mv $ZONEPATH/.attach_root $ZONEROOT + else + # We don't know where this archive was made. + fatal "$e_bad_zone_layout" + fi + + elif [[ ! -d $ZONEROOT/etc ]]; then + # We were expecting that the archive was made inside the + # zoneroot but there's no etc dir, so we don't know where + # this archive was made. + fatal "$e_bad_zone_layout" + fi + + chmod 700 $zonepath + + # Verify this is a valid image. + sanity_check $ZONEROOT + + return 0 +} + # Setup i18n output TEXTDOMAIN="SUNW_OST_OSCMD" export TEXTDOMAIN e_baddir=$(gettext "Invalid '%s' directory within the zone") e_badfile=$(gettext "Invalid '%s' file within the zone") +e_bad_zone_layout=$(gettext "Unexpected zone layout.") +e_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.") +e_not_found=$(gettext "%s: error: file or directory not found.") +e_install_abort=$(gettext "Installation aborted.") +e_not_readable=$(gettext "Cannot read directory '%s'") +e_not_dir=$(gettext "Error: must be a directory") +e_unknown_archive=$(gettext "Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.") +e_tmpfile=$(gettext "Unable to create temporary file") +e_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.") + + +not_readable=$(gettext "Cannot read file '%s'") +not_flar=$(gettext "Input is not a flash archive") +bad_flar=$(gettext "Flash archive is a corrupt") +unknown_archiver=$(gettext "Archiver %s is not supported") +cmd_not_exec=$(gettext "Required command '%s' not executable!") # # Exit values used by the script, as #defined in <sys/zone.h> diff --git a/usr/src/lib/brand/native/zone/image_install.ksh b/usr/src/lib/brand/native/zone/image_install.ksh index ba383a61ef..24d005b479 100644 --- a/usr/src/lib/brand/native/zone/image_install.ksh +++ b/usr/src/lib/brand/native/zone/image_install.ksh @@ -29,31 +29,19 @@ PATH=/bin:/usr/bin:/usr/sbin:/usr/sfw/bin export PATH -cmd_not_found=$(gettext "Required command '%s' cannot be found!") -cmd_not_exec=$(gettext "Required command '%s' not executable!") zone_initfail=$(gettext "Attempt to initialize zone '%s' FAILED.") path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.") -e_tmpfile=$(gettext "Unable to create temporary file") - both_modes=$(gettext "%s: cannot select both silent and verbose modes") both_choices=$(gettext "%s: cannot select both preserve and unconfigure options") both_kinds=$(gettext "%s: cannot specify both archive and directory") -not_found=$(gettext "%s: error: file or directory not found.") - -wrong_dir_type=$(gettext "error: must be a directory") - -not_readable=$(gettext "Cannot read file '%s'") - no_install=$(gettext "Could not create install directory '%s'") no_log=$(gettext "Could not create log directory '%s'") media_taste=$(gettext " Media Type: %s") -bad_archive=$(gettext "ERROR: must be a flash archive, a cpio archive (can also -be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.") product_vers=$(gettext " Product: %s") install_vers=$(gettext " Installer: %s") @@ -82,8 +70,6 @@ p2v_prog=$(gettext " Postprocess: ") p2v_done=$(gettext " Result: Postprocessing complete.") p2v_fail=$(gettext " Result: Postprocessing failed.") -root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.") - media_missing=\ $(gettext "%s: you must specify an installation source using '-a' or '-d'.") @@ -92,10 +78,6 @@ $(gettext "%s: you must specify -u (sys-unconfig) or -p (preserve identity).") mount_failed=$(gettext "ERROR: zonecfg(1M) 'fs' mount failed") -not_flar=$(gettext "Input is not a flash archive") -bad_flar=$(gettext "Flash archive is a corrupt") -unknown_archiver=$(gettext "Archiver %s is not supported") - e_baddir=$(gettext "Invalid '%s' directory within the zone") # Clean up on interrupt @@ -114,14 +96,14 @@ sanity_check() { typeset dir="$1" shift - ret=0 + res=0 # These checks must work with a sparse zone. checks="etc etc/svc usr sbin lib var var/svc" for x in $checks; do if [[ ! -e $dir/$x ]]; then vlog "$sanity_fail_detail" "$x" "$dir" - ret=1 + res=1 fi done @@ -143,10 +125,17 @@ sanity_check() if (( $sys_vers != $image_vers )); then vlog "$sanity_fail_vers" "$image_vers" "$sys_vers" - ret=1 + res=1 fi - return $ret + if (( $res != 0 )); then + log "$sanity_fail" + log "" + log "$install_log" "$LOGFILE" + fatal "$install_fail" "$zonename" + fi + + vlog "$sanity_ok" } # @@ -176,8 +165,7 @@ logdir="$ZONEROOT/var/log" shift; shift # remove zonename and zonepath from arguments array unset backout -unset install_archive -unset source_dir +unset inst_type unset msg unset silent_mode unset OPT_V @@ -195,14 +183,27 @@ unset preserve_zone while getopts "a:b:d:psuv" opt do case "$opt" in - a) install_archive="$OPTARG" ; install_media="$OPTARG";; + a) + if [[ -n "$inst_type" ]]; then + fatal "$both_kinds" "zoneadm install" + fi + inst_type="archive" + install_media="$OPTARG" + ;; + b) if [[ -n "$backout" ]]; then backout="$backout -b $OPTARG" else backout="-b $OPTARG" fi ;; - d) source_dir="$OPTARG" ; install_media="$OPTARG";; + d) + if [[ -n "$inst_type" ]]; then + fatal "$both_kinds" "zoneadm install" + fi + inst_type="directory" + install_media="$OPTARG" + ;; p) preserve_zone="-p";; s) silent_mode=1;; u) unconfig_zone="-u";; @@ -221,10 +222,6 @@ if [[ -z $install_media ]]; then fatal "$media_missing" "zoneadm install" fi -if [[ -n $install_archive && -n $source_dir ]]; then - fatal "$both_kinds" "zoneadm install" -fi - # The install can't both preserve and unconfigure if [[ -n $unconfig_zone && -n $preserve_zone ]]; then fatal "$both_choices" "zoneadm install" @@ -235,42 +232,6 @@ if [[ -z $unconfig_zone && -z $preserve_zone ]]; then fatal "$cfgchoice_missing" "zoneadm install" fi -# -# Handle "-d -" option to use whatever is already installed into the zonepath. -# -if [ "$source_dir" != "-" ]; then - # - # Validate $install_media (things common to archive/dir) - # - if [[ "$(echo $install_media | cut -c 1)" != "/" ]]; then - fatal "$path_abs" "$install_media" - fi - - if [[ ! -e "$install_media" ]]; then - log "$not_found" "$install_media" - fatal "$install_abort" "$zonename" - fi - - if [[ ! -r "$install_media" ]]; then - log "$not_readable" "$install_media" - fatal "$install_abort" "$zonename" - fi - - if [[ -n $install_archive ]]; then - if [[ ! -f "$install_archive" ]]; then - log "$media_taste" "$bad_archive" - fatal "$install_abort" "$zonename" - fi - fi - - if [[ -n $source_dir ]]; then - if [[ ! -d "$source_dir" ]]; then - log "$media_taste" "$wrong_dir_type" - fatal "$install_abort" "$zonename" - fi - fi -fi - LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $zonename.install_log.XXXXXX) if [[ -z "$LOGFILE" ]]; then fatal "$e_tmpfile" @@ -281,50 +242,6 @@ log "$install_log" "$LOGFILE" vlog "Starting pre-installation tasks." -if [[ -z $install_archive && -n $source_dir ]]; then - # - # Minimal check to make sure that the user is passing - # us something that at least seems to be a native image. - # - if [[ "$source_dir" == "-" ]]; then - filetype="existing" - filetypename="existing" - else - sanity_check $source_dir - if (( $? != 0 )); then - fatal "$not_native_image" "$source_dir" - fi - - filetype="directory" - filetypename="directory" - fi -else - ftype="$(LC_ALL=C file $install_archive | cut -d: -f 2)" - case "$ftype" in - *cpio*) filetype="cpio" - filetypename="cpio archive" - ;; - *bzip2*) filetype="bzip2" - filetypename="bzipped cpio archive" - ;; - *gzip*) filetype="gzip" - filetypename="gzipped cpio archive" - ;; - *ufsdump*) filetype="ufsdump" - filetypename="ufsdump archive" - ;; - *Flash\ Archive*) filetype="flar" - filetypename="flash archive" - ;; - *USTAR\ tar\ archive\ extended\ format*) filetype="xustar" - filetypename="pax (xustar) archive" - ;; - *) log "$media_taste" "$bad_archive" - fatal "$install_abort" "$zonename" - ;; - esac -fi - # # From here on out, an unspecified exit or interrupt should exit with # ZONE_SUBPROC_NOTCOMPLETE, meaning a user will need to do an uninstall before @@ -340,124 +257,8 @@ then fi fi -# -# Check for a non-empty root if no '-d -' option. -# -if [[ "$filetype" != "existing" ]]; then - cnt=$(ls $ZONEROOT | wc -l) - if (( $cnt != 0 )); then - fatal "$root_full" "$ZONEROOT" - fi -fi - vlog "Installation started for zone \"$zonename\"" - -log "$install_from" "$install_media" -vlog "$media_taste" "$filetypename" - -fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp) -if [[ -z "$fstmpfile" ]]; then - fatal "$e_tmpfile" -fi - -# Make sure we always have the files holding the directories to filter -# out when extracting from a CPIO or PAX archive. We'll add the IPDs to these -# files in get_fs_info(). -ipdcpiofile=$(/usr/bin/mktemp -t -p /var/tmp ipd.cpio.XXXXXX) -if [[ -z "$ipdcpiofile" ]]; then - rm -f $fstmpfile - fatal "$e_tmpfile" -fi - -# In addition to the IPDs, also filter out these directories. -echo 'dev/*' >>$ipdcpiofile -echo 'devices/*' >>$ipdcpiofile -echo 'devices' >>$ipdcpiofile -echo 'proc/*' >>$ipdcpiofile -echo 'tmp/*' >>$ipdcpiofile -echo 'var/run/*' >>$ipdcpiofile -echo 'system/contract/*' >>$ipdcpiofile -echo 'system/object/*' >>$ipdcpiofile - -ipdpaxfile=$(/usr/bin/mktemp -t -p /var/tmp ipd.pax.XXXXXX) -if [[ -z "$ipdpaxfile" ]]; then - rm -f $fstmpfile $ipdcpiofile - fatal "$e_tmpfile" -fi - -printf "%s " "dev devices proc tmp var/run system/contract system/object" \ - >>$ipdpaxfile - -# Set up any fs mounts so the archive will install into the correct locations. -get_fs_info -mnt_fs -if (( $? != 0 )); then - umnt_fs >/dev/null 2>&1 - rm -f $fstmpfile $ipdcpiofile $ipdpaxfile - fatal "$mount_failed" -fi - -if [[ "$filetype" == "existing" ]]; then - log "$no_installing" -else - log "$installing" -fi - -unpack_result=0 -stage1="cat" -if [[ "$filetype" == "gzip" ]]; then - stage1="gzcat" - filetype="cpio" -fi - -if [[ "$filetype" == "bzip2" ]]; then - stage1="bzcat" - filetype="cpio" -fi - -if [[ "$filetype" == "cpio" ]]; then - install_cpio "$stage1" "$install_archive" - unpack_result=$? - -elif [[ "$filetype" == "flar" ]]; then - ( cd "$ZONEROOT" && install_flar < "$install_archive" ) - unpack_result=$? - -elif [[ "$filetype" == "xustar" ]]; then - install_pax "$install_archive" - unpack_result=$? - -elif [[ "$filetype" == "ufsdump" ]]; then - install_ufsdump "$install_archive" - unpack_result=$? - -elif [[ "$filetype" == "directory" ]]; then - install_dir "$source_dir" - unpack_result=$? -fi - -# Clean up any fs mounts used during unpacking. -umnt_fs -rm -f $fstmpfile $ipdcpiofile $ipdpaxfile - -# -# Do a sanity check to see if various things we think should be present -# are present. If not, the user might have supplied a cpio archive which was -# not created properly. -# -if (( $unpack_result == 0 )); then - sanity_check $ZONEROOT - if (( $? != 0 )); then - log "$sanity_fail" - log "" - log "$install_log" "$LOGFILE" - fatal "$install_fail" "$zonename" - else - vlog "$sanity_ok" - fi -fi - -chmod 700 $zonepath +install_image "$inst_type" "$install_media" log "$p2ving" vlog "running: p2v $OPT_V $unconfig_zone $backout $zonename $zonepath" |