3979 zone fs only available from Global zone, when zone is booted
author<gerald.jelinek@sun.com>
Fri, 13 Nov 2009 15:13:18 -0700
changeset 1493 625950c12e71
parent 1492 11e467a501b0
child 1494 fae43eb02e83
3979 zone fs only available from Global zone, when zone is booted
src/brand/attach
src/brand/clone
src/brand/common.ksh
src/brand/config.xml
src/brand/image_install
src/brand/p2v
src/brand/pkgcreatezone
src/brand/poststate
src/brand/prestate
--- a/src/brand/attach	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/attach	Fri Nov 13 15:13:18 2009 -0700
@@ -75,8 +75,10 @@
 trap_exit()
 {
 	if [[ $EXIT_CODE == $ZONE_SUBPROC_OK ]]; then
-		# unmount the zoneroot
-		umount $ZONEROOT > /dev/null 2>&1
+		# unmount the zoneroot if labeled brand
+		is_brand_labeled
+		(( $? == 1 )) && ( umount $ZONEROOT || \
+		    printf "$f_zfs_unmount" "$ZONEPATH/root" )
 	else
 		if [[ "$install_media" != "-" ]]; then
 			/usr/lib/brand/ipkg/uninstall $ZONENAME $ZONEPATH -F
--- a/src/brand/clone	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/clone	Fri Nov 13 15:13:18 2009 -0700
@@ -28,8 +28,17 @@
 
 m_usage=$(gettext "clone {sourcezone}")
 f_nosource=$(gettext "Error: unable to determine source zone dataset.")
-f_sysunconfig=$(gettext "Error: sys-unconfig failed.")
-f_nobrand=$(gettext "Error: unable to determine source zone brand.")
+
+# Clean up on failure
+trap_exit()
+{
+	if (( $ZONE_IS_MOUNTED != 0 )); then
+		error "$v_unmount"
+		zoneadm -z $ZONENAME unmount
+	fi
+
+	exit $ZONE_SUBPROC_INCOMPLETE
+}
 
 # Set up ZFS dataset hierarchy for the zone.
 
@@ -38,8 +47,8 @@
 # Other brand clone options are invalid for this brand.
 while getopts "R:z:" opt; do
 	case $opt in
-		R)	zonepath="$OPTARG" ;;
-		z)	zonename="$OPTARG" ;;
+		R)	ZONEPATH="$OPTARG" ;;
+		z)	ZONENAME="$OPTARG" ;;
 		*)	fail_usage "";;
 	esac
 done
@@ -57,13 +66,6 @@
 	fail_fatal "$f_nosource"
 fi
 
-# Find the active source zone brand
-brand=`/usr/sbin/zoneadm -z $sourcezone list -p | awk -F: '{print $6}'`
-
-if [ -z "$brand" ]; then
-	fail_fatal "$f_nobrand"
-fi
-
 get_current_gzbe
 get_zonepath_ds $sourcezonepath
 get_active_ds $CURRENT_GZBE $ZONEPATH_DS
@@ -76,8 +78,8 @@
 # First make the top-level dataset.
 #
 
-pdir=`/usr/bin/dirname $zonepath`
-zpname=`/usr/bin/basename $zonepath`
+pdir=`/usr/bin/dirname $ZONEPATH`
+zpname=`/usr/bin/basename $ZONEPATH`
 
 get_zonepath_ds $pdir
 zpds=$ZONEPATH_DS
@@ -94,7 +96,7 @@
 /usr/sbin/zfs create -o mountpoint=legacy -o zoned=on $zpds/$zpname/ROOT
 
 # make snapshot
-SNAPNAME=${zonename}_snap
+SNAPNAME=${ZONENAME}_snap
 SNAPNUM=0
 while [ $SNAPNUM -lt 100 ]; do
 	/usr/sbin/zfs snapshot $ACTIVE_DS@$SNAPNAME
@@ -102,7 +104,7 @@
                 break
 	fi
 	SNAPNUM=`expr $SNAPNUM + 1`
-	SNAPNAME="${zonename}_snap$SNAPNUM"
+	SNAPNAME="${ZONENAME}_snap$SNAPNUM"
 done
 
 if [ $SNAPNUM -ge 100 ]; then
@@ -134,19 +136,20 @@
 /usr/sbin/zfs set canmount=noauto $zpds/$zpname/ROOT/$BENAME || \
 	fail_incomplete "$f_zfs_create"
 
-if [ ! -d $zonepath/root ]; then
-	/usr/bin/mkdir -p $zonepath/root
-	/usr/bin/chmod 700 $zonepath
+if [ ! -d $ZONEPATH/root ]; then
+	/usr/bin/mkdir -p $ZONEPATH/root
+	/usr/bin/chmod 700 $ZONEPATH
 fi
 
-/usr/sbin/mount -F zfs $zpds/$zpname/ROOT/$BENAME $zonepath/root || \
-	fail_incomplete "$f_zfs_mount"
+ZONE_IS_MOUNTED=0
+trap trap_exit EXIT
 
-if [ $brand != labeled ]; then
-	/usr/sbin/sys-unconfig -R $zonepath/root || \
-	    fail_incomplete "$f_sysunconfig"
-fi
+#
+# Completion of unconfigure_zone will leave the zone root mounted for
+# ipkg brand zones.  The root won't be mounted for labeled brand zones.
+#
+is_brand_labeled
+(( $? == 0 )) && unconfigure_zone
 
-/usr/sbin/umount $zonepath/root || fail_fatal "$f_umount"
-
+trap - EXIT
 exit $ZONE_SUBPROC_OK
--- a/src/brand/common.ksh	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/common.ksh	Fri Nov 13 15:13:18 2009 -0700
@@ -46,6 +46,7 @@
 f_no_ds=$(gettext "the zonepath must be a ZFS dataset.\nThe parent directory of the zonepath must be a ZFS dataset so that the\nzonepath ZFS dataset can be created properly.")
 f_multiple_ds=$(gettext "multiple active datasets.")
 f_no_active_ds=$(gettext "no active dataset.")
+f_zfs_unmount=$(gettext "Unable to unmount the zone's root ZFS dataset (%s).\nIs there a global zone process inside the zone root?\nThe current zone boot environment will remain mounted.\n")
 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.")
 
 f_safedir=$(gettext "Expected %s to be a directory.")
@@ -54,6 +55,14 @@
 
 m_brnd_usage=$(gettext "brand-specific usage: ")
 
+v_unconfig=$(gettext "Performing zone sys-unconfig")
+e_unconfig=$(gettext "sys-unconfig failed")
+v_mounting=$(gettext "Mounting the zone")
+e_badmount=$(gettext "Zone mount failed")
+v_unmount=$(gettext "Unmounting zone")
+e_badunmount=$(gettext "Zone unmount failed")
+e_exitfail=$(gettext "Postprocessing failed.")
+
 m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
 m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console (zlogin -C)")
 m_postnote2=$(gettext "              to complete the configuration process.")
@@ -73,6 +82,12 @@
 	exit $ZONE_SUBPROC_USAGE
 }
 
+is_brand_labeled() {
+	brand=$(/usr/sbin/zoneadm -z $ZONENAME list -p | awk -F: '{print $6}')
+	[[ $brand == "labeled" ]] && return 1
+	return 0
+}
+
 sanity_check()
 {
 	typeset dir="$1"
@@ -180,6 +195,34 @@
 }
 
 #
+# Make sure the active dataset is mounted for the zone.  There are several
+# cases to consider:
+# 1) First boot of the zone, nothing is mounted
+# 2) Zone is halting, active dataset remains the same.
+# 3) Zone is halting, there is a new active dataset to mount.
+#
+mount_active_ds() {
+	mount -p | cut -d' ' -f3 | egrep -s "^$ZONEPATH/root$"
+	if (( $? == 0 )); then
+		# Umount current dataset on the root (it might be an old BE).
+		umount $ZONEPATH/root
+		if (( $? != 0 )); then
+			# The umount failed, leave the old BE mounted.
+			# Warn about gz process preventing umount.
+			printf "$f_zfs_unmount" "$ZONEPATH/root"
+			return
+		fi
+	fi
+
+	# Mount active dataset on the root.
+	get_current_gzbe
+	get_zonepath_ds $ZONEPATH
+	get_active_ds $CURRENT_GZBE $ZONEPATH_DS
+
+	mount -F zfs $ACTIVE_DS $ZONEPATH/root || fail_fatal "$f_zfs_mount"
+}
+
+#
 # Set up ZFS dataset hierarchy for the zone root dataset.
 #
 create_active_ds() {
@@ -240,6 +283,30 @@
 }
 
 #
+# Run sys-unconfig on the zone.
+#
+unconfigure_zone() {
+	vlog "$v_unconfig"
+
+	vlog "$v_mounting"
+	ZONE_IS_MOUNTED=1
+	zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
+
+	zlogin -S $ZONENAME /usr/sbin/sys-unconfig -R /a \
+            </dev/null >/dev/null 2>&1
+        if (( $? != 0 )); then
+                error "$e_unconfig"
+		failed=1
+        fi
+
+	vlog "$v_unmount"
+	zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
+	ZONE_IS_MOUNTED=0
+
+	[[ -n $failed ]] && fatal "$e_exitfail"
+}
+
+#
 # Emits to stdout the entire incorporation for this image,
 # stripped of publisher name and other junk.
 #
--- a/src/brand/config.xml	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/config.xml	Fri Nov 13 15:13:18 2009 -0700
@@ -40,6 +40,7 @@
 	<install>/usr/lib/brand/ipkg/pkgcreatezone -z %z -R %R</install>
 	<installopts>a:c:d:e:hk:P:p:suv</installopts>
 	<boot></boot>
+	<sysboot>/usr/lib/brand/ipkg/prestate %z %R 2 0</sysboot>
 	<halt></halt>
 	<verify_cfg>/usr/lib/brand/ipkg/support verify</verify_cfg>
 	<verify_adm></verify_adm>
--- a/src/brand/image_install	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/image_install	Fri Nov 13 15:13:18 2009 -0700
@@ -221,6 +221,11 @@
 
 trap - EXIT
 rm -f $LOGFILE
+
+# Mount active dataset on the root.
+is_brand_labeled
+(( $? == 0 )) && mount_active_ds
+
 log ""
 log "$m_complete" ${SECONDS}
 printf "$install_log\n" "$ZONEROOT/var/log/$ZONENAME.install$$.log"
--- a/src/brand/p2v	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/p2v	Fri Nov 13 15:13:18 2009 -0700
@@ -40,7 +40,7 @@
 # Clean up on failure
 trap_exit()
 {
-	if (( $zone_is_mounted != 0 )); then
+	if (( $ZONE_IS_MOUNTED != 0 )); then
 		error "$v_unmount"
 		zoneadm -z $ZONENAME unmount
 	fi
@@ -323,7 +323,7 @@
 #
 # failure should unmount the zone if necessary;
 #
-zone_is_mounted=0
+ZONE_IS_MOUNTED=0
 trap trap_exit EXIT
 
 #
@@ -363,10 +363,6 @@
 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_mounting=$(gettext "Mounting the zone")
-e_badmount=$(gettext "Zone mount failed")
-v_unmount=$(gettext "Unmounting zone")
-e_badunmount=$(gettext "Zone unmount failed")
 v_rmhollowsvcs=$(gettext "Deleting global zone-only SMF services")
 v_fixnetsvcs=$(gettext "Adjusting network SMF services")
 v_rminvalidsvcs=$(gettext "Disabling invalid SMF services")
@@ -381,10 +377,7 @@
 e_rmpkg=$(gettext "removing package '%s'")
 v_rmzones=$(gettext "The following zones in this image will be unusable: %s")
 v_rmzonepaths=$(gettext "These zonepaths could be removed from this image:")
-v_unconfig=$(gettext "Performing zone sys-unconfig")
-e_unconfig=$(gettext "sys-unconfig failed")
 v_exitgood=$(gettext "Postprocessing successful.")
-e_exitfail=$(gettext "Postprocessing failed.")
 
 #
 # Do some validation on the paths we'll be accessing
@@ -442,11 +435,9 @@
 
 #
 # Mount the zone so that we can do all of the updates needed on the zone.
-# The zone's root dataset is currently mounted so we have to first umount it.
 #
-umount $ZONEROOT || fatal "$f_umount"
 vlog "$v_mounting"
-zone_is_mounted=1
+ZONE_IS_MOUNTED=1
 zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
 
 #
@@ -463,13 +454,15 @@
 
 vlog "$v_unmount"
 zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
-zone_is_mounted=0
+ZONE_IS_MOUNTED=0
 
-# Mount the zone's root dataset back onto ZONEROOT.
-get_current_gzbe
-get_zonepath_ds $ZONEPATH
-get_active_ds $CURRENT_GZBE $ZONEPATH_DS
-mount -F zfs -O $ACTIVE_DS $ZONEROOT || fail_fatal "$f_mount"
+is_brand_labeled
+brand_labeled=$?
+if (( $brand_labeled == 1 )); then
+	# The labeled brand needs to mount the zone's root dataset back onto
+	# ZONEROOT so we can finish processing.
+	mount_active_ds
+fi
 
 # Change the pkging variant from global zone to non-global zone.
 log "$v_change_var"
@@ -478,8 +471,7 @@
 
 #
 # Run update on attach.  State is currently 'incomplete' so use the private
-# force-update option.  The zone's root dataset is still mounted at this point.
-# update-on-attach will unmount the zonepath dataset when its done.
+# force-update option.
 # This also leaves the zone in the 'installed' state.  This is a known bug
 # in 'zoneadm attach'.  We change the zone state back to 'incomplete' for
 # now but this can be removed once 'zoneadm attach' is fixed.
@@ -489,27 +481,9 @@
 zoneadm -z $ZONENAME mark incomplete || fatal "$e_badupdate"
 log "$v_updatedone"
 
-if [[ -n $OPT_U ]]; then
-	# We're sys-unconfiging the zone.
-	vlog "$v_unconfig"
-
-	vlog "$v_mounting"
-	zone_is_mounted=1
-	zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
+[[ -n $OPT_U ]] && unconfigure_zone
 
-	/usr/sbin/zlogin -S $ZONENAME /usr/sbin/sys-unconfig -R /a \
-            </dev/null >/dev/null 2>&1
-        if (( $? != 0 )); then
-                error "$e_unconfig"
-		failed=1
-        fi
-
-	vlog "$v_unmount"
-	zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
-	zone_is_mounted=0
-
-	[[ -n $failed ]] && fatal "$e_exitfail"
-fi
+(( $brand_labeled == 1 )) && mount_active_ds
 
 trap - EXIT
 vlog "$v_exitgood"
--- a/src/brand/pkgcreatezone	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/pkgcreatezone	Fri Nov 13 15:13:18 2009 -0700
@@ -68,14 +68,6 @@
 
 m_done=$(gettext      " done.")
 
-is_brand_labeled() {
-	brand_labeled=0
-	brand=$(/usr/sbin/zoneadm -z $ZONENAME list -p | awk -F: '{print $6}')
-	if [[ $brand == "labeled" ]]; then
-		brand_labeled=1
-	fi
-}
-
 trap_cleanup() {
 	print "$f_interrupted"
 	exit $int_code
@@ -147,6 +139,7 @@
 zonepath="$ZONEPATH"
 
 is_brand_labeled
+brand_labeled=$?
 
 ZONEROOT=$ZONEPATH/root
 secinfo=""
@@ -423,9 +416,7 @@
 #
 # Get packages for TX zones if appropriate.
 #
-if [ $brand_labeled -ne 0 ]; then
-	pkglist="$pkglist system/trusted/trusted-nonglobal"
-fi
+(( $brand_labeled == 1 )) && pkglist="$pkglist system/trusted/trusted-nonglobal"
 
 #
 # Get man(1) but not the man pages
@@ -486,13 +477,13 @@
 /usr/sbin/sysidconfig -b $ZONEROOT -a /lib/svc/method/sshd
 touch $ZONEROOT/etc/.UNCONFIGURED
 
-# Umount the dataset on the root.
-/usr/sbin/umount $ZONEROOT
-
 printf "$m_complete\n\n" ${SECONDS}
-if [ $brand_labeled -eq 0 ]; then
+if (( $brand_labeled == 0 )); then
 	printf "$m_postnote\n"
 	printf "$m_postnote2\n"
+else
+	# Umount the dataset on the root.
+	umount $ZONEROOT || printf "$f_zfs_unmount" "$ZONEPATH/root"
 fi
 
 exit $ZONE_SUBPROC_OK
--- a/src/brand/poststate	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/poststate	Fri Nov 13 15:13:18 2009 -0700
@@ -20,14 +20,12 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
 
-f_umount=$(gettext "Error: error unmounting zone root dataset.")
-
 # States
 # ZONE_STATE_CONFIGURED           0 (never see)
 # ZONE_STATE_INCOMPLETE           1 (never see)
@@ -44,15 +42,23 @@
 # boot			1
 # halt			4
 
-zonename=$1
-zonepath=$2
+ZONENAME=$1
+ZONEPATH=$2
 state=$3
 cmd=$4
 
 # If we're not halting the zone, then just return.
 if [ $cmd -eq 4 ]; then
-	# Umount dataset on the root.
-	/usr/sbin/umount $zonepath/root || fail_fatal "$f_umount"
+	is_brand_labeled
+	if (( $? == 0 )); then
+		# Leave the active dataset mounted after halting (this might be
+		# a different dataset than what was mounted).
+		mount_active_ds
+	else
+		# Umount dataset on the root.
+		zoneroot="$ZONEPATH/root"
+		umount $zoneroot || printf "$f_zfs_unmount" "$zoneroot"
+	fi
 fi
 
 exit $ZONE_SUBPROC_OK
--- a/src/brand/prestate	Fri Nov 13 13:04:50 2009 -0800
+++ b/src/brand/prestate	Fri Nov 13 15:13:18 2009 -0700
@@ -20,14 +20,12 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
 
-f_mount=$(gettext "Error: error mounting zone root dataset.")
-
 # States
 # ZONE_STATE_CONFIGURED           0 (never see)
 # ZONE_STATE_INCOMPLETE           1 (never see)
@@ -44,20 +42,15 @@
 # boot			1
 # halt			4
 
-zonename=$1
-zonepath=$2
+ZONENAME=$1
+ZONEPATH=$2
 state=$3
 cmd=$4
 
 # If we're not readying the zone, then just return.
 if [ $cmd -eq 0 ]; then
 	# Mount active dataset on the root.
-	get_current_gzbe
-	get_zonepath_ds $zonepath
-	get_active_ds $CURRENT_GZBE $ZONEPATH_DS
-
-	/usr/sbin/mount -F zfs -O $ACTIVE_DS $zonepath/root || \
-	    fail_fatal "$f_mount"
+	mount_active_ds
 fi
 
 exit $ZONE_SUBPROC_OK