#!/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