#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
#
# NOTE: this script runs in the global zone and touches the non-global
# zone, so care should be taken to validate any modifications so that they
# are safe.
#
# Only change PATH if you give full consideration to GNU or other variants
# of common commands having different arguments and output.
#
export PATH=/usr/bin:/usr/sbin
unset LD_LIBRARY_PATH
. /usr/lib/brand/solaris/common.ksh
# Allows developer to override some things like PATH and PYTHONPATH
. /usr/lib/brand/solaris/developerenv.ksh
e_badinfo=$(gettext "Failed to get '%s' zone resource")
e_badfile=$(gettext "Invalid '%s' file within the zone")
v_mkdirs=$(gettext "Creating mount points")
v_change_var=$(gettext "Changing the pkg variant to nonglobal...")
e_change_var=$(gettext "Changing the pkg variant to nonglobal failed")
v_update=$(gettext "Updating the zone software to match the global zone...")
e_badupdate=$(gettext "Updating the Zone software failed")
v_adjust=$(gettext "Updating the image to run within a zone")
v_stacktype=$(gettext "Stack type '%s'")
v_fixnetsvcs=$(gettext "Adjusting network SMF services")
v_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
v_enblsvc=$(gettext "Enable SMF svc '%s'")
v_dissvc=$(gettext "Disable SMF svc '%s'")
v_rmpkg=$(gettext "Remove package '%s'")
e_rmpkg=$(gettext "removing package '%s'")
v_exitgood=$(gettext "Postprocessing successful.")
f_missing_zone_zp=$(gettext "Missing zone or zonepath argument.")
m_usage=$(gettext "/usr/lib/brand/solaris/p2v [-uv] [-c sysconfig] zone zonepath")
set -A save_args "$0" "$@"
PKG=pkg
EXIT_CODE=$ZONE_SUBPROC_USAGE
# Clean up on failure
trap_exit()
{
if (( $ZONE_IS_MOUNTED != 0 )); then
error "$v_unmount"
zoneadm -z $ZONENAME unmount
fi
vlog "Exiting with exit code $EXIT_CODE"
finish_log zone
exit $EXIT_CODE
}
#
# Comment out most of the old mounts since they are either unneeded or
# likely incorrect within a zone. Specific mounts can be manually
# reenabled if the corresponding device is added to the zone.
#
fix_vfstab()
{
if [[ -h $ZONEROOT/etc/vfstab || ! -f $ZONEROOT/etc/vfstab ]]; then
error "$e_badfile" "/etc/vfstab"
return
fi
tmpfile=$(mktemp -t)
if [[ -z "$tmpfile" ]]; then
error "$e_tmpfile"
return
fi
nawk '{
if (substr($1, 0, 1) == "#") {
print $0
} else if ($1 == "fd" || $1 == "/proc" || $1 == "swap" ||
$1 == "ctfs" || $1 == "objfs" || $1 == "sharefs" ||
$4 == "nfs" || $4 == "lofs") {
print $0
} else {
print "#", $0
modified=1
}
}
END {
if (modified == 1) {
printf("# Modified by p2v ")
system("/usr/bin/date")
exit 0
}
exit 1
}' $ZONEROOT/etc/vfstab >>$tmpfile
if (( $? == 0 )); then
if [[ ! -f $ZONEROOT/etc/vfstab.pre_p2v ]]; then
safe_copy $ZONEROOT/etc/vfstab \
$ZONEROOT/etc/vfstab.pre_p2v
fi
safe_copy $tmpfile $ZONEROOT/etc/vfstab
fi
rm -f $tmpfile
}
#
# Delete or disable SMF services.
#
fix_smf()
{
SMF_UPGRADE=/a/var/svc/profile/upgrade
#
# Fix network services if shared stack.
#
if [[ "$STACK_TYPE" == "shared" ]]; then
vlog "$v_fixnetsvcs"
NETPHYSDEF="svc:/network/physical:default"
NETPHYSNWAM="svc:/network/physical:nwam"
vlog "$v_enblsvc" "$NETPHYSDEF"
zlogin -S $ZONENAME "echo /usr/sbin/svcadm enable $NETPHYSDEF \
>>$SMF_UPGRADE" </dev/null
vlog "$v_dissvc" "$NETPHYSNWAM"
zlogin -S $ZONENAME \
"echo /usr/sbin/svcadm disable $NETPHYSNWAM \
>>$SMF_UPGRADE" </dev/null
# Disable routing svcs.
vlog "$v_dissvc" 'svc:/network/routing/*'
zlogin -S $ZONENAME \
"echo /usr/sbin/svcadm disable 'svc:/network/routing/*' \
>>$SMF_UPGRADE" </dev/null
fi
#
# Disable well-known services that don't run in a zone.
#
vlog "$v_rminvalidsvcs"
for i in $(egrep -hv "^#" \
/usr/lib/brand/solaris/smf_disable.lst \
/etc/brand/solaris/smf_disable.conf)
do
# Disable the svc.
vlog "$v_dissvc" "$i"
zlogin -S $ZONENAME \
"echo /usr/sbin/svcadm disable $i >>$SMF_UPGRADE" </dev/null
done
}
#
# Remove well-known pkgs that do not work inside a zone.
#
rm_pkgs()
{
for i in $(egrep -hv "^#" /usr/lib/brand/solaris/pkgrm.lst \
/etc/brand/solaris/pkgrm.conf)
do
$PKG info $i >/dev/null 2>&1
if (( $? != 0 )); then
continue
fi
vlog "$v_rmpkg" "$i"
zlogin -S $ZONENAME LC_ALL=C \
/usr/bin/pkg -R /a uninstall -r $i </dev/null >&2 || \
error "$e_rmpkg" $i
done
}
#
# Parse the command line options.
#
OPT_V=
while getopts "v" opt
do
case "$opt" in
v) # Used by vlog()
OPT_V="-v"
;;
*) fail_usage ""
;;
esac
done
shift OPTIND-1
(( $# != 2 )) && fail_usage "$f_missing_zone_zp"
# If fixing up the image fails, force an uninstall.
EXIT_CODE=$ZONE_SUBPROC_FATAL
init_zone zone "$1" "$2"
eval $(bind_legacy_zone_globals zone)
#
# failure should unmount the zone if necessary;
#
ZONE_IS_MOUNTED=0
trap trap_exit EXIT
start_log zone install "${save_args[@]}"
#
# Do some validation on the paths we'll be accessing
#
safe_dir etc
safe_dir etc/dfs
safe_dir etc/zones
safe_dir var
safe_dir var/log
safe_dir var/pkg
# If these paths exist, they must be directories. If they don't exist,
# they will be created below.
safe_opt_dir etc/svc
safe_opt_dir system
safe_opt_dir system/volatile
# Now do the work to update the zone.
# Before booting the zone we may need to create a few mnt points, just in
# case they don't exist for some reason.
#
# Whenever we reach into the zone while running in the global zone we
# need to validate that none of the interim directories are symlinks
# that could cause us to inadvertently modify the global zone.
vlog "$v_mkdirs"
if [[ ! -f $ZONEROOT/tmp && ! -d $ZONEROOT/tmp ]]; then
mkdir -m 1777 -p $ZONEROOT/tmp || exit $EXIT_CODE
fi
if [[ ! -h $ZONEROOT/etc && ! -f $ZONEROOT/etc/mnttab ]]; then
touch $ZONEROOT/etc/mnttab || exit $EXIT_CODE
chmod 444 $ZONEROOT/etc/mnttab || exit $EXIT_CODE
fi
if [[ ! -f $ZONEROOT/proc && ! -d $ZONEROOT/proc ]]; then
mkdir -m 755 -p $ZONEROOT/proc || exit $EXIT_CODE
fi
if [[ ! -f $ZONEROOT/dev && ! -d $ZONEROOT/dev ]]; then
mkdir -m 755 -p $ZONEROOT/dev || exit $EXIT_CODE
fi
if [[ ! -d $ZONEROOT/system/volatile ]]; then
mkdir -m 755 -p $ZONEROOT/system/volatile || exit $EXIT_CODE
fi
# symlink: /etc/svc/volatile -> /system/volatile
if [[ ! -d $ZONEROOT/etc/svc ]]; then
mkdir -m 755 -p $ZONEROOT/etc/svc || exit $EXIT_CODE
fi
if [[ -e $ZONEROOT/etc/svc/volatile || -h $ZONEROOT/etc/svc/volatile ]]; then
rm -rf $ZONEROOT/etc/svc/volatile || exit $EXIT_CODE
fi
ln -s ../../system/volatile $ZONEROOT/etc/svc/volatile
# symlink: /var/run -> /system/volatile
if [[ -e $ZONEROOT/var/run || -h $ZONEROOT/var/run ]]; then
rm -rf $ZONEROOT/var/run || exit $EXIT_CODE
fi
ln -s ../system/volatile $ZONEROOT/var/run
# Check for zones inside of image.
warn_zones
STACK_TYPE=$(zoneadm -z $ZONENAME list -p | nawk -F: '{print $7}')
if (( $? != 0 )); then
error "$e_badinfo" "stacktype"
fi
vlog "$v_stacktype" "$STACK_TYPE"
# Note that we're doing this before update-on-attach has run.
fix_vfstab
#
# Mount the zone so that we can do all of the updates needed on the zone.
#
vlog "$v_mounting"
ZONE_IS_MOUNTED=1
zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
#
# Any errors in these functions are not considered fatal. The zone can be
# be fixed up manually afterwards and it may need some additional manual
# cleanup in any case.
#
log "$v_adjust"
# cleanup SMF services
fix_smf
# remove invalid pkgs
rm_pkgs
# If anything below here fails, a subsequent attach can likely fix it up.
EXIT_CODE=$ZONE_SUBPROC_UNAVAILABLE
#
# This is unintuitive: The call to 'zoneadm unmount' tears down the scratch
# zone. Upon completion of 'zoneadm unmount' the zone is in the same state
# that it would be in after 'zoneadm sysboot'. That is, brands other than
# labeled have the complete active ZBE mounted on the zone root.
#
vlog "$v_unmount"
zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
ZONE_IS_MOUNTED=0
if is_brand_labeled; then
# The labeled brand needs to mount the zone's root dataset back onto
# ZONEROOT so we can finish processing.
mount_active_be -C zone || fatal "$f_mount_active_be"
fi
#
# Change the pkg variant from global zone to non-global zone. This assumes
# that the caller has already:
# - updated the image format
# - refreshed the catalog in the zone's image
# - set the pkg image property use-system-repo=true
#
log "$v_change_var"
$PKG -R "$ZONEROOT" change-variant --no-refresh -I \
variant.opensolaris.zone=nonglobal || pkg_err_check "$e_change_var"
trap - EXIT
vlog "$v_exitgood"
finish_log zone
exit $ZONE_SUBPROC_OK