#!/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, 2010, Oracle and/or its affiliates. All rights reserved.
#
. /usr/lib/brand/solaris10/common.ksh
m_attach_log=$(gettext "Log File: %s")
m_zfs=$(gettext "A ZFS file system was created for the zone.")
m_attaching=$(gettext "Attaching...")
m_usage=$(gettext "solaris10 brand usage:\n\tattach [-a archive | -d directory | -r recv_type]\n\tThe -a archive option specifies an archive name which can be a flar,\n\ttar, pax or cpio archive.\n\tThe -d directory option specifies an existing directory.\n\tThe -r recv_type option specifies the type of archive to be read from\n\tstdin.")
m_complete=$(gettext "Attach complete.")
install_fail=$(gettext "*** Attach FAILED ***")
f_n_unimpl=$(gettext "The -n option is not yet implemented.")
f_zfs=$(gettext "Error creating a ZFS file system (%s) for the zone.")
f_nodataset=$(gettext "Error: there is no ZFS file system for the zone.")
f_zfsdestroy=$(gettext "Error destroying ZFS file system %s.")
f_sanity_notzone=$(gettext "Error: this is a system image and not a zone image.")
f_baddir=$(gettext "Invalid '%s' directory within the zone")
# Clean up on interrupt
trap_cleanup()
{
msg=$(gettext "Installation cancelled due to interrupt.")
log "$msg"
# umount any mounted file systems
umnt_fs
trap_exit
}
# If the attach failed then clean up the ZFS datasets we created.
trap_exit()
{
if [[ $EXIT_CODE != $ZONE_SUBPROC_OK && $rm_ds == 1 ]]; then
/usr/lib/brand/solaris10/uninstall $ZONENAME $ZONEPATH -F
fi
exit $EXIT_CODE
}
EXIT_CODE=$ZONE_SUBPROC_USAGE
install_media="-"
rm_ds=0
trap trap_cleanup INT
trap trap_exit EXIT
# If we weren't passed at least two arguments, exit now.
(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
ZONENAME="$1"
ZONEPATH="$2"
# XXX shared/common script currently uses lower case zonename & zonepath
zonename="$ZONENAME"
zonepath="$ZONEPATH"
shift; shift # remove ZONENAME and ZONEPATH from arguments array
ZONEROOT="$ZONEPATH/root"
logdir="$ZONEROOT/var/log"
noexecute=0
unset inst_type
# Other brand attach options are invalid for this brand.
while getopts "a:d:nr:" opt; do
case $opt in
a)
if [[ -n "$inst_type" ]]; then
fatal "$incompat_options" "$m_usage"
fi
inst_type="archive"
install_media="$OPTARG"
;;
d)
if [[ -n "$inst_type" ]]; then
fatal "$incompat_options" "$m_usage"
fi
inst_type="directory"
install_media="$OPTARG"
# '-d -' means use the existing zonepath.
if [[ "$install_media" == "$ZONEPATH" ]]; then
install_media="-"
fi
;;
n) noexecute=1 ;;
r)
if [[ -n "$inst_type" ]]; then
fatal "$incompat_options" "$m_usage"
fi
inst_type="stdin"
install_media="$OPTARG"
;;
?) printf "$m_usage\n"
exit $ZONE_SUBPROC_USAGE;;
*) printf "$m_usage\n"
exit $ZONE_SUBPROC_USAGE;;
esac
done
shift $((OPTIND-1))
if [[ $noexecute == 1 && -n "$inst_type" ]]; then
fatal "$m_usage"
fi
if [ $noexecute -eq 1 ]; then
#
# The zone doesn't have to exist when the -n option is used, so do
# this work early.
#
# XXX do the sw validation for solaris10 minimal patch level to ensure
# everything will be ok.
EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
fatal "$f_n_unimpl"
fi
EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
if [[ -z "$inst_type" ]]; then
inst_type="directory"
elif [[ "$install_media" != "-" ]]; then
#
# If we're not using a pre-existing zone directory layout then create
# the zone datasets and mount them.
#
unset DATASET
pdir=$(/usr/bin/dirname $ZONEPATH)
zds=$(/usr/sbin/zfs list -H -t filesystem -o name $pdir 2>/dev/null)
if (( $? == 0 )); then
pnm=$(/usr/bin/basename $ZONEPATH)
/usr/sbin/zfs create "$zds/$pnm"
if (( $? == 0 )); then
vlog "$m_zfs"
DATASET="$zds/$pnm"
rm_ds=1
else
log "$f_zfs" "$zds/$pnm"
fi
fi
create_active_ds
fi
#
# The zone's datasets are now in place, validate that things
# are setup correctly.
#
get_zonepath_ds $zonepath
/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
(( $? != 0 )) && fail_fatal "$f_no_active_ds"
zfs set mountpoint=legacy $ZONEPATH_DS/ROOT >/dev/null 2>&1
zfs set zoned=on $ZONEPATH_DS/ROOT >/dev/null 2>&1
get_active_ds $ZONEPATH_DS
zfs list -H -o name $ACTIVE_DS >/dev/null 2>&1
(( $? != 0 )) && fail_fatal "$f_zfs_create"
zfs set canmount=noauto $ACTIVE_DS >/dev/null 2>&1
zfs inherit mountpoint $ACTIVE_DS >/dev/null 2>&1
zfs inherit zoned $ACTIVE_DS >/dev/null 2>&1
if [ ! -d $ZONEROOT ]; then
mkdir -p $ZONEROOT || fail_fatal "$f_mkdir" "$ZONEROOT"
chmod 700 $ZONEPATH || fail_fatal "$f_chmod" "$ZONEPATH"
fi
mnted=`zfs get -H mounted $ACTIVE_DS | cut -f3`
if [[ $mnted = "no" ]]; then
mount -F zfs $ACTIVE_DS $ZONEROOT || fail_fatal "$f_zfs_mount"
fi
LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $zonename.attach_log.XXXXXX)
if [[ -z "$LOGFILE" ]]; then
fatal "$e_tmpfile"
fi
exec 2>>"$LOGFILE"
log "$m_attach_log" "$LOGFILE"
log "$m_attaching"
install_image "$inst_type" "$install_media"
mk_zone_dirs
#
# Perform a final check that this is really a zone image and not an archive of
# a system image which would need p2v. Check for a well-known S10 SMF service
# that shouldn't exist in a zone.
#
if [[ -e $ZONEROOT/var/svc/manifest/system/sysevent.xml ]]; then
log "$f_sanity_notzone"
exit $ZONE_SUBPROC_NOTCOMPLETE
fi
EXIT_CODE=$ZONE_SUBPROC_OK
log "$m_complete"
zone_logfile="${logdir}/$zonename.attach$$.log"
safe_dir /var
safe_dir /var/log
safe_copy $LOGFILE $zone_logfile
log "$m_attach_log" "$zone_logfile"
rm -f $LOGFILE
exit $ZONE_SUBPROC_OK