1#!/bin/ksh -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27. /usr/lib/brand/solaris10/common.ksh
28
29m_attach_log=$(gettext "Log File: %s")
30m_zfs=$(gettext "A ZFS file system was created for the zone.")
31m_attaching=$(gettext "Attaching...")
32m_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.")
33m_complete=$(gettext "Attach complete.")
34
35install_fail=$(gettext  "*** Attach FAILED ***")
36
37f_n_unimpl=$(gettext "The -n option is not yet implemented.")
38f_zfs=$(gettext "Error creating a ZFS file system (%s) for the zone.")
39f_nodataset=$(gettext "Error: there is no ZFS file system for the zone.")
40f_zfsdestroy=$(gettext "Error destroying ZFS file system %s.")
41
42f_sanity_notzone=$(gettext "Error: this is a system image and not a zone image.")
43
44f_baddir=$(gettext "Invalid '%s' directory within the zone")
45
46# Clean up on interrupt
47trap_cleanup()
48{
49	msg=$(gettext "Installation cancelled due to interrupt.")
50	log "$msg"
51
52	# umount any mounted file systems
53	umnt_fs
54
55	trap_exit
56}
57
58# If the attach failed then clean up the ZFS datasets we created.
59trap_exit()
60{
61	if [[ $EXIT_CODE != $ZONE_SUBPROC_OK && "$install_media" != "-" ]]; then
62		/usr/lib/brand/solaris10/uninstall $ZONENAME $ZONEPATH -F
63	fi
64
65	exit $EXIT_CODE
66}
67
68EXIT_CODE=$ZONE_SUBPROC_USAGE
69install_media="-"
70
71trap trap_cleanup INT
72trap trap_exit EXIT
73
74# If we weren't passed at least two arguments, exit now.
75(( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
76
77ZONENAME="$1"
78ZONEPATH="$2"
79# XXX shared/common script currently uses lower case zonename & zonepath
80zonename="$ZONENAME"
81zonepath="$ZONEPATH"
82
83shift; shift	# remove ZONENAME and ZONEPATH from arguments array
84
85ZONEROOT="$ZONEPATH/root"
86logdir="$ZONEROOT/var/log"
87
88noexecute=0
89
90unset inst_type
91
92# Other brand attach options are invalid for this brand.
93while getopts "a:d:nr:" opt; do
94	case $opt in
95		a)
96			if [[ -n "$inst_type" ]]; then
97				fatal "$incompat_options" "$m_usage"
98			fi
99		 	inst_type="archive"
100			install_media="$OPTARG"
101			;;
102		d)
103			if [[ -n "$inst_type" ]]; then
104				fatal "$incompat_options" "$m_usage"
105			fi
106		 	inst_type="directory"
107			install_media="$OPTARG"
108			;;
109		n)	noexecute=1 ;;
110		r)
111			if [[ -n "$inst_type" ]]; then
112				fatal "$incompat_options" "$m_usage"
113			fi
114		 	inst_type="stdin"
115			install_media="$OPTARG"
116			;;
117		?)	printf "$m_usage\n"
118			exit $ZONE_SUBPROC_USAGE;;
119		*)	printf "$m_usage\n"
120			exit $ZONE_SUBPROC_USAGE;;
121	esac
122done
123shift $((OPTIND-1))
124
125if [[ $noexecute == 1 && -n "$inst_type" ]]; then
126	fatal "$m_usage"
127fi
128
129if [ $noexecute -eq 1 ]; then
130	#
131	# The zone doesn't have to exist when the -n option is used, so do
132	# this work early.
133	#
134
135	# XXX do the sw validation for solaris10 minimal patch level to ensure
136	# everything will be ok.
137	EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
138	fatal "$f_n_unimpl"
139fi
140
141EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
142
143if [[ -z "$inst_type" ]]; then
144 	inst_type="directory"
145
146elif [[ "$install_media" != "-" ]]; then
147	#
148	# If we're not using a pre-existing zone directory layout then create
149	# the zone datasets and mount them.
150	#
151	unset DATASET
152	pdir=$(/usr/bin/dirname $ZONEPATH)
153	zds=$(/usr/sbin/zfs list -H -t filesystem -o name $pdir 2>/dev/null)
154	if (( $? == 0 )); then
155		pnm=$(/usr/bin/basename $ZONEPATH)
156		/usr/sbin/zfs create "$zds/$pnm"
157		if (( $? == 0 )); then
158			vlog "$m_zfs"
159			DATASET="$zds/$pnm"
160		else
161			log "$f_zfs" "$zds/$pnm"
162		fi
163	fi
164
165	create_active_ds
166fi
167
168#
169# The zone's datasets are now in place, validate that things
170# are setup correctly.
171#
172
173get_zonepath_ds $zonepath
174
175/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
176(( $? != 0 )) && fail_fatal "$f_no_active_ds"
177
178zfs set mountpoint=legacy $ZONEPATH_DS/ROOT >/dev/null 2>&1
179zfs set zoned=on $ZONEPATH_DS/ROOT >/dev/null 2>&1
180
181get_active_ds $ZONEPATH_DS
182zfs list -H -o name $ACTIVE_DS >/dev/null 2>&1
183(( $? != 0 )) && fail_fatal "$f_zfs_create"
184
185zfs set canmount=noauto $ACTIVE_DS >/dev/null 2>&1
186zfs inherit mountpoint $ACTIVE_DS >/dev/null 2>&1
187zfs inherit zoned $ACTIVE_DS >/dev/null 2>&1
188
189if [ ! -d $ZONEROOT ]; then
190	mkdir -p $ZONEROOT || fail_fatal "$f_mkdir" "$ZONEROOT"
191	chmod 700 $ZONEPATH || fail_fatal "$f_chmod" "$ZONEPATH"
192fi
193
194mnted=`zfs get -H mounted $ACTIVE_DS | cut -f3`
195if [[ $mnted = "no" ]]; then
196	mount -F zfs $ACTIVE_DS $ZONEROOT || fail_fatal "$f_zfs_mount"
197fi
198
199LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $zonename.attach_log.XXXXXX)
200if [[ -z "$LOGFILE" ]]; then
201	fatal "$e_tmpfile"
202fi
203exec 2>>"$LOGFILE"
204log "$m_attach_log" "$LOGFILE"
205
206log "$m_attaching"
207install_image "$inst_type" "$install_media"
208
209mk_zone_dirs
210
211#
212# Perform a final check that this is really a zone image and not an archive of
213# a system image which would need p2v.  Check for a well-known S10 SMF service
214# that shouldn't exist in a zone.
215#
216if [[ -e $ZONEROOT/var/svc/manifest/system/sysevent.xml ]]; then
217	log "$f_sanity_notzone"
218	exit $ZONE_SUBPROC_NOTCOMPLETE
219fi
220
221EXIT_CODE=$ZONE_SUBPROC_OK
222
223log "$m_complete"
224
225zone_logfile="${logdir}/$zonename.attach$$.log"
226
227safe_dir /var
228safe_dir /var/log
229safe_copy $LOGFILE $zone_logfile
230
231log "$m_attach_log" "$zone_logfile"
232rm -f $LOGFILE
233
234exit $ZONE_SUBPROC_OK
235