17791 ipkg brand needs to be in sync with revised dataset layout
authorMike Gerdts <mike.gerdts@oracle.com>
Fri, 11 Feb 2011 14:04:06 -0800
changeset 2235 1f446820dcb0
parent 2234 33dd51b5ca54
child 2236 7b074b5316ec
17791 ipkg brand needs to be in sync with revised dataset layout 17654 check for zonepath in GZ ROOT assumes root pool named rpool
src/brand/Makefile
src/brand/attach
src/brand/clone
src/brand/common.ksh
src/brand/detach
src/brand/image_install
src/brand/p2v
src/brand/pkgcreatezone
src/brand/poststate
src/brand/prestate
src/brand/sysboot
src/brand/uninstall
src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m
--- a/src/brand/Makefile	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/Makefile	Fri Feb 11 14:04:06 2011 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 MACH:sh = uname -p
@@ -63,6 +63,7 @@
 	$(ROOTBRANDPKG)/prestate \
 	$(ROOTBRANDPKG)/smf_disable.lst \
 	$(ROOTBRANDPKG)/support \
+	$(ROOTBRANDPKG)/sysboot \
 	$(ROOTBRANDPKG)/uninstall
 
 BIN = \
--- a/src/brand/attach	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/attach	Fri Feb 11 14:04:06 2011 -0800
@@ -55,6 +55,9 @@
 f_nosuch_cert=$(gettext "Failed to find cert %s for global zone publisher")
 f_ds_config=$(gettext  "Failed to configure dataset %s: could not set %s.")
 f_no_active_ds_mounted=$(gettext  "Failed to locate any dataset mounted at %s.  Attach requires a mounted dataset.")
+e_dataset_disappeared=$(gettext "Dataset %s was unexpectedly unmounted")
+e_dataset_not_mounted=$(gettext "Dataset %s exists in boot environment but not mounted")
+e_dataset_not_in_be=$(gettext "Dataset %s mountpoint %s is not under zone root %s")
 
 # Clean up on interrupt
 trap_cleanup() {
@@ -82,15 +85,20 @@
 			# Restore the zone properties for the pre-existing
 			# dataset.
 			if [[ -n "$ACTIVE_DS" ]]; then
+				zfs set canmount=off $ACTIVE_DS
+				(( $? != 0 )) && error "$f_ds_config" \
+				    "$ACTIVE_DS" "canmount=on"
 				zfs set zoned=off $ACTIVE_DS
 				(( $? != 0 )) && error "$f_ds_config" \
 				    "$ACTIVE_DS" "zoned=off"
+				zfs set mountpoint=$ZONEROOT $ACTIVE_DS
+				(( $? != 0 )) && error "$f_ds_config" \
+				    "$ACTIVE_DS" "mountpoint=$ZONEROOT"
 				zfs set canmount=on $ACTIVE_DS
 				(( $? != 0 )) && error "$f_ds_config" \
 				    "$ACTIVE_DS" "canmount=on"
-				zfs set mountpoint=$ZONEROOT $ACTIVE_DS
-				(( $? != 0 )) && error "$f_ds_config" \
-				    "$ACTIVE_DS" "mountpoint=$ZONEROOT"
+				zfs mount "$ACTIVE_DS" || \
+				    error "$e_mount1_failed" "$ACTIVE_DS"
 			fi
 		fi
 		log "$m_failed"
@@ -105,23 +113,19 @@
 trap trap_cleanup INT
 trap trap_exit EXIT
 
-#set -o xtrace
-
 PKG="/usr/bin/pkg"
 KEYDIR=/var/pkg/ssl
 
 # 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"
+zone=
+init_zone zone "$1" "$2"
+# Set ZONEPATH, etc.
+eval $(bind_legacy_zone_globals zone)
 
 shift; shift	# remove ZONENAME and ZONEPATH from arguments array
 
-ZONEROOT="$ZONEPATH/root"
 logdir="$ZONEROOT/var/log"
 
 #
@@ -190,8 +194,8 @@
 			typeset publisher.sticky=""
 			typeset publisher.preferred=""
 			typeset publisher.enabled=""
-			typeset -a publisher.origins=""
-			typeset -a publisher.mirrors=""
+			typeset -a publisher.origins
+			typeset -a publisher.mirrors
 			typeset publisher.name=$name
 			typeset publisher.keyfile=""
 			typeset publisher.certfile=""
@@ -297,11 +301,11 @@
 		args="$args -P"
 	fi
 
-	for origin in ${publisher.origins[*]}; do
+	for origin in "${publisher.origins[@]}"; do
 		args="$args -g $origin"
 	done
 
-	for mirror in ${publisher.mirrors[*]}; do
+	for mirror in "${publisher.mirrors[@]}"; do
 		args="$args -m $mirror"
 	done
 
@@ -370,125 +374,17 @@
 	exit $ZONE_SUBPROC_OK
 fi
 
-LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $ZONENAME.attach_log.XXXXXX)
+LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp ${zone.name}.attach_log.XXXXXX)
 if [[ -z "$LOGFILE" ]]; then
 	fatal "$e_tmpfile"
 fi
 exec 2>>"$LOGFILE"
-
 log "$m_attach_log" "$LOGFILE"
 
-#
-# TODO - once sxce is gone, move the following block into
-# usr/lib/brand/shared/common.ksh code to share with other brands using
-# the same zfs dataset logic for attach. This currently uses get_current_gzbe
-# so we can't move it yet since beadm isn't in sxce.
-#
-
-# Validate that the zonepath is not in the root dataset.
-pdir=`dirname $ZONEPATH`
-get_zonepath_ds $pdir
-fail_zonepath_in_rootds $ZONEPATH_DS
-
-EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
-
-if [[ "$install_media" == "-" ]]; then
-	#
-	# Since we're using a pre-existing dataset, the dataset currently
-	# mounted on the {zonepath}/root becomes the active dataset.  We
-	# can't depend on the usual dataset attributes to detect this since
-	# the dataset could be a detached zone or one that the user set up by
-	# hand and lacking the proper attributes.  However, since the zone is
-	# not attached yet, the 'install_media == -' means the dataset must be
-	# mounted at this point.
-	#
-	ACTIVE_DS=`mount -p | nawk -v zroot=$ZONEROOT '{
-	    if ($3 == zroot && $4 == "zfs")
-		    print $1
-	}'`
-
-	[[ -z "$ACTIVE_DS" ]] && fatal "$f_no_active_ds_mounted" $ZONEROOT
-
-	# Set up proper attributes on the ROOT dataset.
-	get_zonepath_ds $ZONEPATH
-	zfs list -H -t filesystem -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
-	(( $? != 0 )) && fatal "$f_no_active_ds"
-
-	# need to ensure zoned is off to set mountpoint=legacy.
-	zfs set zoned=off $ZONEPATH_DS/ROOT
-	(( $? != 0 )) && fatal "$f_ds_config" $ZONEPATH_DS/ROOT "zoned=off"
-
-	zfs set mountpoint=legacy $ZONEPATH_DS/ROOT
-	(( $? != 0 )) && fatal "$f_ds_config" $ZONEPATH_DS/ROOT \
-	    "mountpoint=legacy"
-	zfs set zoned=on $ZONEPATH_DS/ROOT
-	(( $? != 0 )) && fatal "$f_ds_config" $ZONEPATH_DS/ROOT "zoned=on"
-
-	#
-	# We're typically using a pre-existing mounted dataset so setting the
-	# following propery changes will cause the {zonepath}/root dataset to
-	# be unmounted.  However, a p2v with an update-on-attach will have
-	# created the dataset with the correct properties, so setting these
-	# attributes won't unmount the dataset.  Thus, we check the mount
-	# and attempt the remount if necessary.
-	#
-	get_current_gzbe
-	zfs set $PROP_PARENT=$CURRENT_GZBE $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS \
-	    "$PROP_PARENT=$CURRENT_GZBE"
-	zfs set $PROP_ACTIVE=on $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS "$PROP_ACTIVE=on"
-	zfs set canmount=noauto $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS "canmount=noauto"
-	zfs set zoned=off $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS "zoned=off"
-	zfs inherit mountpoint $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS "'inherit mountpoint'"
-	zfs inherit zoned $ACTIVE_DS
-	(( $? != 0 )) && fatal "$f_ds_config" $ACTIVE_DS "'inherit zoned'"
-
-	mounted_ds=`mount -p | nawk -v zroot=$ZONEROOT '{
-	    if ($3 == zroot && $4 == "zfs")
-		    print $1
-	}'`
-
-	if [[ -z $mounted_ds ]]; then
-		mount -F zfs $ACTIVE_DS $ZONEROOT || fatal "$f_zfs_mount"
-	fi
-else
-	#
-	# Since we're not using a pre-existing ZFS dataset layout, create
-	# the zone datasets and mount them.  Start by creating the zonepath
-	# dataset, similar to what zoneadm would do for an initial install.
-	#
-	zds=$(zfs list -H -t filesystem -o name $pdir 2>/dev/null)
-	if (( $? == 0 )); then
-		pnm=$(/usr/bin/basename $ZONEPATH)
-		# The zonepath dataset might already exist.
-		zfs list -H -t filesystem -o name $zds/$pnm >/dev/null 2>&1
-		if (( $? != 0 )); then
-			zfs create "$zds/$pnm"
-			(( $? != 0 )) && fatal "$f_zfs_create"
-			vlog "$m_zfs"
-		fi
-	fi
-
-	create_active_ds
-fi
-
-#
-# The zone's datasets are now in place.
-#
-
-log "$m_attach_root" "$ZONEROOT"
-# note \n to add whitespace
-log "$m_attach_ds\n" "$ACTIVE_DS"
-
-install_image "$inst_type" "$install_media"
-
-#
-# End of TODO block to move to common code.
-#
+# Remember what was mounted on the zone root in case the attach fails.
+get_ds_from_path "${zone.root}" ACTIVE_DS
+attach_datasets -t "$inst_type" -m "$install_media" zone
+migrate_export zone
 
 #
 # Perform a sanity check to confirm that the image is not a global zone.
--- a/src/brand/clone	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/clone	Fri Feb 11 14:04:06 2011 -0800
@@ -19,9 +19,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -32,7 +30,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
@@ -40,108 +38,39 @@
 	exit $ZONE_SUBPROC_INCOMPLETE
 }
 
-# Set up ZFS dataset hierarchy for the zone.
-
-ROOT="rpool/ROOT"
-
+# Source and destination zones
+typeset src dst	
 # 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)	opt_R="$OPTARG" ;;
+		z)	opt_z="$OPTARG" ;;
 		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
-if [ $# -ne 1 ]; then
+if (($# != 1)); then
 	fail_usage "";
 fi
 
-sourcezone=$1
-
-# Find the active source zone dataset to clone.
-sourcezonepath=`/usr/sbin/zoneadm -z $sourcezone list -p | awk -F: '{print $4}'`
-if [ -z "$sourcezonepath" ]; then
-	fail_fatal "$f_nosource"
-fi
+init_zone dst "$opt_z" "$opt_R"
+init_zone src "$1"
 
 get_current_gzbe
-get_zonepath_ds $sourcezonepath
-get_active_ds $CURRENT_GZBE $ZONEPATH_DS
-
-#
-# Now set up the zone's datasets
-#
-
-#
-# First make the top-level dataset.
-#
-
-pdir=`/usr/bin/dirname $ZONEPATH`
-zpname=`/usr/bin/basename $ZONEPATH`
+get_active_be src || fatal "$e_no_active_be"
 
-get_zonepath_ds $pdir
-zpds=$ZONEPATH_DS
-
-fail_zonepath_in_rootds $zpds
-
-#
-# We need to tolerate errors while creating the datasets and making the
-# mountpoint, since these could already exist from some other BE.
-#
-
-/usr/sbin/zfs create $zpds/$zpname
-
-/usr/sbin/zfs create -o mountpoint=legacy -o zoned=on $zpds/$zpname/ROOT
+# From here on out the global variables referenced are for the destination zone
+eval $(bind_legacy_zone_globals dst)
 
-# make snapshot
-SNAPNAME=${ZONENAME}_snap
-SNAPNUM=0
-while [ $SNAPNUM -lt 100 ]; do
-	/usr/sbin/zfs snapshot $ACTIVE_DS@$SNAPNAME
-        if [ $? = 0 ]; then
-                break
-	fi
-	SNAPNUM=`expr $SNAPNUM + 1`
-	SNAPNAME="${ZONENAME}_snap$SNAPNUM"
-done
-
-if [ $SNAPNUM -ge 100 ]; then
-	fail_fatal "$f_zfs_create"
-fi
+# Make dataset snapshots
+snapshot_zone_rpool src "${dst}_snap%02d" snapname \
+    || fail_incomplete "$f_zfs_snapshot"
 
-# do clone
-BENAME=zbe
-BENUM=0
-while [ $BENUM -lt 100 ]; do
-	/usr/sbin/zfs clone $ACTIVE_DS@$SNAPNAME $zpds/$zpname/ROOT/$BENAME
-	if [ $? = 0 ]; then
-		break
-	fi
-	BENUM=`expr $BENUM + 1`
-	BENAME="zbe-$BENUM"
-done
-
-if [ $BENUM -ge 100 ]; then
-	fail_fatal "$f_zfs_create"
-fi
+# Make dataset clones
+clone_zone_rpool src dst "$snapname" || fail_incomplete "$f_zone_clone"
 
-/usr/sbin/zfs set $PROP_ACTIVE=on $zpds/$zpname/ROOT/$BENAME || \
-	fail_incomplete "$f_zfs_create"
-
-/usr/sbin/zfs set $PROP_PARENT=$CURRENT_GZBE $zpds/$zpname/ROOT/$BENAME || \
-	fail_incomplete "$f_zfs_create"
-
-/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
-fi
-
-ZONE_IS_MOUNTED=0
+ZONE_IS_MOUNTED=1
 trap trap_exit EXIT
 
 #
--- a/src/brand/common.ksh	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/common.ksh	Fri Feb 11 14:04:06 2011 -0800
@@ -23,14 +23,20 @@
 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
+#
+# Only change PATH if you give full consideration to GNU or other variants
+# of common commands having different arguments and output.  Setting PATH is
+# and not using the full path to executables provides a performance improvement
+# by using the ksh builtin equivalent of many common commands.
+#
+export PATH=/usr/bin:/usr/sbin
 unset LD_LIBRARY_PATH
-PATH=/usr/bin:/usr/sbin
-export PATH
 
 . /usr/lib/brand/shared/common.ksh
 
 PROP_PARENT="org.opensolaris.libbe:parentbe"
 PROP_ACTIVE="org.opensolaris.libbe:active"
+PROP_BE_HANDLE="com.oracle.libbe:nbe_handle"
 
 f_incompat_options=$(gettext "cannot specify both %s and %s options")
 f_sanity_detail=$(gettext  "Missing %s at %s")
@@ -40,10 +46,8 @@
 sanity_fail_vers=$(gettext  "  Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.")
 install_fail=$(gettext  "        Result: *** Installation FAILED ***")
 f_zfs_in_root=$(gettext "Installing a zone inside of the root pool's 'ROOT' dataset is unsupported.")
-f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.")
 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.")
 f_no_gzbe=$(gettext "unable to determine global zone boot environment.")
-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")
@@ -67,23 +71,8 @@
 m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console (zlogin -C)")
 m_postnote2=$(gettext "              to complete the configuration process.")
 
-fail_incomplete() {
-	printf "ERROR: " 1>&2
-	printf "$@" 1>&2
-	printf "\n" 1>&2
-	exit $ZONE_SUBPROC_NOTCOMPLETE
-}
-
-fail_usage() {
-	printf "$@" 1>&2
-	printf "\n" 1>&2
-	printf "$m_brnd_usage" 1>&2
-	printf "$m_usage\n" 1>&2
-	exit $ZONE_SUBPROC_USAGE
-}
-
 is_brand_labeled() {
-	if [ -z $ALTROOT ]; then
+	if [[ -z $ALTROOT ]]; then
 		AR_OPTIONS=""
 	else
 		AR_OPTIONS="-R $ALTROOT"
@@ -140,7 +129,7 @@
 	vlog "$sanity_ok"
 }
 
-get_current_gzbe() {
+function get_current_gzbe {
 	#
 	# If there is no alternate root (normal case) then set the
 	# global zone boot environment by finding the boot environment
@@ -148,156 +137,97 @@
 	# If a zone exists in a boot environment mounted on an alternate root,
 	# then find the boot environment where the alternate root is mounted.
 	#
-	if [ -x /usr/sbin/beadm ]; then
-		CURRENT_GZBE=`/usr/sbin/beadm list -H | /usr/bin/nawk \
-				-v alt=$ALTROOT -F\; '{
-			if (length(alt) == 0) {
-			    # Field 3 is the BE status.  'N' is the active BE.
-			    if ($3 !~ "N")
-				next
-			} else {
-			    # Field 4 is the BE mountpoint.
-			    if ($4 != alt)
-				next
-			}
-			# Field 2 is the BE UUID
-			print $2
-		}'`
-	else
-		# If there is no beadm command then the system doesn't really
-		# support multiple boot environments.  We still want zones to
-		# work so simulate the existence of a single boot environment.
-		CURRENT_GZBE="opensolaris"
-	fi
-
+	CURRENT_GZBE=$(beadm list -H | nawk -v alt=$ALTROOT -F\; '{
+		if (length(alt) == 0) {
+		    # Field 3 is the BE status.  'N' is the active BE.
+		    if ($3 !~ "N")
+			next
+		} else {
+		    # Field 4 is the BE mountpoint.
+		    if ($4 != alt)
+		next
+		}
+		# Field 2 is the BE UUID
+		print $2
+	    }')
 	if [ -z "$CURRENT_GZBE" ]; then
-		fail_fatal "$f_no_gzbe"
+		return 1
 	fi
-}
-
-# Find the active dataset under the zonepath dataset to mount on zonepath/root.
-# $1 CURRENT_GZBE
-# $2 ZONEPATH_DS
-get_active_ds() {
-	ACTIVE_DS=`/usr/sbin/zfs list -H -r -t filesystem \
-	    -o name,$PROP_PARENT,$PROP_ACTIVE $2/ROOT | \
-	    /usr/bin/nawk -v gzbe=$1 ' {
-		if ($1 ~ /ROOT\/[^\/]+$/ && $2 == gzbe && $3 == "on") {
-			print $1
-			if (found == 1)
-				exit 1
-			found = 1
-		}
-	    }'`
-
-	if [ $? -ne 0 ]; then
-		fail_fatal "$f_multiple_ds"
-	fi
-
-	if [ -z "$ACTIVE_DS" ]; then
-		fail_fatal "$f_no_active_ds"
-	fi
-}
-
-# Check that zone is not in the ROOT dataset.
-fail_zonepath_in_rootds() {
-	case $1 in
-		rpool/ROOT/*)
-			fail_fatal "$f_zfs_in_root"
-			break;
-			;;
-		*)
-			break;
-			;;
-	esac
+	return 0
 }
 
 #
-# 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.
+# get_active_be zone
+#
+# Finds the active boot environment for the given zone.
+#
+# Arguments:
+#
+#  zone		zone structure initialized with init_zone
+#
+# Globals:
+#
+#  CURRENT_GZBE	Current global zone boot environment.  If not already set,
+#		it will be set.
+#
+# Returns:
+#
+#  0 on success, else 1.
 #
-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
+function get_active_be {
+	typeset -n zone=$1
+	typeset active_ds=
+	typeset tab=$(printf "\t")
+
+	[[ -z "$CURRENT_GZBE" ]] && get_current_gzbe
+
+	typeset name parent active
+	zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \
+	    ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do
+		[[ $parent == "$CURRENT_GZBE" ]] || continue
+		[[ $active == on ]] || continue
+		vlog "Found active dataset %s" "$name"
+		if [[ -n "$active_ds" ]] ; then
+			error "$f_multiple_ds"
+			return 1
 		fi
+		active_ds=$name
+	done
+	if [[ -z $active_ds ]]; then
+		error "$f_no_active_ds"
+		return 1
 	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"
+	zone.active_ds=$active_ds
 }
 
-#
-# Set up ZFS dataset hierarchy for the zone root dataset.
-#
-create_active_ds() {
-	get_current_gzbe
+function set_active_be {
+	typeset -n zone="$1"
+	typeset be="$2"
 
-	#
-	# Find the zone's current dataset.  This should have been created by
-	# zoneadm.
-	#
-	get_zonepath_ds $zonepath
-
-	# Check that zone is not in the ROOT dataset.
-	fail_zonepath_in_rootds $ZONEPATH_DS
+	[[ -z "$CURRENT_GZBE" ]] && get_current_gzbe
 
 	#
-	# From here on, errors should cause the zone to be incomplete.
-	#
-	int_code=$ZONE_SUBPROC_FATAL
-
-	#
-	# We need to tolerate errors while creating the datasets and making the
-	# mountpoint, since these could already exist from some other BE.
+	# Turn off the active property on BE's with the same GZBE
 	#
-
-	/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
-	if (( $? != 0 )); then
-		/usr/sbin/zfs create -o mountpoint=legacy \
-		    -o zoned=on $ZONEPATH_DS/ROOT
-		if (( $? != 0 )); then
-			fail_fatal "$f_zfs_create"
-		fi
-	fi
-
-	BENAME=zbe
-	BENUM=0
-	# Try 100 different names before giving up.
-	while [ $BENUM -lt 100 ]; do
-       		/usr/sbin/zfs create -o $PROP_ACTIVE=on \
-		    -o $PROP_PARENT=$CURRENT_GZBE \
-		    -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME >/dev/null 2>&1
-		if (( $? == 0 )); then
-			break
-		fi
-		BENUM=`expr $BENUM + 1`
-		BENAME="zbe-$BENUM"
+	zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \
+	    ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do
+		[[ $parent == "$CURRENT_GZBE" ]] || continue
+		[[ $active == on ]] || continue
+		[[ $name ==  "${zone.ROOT_ds}/$be" ]] && continue
+		vlog "Deactivating active dataset %s" "$name"
+		zfs set $PROP_ACTIVE=off "$name" || return 1
 	done
 
-	if [ $BENUM -ge 100 ]; then
-		fail_fatal "$f_zfs_create"
-	fi
+	zone.active_ds="${zone.ROOT_ds}/$be"
 
-	if [ ! -d $ZONEROOT ]; then
-		/usr/bin/mkdir $ZONEROOT
-	fi
+	zfs set "$PROP_PARENT=$CURRENT_GZBE" ${zone.active_ds} \
+	    || return 1
+	zfs set "$PROP_ACTIVE=on" ${zone.active_ds} || return 1
 
-	/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $ZONEROOT || \
-	    fail_incomplete "$f_zfs_mount"
+	zfs set "$PROP_BE_HANDLE=on" "${zone.rpool_ds}" || return 1
+
+	return 0
 }
 
 #
--- a/src/brand/detach	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/detach	Fri Feb 11 14:04:06 2011 -0800
@@ -24,61 +24,33 @@
 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
-
 . /usr/lib/brand/ipkg/common.ksh
 
 m_usage=$(gettext  "detach [-n ].")
 
-f_mount=$(gettext "Error: error mounting zone root dataset.")
-f_ds_config=$(gettext  "Failed to configure dataset %s: could not set %s.")
-
 noexecute=0
 
 # Other brand detach options are invalid for this brand.
 while getopts "nR:z:" opt; do
 	case $opt in
 		n)	noexecute=1 ;;
-		R)	zonepath="$OPTARG" ;;
-		z)	zonename="$OPTARG" ;;
+		R)	ZONEPATH="$OPTARG" ;;
+		z)	ZONENAME="$OPTARG" ;;
 		?)	fail_usage "" ;;
 		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
-if [ $noexecute -eq 1 ]; then
-	# dry-run - output zone's config and exit
-	cat /etc/zones/$zonename.xml
+init_zone zone "$ZONENAME" "$ZONEPATH"
+eval $(bind_legacy_zone_globals zone)
+
+if (( $noexecute == 1 )); then
+	cat /etc/zones/$ZONENAME.xml
 	exit $ZONE_SUBPROC_OK
 fi
 
-#
-# Detaching
-#
-# Leave the active dataset mounted on the zone's rootpath for ease of
-# migration.
-#
-get_current_gzbe
-get_zonepath_ds $zonepath
-get_active_ds $CURRENT_GZBE $ZONEPATH_DS
-
-/usr/sbin/zfs set zoned=off $ACTIVE_DS || \
-    fail_incomplete "$f_ds_config" "$ACTIVE_DS" "zoned=off"
-
-/usr/sbin/zfs set canmount=on $ACTIVE_DS || \
-    fail_incomplete "$f_ds_config" "$ACTIVE_DS" "canmount=on"
-
-#
-# This mounts the dataset.
-# XXX do we have to worry about subsidiary datasets?
-#
-/usr/sbin/zfs set mountpoint=$zonepath/root $ACTIVE_DS || \
-    fail_incomplete "$f_ds_config" "$ACTIVE_DS" "mountpoint=$zonepath/root"
-
-#
-# There is no sw inventory in an ipkg branded zone, so just use the original
-# xml file.
-#
-cp /etc/zones/$zonename.xml $zonepath/SUNWdetached.xml
+# All of the hard stuff is done in commmon code.
+detach_zone zone
 
 exit $ZONE_SUBPROC_OK
--- a/src/brand/image_install	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/image_install	Fri Feb 11 14:04:06 2011 -0800
@@ -19,8 +19,9 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
+
+#
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 #
@@ -97,14 +98,8 @@
 # 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"
-
-ZONEROOT="$ZONEPATH/root"
-
+init_zone zone "$1" "$2"
+eval $(bind_legacy_zone_globals zone)
 shift; shift	# remove zonename and zonepath from arguments array
 
 unset inst_type
@@ -204,8 +199,7 @@
 
 if (( $p2v_result != 0 )); then
 	log "$p2v_fail"
-	log ""
-	log "$install_fail"
+	log "\n$install_fail"
 	log "$install_log" "$LOGFILE"
 	exit $ZONE_SUBPROC_FATAL
 fi
@@ -224,10 +218,9 @@
 
 # Mount active dataset on the root.
 is_brand_labeled
-(( $? == 0 )) && mount_active_ds
+(( $? == 0 )) && mount_active_be -c zone
 
-log ""
-log "$m_complete" ${SECONDS}
+log "\n$m_complete" ${SECONDS}
 printf "$install_log\n" "$ZONEROOT/var/log/$ZONENAME.install$$.log"
 printf "$m_postnote\n"
 printf "$m_postnote2\n"
--- a/src/brand/p2v	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/p2v	Fri Feb 11 14:04:06 2011 -0800
@@ -27,9 +27,13 @@
 # zone, so care should be taken to validate any modifications so that they
 # are safe.
 
-# Restrict executables to /usr/bin and /usr/sbin
-PATH=/usr/bin:/usr/sbin
-export PATH
+#
+# Only change PATH if you give full consideration to GNU or other variants
+# of common commands having different arguments and output.  Setting PATH is
+# and not using the full path to executables provides a performance improvement
+# by using the ksh builtin equivalent of many common commands.
+#
+export PATH=/usr/bin:/usr/sbin
 unset LD_LIBRARY_PATH
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -346,10 +350,8 @@
 (( $# != 2 )) && exit 1
 
 [[ -n $LOGFILE ]] && exec 2>>$LOGFILE
-
-ZONENAME=$1
-ZONEPATH=$2
-ZONEROOT=$ZONEPATH/root
+init_zone zone "$1" "$2"
+eval $(bind_legacy_zone_globals zone)
 
 e_badinfo=$(gettext "Failed to get '%s' zone resource")
 e_badfile=$(gettext "Invalid '%s' file within the zone")
@@ -461,7 +463,7 @@
 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
+	mount_active_be zone
 fi
 
 # Change the pkging variant from global zone to non-global zone.
@@ -483,7 +485,7 @@
 
 [[ -n $OPT_U ]] && unconfigure_zone
 
-(( $brand_labeled == 1 )) && mount_active_ds
+(( $brand_labeled == 1 )) && mount_active_be zone
 
 trap - EXIT
 vlog "$v_exitgood"
--- a/src/brand/pkgcreatezone	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/pkgcreatezone	Fri Feb 11 14:04:06 2011 -0800
@@ -68,10 +68,10 @@
 
 trap_cleanup() {
 	print "$f_interrupted"
-	exit $int_code
+	exit $EXIT_CODE
 }
 
-int_code=$ZONE_SUBPROC_NOTCOMPLETE
+EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
 trap trap_cleanup INT
 
 extra_packages=""
@@ -132,15 +132,13 @@
 	print -u2 "Brand error: No zone path or name"
 	exit $ZONE_SUBPROC_USAGE
 fi
-
-# XXX shared/common script currently uses lower case zonename & zonepath
-zonename="$ZONENAME"
-zonepath="$ZONEPATH"
+zone=
+init_zone zone "$ZONENAME" "$ZONEPATH"
+eval $(bind_legacy_zone_globals zone)
 
 is_brand_labeled
 brand_labeled=$?
 
-ZONEROOT=$ZONEPATH/root
 secinfo=""
 
 # An image install can't use both -a AND -d...
@@ -293,7 +291,8 @@
 # Before installing the zone, set up ZFS dataset hierarchy for the zone root
 # dataset.
 #
-create_active_ds
+create_active_ds zone || fail_fatal "$f_no_ds"
+mount_active_be -c zone || fail_fatal "$f_no_ds"
 
 #
 # If we're installing from an image, branch off to that installer.
--- a/src/brand/poststate	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/poststate	Fri Feb 11 14:04:06 2011 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -48,17 +48,20 @@
 cmd=$4
 ALTROOT=$5
 
+typeset zone
+init_zone zone "$ZONENAME" "$ZONEPATH"
+eval $(bind_legacy_zone_globals zone)
+
 # If we're not halting the zone, then just return.
 if [ $cmd -eq 4 ]; then
-	is_brand_labeled
+	is_brand_labeled	# Note: return value is C-style, not shell-style
 	if (( $? == 0 )); then
-		# Leave the active dataset mounted after halting (this might be
-		# a different dataset than what was mounted).
-		mount_active_ds
+		# Leave the active boot environment mounted after halting (this
+		# might be a different dataset than what was mounted).
+		mount_active_be -c zone
 	else
 		# Umount dataset on the root.
-		zoneroot="$ZONEPATH/root"
-		umount $zoneroot || printf "$f_zfs_unmount" "$zoneroot"
+		unmount_be zone
 	fi
 fi
 
--- a/src/brand/prestate	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/prestate	Fri Feb 11 14:04:06 2011 -0800
@@ -18,9 +18,10 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
+#
 
 #
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -47,10 +48,15 @@
 cmd=$4
 ALTROOT=$5
 
+typeset zone
+init_zone zone "$ZONENAME" "$ZONEPATH"
+eval $(bind_legacy_zone_globals zone)
+
 # If we're not readying the zone, then just return.
-if [ $cmd -eq 0 ]; then
-	# Mount active dataset on the root.
-	mount_active_ds
-fi
+case $cmd in
+	0)
+		mount_active_be zone || exit $ZONE_SUBPROC_NOTCOMPLETE
+		;;
+esac
 
 exit $ZONE_SUBPROC_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/brand/sysboot	Fri Feb 11 14:04:06 2011 -0800
@@ -0,0 +1,38 @@
+#!/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) 2011, Oracle and/or its affiliates. All rights reserved.
+#
+
+. /usr/lib/brand/ipkg/common.ksh
+
+typeset zone
+init_zone zone "$1" "$2" || {
+	error "Usage: %s zone zonepath" "$0"
+	exit $ZONE_SUBPROC_USAGE
+}
+
+# Mount the active boot environment on the zoneroot.
+mount_active_be -c zone || exit $ZONE_SUBPROC_NOTCOMPLETE
+
+exit $ZONE_SUBPROC_OK
--- a/src/brand/uninstall	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/brand/uninstall	Fri Feb 11 14:04:06 2011 -0800
@@ -19,15 +19,10 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
 
 #
-# get script name (bname) and path (dname)
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
-bname=`basename $0`
 
 #
 # common shell script functions
@@ -38,16 +33,13 @@
 #
 # options processing
 #
-zonename=$1
-if [ -z "$zonename" ]; then
-	printf "$f_abort\n" >&2
-	exit $ZONE_SUBPROC_FATAL
-fi
-zonepath=$2
-if [ -z "$zonepath" ]; then
-	printf "$f_abort" >&2
-	exit $ZONE_SUBPROC_FATAL
-fi
+
+# If we weren't passed at least two arguments, exit now.
+(( $# < 2 )) && fail_fatal "$f_abort"
+
+typeset zone
+init_zone zone "$1" "$2"
+eval $(bind_legacy_zone_globals zone)
 shift 2
 
 options="FhHnv"
@@ -101,7 +93,6 @@
 #
 # main
 #
-zoneroot=$zonepath/root
 
 nop=""
 if [[ -n "$opt_n" ]]; then
@@ -113,49 +104,28 @@
 	ZONE_SUBPROC_OK=$ZONE_SUBPROC_FATAL
 fi
 
-#
-# We want uninstall to work in the face of various problems, such as a
-# zone with no delegated root dataset or multiple active datasets, so we
-# don't use the common functions.  Instead, we do our own work here and
-# are tolerant of errors.
-#
+# get_current_gzbe
+get_current_gzbe || fail_fatal "$f_no_gzbe"
 
-# get_current_gzbe
-CURRENT_GZBE=`/sbin/beadm list -H | /bin/nawk -F\; '{
-	# Field 3 is the BE status.  'N' is the active BE.
-	if ($3 ~ "N")
-		# Field 2 is the BE UUID
-		print $2
-	}'`
-
-if [ -z "$CURRENT_GZBE" ]; then
-	print "$f_no_gzbe"
-fi
+# find all the zone BEs associated with this global zone BE.
+typeset -a belist
+if [[ -n "$CURRENT_GZBE" ]]; then
+	zfs list -H -t filesystem -o $PROP_PARENT,name -r -d 1 \
+	    ${zone.ROOT_ds} 2>/dev/null | while IFS=$'\t' read uid fs; do
 
-uninstall_get_zonepath_ds
-uninstall_get_zonepath_root_ds
-
-# find all the zone BEs datasets associated with this global zone BE.
-unset fs_all
-(( fs_all_c = 0 ))
-if [ -n "$CURRENT_GZBE" ]; then
-	/sbin/zfs list -H -t filesystem -o $PROP_PARENT,name \
-	    -r $ZONEPATH_RDS |
-	    while IFS="	" read uid fs; do
+		# Skip the ROOT dataset
+		[[ "$fs" == "${zone.ROOT_ds}" ]] && continue
 
-		# only look at filesystems directly below $ZONEPATH_RDS
-		[[ "$fs" != ~()($ZONEPATH_RDS/+([^/])) ]] &&
-			continue
-
-		# match by PROP_PARENT uuid
-		[[ "$uid" != ${CURRENT_GZBE} ]] &&
-			continue
-
-		fs_all[$fs_all_c]=$fs
-		(( fs_all_c = $fs_all_c + 1 ))
+		#
+		# match by PROP_PARENT uuid.  If the uuid is not set ("-"), the
+		# BE is invalid (interrupted install?) and should be deleted.
+		#
+		if [[ $uid == "-" || $uid == "${CURRENT_GZBE}" ]] ; then
+			a_push belist "$(basename "$fs")"
+		fi
 	done
 fi
 
-destroy_zone_datasets
+destroy_zone_datasets zone -b belist
 
 exit $ZONE_SUBPROC_OK
--- a/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Fri Feb 18 16:57:31 2011 -0800
+++ b/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Fri Feb 11 14:04:06 2011 -0800
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/system/zones/brand/ipkg@$(PKGVERS)
@@ -51,6 +51,7 @@
 file path=usr/lib/brand/ipkg/prestate mode=0755
 file path=usr/lib/brand/ipkg/smf_disable.lst
 file path=usr/lib/brand/ipkg/support mode=0755
+file path=usr/lib/brand/ipkg/sysboot mode=0755
 file path=usr/lib/brand/ipkg/uninstall mode=0755
 license cr_Oracle license=cr_Oracle
 legacy pkg=SUNWipkg-brand version=0.0.0