Merge
authorAndrzej Szeszo <aszeszo@gmail.com>
Wed, 01 Jun 2011 13:11:09 +0100
changeset 2391 90c532b69592
parent 2389 30ea7b982e91 (current diff)
parent 2390 f1c659f5c28e (diff)
child 2392 57fd6b333437
Merge
src/brand/Makefile
src/brand/attach
src/brand/common.ksh
src/brand/image_install
src/brand/p2v
src/brand/pkgcreatezone
src/brand/sysboot
src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m
--- a/src/brand/Makefile	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/Makefile	Wed Jun 01 13:11:09 2011 +0100
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 MACH:sh = uname -p
@@ -58,7 +58,6 @@
 	$(ROOTBRANDPKG)/poststate \
 	$(ROOTBRANDPKG)/prestate \
 	$(ROOTBRANDPKG)/support \
-	$(ROOTBRANDPKG)/sysboot \
 	$(ROOTBRANDPKG)/uninstall
 
 ROOTFILES = \
--- a/src/brand/attach	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/attach	Wed Jun 01 13:11:09 2011 +0100
@@ -97,20 +97,15 @@
 			# 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 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 set canmount=on $ACTIVE_DS
-				(( $? != 0 )) && error "$f_ds_config" \
-				    "$ACTIVE_DS" "canmount=on"
-				zfs mount "$ACTIVE_DS" || \
-				    error "$e_mount1_failed" "$ACTIVE_DS"
 			fi
 		fi
 		log "$m_failed"
@@ -125,19 +120,27 @@
 trap trap_cleanup INT
 trap trap_exit EXIT
 
+<<<<<<< local
 PKG=pkg
+=======
+#set -o xtrace
+
+PKG="/usr/bin/pkg"
+>>>>>>> other
 KEYDIR=/var/pkg/ssl
 
 # If we weren't passed at least two arguments, exit now.
 (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
 
-zone=
-init_zone zone "$1" "$2"
-# Set ZONEPATH, etc.
-eval $(bind_legacy_zone_globals zone)
+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"
 
 #
@@ -161,7 +164,184 @@
 typeset gz_incorporations=""
 
 #
+<<<<<<< local
 verbose=""
+=======
+# Gather the zone publisher details. $1 is the location of the image we
+# are processing and $2 is an associative array used to store publisher
+# details.
+#
+gather_zone_publisher_details() {
+	STORED_IMAGE=$PKG_IMAGE
+	PKG_IMAGE=$1;export PKG_IMAGE
+	typeset -n publishers=$2
+	typeset -li publisher_count=0
+	typeset -li url_count=0
+	typeset line=
+	typeset name=
+	typeset mirror=
+	typeset origin=
+	typeset opublisher=
+
+	#
+	# Store publisher, origin and security details. It is assumed
+	# that mirrors all use the same key as the origins.
+	#
+	for line in $(get_publisher_urls all origin); do
+		print $line | IFS="=" read name origin
+		# When a publisher has multiple origins, the
+		# additional origins don't contain the publisher
+		# name. Correct for this by checking if origin is not
+		# set by get_publisher_urls() and, if so, use the
+		# "name" as the origin and set the name to the value
+		# we have already saved.
+		if [[ -z $origin ]]; then
+			origin=$name
+			name=${publisher.name}
+		elif [[ "$origin" == "None" ]]; then
+			# Publisher with no origins.
+			origin=""
+		fi
+
+		# Use a compound variable to store all the data
+		# relating to a publisher.
+		if [[ -z ${publishers[$name]} ]]; then
+			typeset -C publisher_$publisher_count
+			typeset -n publisher=publisher_$publisher_count
+			typeset publisher.sticky=""
+			typeset publisher.preferred=""
+			typeset publisher.enabled=""
+			typeset -a publisher.origins=""
+			typeset -a publisher.mirrors=""
+			typeset publisher.name=$name
+			typeset publisher.keyfile=""
+			typeset publisher.certfile=""
+
+			get_publisher_attrs ${publisher.name} origin | \
+			    IFS=" " read publisher.sticky publisher.preferred \
+			    publisher.enabled
+			if [[ -n "$origin" ]]; then
+				get_pub_secinfo ${publisher.name} | \
+				    read publisher.keyfile publisher.certfile
+				[[ ${publisher.keyfile} != "None" && \
+				    ! -f ${PKG_IMAGE}/${publisher.keyfile} ]] && \
+				    fail_usage "$f_nosuch_key" \
+				        ${publisher.keyfile}
+				[[ ${publisher.certfile} != "None" && \
+				    ! -f ${PKG_IMAGE}/${publisher.certfile} ]] && \
+				    fail_usage "$f_nosuch_cert" \
+				        ${publisher.certfile}
+			else
+				# Publisher has no origins.
+				publisher.keyfile="None"
+				publisher.certfile="None"
+			fi
+			publisher_count=publisher_count+1
+			url_count=0
+		fi
+		publisher.origins[$url_count]=$origin
+		publishers[$name]=${publisher}
+		url_count=url_count+1
+	done
+
+	#
+	# Store mirror details
+	#
+	url_count=0
+	for line in $(get_publisher_urls all mirror); do
+		print $line | IFS="=" read name mirror
+		if [[ -z $mirror ]]; then
+			mirror=$name
+			name=${publisher.name}
+		fi
+		if [[ -z $opublisher || $opublisher != $name ]]; then
+			opublisher=$name
+			eval publisher="${publishers[$name]}"
+			url_count=0
+		fi
+		publisher.mirrors[$url_count]=$mirror
+		publishers[$name]=${publisher}
+		url_count=url_count+1
+	done
+	
+	PKG_IMAGE=$STORED_IMAGE;export PKG_IMAGE
+}
+
+#
+# $1 is an associative array of publishers. Search this array and
+# return the preferred publisher.
+#
+get_preferred_publisher() {
+	typeset -n publishers=$1
+	typeset publisher=
+
+	for key in ${!publishers[*]}; do
+		eval publisher="${publishers[$key]}"
+		if [[ ${publisher.preferred}  ==  "true" ]]; then
+			print ${key}
+			return 0
+		fi
+	done
+	return 1
+}
+
+#
+# $1 is an empty string to be populated with a list of incorporation
+# fmris.
+#
+gather_incorporations() {
+	typeset -n incorporations=$1
+	typeset p=
+
+	for p in \
+	    $(LC_ALL=C $PKG search -Hl -o pkg.name \
+	    ':pkg.depend.install-hold:core-os*');do
+		incorporations="$incorporations $(get_pkg_fmri $p)"
+	done
+}
+
+#
+# Print the pkg(1) command which defines a publisher. $1 is an associative 
+# array of publisher details and $2 is the publisher to be printed.
+#
+print_publisher_pkg_defn() {
+	typeset -n publishers=$1
+	typeset pname=$2
+	typeset publisher=
+	typeset args=""
+	typeset origin=
+	typeset mirror=
+
+	eval publisher="${publishers[$pname]}"
+
+	if [[ ${publisher.preferred} == "true" ]]; then
+		args="$args -P"
+	fi
+
+	for origin in ${publisher.origins[*]}; do
+		args="$args -g $origin"
+	done
+
+	for mirror in ${publisher.mirrors[*]}; do
+		args="$args -m $mirror"
+	done
+
+	if [[ ${publisher.sticky} == "true" ]]; then
+		args="$args --sticky"
+	else
+		args="$args --non-sticky"
+	fi
+
+	if [[ ${publisher.enabled} == "true" ]]; then
+		args="$args --enable"
+	else
+		args="$args --disable"
+	fi
+
+	echo "$args"
+}
+
+>>>>>>> other
 # Other brand attach options are invalid for this brand.
 while getopts "a:d:n:r:uv" opt; do
 	case $opt in
@@ -224,17 +404,125 @@
 	exit $ZONE_SUBPROC_NOTCOMPLETE
 fi
 
-LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp ${zone.name}.attach_log.XXXXXX)
+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"
 
-# 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
+#
+# 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.
+#
 
 #
 # Perform a sanity check to confirm that the image is not a global zone.
--- a/src/brand/clone	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/clone	Wed Jun 01 13:11:09 2011 +0100
@@ -19,7 +19,9 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+#
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -30,7 +32,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
@@ -38,39 +40,108 @@
 	exit $ZONE_SUBPROC_INCOMPLETE
 }
 
-# Source and destination zones
-typeset src dst	
+# Set up ZFS dataset hierarchy for the zone.
+
+ROOT="rpool/ROOT"
+
 # Other brand clone options are invalid for this brand.
 while getopts "R:z:" opt; do
 	case $opt in
-		R)	opt_R="$OPTARG" ;;
-		z)	opt_z="$OPTARG" ;;
+		R)	ZONEPATH="$OPTARG" ;;
+		z)	ZONENAME="$OPTARG" ;;
 		*)	fail_usage "";;
 	esac
 done
 shift $((OPTIND-1))
 
-if (($# != 1)); then
+if [ $# -ne 1 ]; then
 	fail_usage "";
 fi
 
-init_zone dst "$opt_z" "$opt_R"
-init_zone src "$1"
+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
 
 get_current_gzbe
-get_active_be src || fatal "$e_no_active_be"
+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`
 
-# From here on out the global variables referenced are for the destination zone
-eval $(bind_legacy_zone_globals dst)
+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
 
-# Make dataset snapshots
-snapshot_zone_rpool src "${dst}_snap%02d" snapname \
-    || fail_incomplete "$f_zfs_snapshot"
+# 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 clones
-clone_zone_rpool src dst "$snapname" || fail_incomplete "$f_zone_clone"
+# 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
 
-ZONE_IS_MOUNTED=1
+/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
 trap trap_exit EXIT
 
 #
--- a/src/brand/common.ksh	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/common.ksh	Wed Jun 01 13:11:09 2011 +0100
@@ -23,20 +23,14 @@
 # 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")
@@ -46,8 +40,10 @@
 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")
@@ -77,8 +73,23 @@
 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"
@@ -135,7 +146,7 @@
 	vlog "$sanity_ok"
 }
 
-function get_current_gzbe {
+get_current_gzbe() {
 	#
 	# If there is no alternate root (normal case) then set the
 	# global zone boot environment by finding the boot environment
@@ -143,97 +154,156 @@
 	# If a zone exists in a boot environment mounted on an alternate root,
 	# then find the boot environment where the alternate root is mounted.
 	#
-	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
+	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
+
+	if [ -z "$CURRENT_GZBE" ]; then
+		fail_fatal "$f_no_gzbe"
+	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
 		}
-		# Field 2 is the BE UUID
-		print $2
-	    }')
-	if [ -z "$CURRENT_GZBE" ]; then
-		return 1
+	    }'`
+
+	if [ $? -ne 0 ]; then
+		fail_fatal "$f_multiple_ds"
+	fi
+
+	if [ -z "$ACTIVE_DS" ]; then
+		fail_fatal "$f_no_active_ds"
 	fi
-	return 0
+}
+
+# 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
 }
 
 #
-# 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.
+# 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.
 #
-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
+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
-		active_ds=$name
-	done
-	if [[ -z $active_ds ]]; then
-		error "$f_no_active_ds"
-		return 1
 	fi
 
-	zone.active_ds=$active_ds
+	# 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"
 }
 
-function set_active_be {
-	typeset -n zone="$1"
-	typeset be="$2"
+#
+# Set up ZFS dataset hierarchy for the zone root dataset.
+#
+create_active_ds() {
+	get_current_gzbe
 
-	[[ -z "$CURRENT_GZBE" ]] && get_current_gzbe
+	#
+	# 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
+
+	#
+	# From here on, errors should cause the zone to be incomplete.
+	#
+	int_code=$ZONE_SUBPROC_FATAL
 
 	#
-	# Turn off the active property on BE's with the same GZBE
+	# We need to tolerate errors while creating the datasets and making the
+	# mountpoint, since these could already exist from some other BE.
 	#
-	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
+
+	/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"
 	done
 
-	zone.active_ds="${zone.ROOT_ds}/$be"
+	if [ $BENUM -ge 100 ]; then
+		fail_fatal "$f_zfs_create"
+	fi
 
-	zfs set "$PROP_PARENT=$CURRENT_GZBE" ${zone.active_ds} \
-	    || return 1
-	zfs set "$PROP_ACTIVE=on" ${zone.active_ds} || return 1
+	if [ ! -d $ZONEROOT ]; then
+		/usr/bin/mkdir $ZONEROOT
+	fi
 
-	zfs set "$PROP_BE_HANDLE=on" "${zone.rpool_ds}" || return 1
-
-	return 0
+	/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $ZONEROOT || \
+	    fail_incomplete "$f_zfs_mount"
 }
 
 #
--- a/src/brand/detach	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/detach	Wed Jun 01 13:11:09 2011 +0100
@@ -24,33 +24,61 @@
 # 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))
 
-init_zone zone "$ZONENAME" "$ZONEPATH"
-eval $(bind_legacy_zone_globals zone)
-
-if (( $noexecute == 1 )); then
-	cat /etc/zones/$ZONENAME.xml
+if [ $noexecute -eq 1 ]; then
+	# dry-run - output zone's config and exit
+	cat /etc/zones/$zonename.xml
 	exit $ZONE_SUBPROC_OK
 fi
 
-# All of the hard stuff is done in commmon code.
-detach_zone zone
+#
+# 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
 
 exit $ZONE_SUBPROC_OK
--- a/src/brand/image_install	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/image_install	Wed Jun 01 13:11:09 2011 +0100
@@ -19,9 +19,8 @@
 #
 # CDDL HEADER END
 #
-
-#
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
 #
 
 #
@@ -101,8 +100,14 @@
 # If we weren't passed at least two arguments, exit now.
 (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
 
-init_zone zone "$1" "$2"
-eval $(bind_legacy_zone_globals zone)
+ZONENAME="$1"
+ZONEPATH="$2"
+# XXX shared/common script currently uses lower case zonename & zonepath
+zonename="$ZONENAME"
+zonepath="$ZONEPATH"
+
+ZONEROOT="$ZONEPATH/root"
+
 shift; shift	# remove zonename and zonepath from arguments array
 
 unset inst_type
@@ -202,7 +207,8 @@
 
 if (( $p2v_result != 0 )); then
 	log "$p2v_fail"
-	log "\n$install_fail"
+	log ""
+	log "$install_fail"
 	log "$install_log" "$LOGFILE"
 	exit $ZONE_SUBPROC_FATAL
 fi
@@ -221,9 +227,10 @@
 
 # Mount active dataset on the root.
 is_brand_labeled
-(( $? == 0 )) && mount_active_be -c zone
+(( $? == 0 )) && mount_active_ds
 
-log "\n$m_complete" ${SECONDS}
+log ""
+log "$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	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/p2v	Wed Jun 01 13:11:09 2011 +0100
@@ -28,13 +28,9 @@
 # zone, so care should be taken to validate any modifications so that they
 # are safe.
 
-#
-# 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
+# Restrict executables to /usr/bin and /usr/sbin
+PATH=/usr/bin:/usr/sbin
+export PATH
 unset LD_LIBRARY_PATH
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -355,8 +351,10 @@
 (( $# != 2 )) && exit 1
 
 [[ -n $LOGFILE ]] && exec 2>>$LOGFILE
-init_zone zone "$1" "$2"
-eval $(bind_legacy_zone_globals zone)
+
+ZONENAME=$1
+ZONEPATH=$2
+ZONEROOT=$ZONEPATH/root
 
 e_badinfo=$(gettext "Failed to get '%s' zone resource")
 e_badfile=$(gettext "Invalid '%s' file within the zone")
@@ -468,7 +466,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_be zone
+	mount_active_ds
 fi
 
 #
@@ -504,7 +502,7 @@
 
 [[ -n $OPT_U ]] && unconfigure_zone
 
-(( $brand_labeled == 1 )) && mount_active_be zone
+(( $brand_labeled == 1 )) && mount_active_ds
 
 trap - EXIT
 vlog "$v_exitgood"
--- a/src/brand/pkgcreatezone	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/pkgcreatezone	Wed Jun 01 13:11:09 2011 +0100
@@ -58,10 +58,10 @@
 
 trap_cleanup() {
 	print "$f_interrupted"
-	exit $EXIT_CODE
+	exit $int_code
 }
 
-EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
+int_code=$ZONE_SUBPROC_NOTCOMPLETE
 trap trap_cleanup INT
 
 extra_packages=""
@@ -109,13 +109,17 @@
 	print -u2 "Brand error: No zone path or name"
 	exit $ZONE_SUBPROC_USAGE
 fi
-zone=
-init_zone zone "$ZONENAME" "$ZONEPATH"
-eval $(bind_legacy_zone_globals zone)
+
+# XXX shared/common script currently uses lower case zonename & zonepath
+zonename="$ZONENAME"
+zonepath="$ZONEPATH"
 
 is_brand_labeled
 brand_labeled=$?
 
+ZONEROOT=$ZONEPATH/root
+secinfo=""
+
 # An image install can't use both -a AND -d...
 [[ -n "$install_archive" && -n "$source_dir" ]] &&
     fail_usage "$f_incompat_options" "-a" "-d"
@@ -153,8 +157,7 @@
 # Before installing the zone, set up ZFS dataset hierarchy for the zone root
 # dataset.
 #
-create_active_ds zone || fail_fatal "$f_no_ds"
-mount_active_be -c zone || fail_fatal "$f_no_ds"
+create_active_ds
 
 #
 # If we're installing from an image, branch off to that installer.
--- a/src/brand/poststate	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/poststate	Wed Jun 01 13:11:09 2011 +0100
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -48,20 +48,17 @@
 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	# Note: return value is C-style, not shell-style
+	is_brand_labeled
 	if (( $? == 0 )); then
-		# Leave the active boot environment mounted after halting (this
-		# might be a different dataset than what was mounted).
-		mount_active_be -c zone
+		# 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.
-		unmount_be zone
+		zoneroot="$ZONEPATH/root"
+		umount $zoneroot || printf "$f_zfs_unmount" "$zoneroot"
 	fi
 fi
 
--- a/src/brand/prestate	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/prestate	Wed Jun 01 13:11:09 2011 +0100
@@ -18,10 +18,9 @@
 # information: Portions Copyright [yyyy] [name of copyright owner]
 #
 # CDDL HEADER END
-#
 
 #
-# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 . /usr/lib/brand/ipkg/common.ksh
@@ -48,15 +47,10 @@
 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.
-case $cmd in
-	0)
-		mount_active_be zone || exit $ZONE_SUBPROC_NOTCOMPLETE
-		;;
-esac
+if [ $cmd -eq 0 ]; then
+	# Mount active dataset on the root.
+	mount_active_ds
+fi
 
 exit $ZONE_SUBPROC_OK
--- a/src/brand/sysboot	Wed Jun 01 13:04:21 2011 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-#!/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
-
-enable_zones_services || exit $ZONE_SUBPROC_NOTCOMPLETE
-
-exit $ZONE_SUBPROC_OK
--- a/src/brand/uninstall	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/brand/uninstall	Wed Jun 01 13:11:09 2011 +0100
@@ -19,10 +19,15 @@
 #
 # 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.
+# get script name (bname) and path (dname)
 #
+bname=`basename $0`
 
 #
 # common shell script functions
@@ -33,13 +38,16 @@
 #
 # options processing
 #
-
-# 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)
+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
 shift 2
 
 options="FhHnv"
@@ -93,6 +101,7 @@
 #
 # main
 #
+zoneroot=$zonepath/root
 
 nop=""
 if [[ -n "$opt_n" ]]; then
@@ -104,28 +113,49 @@
 	ZONE_SUBPROC_OK=$ZONE_SUBPROC_FATAL
 fi
 
-# get_current_gzbe
-get_current_gzbe || fail_fatal "$f_no_gzbe"
+#
+# 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.
+#
 
-# 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
+# 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
 
-		# Skip the ROOT dataset
-		[[ "$fs" == "${zone.ROOT_ds}" ]] && continue
+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
 
-		#
-		# 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
+		# 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 ))
 	done
 fi
 
-destroy_zone_datasets zone -b belist
+destroy_zone_datasets
 
 exit $ZONE_SUBPROC_OK
--- a/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Wed Jun 01 13:04:21 2011 +0100
+++ b/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Wed Jun 01 13:11:09 2011 +0100
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/system/zones/brand/ipkg@$(PKGVERS)
@@ -53,7 +53,6 @@
 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