11684 desire option to not propagate certs to non-global zones (remove brand script changes)
authorBrock Pytlik <brock.pytlik@oracle.com>
Thu, 28 Apr 2011 12:52:19 -0700
changeset 2315 c9b0cbb2c713
parent 2314 01eadc7466f8
child 2316 9eb53e68d674
11684 desire option to not propagate certs to non-global zones (remove brand script changes)
src/brand/Makefile
src/brand/attach
src/brand/boot
src/brand/common.ksh
src/brand/halt
src/brand/p2v
src/brand/pkgcreatezone
src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m
--- a/src/brand/Makefile	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/brand/Makefile	Thu Apr 28 12:52:19 2011 -0700
@@ -51,12 +51,10 @@
 	$(ROOTETCBRAND)/smf_disable.conf \
 	$(ROOTETCZONES)/SUNWipkg.xml \
 	$(ROOTBRANDPKG)/attach \
-	$(ROOTBRANDPKG)/boot \
 	$(ROOTBRANDPKG)/clone \
 	$(ROOTBRANDPKG)/common.ksh \
 	$(ROOTBRANDPKG)/detach \
 	$(ROOTBRANDPKG)/fmri_compare \
-	$(ROOTBRANDPKG)/halt \
 	$(ROOTBRANDPKG)/image_install \
 	$(ROOTBRANDPKG)/p2v \
 	$(ROOTBRANDPKG)/pkgcreatezone \
--- a/src/brand/attach	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/brand/attach	Thu Apr 28 12:52:19 2011 -0700
@@ -34,6 +34,7 @@
 m_gzinc=$(gettext       "       Global zone version: %s")
 m_zinc=$(gettext        "   Non-Global zone version: %s")
 m_need_update=$(gettext "                Evaluation: Packages in zone %s are out of sync with the global zone. To proceed, retry with the -u flag.")
+m_need_nonsticky=$(gettext "                Evaluation: Publisher %s in zone %s needs to be set to non-sticky")
 m_cache=$(gettext       "                     Cache: Using %s.")
 m_updating=$(gettext    "  Updating non-global zone: Output follows")
 m_sync_done=$(gettext   "  Updating non-global zone: Zone updated.")
@@ -50,6 +51,9 @@
 f_sanity_variant=$(gettext "  Sanity Check: FAILED, couldn't determine %s from image.")
 f_sanity_global=$(gettext  "  Sanity Check: FAILED, appears to be a global zone (%s=%s).")
 f_update=$(gettext "Could not update attaching zone")
+f_no_pref_publisher=$(gettext "Unable to get preferred publisher information for zone '%s'.")
+f_nosuch_key=$(gettext "Failed to find key %s for global zone publisher")
+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.")
 f_nonsticky=$(gettext "Could not set legacy publisher to non-sticky")
@@ -144,9 +148,129 @@
 # to store information about the global zone publishers and
 # incorporations.
 
+typeset -A gz_publishers
 typeset gz_incorporations=""
 
 #
+# 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.
 #
@@ -161,6 +285,47 @@
 	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 brand attach options are invalid for this brand.
 while getopts "a:d:nr:u" opt; do
 	case $opt in
@@ -211,11 +376,6 @@
 	exit $ZONE_SUBPROC_OK
 fi
 
-enable_zones_services
-if [[ $? -ne 0 ]]; then
-	exit $ZONE_SUBPROC_NOTCOMPLETE
-fi
-
 LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp ${zone.name}.attach_log.XXXXXX)
 if [[ -z "$LOGFILE" ]]; then
 	fatal "$e_tmpfile"
@@ -244,6 +404,28 @@
 # Check that the variant is non-global, else fail
 [[ $variantval = "nonglobal" ]] || fatal "$f_sanity_global" $VARIANT $variantval
 
+# We would like to ensure that our NGZ publishers are a superset of
+# those in the GZ. We do this by building a list of all publishers in
+# the GZ. We then process this list in the NGZ, first removing (if
+# present) and then installing all publishers in this list. Other
+# publisher, i.e. those not in the GZ list, are left as is.
+
+#
+# Gather all the publisher details for the global zone
+#
+gather_zone_publisher_details $PKG_IMAGE gz_publishers
+
+#
+# Get the preferred publisher for the global zone
+# If we were not able to get the zone's preferred publisher, complain.
+#
+gz_publisher_pref=$(get_preferred_publisher gz_publishers)
+
+if [[ $? -ne 0 ]]; then
+	fail_usage "$f_no_pref_publisher" "global"
+fi
+
+vlog "Preferred global publisher: $gz_publisher_pref"
 
 #
 # Try to find the "entire" incorporation's FMRI in the gz.
@@ -304,9 +486,69 @@
 fi
 
 #
-# Set the use-system-repo property.
+# The NGZ publishers must be a superset of the GZ publisher. Process
+# the GZ publishers and make the NGZ publishers match them.
+# You can't remove a preferred publisher, so temporarily create
+# a preferred publisher
+RANDOM=$$
+
+ZNAME=za$RANDOM
+
+LC_ALL=C $PKG set-publisher --no-refresh -P -g http://localhost:10000 $ZNAME
+for key in ${!gz_publishers[*]}; do
+	typeset newloc=""
+
+	args=$(print_publisher_pkg_defn gz_publishers $key)
+
+	# Copy credentials from global zone.
+	safe_dir var
+	safe_dir var/pkg
+
+	eval publisher="${gz_publishers[$key]}"
+	if [[ ${publisher.keyfile} != "None" || \
+	    ${publisher.certfile} != "None" ]]; then
+		if [[ -e $ZONEROOT/$KEYDIR ]]; then
+			safe_dir $KEYDIR
+		else
+			mkdir -m 755 $ZONEROOT/$KEYDIR
+		fi
+	fi
+
+	if [[ ${publisher.keyfile} != "None" ]]; then
+		relnewloc="$KEYDIR/$(basename ${publisher.keyfile})"
+		newloc="$ZONEROOT/$relnewloc"
+		safe_copy ${publisher.keyfile} $newloc
+		chmod 644 $newloc
+		chown -h root:root $newloc
+		args="$args -k $relnewloc"
+	fi
+	if [[ ${publisher.certfile} != "None" ]]; then
+		relnewloc="$KEYDIR/$(basename ${publisher.certfile})"
+		newloc="$ZONEROOT/$relnewloc"
+		safe_copy ${publisher.certfile} $newloc
+		chmod 644 $newloc
+		chown -h root:root $newloc
+		args="$args -c $relnewloc"
+	fi
+	LC_ALL=C $PKG unset-publisher $key >/dev/null 2>&1
+	LC_ALL=C $PKG set-publisher $args $key
+	
+done
+
 #
-LC_ALL=C $PKG set-property use-system-repo true
+# Now remove our temporary publisher
+#
+LC_ALL=C $PKG unset-publisher $ZNAME
+
+#
+# Make sure that the solaris publisher can update packages that first
+# came from opensolaris.org.
+#
+if [[ $allow_update == 1 ]] && \
+    $PKG publisher opensolaris.org >/dev/null 2>&1; then
+	LC_ALL=C $PKG set-publisher --no-refresh --non-sticky \
+	    opensolaris.org || pkg_err_check "$f_nonsticky"
+fi
 
 #
 # Bring the ngz entire incorporation into sync with the gz as follows:
@@ -329,7 +571,7 @@
 fi
 
 if [[ $allow_update == 0 ]]; then
-	LC_ALL=C $PKG install --accept -n $incorp_list
+	LC_ALL=C $PKG install --accept --no-refresh -n $incorp_list
 	if [[ $? == 4 ]]; then
 		log "\n$m_complete"
 		EXIT_CODE=$ZONE_SUBPROC_OK
@@ -348,11 +590,11 @@
 # same version as we have in the GZ.
 #
 if [[ -n $gz_entire_fmri && -z $ngz_entire_fmri ]]; then
-	LC_ALL=C $PKG install --accept entire  || \
+	LC_ALL=C $PKG install --accept --no-refresh entire  || \
 	    pkg_err_check "$f_update"
 fi
 
-LC_ALL=C $PKG install --accept $incorp_list  || \
+LC_ALL=C $PKG install --accept --no-refresh $incorp_list  || \
     pkg_err_check "$f_update"
 
 log "\n$m_sync_done"
--- a/src/brand/boot	Thu Apr 28 11:44:04 2011 -0700
+++ /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
-
-ZONENAME=$1
-ZONEPATH=$2
-
-enable_zones_services
-if [[ $? -ne 0 ]]; then
-	exit $ZONE_SUBPROC_NOTCOMPLETE
-fi
-
-/usr/lib/zones/zpadm $ZONENAME
-if [[ $? -ne 0 ]]; then
-	exit $ZONE_SUBPROC_NOTCOMPLETE
-fi
--- a/src/brand/common.ksh	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/brand/common.ksh	Thu Apr 28 12:52:19 2011 -0700
@@ -57,9 +57,6 @@
 f_cp=$(gettext "Failed to cp %s %s.")
 f_cp_unsafe=$(gettext "Failed to safely copy %s to %s.")
 
-f_sysrepo_fail=$(gettext "Unable to enable svc:/system/pkg/sysrepo, please enable the service manually.")
-f_zones_proxyd_fail=$(gettext "Unable to enable svc:/system/zones-proxyd, please enable the service manually.")
-
 m_brnd_usage=$(gettext "brand-specific usage: ")
 
 v_unconfig=$(gettext "Performing zone sys-unconfig")
@@ -287,6 +284,130 @@
 }
 
 #
+# Emits to stdout the extended attributes for a publisher. The
+# attributes are emitted in the order "sticky preferred enabled". It
+# expects two parameters: publisher name and URL type which can be
+# ("mirror" or "origin").
+#
+get_publisher_attrs() {
+	typeset pname=$1
+	typeset utype=$2
+
+	LC_ALL=C $PKG publisher -HF tsv| \
+	    nawk '($5 == "'"$utype"'" || \
+	    ("'"$utype"'" == "origin" && $5 == "")) \
+	    && $1 == "'"$pname"'" \
+	    {printf "%s %s %s\n", $2, $3, $4;}'
+	return 0
+}
+
+#
+# Emits to stdout the extended attribute arguments for a publisher. It
+# expects two parameters: publisher name and URL type which can be
+# ("mirror" or "origin").
+#
+get_publisher_attr_args() {
+	typeset args=
+	typeset sticky=
+	typeset preferred=
+	typeset enabled=
+
+	get_publisher_attrs $1 $2 |
+	while IFS=" " read sticky preferred enabled; do
+		if [ $sticky == "true" ]; then
+			args="--sticky"
+		else
+			args="--non-sticky"
+		fi
+
+		if [ $preferred == "true" ]; then
+			args="$args -P"
+		fi
+
+		if [ $enabled == "true" ]; then
+			args="$args --enable"
+		else
+			args="$args --disable"
+		fi
+	done
+	echo $args
+
+	return 0
+}
+
+#
+# Emits to stdout the publisher's prefix followed by a '=', and then
+# the list of the requested URLs separated by spaces, followed by a
+# newline after each unique publisher.  It expects two parameters,
+# publisher type ("all", "preferred", "non-preferred") and URL type
+# ("mirror" or "origin".)
+#
+get_publisher_urls() {
+	typeset ptype=$1
+	typeset utype=$2
+	typeset __pub_prefix=
+	typeset __publisher_urls=
+	typeset ptype_filter=
+
+	if [ "$ptype" == "all" ]
+	then
+		ptype_filter=""
+	elif [ "$ptype" == "preferred" ]
+	then
+		ptype_filter="true"
+	elif [ "$ptype" == "non-preferred" ]
+	then
+		ptype_filter="false"
+	fi
+
+	LC_ALL=C $PKG publisher -HF tsv | \
+		nawk '($5 == "'"$utype"'" || \
+		("'"$utype"'" == "origin" && $5 == "")) && \
+		( "'"$ptype_filter"'" == "" || $3 == "'"$ptype_filter"'" ) \
+		{printf "%s %s\n", $1, $7;}' |
+		while IFS=" " read __publisher __publisher_url; do
+			if [[ "$utype" == "origin" && \
+			    -z "$__publisher_url" ]]; then
+				# Publisher without origins.
+				__publisher_url="None"
+			fi
+
+			if [[ -n "$__pub_prefix" && \
+				"$__pub_prefix" != "$__publisher" ]]; then
+				# Different publisher so emit accumulation and
+				# clear existing data.
+				echo $__pub_prefix=$__publisher_urls
+				__publisher_urls=""
+			fi
+			__pub_prefix=$__publisher
+			__publisher_urls="$__publisher_urls$__publisher_url "
+		done
+
+	if [[ -n "$__pub_prefix" && -n "$__publisher_urls" ]]; then
+		echo $__pub_prefix=$__publisher_urls
+	fi
+
+	return 0
+}
+
+#
+# Emit to stdout the key and cert associated with the publisher
+# name provided.  Returns 'None' if no information is present.
+# For now we assume that the mirrors all use the same key and cert
+# as the main publisher.
+#
+get_pub_secinfo() {
+	typeset key=
+	typeset cert=
+
+	key=$(LC_ALL=C $PKG publisher $1 |
+	    nawk -F': ' '/SSL Key/ {print $2; exit 0}')
+	cert=$(LC_ALL=C $PKG publisher $1 |
+	    nawk -F': ' '/SSL Cert/ {print $2; exit 0}')
+	print $key $cert
+}
+
+#
 # Handle pkg exit code.  Exit 0 means Command succeeded, exit 4 means
 # No changes were made - nothing to do.  Any other exit code is an error.
 #
@@ -294,20 +415,3 @@
 	typeset res=$?
 	(( $res != 0 && $res != 4 )) && fail_fatal "$1"
 }
-
-#
-# Enable the services needed to perform packaging operations inside a zone.
-#
-enable_zones_services() {                                                       
-	/usr/sbin/svcadm enable -t -s /system/pkg/sysrepo
-	if [[ $? -ne 0 ]]; then
-		error "$f_sysrepo_fail"
-		return 1
-	fi
-	/usr/sbin/svcadm enable -t -s /system/zones-proxyd
-	if [[ $? -ne 0 ]]; then
-		error "$f_zones_proxyd_fail"
-		return 1
-	fi
-	return 0
-}
--- a/src/brand/halt	Thu Apr 28 11:44:04 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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
-
-ZONENAME=$1
-ZONEPATH=$2
-
-/usr/lib/zones/zpadm -R $ZONENAME
-if [[ $? -ne 0 ]]; then
-	exit $ZONE_SUBPROC_NOTCOMPLETE
-fi
--- a/src/brand/p2v	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/brand/p2v	Thu Apr 28 12:52:19 2011 -0700
@@ -477,8 +477,6 @@
 log "$v_change_var"
 pkg -R $ZONEROOT change-variant variant.opensolaris.zone=nonglobal || \
     fatal "$e_change_var"
-# Set the property which tells the image to use the system publisher.
-pkg -R $ZONEROOT set-property use-system-repo true
 
 #
 # Run update on attach.  State is currently 'incomplete' so use the private
--- a/src/brand/pkgcreatezone	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/brand/pkgcreatezone	Thu Apr 28 12:52:19 2011 -0700
@@ -35,20 +35,34 @@
 
 . /usr/lib/brand/ipkg/common.ksh
 
-f_a_obs=$(gettext "-a publisher=uri option is obsolete.")
+f_a_obs=$(gettext "-a publisher=uri option is obsolete, use -P instead.")
 f_pkg5_missing=$(gettext "pkg(5) does not seem to be present on this system.\n")
+f_no_pref_publisher=$(gettext "Unable to get global zone preferred publisher information, and none was supplied.\nYou must specify one using the -P option.")
+f_key_file=$(gettext "Key file not allowed without -P")
+f_cert_file=$(gettext "Cert file not allowed without -P")
 f_img=$(gettext "failed to create image\n")
 f_pkg=$(gettext "failed to install package\n")
 f_interrupted=$(gettext "Installation cancelled due to interrupt.\n")
 f_bad_publisher=$(gettext "Syntax error in publisher information.")
+f_no_entire_in_pref=$(gettext "Unable to locate the incorporation '%s' in the preferred publisher '%s'.\nUse -P to supply a publisher which contains this package.\n")
+f_key_prop=$(gettext "Unable to propagate key %s to %s")
+f_cert_prop=$(gettext "Unable to propagate cert %s to %s")
+f_get_secinfo=$(gettext "Failed to get key/cert information for publisher %s")
+f_nosuch_key=$(gettext "Failed to find key %s")
+f_nosuch_cert=$(gettext "Failed to find cert %s")
 
+m_publisher=$(gettext   "   Publisher: Using %s (%s).")
+m_cache=$(gettext       "       Cache: Using %s.")
 m_image=$(gettext       "       Image: Preparing at %s.")
+m_incorp=$(gettext      "Sanity Check: Looking for 'entire' incorporation.\n")
+m_key_prop=$(gettext    " Credentials: Propagating %s\n")
+m_cert_prop=$(gettext   " Credentials: Propagating %s\n")
 m_core=$(gettext	"  Installing: Packages (output follows)\n")
 m_smf=$(gettext		" Postinstall: Copying SMF seed repository ...")
 m_more_brokenness=$(gettext " Postinstall: Applying workarounds.")
 m_mannote=$(gettext     "        Note: Man pages can be obtained by installing pkg:/system/manual")
 
-m_usage=$(gettext "\n        install [-h]\n        install\n                [-e extrapkg [...]]\n        install {-a archive|-d path} {-p|-u} [-s|-v]")
+m_usage=$(gettext "\n        install [-h]\n        install [-c certificate_file] [-k key_file] [-P publisher=uri]\n                [-e extrapkg [...]]\n        install {-a archive|-d path} {-p|-u} [-s|-v]")
 
 m_done=$(gettext      " done.")
 
@@ -63,26 +77,30 @@
 extra_packages=""
 ZONENAME=""
 ZONEPATH=""
+pub_and_origins=""
+pub_and_mirrors=""
 
 # Setup i18n output
 TEXTDOMAIN="SUNW_OST_OSCMD"
 export TEXTDOMAIN
 
+KEYDIR=/var/pkg/ssl
 PKG=/usr/bin/pkg
-export PKG
 
 #
 # Just in case.  This should probably be removed later.
 #
 [[ ! -x $PKG ]] && fail_incomplete "$f_pkg5_missing"
 
+certfile="None"
+keyfile="None"
 unset install_archive
 unset source_dir
 unset msg
 unset silent_mode
 unset verbose_mode
 
-while getopts "a:d:e:hpR:suvz:" opt; do
+while getopts "a:c:d:e:hk:P:pR:suvz:" opt; do
 	case $opt in
 		a)	# We're expecting a path to an archive
 			if [[ ! -f $OPTARG ]]; then
@@ -93,9 +111,12 @@
 				fi
 			fi
 			install_archive="-a $OPTARG";;
+		c)	certfile="$OPTARG" ;;
 		d)	source_dir="-d $OPTARG";;
 		e)	extra_packages="$extra_packages $OPTARG" ;;
 		h)	fail_usage "";;
+		k)	keyfile="$OPTARG" ;;
+		P)	pub_and_origins="$OPTARG" ;;
 		p)	preserve_zone="-p";;
 		R)	ZONEPATH="$OPTARG" ;;
 		s)	silent_mode=1;;
@@ -118,6 +139,8 @@
 is_brand_labeled
 brand_labeled=$?
 
+secinfo=""
+
 # An image install can't use both -a AND -d...
 [[ -n "$install_archive" && -n "$source_dir" ]] &&
     fail_usage "$f_incompat_options" "-a" "-d"
@@ -132,8 +155,14 @@
 
 # IPS options aren't allowed when installing from a system image.
 if [[ -n "$install_archive" || -n "$source_dir" ]]; then
+	[[ -n $pub_and_origins ]] && fail_usage "$f_incompat_options" \
+	    "-a|-d" "-P"
 	[[ -n "$extra_packages" ]] && \
 	    fail_usage "$f_incompat_options" "-a|-d" "-e"
+	[[ "$certfile" != "None" ]] && \
+	    fail_usage "$f_incompat_options" "-a|-d" "-c"
+	[[ "$keyfile" != "None" ]] && \
+	    fail_usage "$f_incompat_options" "-a|-d" "-k"
 fi
 
 # p2v options aren't allowed when installing from a repo.
@@ -143,6 +172,113 @@
 fi
 
 #
+# If the user didn't give us a publisher, and there's a preferred publisher set
+# for the system, set that as the default.
+#
+propagate_secinfo=
+propagate_extra=
+if [[ -z $pub_and_origins ]]; then
+	if [[ $keyfile != "None" ]]; then
+		fail_usage "$f_key_file"
+	fi
+	if [[ $certfile != "None" ]]; then
+		fail_usage "$f_cert_file"
+	fi
+
+	# Look for a preferred online origin.
+	tpub_and_origins=$(get_publisher_urls preferred origin)
+	[[ $? -eq 0 && -n $tpub_and_origins ]] && \
+	    pub_and_origins="$tpub_and_origins"
+
+	# Get preferred mirror information as well if the above succeeded.
+	if [[ -n "$tpub_and_origins" ]]; then
+		tpub_and_mirrors=$(get_publisher_urls preferred mirror)
+		[[ $? -eq 0 && -n $tpub_and_mirrors ]] && \
+		    pub_and_mirrors="$tpub_and_mirrors"
+	fi
+
+	# Note that later we need to propagate key & cert.
+	propagate_secinfo=1
+
+	#
+	# since the user didn't specify a publisher, propagate all the
+	# publishers that don't have a key.
+	#
+	propagate_extra=1
+fi
+[[ -z $pub_and_origins ]] && fail_usage "$f_no_pref_publisher"
+
+# find the remaining publishers in the global zone
+publishers_extra_origins=""
+publishers_extra_mirrors=""
+
+if [[ -n $propagate_extra ]]; then
+
+	# If cert and key information are ever allowed at the origin or
+	# mirror level, then this will have to be changed.
+	get_publisher_urls non-preferred origin | \
+	    while IFS="=" read pub pub_urls; do
+		if [[ "$pub_urls" != "None" ]]; then
+			# skip extra publishers that need a key/cert
+			[[ "`get_pub_secinfo $pub`" != "None None" ]] && \
+			    continue
+		else
+			pub_urls=""
+		fi
+
+		if [[ -z "$publishers_extra_origins" ]]; then
+			publishers_extra_origins="$pub=$pub_urls"
+		else
+			publishers_extra_origins=$(printf "%s\n%s" \
+			    "$publishers_extra_origins" \
+			    "$pub=$pub_urls")
+		fi
+	done
+
+	get_publisher_urls non-preferred mirror | \
+	    while IFS="=" read pub pub_urls; do
+		# skip extra publishers that need a key/cert
+		[[ "`get_pub_secinfo $pub`" != "None None" ]] && \
+		    continue
+
+		if [[ -z "$publishers_extra_mirrors" ]]; then
+			publishers_extra_mirrors="$pub=$pub_urls"
+		else
+			publishers_extra_mirrors=$(printf "%s\n%s" \
+			    "$publishers_extra_mirrors" \
+			    "$pub=$pub_urls")
+		fi
+	done
+fi
+
+#
+# Crack pub=url into two pieces.
+#
+echo $pub_and_origins | IFS="=" read publisher pub_origins
+if [[ -z $publisher || -z $pub_origins ]]; then
+	fail_usage "$f_bad_publisher"
+fi
+echo $pub_and_mirrors | IFS="=" read ignored pub_mirrors
+
+if [[ -n $propagate_secinfo ]]; then
+	#
+	# Get the global zone's cert and key (if any) so that we can propagate
+	# them into the new image.
+	#
+	get_pub_secinfo $publisher | read keyfile certfile
+	if [[ $? -ne 0 ]]; then
+		fail_usage "$f_get_secinfo" $publisher
+	fi
+fi
+#
+# Do some sanity checks on key and cert.
+#
+[[ $keyfile != "None" && ! -f $keyfile ]] && \
+    fail_usage "$f_nosuch_key" $keyfile
+[[ $certfile != "None" && ! -f $certfile ]] && \
+    fail_usage "$f_nosuch_cert" $certfile
+
+#
 # Look for the 'entire' incorporation's FMRI in the current image; due to users
 # doing weird machinations with their publishers, we strip off the publisher
 # from the FMRI if it is present.
@@ -173,26 +309,182 @@
 	exit $ZONE_SUBPROC_OK
 fi
 
+# Display preferred publisher origin and mirror information.
+printf "$m_publisher\n" $publisher "$pub_origins $pub_mirrors"
+
+# Display extra publisher origin and mirror information.  This does mean that
+# the extras have to be displayed twice to show mirror information.
+if [[ -n "$publishers_extra_origins" ]]; then
+	echo "$publishers_extra_origins" | while IFS="=" read pub pub_urls; do
+		printf "$m_publisher\n" $pub "$pub_urls"
+	done
+	if [[ -n "$publishers_extra_mirrors" ]]; then
+		echo "$publishers_extra_mirrors" | while IFS="=" read pub pub_urls; do
+			printf "$m_publisher\n" $pub "$pub_urls"
+		done
+	fi
+fi
+
 printf "$m_image\n" $ZONEROOT
 
-enable_zones_services
-if [[ $? -ne 0 ]]; then
-	exit $ZONE_SUBPROC_NOTCOMPLETE
+#
+# We copy the credentials from the global zone into the new image
+# we're about to create.
+#
+if [[ $keyfile != "None" ]]; then
+	newkeylocation="$KEYDIR/$(basename $keyfile)"
+	secinfo="$secinfo -k $newkeylocation"
+	printf "$m_key_prop\n" $(basename $keyfile)
+	mkdir -p -m 755 $ZONEROOT/$KEYDIR || fail_fatal "$f_key_prop"
+	cp $keyfile $ZONEROOT/$newkeylocation || fail_fatal "$f_key_prop"
+	chmod 644 $ZONEROOT/$newkeylocation
+	chown -h root:root $ZONEROOT/$newkeylocation
+fi
+if [[ $certfile != "None" ]]; then
+	newcertlocation="$KEYDIR/$(basename $certfile)"
+	secinfo="$secinfo -c $newcertlocation"
+	printf "$m_cert_prop\n" $(basename $certfile)
+	mkdir -p -m 755 $ZONEROOT/$KEYDIR || fail_fatal "$f_cert_prop"
+	cp $certfile $ZONEROOT/$newcertlocation || fail_fatal "$f_cert_prop"
+	chmod 644 $ZONEROOT/$newcertlocation
+	chown -h root:root $ZONEROOT/$newcertlocation
 fi
 
 #
-# The image is created.
+# Regrettably, since we already copied the key information into place,
+# we must pass the -f (force) option to image-create, since it thinks that
+# something must be wrong, as the image exists.
 #
-LC_ALL=C $PKG image-create --zone --full \
-    --set-property use-system-repo=true \
+pub_first_origin=""
+pub_add_origins=""
+for origin in $pub_origins; do
+	if [[ -z "$pub_first_origin" ]]; then
+		# The first origin is semi-special in that the publisher
+		# argument to image-create requires it to be specified
+		# by itself and then any additional origins after that.
+		# Technically, image-create doesn't care if you specify
+		# the first one again using -g, but there's no point in
+		# doing so.
+		pub_first_origin=$origin
+		continue
+	fi
+	pub_add_origins="${pub_add_origins}-g $origin "
+done
+
+pub_add_mirrors=""
+for mirror in $pub_mirrors; do
+	pub_add_mirrors="${pub_add_mirrors}-m $mirror "
+done
+
+#
+# The image is created with --no-refresh so that all of the publisher
+# configuration can be put into place first before attempting to retrieve
+# and build catalog information.  This substantially reduces the amount of
+# time needed to create a zone.
+#
+LC_ALL=C $PKG image-create -f --no-refresh --zone --full \
+    -p $publisher=$pub_first_origin $pub_add_origins $pub_add_mirrors $secinfo \
     $ZONEROOT || fail_incomplete "$f_img"
 
+# Retrieve publisher attributes and update our new publisher
+attrs=$(get_publisher_attr_args $publisher "origin")
+
 # Change the value of PKG_IMAGE so that future PKG operation will work
 # on the newly created zone rather than the global zone
 
 PKG_IMAGE="$ZONEROOT"
 export PKG_IMAGE
 
+# --no-refresh is used here so that update operations can be
+# coalesced.
+# Update our new publisher
+LC_ALL=C $PKG set-publisher --no-refresh $attrs $publisher \
+    || fail_incomplete "$f_img"
+
+# add extra publishers
+# If cert and key information are ever allowed at the origin or
+# mirror level, then this will have to be changed.
+if [[ -n "$publishers_extra_origins" ]]; then
+	echo "$publishers_extra_origins" | while IFS="=" read pub pub_urls; do
+		pub_prefix=$pub
+		pub_add_origins=""
+		for origin in $pub_urls; do
+			pub_add_origins="${pub_add_origins}-g $origin "
+		done
+
+		# Retrieve publisher attributes. Since we are retrieving
+		# these attributes from the GLOBAL zone, we must reset
+		# PKG_IMAGE temporarily
+		SAVE_PKG_IMAGE=$PKG_IMAGE
+		PKG_IMAGE=$GZ_IMAGE
+		export PKG_IMAGE
+		attrs=$(get_publisher_attr_args $pub_prefix "origin")
+		# Now restore the save PKG_IMAGE value
+		PKG_IMAGE=$SAVE_PKG_IMAGE
+		export PKG_IMAGE
+		# --no-refresh is used here so that update operations can be
+		# coalesced.
+		LC_ALL=C $PKG set-publisher --no-refresh $attrs \
+                    ${pub_add_origins}${pub_prefix} || fail_incomplete "$f_img"
+	done
+
+	if [[ -n "$publishers_extra_mirrors" ]]; then
+		echo "$publishers_extra_mirrors" | \
+		    while IFS="=" read pub pub_urls; do
+			pub_prefix=$pub
+			pub_add_mirrors=""
+			for mirror in $pub_urls; do
+				pub_add_mirrors="${pub_add_mirrors}-m $mirror "
+			done
+
+			# Retrieve publisher attributes. Since we are retrieving
+			# these attributes from the GLOBAL zone, we must reset
+			# PKG_IMAGE temporarily
+			SAVE_PKG_IMAGE=$PKG_IMAGE
+			PKG_IMAGE=$GZ_IMAGE
+			export PKG_IMAGE
+			attrs=$(get_publisher_attr_args $pub_prefix "mirror")
+			PKG_IMAGE=$SAVE_PKG_IMAGE
+			export PKG_IMAGE
+			# --no-refresh is used here so that update operations
+			# can be coalesced.
+			LC_ALL=C $PKG set-publisher --no-refresh $attrs \
+			    ${pub_add_mirrors}${pub_prefix} || \
+			    fail_incomplete "$f_img"
+		done
+	fi
+fi
+
+# Now that all of the publisher configurations are in place, attempt a refresh.
+# If this fails, assume the image is incomplete.
+LC_ALL=C $PKG refresh || fail_incomplete "$f_img"
+
+if [[ -f /var/pkg/pkg5.image && -d /var/pkg/publisher ]]; then
+	PKG_CACHEROOT=/var/pkg/publisher
+	export PKG_CACHEROOT
+	printf "$m_cache\n" $PKG_CACHEROOT
+fi
+
+#
+# If we found an "entire" incorporation in the current image, then
+# check to see if the user's choice of preferred publisher contains the
+# version of the 'entire' incorporation needed.  This helps us to prevent
+# mishaps in the event the user selected some weirdo publisher as their
+# preferred one, or passed a preferred pub on the command line which doesn't
+# have a suitable 'entire' in it.
+#
+# n.b. it would be nice to do this before we provision the zfs dataset, etc.
+# but since the publisher specified by the user might not be known to
+# the system, we can't do this test without first configuring the image.
+#
+if [[ -n $entire_fmri ]]; then
+	printf "$m_incorp\n"
+	LC_ALL=C $PKG list -af pkg://$publisher/$entire_fmri > /dev/null 2>&1
+	if [[ $? -ne 0 ]]; then
+		fail_fatal "$f_no_entire_in_pref" $entire_fmri $publisher
+	fi
+fi
+
 printf "$m_core\n"
 pkglist=""
 if [[ -n $entire_fmri ]]; then
@@ -210,9 +502,7 @@
 	pkg:///compress/gzip
 	pkg:///compress/zip
 	pkg:///compress/unzip
-	pkg:///package/pkg
-        pkg:///package/sysrepo
-        pkg:///package/sysrepo-K"
+	pkg:///package/pkg"
 
 #
 # Get some diagnostic tools, truss, dtrace, etc.
--- a/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Thu Apr 28 11:44:04 2011 -0700
+++ b/src/pkg/manifests/system%2Fzones%2Fbrand%2Fipkg.p5m	Thu Apr 28 12:52:19 2011 -0700
@@ -41,12 +41,10 @@
 dir path=usr/lib/brand
 dir path=usr/lib/brand/ipkg
 file path=usr/lib/brand/ipkg/attach mode=0755
-file path=usr/lib/brand/ipkg/boot mode=0755
 file path=usr/lib/brand/ipkg/clone mode=0755
 file path=usr/lib/brand/ipkg/common.ksh
 file path=usr/lib/brand/ipkg/detach mode=0755
 file path=usr/lib/brand/ipkg/fmri_compare mode=0755
-file path=usr/lib/brand/ipkg/halt mode=0755
 file path=usr/lib/brand/ipkg/image_install mode=0755
 file path=usr/lib/brand/ipkg/p2v mode=0755
 file path=usr/lib/brand/ipkg/pkgcreatezone mode=0755