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