src/brand/pkgcreatezone
author Dan Price <dp@eng.sun.com>
Wed, 29 Apr 2009 15:49:05 -0700
changeset 1091 fc73bc2d78ce
parent 954 8614b0c63fb3
child 1108 14533641d138
permissions -rwxr-xr-x
7490 ipkg brand attach needs similar logic to pkgcreatezone for 'entire' incorporation 8500 ipkg brand should mimic live cd, not create search index until user asks for it 8501 Chaff on the screen in zone install due to image-create's refresh progress display

#!/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 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

. /usr/lib/brand/ipkg/common.ksh

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_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() {
	print "$f_interrupted"
	exit $int_code
}

int_code=$ZONE_SUBPROC_NOTCOMPLETE
trap trap_cleanup INT

extra_packages=""
zonename=""
zonepath=""
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:P:z:R:h:e:" opt; do
	case $opt in
		h)	fail_usage "$m_usage";;
		R)	zonepath="$OPTARG" ;;
		z)	zonename="$OPTARG" ;;
		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))

if [[ -z $zonepath || -z $zonename ]]; then
	print -u2 "Brand error: No zone path or name"
	exit $ZONE_SUBPROC_USAGE
fi

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 [[ -z $entire_fmri ]]; then
	fail_incomplete "$f_no_entire"
fi

#
# Before installing the zone, set up ZFS dataset hierarchy for the zone root
# dataset.
#

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

#
# 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
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

if [ $BENUM -ge 100 ]; then
	fail_fatal "$f_zfs_create"
fi

if [ ! -d $zoneroot ]; then
	/usr/bin/mkdir $zoneroot
fi

/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $zoneroot || \
	fail_incomplete "$f_zfs_mount"

#
# Done setting up the zone's datasets.
#
printf "$m_publisher" $publisher $publisherurl
printf "\n$m_image\n" $zoneroot
$PKG image-create --zone --full -p "$pub_and_url" $zoneroot || \
	fail_incomplete "$f_img"


PKG_IMAGE="$zoneroot"
export PKG_IMAGE
if [ -d /var/pkg/download ]; then
	PKG_CACHEDIR=/var/pkg/download
	export PKG_CACHEDIR
	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"
#
# 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 dependency on python, so we supply it.
#
pkglist="$pkglist SUNWPython SUNWipkg"

#
# Get some diagnostic tools, truss, dtrace, etc.
#
pkglist="$pkglist SUNWtoo SUNWdtrc SUNWrcmdc SUNWbip"

#
# Get at least one sensible shell, and vi
#
pkglist="$pkglist SUNWbash SUNWvim"

#
# Get ssh and sshd.
#
pkglist="$pkglist SUNWsshcu SUNWssh SUNWsshd"

#
# Get some name services.
#
pkglist="$pkglist SUNWnis SUNWlldap"

#
# Get nfs client and autofs; it's a pain not to have them.
#
pkglist="$pkglist SUNWnfsc SUNWatfs"


#
# Get man(1) but not the man pages
#
pkglist="$pkglist SUNWdoc"

#
# 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 here, as that is also what the LiveCD does.
#
$PKG install --no-index --no-refresh $pkglist || fail_fatal "$f_pkg"

printf "\n$m_mannote\n"

printf "$m_smf"
ln -s ns_files.xml $zoneroot/var/svc/profile/name_service.xml
ln -s generic_limited_net.xml $zoneroot/var/svc/profile/generic.xml
ln -s inetd_generic.xml $zoneroot/var/svc/profile/inetd_services.xml
ln -s platform_none.xml $zoneroot/var/svc/profile/platform.xml

# This was formerly done in i.manifest
repfile=$zoneroot/etc/svc/repository.db
cp $zoneroot/lib/svc/seed/nonglobal.db $repfile
chmod 0600 $repfile
chown root:sys $repfile

printf "$m_done\n"

# Clean up root as a role and jack if needed
if grep "^root::::type=role;" $zoneroot/etc/user_attr >/dev/null 2>&1; then
	printf "$m_brokenness\n"
	#
	# Remove "jack" user.
	#
	print "/^jack:/d\nw" | ed -s $zoneroot/etc/passwd
	chmod u+w $zoneroot/etc/shadow
	print "/^jack:/d\nw" | ed -s $zoneroot/etc/shadow
	chmod u-w $zoneroot/etc/shadow

	#
	# Set root from a role back to... not a role.  Grr.
	#
	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
touch $zoneroot/etc/.UNCONFIGURED

# Umount the dataset on the root.
/usr/sbin/umount $zoneroot

printf "$m_complete\n\n" ${SECONDS}
printf "$m_postnote\n"
printf "$m_postnote2\n"

exit $ZONE_SUBPROC_OK