usr/src/cmd/auto-install/svc/manifest-locator
author John Fischer <John.Fischer@Sun.COM>
Wed, 23 Feb 2011 15:57:37 -0800
changeset 1015 887661717eb2
parent 926 3e271c0efc4d
child 1075 df96871c232d
permissions -rw-r--r--
7018241 Solaris11 nightly build 2011-02-08 freezes early in install

#!/sbin/sh
#
# 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) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
#

# Use tee(1) when posting messages to both console and log file
TEE_LOGTOCONSOLE="/usr/bin/tee /dev/msglog"
# Architecture
ARCH=$(/sbin/uname -p)
# Installation configuration
INSTALL_CONF=/tmp/install.conf

PRTCONF=/usr/sbin/prtconf
SED=/usr/bin/sed
AWK=/usr/bin/awk
CUT=/usr/bin/cut
GREP=/usr/bin/grep
HEAD=/usr/bin/head
SVCADM=/usr/sbin/svcadm
SVCCFG=/usr/sbin/svccfg

DHCPINFO=/sbin/dhcpinfo
BOOTSERVER=BootSrvA

# Auto Installer service fmri
AI_SMF_FMRI="svc:/application/auto-installer:default"
# Directory location for the AI manifest
AI_MANIFESTDIR=/var/ai
# Filename of the located AI manifest
AI_MANIFEST_FILE=${AI_MANIFESTDIR}/default.xml
# Location of the default AI manifest
# NOTE: VMC also uses this location to store a custom manifest for
# installation
AI_DEFAULT_MANIFEST=/.cdrom/auto_install/default.xml

# Service Discovery Engine
AISD_ENGINE=/usr/bin/ai_sd
# Service Choosing Engine
AISC_ENGINE=/usr/bin/ai_get_manifest
# Auto install and System Configuration combined manifest 
# to be used for installation
AISC_MANIFEST=/tmp/ai_combined_manifest.xml
# List of services which Service Discovery Engine will
# contact for obtaining the manifest
AI_SERVICE_LIST=/tmp/service_list.$$
# debug mode
AI_DBGLVL=4
# timeout for service discovery process
AI_TIMEOUT=5

. /lib/svc/share/smf_include.sh

#
# Do multi-cast DNS service discovery in order
# to obtain installation manifests to use.
#
# Returns 0 for success and 1 for failure
#
do_service_discovery() 
{
	#
	# obtain parameters for service discovery provided in 
	# configuration files
	#  - name of service to look up
	#  - IP address and port number for fallback mechanism
	#  - turning on debug mode
	#
	# For SPARC, parameters are stored in 
	# <install_media_root_dir>/install.conf
	# This file is downloaded using HTTP protocol and saved in /tmp.
	# For X86, parameters are in defined in GRUB menu.lst
	#
	# TODO: Unify the implementation - bug 7789
	# - define one common config file for both Sparc and x86
	#   and avoid using GRUB menu.lst
	#
	if [ "${ARCH}" = "sparc" ]; then
		AI_SERVICE_NAME=$($GREP "^install_service" \
		    $INSTALL_CONF |  /usr/bin/cut -d'=' -f2)

		AI_SERVICE_ADDRESS=$($GREP "^install_svc_address" \
		    $INSTALL_CONF |  /usr/bin/cut -d'=' -f2)
	else
		AI_SERVICE_NAME=$($PRTCONF -v /devices | \
		    /usr/bin/sed -n '/install_service/{;n;p;}' | \
		    /usr/bin/cut -f 2 -d \')

		AI_SERVICE_ADDRESS=$($PRTCONF -v /devices | \
		    /usr/bin/sed -n '/install_svc_address/{;n;p;}' | \
		    /usr/bin/cut -f 2 -d \')
	fi

	#
	# Check to see if AI_SERVICE_ADDRESS has the $serverIP keyword
	#
	if [[ "$AI_SERVICE_ADDRESS" == ~(E)'^\$serverIP:' ]]; then
		# replace the $serverIP keyword with the machine's
		# boot server IP address
		AI_SERVICE_ADDRESS="$($DHCPINFO $BOOTSERVER)${AI_SERVICE_ADDRESS/\$serverIP/}"
	fi

	#
	# Invoke AI Service Discovery engine. For now it tries to look up
	# given service using multicast DNS.
	#

	if [ ! -x  $AISD_ENGINE ] ; then
		print "Could not find Auto Installer Service Discovery Engine" | \
		    $TEE_LOGTOCONSOLE
		return 1
	fi

	if [ -z "$AI_SERVICE_NAME" ] ; then
		print "Service name is required, but not provided" | \
		    $TEE_LOGTOCONSOLE
		return 1
	fi

	print "Service discovery phase initiated" | $TEE_LOGTOCONSOLE
	print "Service name to look up: $AI_SERVICE_NAME" | $TEE_LOGTOCONSOLE

	$AISD_ENGINE -n $AI_SERVICE_NAME -o $AI_SERVICE_LIST -t $AI_TIMEOUT \
	    -d $AI_DBGLVL

	#
	# if service discovery over multicast DNS failed, try fallback 
	# mechanism - service on given machine at given port number will be used
	#
	if [ $? -ne 0 ] ; then
		print "Service discovery over multicast DNS failed" | \
		    $TEE_LOGTOCONSOLE

		# if location of service is not provided, give up
		if [ -z "$AI_SERVICE_ADDRESS" ] ; then
			print "Location of service $AI_SERVICE_NAME not" \
			    "provided, service discovery failed" | \
			    $TEE_LOGTOCONSOLE
			return 1
		fi

		print "Service $AI_SERVICE_NAME located at $AI_SERVICE_ADDRESS" \
			"will be used" | $TEE_LOGTOCONSOLE
		print "$AI_SERVICE_ADDRESS:$AI_SERVICE_NAME" > $AI_SERVICE_LIST
	fi

	print "Service discovery finished successfully" | $TEE_LOGTOCONSOLE

	#
	# Invoke AI Service choosing engine. It takes list of install
	# services to connect and tries to obtain valid manifest
	#

	if [ ! -x  $AISC_ENGINE ] ; then
		print "Could not find Auto Installer Service Choosing Engine" | \
		    $TEE_LOGTOCONSOLE
		return 1
	fi

	print "Process of obtaining configuration manifest initiated" | \
	    $TEE_LOGTOCONSOLE

	$AISC_ENGINE -s $AI_SERVICE_LIST -o $AISC_MANIFEST -d $AI_DBGLVL

	if [ $? -ne 0 ] ; then
		print "Could not obtain valid configuration manifest" | \
		    $TEE_LOGTOCONSOLE
		return 1
	fi
	return 0
}

#
# Invoke the prompt to specify a manifest
# location. Set up the terminal correctly
# before invoking the prompt
#
do_get_manifest()
{
	TERM=sun-color
	export TERM
	/usr/sbin/get_manifest $AI_MANIFESTDIR
	cp $AI_MANIFEST_FILE $AISC_MANIFEST
}

#
# Set up the default manifest to be *the* 
# manifest to be used
#
setup_default_manifest()
{
	mkdir -p $AI_MANIFESTDIR
	cp $AI_DEFAULT_MANIFEST $AISC_MANIFEST
}

#
# Process bootargs
#
if [ "${ARCH}" = "sparc" ]; then

	set -- ""
	set -- $($PRTCONF -vp | $GREP "bootargs" | $CUT -f 2 -d\')
	if [ $# -gt 0 ] ; then
		while [ $# -gt 0 ] ; do
			case $1 in

			install)
				INSTALL_FLAG="true"
				shift
				;;
			prompt)
				PROMPT_FLAG="true"
				shift
				;;
			install_debug*)
				if [ "$1" = "install_debug" ]; then
					INSTALL_DEBUG_MODE="enable"
				else
					case $(print $1 | $CUT -f 1 -d=) in
						install_debug)
							INSTALL_DEBUG_MODE=$(print $1 | $CUT -f 2 -d=)
							;;
						*)
							;;
					esac
				fi
				shift
				;;
			*)
				shift
				;;
			esac
		done
	fi

	# We check for the presence of the block device
	# /devices/ramdisk-bootfs:a in order to determine whether
	# we are booted off of the net for Sparc systems.
	if [ -b "/devices/ramdisk-bootfs:a" ]; then
		NETBOOT="true"
	else
		NETBOOT="false"
	fi
else
	INSTALL_FLAG=$($PRTCONF -v /devices | \
		$SED -n "/'install'/{;n;p;}" | $HEAD -1 | $CUT -f 2 -d\')
	INSTALL_DEBUG_MODE=$($PRTCONF -v /devices | \
		$SED -n "/'install_debug'/{;n;p;}" | $HEAD -1 | $CUT -f 2 -d \')
	AI_MANIFEST_LOCATION=$($PRTCONF -v | \
		$SED -n "/'aimanifest'/{;n;p;}" | $HEAD -1 | $CUT -f 2 -d\')
	INSTALL_MEDIA=$($PRTCONF -v /devices | \
		$SED -n "/'install_media'/{;n;p;}" | $HEAD -1 | $CUT -f 2 -d\')

	#
	# Test to see if the manifest location should be
	# obtained at the command prompt
	#
	if [ "$AI_MANIFEST_LOCATION" = "prompt" ]; then
		PROMPT_FLAG="true"
	fi

	#
	# We check for the existence of the install_media boot property
	# to determine whether we are booted off of the net for x86 systems.
	# We need to find a more reliable way to figure this out longer
	# term, as a boot property is always customizable by the user.
	#
	if [ ! -z "$INSTALL_MEDIA" ] ; then
		NETBOOT="true"
	else
		NETBOOT="false"
	fi
fi


# Set property on auto-installer service to let it know debug mode
# is requested.
if [ -n "$INSTALL_DEBUG_MODE" ] ; then
	print "Setting debug mode to $INSTALL_DEBUG_MODE" | \
	    $TEE_LOGTOCONSOLE

	$SVCCFG -s $AI_SMF_FMRI setprop general/install_debug = astring: \
		$INSTALL_DEBUG_MODE
	$SVCADM refresh $AI_SMF_FMRI
fi

#
# If the "install" bootarg is not specified, disable the auto-installer
# service so that console-login comes up.  (User should be able
# to login, and enable the auto-installer)
#
if [ "$INSTALL_FLAG" != "true" ]; then
	$SVCADM disable $AI_SMF_FMRI
	$SVCADM refresh $AI_SMF_FMRI
fi

#
# If the "prompt" bootarg is specified, prompt for the location of
# the manifest
#
if [ "$PROMPT_FLAG" = "true" ]; then
	do_get_manifest </dev/console >/dev/console 2>&1
#
# Else no "prompt" bootarg, and we're booted from media; use the
# default manifest on the media.
#
elif [ "$NETBOOT" = "false" ]; then
	setup_default_manifest
	print "Using the default configuration manifest for installation" | \
	    $TEE_LOGTOCONSOLE
#
# Else no "prompt" bootarg, and we're booted from network; do
# service discovery to get a manifest.
#
else
	do_service_discovery
	if [ $? -ne 0 ] ; then
		exit $SMF_EXIT_ERR_FATAL
	fi
	print "Using the configuration manifest obtained via service" \
	    "discovery" | $TEE_LOGTOCONSOLE
fi

#
# If the "install" bootarg is not specified, print a message to the user,
# so they know to enable the auto-installer
#
if [ "$INSTALL_FLAG" != "true" ]; then
	print "" | $TEE_LOGTOCONSOLE
	print "Auto-installer disabled. Enable the auto-installer service" | \
	    $TEE_LOGTOCONSOLE
	print "by running the following command:" | $TEE_LOGTOCONSOLE
        print "   svcadm enable $AI_SMF_FMRI" | $TEE_LOGTOCONSOLE
	print "" | $TEE_LOGTOCONSOLE
fi

exit $SMF_EXIT_OK