4771 zone operations fail with package inventory errors when authority changes
authorDan Price <dp@eng.sun.com>
Wed, 18 Mar 2009 18:35:27 -0700
changeset 954 8614b0c63fb3
parent 953 f50ceeff3138
child 955 65a22a086fc9
4771 zone operations fail with package inventory errors when authority changes 7335 zone install needs to be cleverer about publishers 7343 publisher changes broke ipkg zones 7389 Setting ROOT before building should work 7391 need to be able to specify additional packages to install into zones
src/brand/common.ksh
src/brand/config.xml
src/brand/pkgcreatezone
src/setup.py
--- a/src/brand/common.ksh	Fri Mar 13 15:53:27 2009 -0500
+++ b/src/brand/common.ksh	Wed Mar 18 18:35:27 2009 -0700
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -41,12 +41,16 @@
 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.")
 
 fail_incomplete() {
-	print "$1"
+	printf "ERROR: " 1>&2
+	printf "$@" 1>&2
+	printf "\n" 1>&2
 	exit $ZONE_SUBPROC_INCOMPLETE
 }
 
 fail_fatal() {
-	print "$1"
+	printf "ERROR: " 1>&2
+	printf "$@" 1>&2
+	printf "\n" 1>&2
 	exit $ZONE_SUBPROC_FATAL
 }
 
--- a/src/brand/config.xml	Fri Mar 13 15:53:27 2009 -0500
+++ b/src/brand/config.xml	Wed Mar 18 18:35:27 2009 -0700
@@ -20,7 +20,7 @@
 
  CDDL HEADER END
 
- Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  Use is subject to license terms.
 
  DO NOT EDIT THIS FILE.
@@ -38,7 +38,7 @@
 
 	<!-- We may not be able to do the create in pkg(1) proper. -->
 	<install>/usr/lib/brand/ipkg/pkgcreatezone -z %z -R %R</install>
-	<installopts>a:h</installopts>
+	<installopts>a:p:e:h</installopts>
 	<boot></boot>
 	<halt></halt>
 	<verify_cfg></verify_cfg>
--- a/src/brand/pkgcreatezone	Fri Mar 13 15:53:27 2009 -0500
+++ b/src/brand/pkgcreatezone	Wed Mar 18 18:35:27 2009 -0700
@@ -26,22 +26,31 @@
 
 . /usr/lib/brand/ipkg/common.ksh
 
-f_img=$(gettext "failed to create image")
-f_pkg=$(gettext "failed to install package")
-f_interrupted=$(gettext "Installation cancelled due to interrupt.")
+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.\n")
+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.\n")
+f_no_entire=$(gettext "Unable to find 'entire' incorporation in the global zone image.\n")
+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")
+
 
-m_authority=$(gettext   "  Authority: Using %s.")
-m_cache=$(gettext   "      Cache: Using %s.")
-m_image=$(gettext     "      Image: Preparing at %s ...")
-m_core=$(gettext      " Installing: (output follows)\n")
-m_smf=$(gettext	      "Postinstall: Copying SMF seed repository ...")
-m_brokenness=$(gettext "Postinstall: Working around http://defect.opensolaris.org/bz/show_bug.cgi?id=681")
-m_more_brokenness=$(gettext "Postinstall: Working around http://defect.opensolaris.org/bz/show_bug.cgi?id=741")
-m_mannote=$(gettext   "       Note: Man pages can be obtained by installing SUNWman")
-m_complete=$(gettext  "       Done: Installation completed in %s seconds.")
-m_postnote=$(gettext  " Next Steps: Boot the zone, then log into the zone console")
+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_core=$(gettext        "  Installing: Core System (output follows)\n")
+m_more=$(gettext        "  Installing: Additional 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 SUNWman")
+m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
+m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console")
 m_postnote2=$(gettext "             (zlogin -C) to complete the configuration process")
 
+m_usage=$(gettext    "$0: [-h] [-P publisher=uri] [-e extrapkg [...]]")
+
 m_done=$(gettext      " done.")
 
 trap_cleanup() {
@@ -50,36 +59,34 @@
 }
 
 int_code=$ZONE_SUBPROC_NOTCOMPLETE
-
 trap trap_cleanup INT
 
+extra_packages=""
 zonename=""
 zonepath=""
-
-#
-# If there's a preferred authority set for the system, set that as our
-# default.  Otherwise use opensolaris.org.
-#
-authority="opensolaris.org=http://pkg.opensolaris.org"
-if [[ -x /usr/bin/pkg ]]; then
-	sysauth=`LC_ALL=C /usr/bin/pkg authority | grep preferred | awk '{printf "%s=%s", $1, $3}'`
-	if [[ $? -eq 0 && -n "$sysauth" ]]; then
-		authority=$sysauth
-	fi
-fi
+pub_and_url=""
 
 # Setup i18n output
 TEXTDOMAIN="SUNW_OST_OSCMD"
 export TEXTDOMAIN
 
+PKG=/usr/bin/pkg
+#
+# Just in case.  This should probably be removed later.
+#
+[[ ! -x $PKG ]] && fail_incomplete "$f_pkg5_missing"
 
-while getopts "a:z:R:h" opt; do
+while getopts "a:P:z:R:h:e:" opt; do
 	case $opt in
-		h)	fail_usage "$0 [-h] [-a <authority>]";;
+		h)	fail_usage "$m_usage";;
 		R)	zonepath="$OPTARG" ;;
 		z)	zonename="$OPTARG" ;;
-		a)	authority="$OPTARG" ;;
-		*)	fail_usage "$0 [-h] [-a <authority>]";;
+		a)	pub_and_url="$OPTARG";
+			print -u2 \
+			    "WARNING: -a is deprecated.  Use -P instead." ;;
+		P)	pub_and_url="$OPTARG" ;;
+		e)	extra_packages="$extra_packages $OPTARG" ;;
+		*)	fail_usage "$m_usage";;
 	esac
 done
 shift $((OPTIND-1))
@@ -92,6 +99,52 @@
 zoneroot=$zonepath/root
 
 #
+# If the user didn't give us a publisher, and there's a preferred publisher set
+# for the system, set that as the default.
+#
+if [[ -z $pub_and_url ]]; then
+	#
+	# We look for a preferred online origin.
+	#
+	tpub_and_url=`LC_ALL=C $PKG -R / publisher -PH | \
+	    awk '$2 == "origin" && $3 == "online" \
+	    {printf "%s=%s\n", $1, $4; exit 0;}'`
+
+	[[ $? -eq 0 && -n $tpub_and_url ]] && pub_and_url="$tpub_and_url"
+fi
+
+#
+# In the unlikely event that we were not able to get the system's
+# preferred publisher, and that the user didn't give us a publisher, we
+# prompt the user to provide it.
+#
+[[ -z $pub_and_url ]] && fail_usage "$f_no_pref_publisher"
+
+#
+# Crack pub=url into two pieces.
+#
+echo $pub_and_url | IFS== read publisher publisherurl
+if [[ -z $publisher || -z $publisherurl ]]; then
+	fail_usage "$f_bad_publisher"
+fi
+
+#
+# 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.
+#
+raw_entire_fmri=$($PKG list -Hv entire | nawk '{print $1}')
+entire_fmri=$(echo $raw_entire_fmri | sed 's@^pkg://[^/]*/@@')
+entire_fmri=$(echo $entire_fmri | sed 's@^pkg:/@@')
+if [[ $raw_entire_fmri == "pkg://"* ]]; then
+	entire_fmri_pub=$(echo $raw_entire_fmri | sed 's@^pkg://\([^/]*\)/.*@\1@')
+fi
+
+if [[ -z $entire_fmri ]]; then
+	fail_incomplete "$f_no_entire"
+fi
+
+#
 # Before installing the zone, set up ZFS dataset hierarchy for the zone root
 # dataset.
 #
@@ -105,11 +158,16 @@
 fail_zonepath_in_rootds $ZONEPATH_DS
 
 #
+# 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.
 #
 
-/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&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
@@ -144,13 +202,12 @@
 #
 # Done setting up the zone's datasets.
 #
-
-printf "$m_authority" `echo $authority | cut -d= -f 2`
+printf "$m_publisher" $publisher $publisherurl
 printf "\n$m_image" $zoneroot
-pkg image-create -z -F -a "$authority" $zoneroot || fail_incomplete "$f_img"
+$PKG image-create --zone --full -p "$pub_and_url" $zoneroot || \
+	fail_incomplete "$f_img"
 printf "$m_done\n"
 
-entire_fmri=$(pkg list -Hv entire | nawk '{print $1}')
 
 PKG_IMAGE="$zoneroot"
 export PKG_IMAGE
@@ -160,15 +217,42 @@
 	printf "$m_cache\n" $PKG_CACHEDIR
 fi
 
+#
+# 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.
+#
+printf "$m_incorp\n"
+$PKG list -a pkg://$publisher/$entire_fmri > /dev/null 2>&1
+if [[ $? -ne 0 ]]; then
+	fail_fatal "$f_no_entire_in_pref" $entire_fmri $publisher
+fi
+
 printf "$m_core\n"
-pkg install -q $entire_fmri || fail_incomplete "$f_pkg"
-pkg install -q SUNWcsd || fail_incomplete "$f_pkg"
+#
+# We have to take baby steps here: first, by installing entire, to
+# constrain everything.  Then, SUNWcsd, to lay down device files which
+# are subsequently needed by driver actions.  Then SUNWcs to lay down
+# /etc/passwd, /etc/group, etc so that subsequent user and group actions
+# work.  This can all hopefully go away once "primordial" actions
+# arrive.
+#
+$PKG install -q --no-refresh --no-index $entire_fmri || fail_fatal "$f_pkg"
+$PKG install -q --no-refresh --no-index SUNWcsd || fail_fatal "$f_pkg"
+$PKG install --no-refresh --no-index SUNWcs || fail_fatal "$f_pkg"
 
+printf "$m_more\n"
 pkglist=""
 pkglist="$pkglist SUNWcnetr SUNWesu SUNWadmr SUNWadmap SUNWbzip SUNWgzip"
 
 #
-# Workaround: For now, SUNWipkg has no dependencies so we must supply it python.
+# Workaround: For now, SUNWipkg has no dependency on python, so we supply it.
 #
 pkglist="$pkglist SUNWPython SUNWipkg"
 
@@ -203,8 +287,19 @@
 #
 pkglist="$pkglist SUNWdoc"
 
-# Do the install
-pkg install $pkglist || fail_incomplete "$f_pkg"
+#
+# Add in any extra packages requested by the user.
+#
+pkglist="$pkglist $extra_packages"
+
+#
+# Do the install; we just refreshed on image-create, so skip that.  We
+# also skip indexing again here, because, due to the above --no-index
+# operations, pkg(1) will decide that, before doing anything else, it must
+# build the index.  Then it'll do work, and build the index again.
+#
+$PKG install --no-index --no-refresh $pkglist || fail_fatal "$f_pkg"
+$PKG rebuild-index
 
 printf "\n$m_mannote\n"
 
@@ -236,13 +331,14 @@
 	#
 	# Set root from a role back to... not a role.  Grr.
 	#
-	print "s/^root::::type=role;/root::::/\nw" | 
+	print "s/^root::::type=role;/root::::/\nw" |
 	    ed -s $zoneroot/etc/user_attr
 fi
 
 #
 # Make sure sysidtools run; we manually poke in the SSH action
 # so that we get an SSH key.  Yes, this is seriously borken.
+# See http://defect.opensolaris.org/bz/show_bug.cgi?id=741
 #
 printf "$m_more_brokenness\n"
 /usr/sbin/sysidconfig -b $zoneroot -a /lib/svc/method/sshd
--- a/src/setup.py	Fri Mar 13 15:53:27 2009 -0500
+++ b/src/setup.py	Wed Mar 18 18:35:27 2009 -0700
@@ -113,7 +113,10 @@
 
 dist_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "dist_" + arch))
 build_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "build_" + arch))
-root_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "root_" + arch))
+if "ROOT" in os.environ and os.environ["ROOT"] != "":
+        root_dir = os.environ["ROOT"]
+else:
+        root_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "root_" + arch))
 pkgs_dir = os.path.normpath(os.path.join(pwd, os.pardir, "packages", arch))
 
 py_install_dir = 'usr/lib/python2.4/vendor-packages'
@@ -224,6 +227,14 @@
         'brand/config.xml',
         'brand/platform.xml',
         'brand/pkgcreatezone',
+        'brand/attach',
+        'brand/clone',
+        'brand/detach',
+        'brand/prestate',
+        'brand/poststate',
+        'brand/query',
+        'brand/uninstall',
+        'brand/common.ksh',
         ]
 smf_files = [
         'pkg-server.xml',