2N/A#!/bin/ksh -p
2N/A#
2N/A# CDDL HEADER START
2N/A#
2N/A# The contents of this file are subject to the terms of the
2N/A# Common Development and Distribution License (the "License").
2N/A# You may not use this file except in compliance with the License.
2N/A#
2N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A# or http://www.opensolaris.org/os/licensing.
2N/A# See the License for the specific language governing permissions
2N/A# and limitations under the License.
2N/A#
2N/A# When distributing Covered Code, include this CDDL HEADER in each
2N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A# If applicable, add the following below this CDDL HEADER, with the
2N/A# fields enclosed by brackets "[]" replaced with your own identifying
2N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2N/A#
2N/A# CDDL HEADER END
2N/A#
2N/A# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A#
2N/A
2N/A# NOTE: this script runs in the global zone and touches the non-global
2N/A# zone, so care should be taken to validate any modifications so that they
2N/A# are safe.
2N/A
2N/A. /usr/lib/brand/solaris10/common.ksh
2N/A
2N/ALOGFILE=
2N/AMSG_PREFIX="p2v: "
2N/AEXIT_CODE=1
2N/A
2N/Afunction usage {
2N/A echo "$0 [-s] [-m msgprefix] [-u] [-v] [-b patchid]* [-c sysidcfg] zonename" >&2
2N/A exit $EXIT_CODE
2N/A}
2N/A
2N/A# Clean up on interrupt
2N/Afunction trap_cleanup {
2N/A msg=$(gettext "Postprocessing cancelled due to interrupt.")
2N/A error "$msg"
2N/A
2N/A if (( zone_is_running != 0 )); then
2N/A error "$e_shutdown" "$ZONENAME"
2N/A /usr/sbin/zoneadm -z $ZONENAME halt
2N/A fi
2N/A
2N/A #
2N/A # Delete temporary files created during the hollow package removal
2N/A # process.
2N/A #
2N/A rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
2N/A
2N/A finish_log zone
2N/A
2N/A exit $EXIT_CODE
2N/A}
2N/A
2N/A#
2N/A# Disable any existing live-upgrade configuration.
2N/A# We have already called safe_dir to validate the etc/lu directory.
2N/A#
2N/Afunction fix_lu {
2N/A ludir=$ZONEROOT/etc/lu
2N/A
2N/A [[ ! -d $ludir ]] && return
2N/A
2N/A safe_rm etc/lutab
2N/A safe_rm etc/lu/.BE_CONFIG
2N/A safe_rm etc/lu/.CURR_VARS
2N/A safe_rm etc/lu/ludb.local.xml
2N/A for i in $ludir/ICF* $ludir/vtoc* $ludir/GRUB*
2N/A do
2N/A nm=$(basename $i)
2N/A safe_rm etc/lu/$nm
2N/A done
2N/A}
2N/A
2N/A#
2N/A# For an exclusive stack zone, verify the zonecfg network configuration
2N/A# is consistent with the /etc/hostname* files inside the zone.
2N/A#
2N/Afunction fix_net {
2N/A typeset file_list
2N/A typeset net_list
2N/A typeset anet_list
2N/A typeset iface_list
2N/A
2N/A typeset file # Example: /zones/myzone/root/etc/hostname.e1000g0:0
2N/A typeset iface # e1000g0
2N/A typeset device # e1000g
2N/A
2N/A [[ "$STACK_TYPE" == "shared" ]] && return
2N/A
2N/A #
2N/A # Create lists of /etc/hostname* file names inside the zone
2N/A # and interface names from zonecfg net and anet resources.
2N/A # Make sure list items are separated by a space character.
2N/A #
2N/A file_list=$(/usr/bin/ls $ZONEROOT/etc/hostname.* \
2N/A $ZONEROOT/etc/hostname6.* 2>/dev/null)
2N/A [[ -n $file_list ]] && file_list=$(print $file_list)
2N/A net_list=$(LC_ALL=C /usr/sbin/zonecfg -z $ZONENAME info net \
2N/A 2>/dev/null | grep "physical: " | /usr/bin/cut -f2 -d " ")
2N/A [[ -n $net_list ]] && net_list=$(print $net_list)
2N/A anet_list=$(LC_ALL=C /usr/sbin/zonecfg -z $ZONENAME info anet \
2N/A 2>/dev/null | grep "linkname: " | /usr/bin/cut -f2 -d " ")
2N/A [[ -n $anet_list ]] && anet_list=$(print $anet_list)
2N/A
2N/A #
2N/A # Walk the list of /etc/hostname* files looking for interfaces
2N/A # not covered in the zonecfg file.
2N/A #
2N/A iface_list=""
2N/A for file in $file_list; do
2N/A
2N/A # Extract interface name from end of file name
2N/A iface=${file#$ZONEROOT/etc/hostname?(6).}
2N/A
2N/A # Strip logical interface number that may exist
2N/A iface=${iface%:+([0-9])}
2N/A
2N/A # Isolate device name
2N/A device=${iface%%+([0-9])}
2N/A
2N/A # Skip virtual and ppp interfaces.
2N/A [[ " xx lo ip.tun ip6.tun ip.6to4tun vni ppp " \
2N/A == *\ $device\ * ]] && continue
2N/A
2N/A # Do basic validity checks on interface and device names
2N/A if [[ $iface == $device ||
2N/A $device != @([a-zA-Z])*([a-zA-Z0-9.]) ]]; then
2N/A vlog "$v_invalidiface" ${file#$ZONEROOT}
2N/A continue
2N/A fi
2N/A
2N/A # Build list of unique interfaces names we found.
2N/A [[ " $iface_list " != *\ $iface\ * ]] && \
2N/A iface_list="$iface_list $iface"
2N/A
2N/A # Is the interface name we extracted included in
2N/A # net or anet resource interface names?
2N/A if [[ " $net_list $anet_list " != *\ $iface\ * ]]; then
2N/A vlog "$v_noresource" ${file#$ZONEROOT}
2N/A fi
2N/A done
2N/A
2N/A #
2N/A # Walk the list of resources looking for interface names
2N/A # not covered by the zone's /etc/hostname* files.
2N/A #
2N/A for iface in $net_list; do
2N/A if [[ " $iface_list " != *\ $iface\ * ]]; then
2N/A vlog "$v_nonethostname" $iface
2N/A fi
2N/A done
2N/A for iface in $anet_list; do
2N/A if [[ " $iface_list " != *\ $iface\ * ]]; then
2N/A vlog "$v_noanethostname" $iface
2N/A fi
2N/A done
2N/A}
2N/A
2N/A#
2N/A# Disable all of the shares since the zone cannot be an NFS server.
2N/A# Note that we disable the various instances of the svc:/network/shares/group
2N/A# SMF service in the fix_smf function.
2N/A#
2N/Afunction fix_nfs {
2N/A zonedfs=$ZONEROOT/etc/dfs
2N/A
2N/A [[ ! -d $zonedfs ]] && return
2N/A
2N/A if [[ -h $zonedfs/dfstab || ! -f $zonedfs/dfstab ]]; then
2N/A error "$e_badfile" "/etc/dfs/dfstab"
2N/A return
2N/A fi
2N/A
2N/A tmpfile=$(mktemp -t)
2N/A if [[ $? == 1 || -z "$tmpfile" ]]; then
2N/A error "$e_tmpfile"
2N/A return
2N/A fi
2N/A
2N/A /usr/bin/nawk '{
2N/A if (substr($1, 0, 1) == "#") {
2N/A print $0
2N/A } else {
2N/A print "#", $0
2N/A modified=1
2N/A }
2N/A }
2N/A END {
2N/A if (modified == 1) {
2N/A printf("# Modified by p2v ")
2N/A system("/usr/bin/date")
2N/A exit 0
2N/A }
2N/A exit 1
2N/A }' $zonedfs/dfstab >>$tmpfile
2N/A
2N/A if (( $? == 0 )); then
2N/A if [[ ! -f $zonedfs/dfstab.pre_p2v ]]; then
2N/A safe_copy $zonedfs/dfstab $zonedfs/dfstab.pre_p2v
2N/A fi
2N/A safe_copy $tmpfile $zonedfs/dfstab
2N/A chown root:sys $zonedfs/dfstab || \
2N/A fail_fatal "$f_chown" "$zonedfs/dfstab"
2N/A chmod 644 $zonedfs/dfstab || \
2N/A fail_fatal "$f_chmod" "$zonedfs/dfstab"
2N/A fi
2N/A /usr/bin/rm -f $tmpfile
2N/A}
2N/A
2N/A#
2N/A# Comment out most of the old mounts since they are either unneeded or
2N/A# likely incorrect within a zone. Specific mounts can be manually
2N/A# reenabled if the corresponding device is added to the zone.
2N/A#
2N/Afunction fix_vfstab {
2N/A if [[ -h $ZONEROOT/etc/vfstab || ! -f $ZONEROOT/etc/vfstab ]]; then
2N/A error "$e_badfile" "/etc/vfstab"
2N/A return
2N/A fi
2N/A
2N/A tmpfile=$(mktemp -t)
2N/A if [[ $? == 1 || -z "$tmpfile" ]]; then
2N/A error "$e_tmpfile"
2N/A return
2N/A fi
2N/A
2N/A /usr/bin/nawk '{
2N/A if (substr($1, 0, 1) == "#") {
2N/A print $0
2N/A } else if ($1 == "fd" || $1 == "/proc" || $1 == "swap" ||
2N/A $1 == "ctfs" || $1 == "objfs" || $1 == "sharefs" ||
2N/A $4 == "nfs" || $4 == "lofs") {
2N/A print $0
2N/A } else {
2N/A print "#", $0
2N/A modified=1
2N/A }
2N/A }
2N/A END {
2N/A if (modified == 1) {
2N/A printf("# Modified by p2v ")
2N/A system("/usr/bin/date")
2N/A exit 0
2N/A }
2N/A exit 1
2N/A }' $ZONEROOT/etc/vfstab >>$tmpfile
2N/A
2N/A if (( $? == 0 )); then
2N/A if [[ ! -f $ZONEROOT/etc/vfstab.pre_p2v ]]; then
2N/A safe_copy $ZONEROOT/etc/vfstab \
2N/A $ZONEROOT/etc/vfstab.pre_p2v
2N/A fi
2N/A safe_copy $tmpfile $ZONEROOT/etc/vfstab
2N/A chown root:sys $ZONEROOT/etc/vfstab || \
2N/A fail_fatal "$f_chown" "$ZONEROOT/etc/vfstab"
2N/A chmod 644 $ZONEROOT/etc/vfstab || \
2N/A fail_fatal "$f_chmod" "$ZONEROOT/etc/vfstab"
2N/A fi
2N/A /usr/bin/rm -f $tmpfile
2N/A}
2N/A
2N/A#
2N/A# Collect the data needed to delete SMF services. Since we're p2v-ing a
2N/A# physical image there are SMF services which must be deleted.
2N/A#
2N/Afunction get_smf_services_to_delete {
2N/A #
2N/A # Start by getting the svc manifests that are delivered by hollow
2N/A # pkgs then use 'svccfg inventory' to get the names of the svcs
2N/A # delivered by those manifests. The svc names are saved into a
2N/A # temporary file.
2N/A #
2N/A
2N/A SMFTMPFILE=$(mktemp -t smf.XXXXXX)
2N/A if [[ $? == 1 || -z "$SMFTMPFILE" ]]; then
2N/A error "$e_tmpfile"
2N/A return
2N/A fi
2N/A
2N/A for i in $ZONEROOT/var/sadm/pkg/*
2N/A do
2N/A pkg=$(/usr/bin/basename $i)
2N/A [[ ! -f $ZONEROOT/var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap ]] \
2N/A && continue
2N/A
2N/A /usr/bin/egrep -s "SUNW_PKG_HOLLOW=true" \
2N/A $ZONEROOT/var/sadm/pkg/$pkg/pkginfo || continue
2N/A
2N/A for j in $(/usr/bin/nawk '{if ($2 == "f" &&
2N/A substr($4, 1, 17) == "var/svc/manifest/") print $4}' \
2N/A $ZONEROOT/var/sadm/pkg/$pkg/save/pspool/$pkg/pkgmap)
2N/A do
2N/A svcs=$(/usr/sbin/zlogin $ZONENAME /usr/sbin/svccfg \
2N/A inventory /$j)
2N/A for k in $svcs
2N/A do
2N/A echo $k /$j >> $SMFTMPFILE
2N/A done
2N/A done
2N/A done
2N/A}
2N/A
2N/A#
2N/A# Delete or disable SMF services.
2N/A# Zone is booted to milestone=none when this function is called.
2N/A# Use the SMF data collected by get_smf_services_to_delete() to delete the
2N/A# services.
2N/A#
2N/Afunction fix_smf {
2N/A #
2N/A # Zone was already booted to milestone=none, wait until SMF door exists.
2N/A #
2N/A integer i
2N/A
2N/A for i in 0 1 2 3 4 5 6 7 8 9
2N/A do
2N/A [[ -r $ZONEROOT/etc/svc/volatile/repository_door ]] && break
2N/A sleep 5
2N/A done
2N/A
2N/A if (( i == 9 )) && \
2N/A [[ ! -r $ZONEROOT/etc/svc/volatile/repository_door ]]
2N/A then
2N/A #
2N/A # The zone never booted, something is wrong.
2N/A #
2N/A error "$e_nosmf"
2N/A error "$e_bootfail"
2N/A /usr/bin/rm -f $SMFTMPFILE
2N/A return 1
2N/A fi
2N/A
2N/A insttmpfile=$(mktemp -t instsmf.XXXXXX)
2N/A if [[ $? == 1 || -z "$insttmpfile" ]]; then
2N/A error "$e_tmpfile"
2N/A /usr/bin/rm -f $SMFTMPFILE
2N/A return 1
2N/A fi
2N/A
2N/A vlog "$v_rmhollowsvcs"
2N/A while read fmri mfst
2N/A do
2N/A # Delete the svc.
2N/A vlog "$v_delsvc" "$fmri"
2N/A echo "/usr/sbin/svccfg delete -f $fmri"
2N/A echo "/usr/sbin/svccfg delhash -d $mfst"
2N/A echo "rm -f $mfst"
2N/A done < $SMFTMPFILE > $ZONEROOT/tmp/smf_rm
2N/A
2N/A /usr/sbin/zlogin -S $ZONENAME /bin/sh /tmp/smf_rm >/dev/null 2>&1
2N/A
2N/A /usr/bin/rm -f $SMFTMPFILE
2N/A
2N/A # Get a list of the svcs that now exist in the zone.
2N/A LANG=C /usr/sbin/zlogin -S $ZONENAME /usr/bin/svcs -aH | \
2N/A /usr/bin/nawk '{print $3}' >>$insttmpfile
2N/A
2N/A [[ -n $LOGFILE ]] && \
2N/A printf "[$(date)] ${MSG_PREFIX}${v_svcsinzone}\n" >&2
2N/A [[ -n $LOGFILE ]] && cat $insttmpfile >&2
2N/A
2N/A #
2N/A # Fix network services if shared stack.
2N/A #
2N/A if [[ "$STACK_TYPE" == "shared" ]]; then
2N/A vlog "$v_fixnetsvcs"
2N/A
2N/A NETPHYSDEF="svc:/network/physical:default"
2N/A NETPHYSNWAM="svc:/network/physical:nwam"
2N/A
2N/A /usr/bin/egrep -s "$NETPHYSDEF" $insttmpfile
2N/A if (( $? == 0 )); then
2N/A vlog "$v_enblsvc" "$NETPHYSDEF"
2N/A /usr/sbin/zlogin -S $ZONENAME \
2N/A /usr/sbin/svcadm enable $NETPHYSDEF || \
2N/A error "$e_dissvc" "$NETPHYSDEF"
2N/A fi
2N/A
2N/A /usr/bin/egrep -s "$NETPHYSNWAM" $insttmpfile
2N/A if (( $? == 0 )); then
2N/A vlog "$v_dissvc" "$NETPHYSNWAM"
2N/A /usr/sbin/zlogin -S $ZONENAME \
2N/A /usr/sbin/svcadm disable $NETPHYSNWAM || \
2N/A error "$e_enblsvc" "$NETPHYSNWAM"
2N/A fi
2N/A
2N/A for svc in $(/usr/bin/egrep network/routing $insttmpfile)
2N/A do
2N/A # Disable the svc.
2N/A vlog "$v_dissvc" "$svc"
2N/A /usr/sbin/zlogin -S $ZONENAME \
2N/A /usr/sbin/svcadm disable $svc || \
2N/A error "$e_dissvc" $svc
2N/A done
2N/A fi
2N/A
2N/A #
2N/A # Disable well-known services that don't run in a zone.
2N/A #
2N/A vlog "$v_rminvalidsvcs"
2N/A for svc in $(/usr/bin/egrep -hv "^#" \
2N/A /usr/lib/brand/solaris10/smf_disable.lst \
2N/A /etc/brand/solaris10/smf_disable.conf)
2N/A do
2N/A # Skip svcs not installed in the zone.
2N/A /usr/bin/egrep -s "$svc:" $insttmpfile || continue
2N/A
2N/A # Disable the svc.
2N/A vlog "$v_dissvc" "$svc"
2N/A /usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $svc || \
2N/A error "$e_dissvc" $svc
2N/A done
2N/A
2N/A #
2N/A # Since zones can't be NFS servers, disable all of the instances of
2N/A # the shares svc.
2N/A #
2N/A for svc in $(/usr/bin/egrep network/shares/group $insttmpfile)
2N/A do
2N/A vlog "$v_dissvc" "$svc"
2N/A /usr/sbin/zlogin -S $ZONENAME /usr/sbin/svcadm disable $svc || \
2N/A error "$e_dissvc" $svc
2N/A done
2N/A
2N/A /usr/bin/rm -f $insttmpfile
2N/A
2N/A return 0
2N/A}
2N/A
2N/A#
2N/A# Remove well-known pkgs that do not work inside a zone.
2N/A#
2N/Afunction rm_pkgs {
2N/A /usr/bin/cat <<-EOF > $ZONEROOT/tmp/admin || fatal "$e_adminf"
2N/A mail=
2N/A instance=overwrite
2N/A partial=nocheck
2N/A runlevel=nocheck
2N/A idepend=nocheck
2N/A rdepend=nocheck
2N/A space=nocheck
2N/A setuid=nocheck
2N/A conflict=nocheck
2N/A action=nocheck
2N/A basedir=default
2N/A EOF
2N/A
2N/A for i in $(/usr/bin/egrep -hv "^#" /usr/lib/brand/solaris10/pkgrm.lst \
2N/A /etc/brand/solaris10/pkgrm.conf)
2N/A do
2N/A [[ ! -d $ZONEROOT/var/sadm/pkg/$i ]] && continue
2N/A
2N/A vlog "$v_rmpkg" "$i"
2N/A /usr/sbin/zlogin -S $ZONENAME \
2N/A /usr/sbin/pkgrm -na /tmp/admin $i >&2 || error "$e_rmpkg" $i
2N/A done
2N/A}
2N/A
2N/A#
2N/A# ^C Should cleanup; if the zone is running, it should try to halt it.
2N/A#
2N/Ainteger zone_is_running=0
2N/Atrap trap_cleanup INT
2N/A
2N/A# used by start_log
2N/Aset -A save_args "$0" "$@"
2N/A
2N/A#
2N/A# Parse the command line options.
2N/A#
2N/AOPT_U=
2N/AOPT_V=
2N/AOPT_M=
2N/AOPT_L=
2N/Asc_sysidcfg=
2N/Awhile getopts "c:uvm:" opt
2N/Ado
2N/A case "$opt" in
2N/A c) sc_sysidcfg="$OPTARG" ;;
2N/A u) OPT_U="-u";;
2N/A v) OPT_V="-v";;
2N/A m) MSG_PREFIX="$OPTARG"; OPT_M="-m \"$OPTARG\"";;
2N/A *) usage;;
2N/A esac
2N/Adone
2N/Ashift OPTIND-1
2N/A
2N/A(( $# < 1 )) && usage
2N/A
2N/A(( $# > 2 )) && usage
2N/A
2N/A[[ -n $LOGFILE ]] && exec 2>>$LOGFILE
2N/A
2N/Ainit_zone zone "$1" "$2"
2N/Aeval $(bind_legacy_zone_globals zone)
2N/A
2N/A# Clear the child dataset list - solaris10 should not create them.
2N/Aset -A zone.new_be_datasets
2N/A
2N/Astart_log zone install "${save_args[@]}"
2N/A
2N/Ae_badinfo=$(gettext "Failed to get '%s' zone resource")
2N/Ae_badfile=$(gettext "Invalid '%s' file within the zone")
2N/Av_invalidiface=$(gettext "Invalid interface name in '%s'")
2N/Av_noresource=$(gettext "No zonecfg net or anet resource found for %s")
2N/Av_nonethostname=$(gettext \
2N/A "No /etc/hostname\* file found for zonecfg net physical=%s")
2N/Av_noanethostname=$(gettext \
2N/A "No /etc/hostname\* file found for zonecfg anet linkname=%s")
2N/Av_adjust=$(gettext "Updating the image to run within a zone")
2N/Av_stacktype=$(gettext "Stack type '%s'")
2N/Av_booting=$(gettext "Booting zone to single user mode")
2N/Ae_bootfail=$(gettext "Failed to boot zone to single user mode.")
2N/Ae_nosmf=$(gettext "SMF repository unavailable.")
2N/Av_svcsinzone=$(gettext "The following SMF services are installed:")
2N/Av_rmhollowsvcs=$(gettext "Deleting SMF services from hollow packages")
2N/Av_fixnetsvcs=$(gettext "Adjusting network SMF services")
2N/Av_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
2N/Av_delsvc=$(gettext "Delete SMF svc '%s'")
2N/Av_enblsvc=$(gettext "Enable SMF svc '%s'")
2N/Ae_enblsvc=$(gettext "enabling SMF svc '%s'")
2N/Av_dissvc=$(gettext "Disable SMF svc '%s'")
2N/Ae_dissvc=$(gettext "disabling SMF svc '%s'")
2N/Ae_adminf=$(gettext "Unable to create admin file")
2N/Av_rmpkg=$(gettext "Remove package '%s'")
2N/Ae_rmpkg=$(gettext "removing package '%s'")
2N/Av_halting=$(gettext "Halting zone")
2N/Av_sc_config=$(gettext "Copying sysconfig file to zone")
2N/Av_migrate_export=$(gettext "Migrating /export out of boot environment")
2N/Ae_shutdown=$(gettext "Shutting down zone %s...")
2N/Ae_badhalt=$(gettext "Zone halt failed")
2N/Av_exitgood=$(gettext "Postprocessing successful.")
2N/Ae_exitfail=$(gettext "Postprocessing failed.")
2N/A
2N/A#
2N/A# Do some validation on the paths we'll be accessing
2N/A#
2N/Asafe_dir /etc
2N/Asafe_dir /var
2N/Asafe_dir /var/sadm
2N/Asafe_dir /var/sadm/install
2N/Asafe_dir /var/sadm/pkg
2N/Asafe_opt_dir /etc/dfs
2N/Asafe_opt_dir /etc/lu
2N/Asafe_opt_dir /etc/zones
2N/A
2N/Amk_zone_dirs
2N/A
2N/A# Now do the work to update the zone.
2N/A
2N/A# Check for zones inside of image.
2N/Awarn_zones
2N/A
2N/Alog "$v_adjust"
2N/A
2N/A#
2N/A# Any errors in these functions are not considered fatal. The zone can be
2N/A# be fixed up manually afterwards and it may need some additional manual
2N/A# cleanup in any case.
2N/A#
2N/A
2N/ASTACK_TYPE=$(/usr/sbin/zoneadm -z $ZONENAME list -p | \
2N/A /usr/bin/nawk -F: '{print $7}')
2N/Aif (( $? != 0 )); then
2N/A error "$e_badinfo" "stacktype"
2N/Afi
2N/Avlog "$v_stacktype" "$STACK_TYPE"
2N/A
2N/Afix_lu
2N/Aif [[ -z $OPT_U ]]; then
2N/A fix_net
2N/Afi
2N/Afix_nfs
2N/Afix_vfstab
2N/A
2N/Avlog "$v_booting"
2N/A
2N/A#
2N/A# Boot the zone so that we can do all of the SMF updates needed on the zone's
2N/A# repository.
2N/A#
2N/A
2N/Azone_is_running=1
2N/A
2N/A/usr/sbin/zoneadm -z $ZONENAME boot -f -- -m milestone=none
2N/Aif (( $? != 0 )); then
2N/A error "$e_badboot"
2N/A /usr/bin/rm -f $SMFTMPFILE
2N/A fatal "$e_exitfail"
2N/Afi
2N/A
2N/Aget_smf_services_to_delete
2N/A
2N/A#
2N/A# Remove all files and directories installed by hollow packages. Such files
2N/A# and directories shouldn't exist inside zones.
2N/A#
2N/Ahollow_pkgs=$(mktemp -t .hollow.pkgs.XXXXXX)
2N/Ahollow_file_list=$(mktemp $ZONEROOT/.hollow.pkgs.files.XXXXXX)
2N/Ahollow_dir_list=$(mktemp $ZONEROOT/.hollow.pkgs.dirs.XXXXXX)
2N/A[ -f "$hollow_pkgs" -a -f "$hollow_file_list" -a -f "$hollow_dir_list" ] || {
2N/A error "$e_tmpfile"
2N/A rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
2N/A fatal "$e_exitfail"
2N/A}
2N/Afor pkg_name in $ZONEROOT/var/sadm/pkg/*; do
2N/A grep 'SUNW_PKG_HOLLOW=true' $pkg_name/pkginfo >/dev/null 2>&1 && \
2N/A basename $pkg_name >>$hollow_pkgs
2N/Adone
2N/A/usr/bin/nawk -v hollowpkgs=$hollow_pkgs -v filelist=$hollow_file_list \
2N/A -v dirlist=$hollow_dir_list '
2N/A BEGIN {
2N/A while (getline p <hollowpkgs > 0)
2N/A pkgs[p] = 1;
2N/A close(hollowpkgs);
2N/A }
2N/A {
2N/A # fld is the field where the pkg names begin.
2N/A # nm is the file/dir entry name.
2N/A if ($2 == "f") {
2N/A fld=10;
2N/A nm=$1;
2N/A } else if ($2 == "d") {
2N/A fld=7;
2N/A nm=$1;
2N/A } else if ($2 == "s" || $2 == "l") {
2N/A fld=4;
2N/A split($1, a, "=");
2N/A nm=a[1];
2N/A } else {
2N/A next;
2N/A }
2N/A
2N/A # Determine whether the file or directory is delivered by any
2N/A # non-hollow packages. Files and directories can be
2N/A # delivered by multiple pkgs. The file or directory should only
2N/A # be removed if it is only delivered by hollow packages.
2N/A for (i = fld; i <= NF; i++) {
2N/A if (pkgs[get_pkg_name($i)] != 1) {
2N/A # We encountered a non-hollow package. Skip
2N/A # this entry.
2N/A next;
2N/A }
2N/A }
2N/A
2N/A # The file or directory is only delivered by hollow packages.
2N/A # Mark it for removal.
2N/A if (fld != 7)
2N/A print nm >>filelist
2N/A else
2N/A print nm >>dirlist
2N/A }
2N/A
2N/A # Get the clean pkg name from the fld entry.
2N/A function get_pkg_name(fld) {
2N/A # Remove any pkg control prefix (e.g. *, !)
2N/A first = substr(fld, 1, 1)
2N/A if (match(first, /[A-Za-z]/)) {
2N/A pname = fld
2N/A } else {
2N/A pname = substr(fld, 2)
2N/A }
2N/A
2N/A # Then remove any class action script name
2N/A pos = index(pname, ":")
2N/A if (pos != 0)
2N/A pname = substr(pname, 1, pos - 1)
2N/A return (pname)
2N/A }
2N/A' $ZONEROOT/var/sadm/install/contents
2N/A/usr/sbin/zlogin -S $ZONENAME "cat /$(basename $hollow_file_list) | xargs rm -f"
2N/A/usr/sbin/zlogin -S $ZONENAME "sort -r /$(basename $hollow_dir_list) | \
2N/A xargs rmdir >/dev/null 2>&1"
2N/Arm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
2N/A
2N/A# cleanup SMF services
2N/Afix_smf || failed=1
2N/A
2N/A# remove invalid pkgs
2N/A[[ -z $failed ]] && rm_pkgs
2N/A
2N/Aif [[ -z $failed && -n $OPT_U ]]; then
2N/A vlog "$v_unconfig"
2N/A
2N/A sysunconfig_zone
2N/A if (( $? != 0 )); then
2N/A failed=1
2N/A fi
2N/Afi
2N/A
2N/A# Migrate /export to the non-BE dataset(s).
2N/Avlog "$v_migrate_export"
2N/Amigrate_export zone
2N/Amigrate_rpool zone
2N/A
2N/Avlog "$v_halting"
2N/A/usr/sbin/zoneadm -z $ZONENAME halt
2N/Aif (( $? != 0 )); then
2N/A error "$e_badhalt"
2N/A failed=1
2N/Afi
2N/Azone_is_running=0
2N/A
2N/A# Copy in sysidcfg file after zone is halted
2N/Aif [[ -n $sc_sysidcfg ]]; then
2N/A vlog "$v_sc_config"
2N/A safe_copy $sc_sysidcfg $ZONEROOT/etc/sysidcfg
2N/Afi
2N/A
2N/Aif [[ -n $failed ]]; then
2N/A fatal "$e_exitfail"
2N/Afi
2N/A
2N/Avlog "$v_exitgood"
2N/Afinish_log zone
2N/Aexit 0