#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. # . /usr/lib/brand/solaris-kz/common.ksh # Allows developers to override some things like PATH and PYTHONPATH . /usr/lib/brand/solaris/developerenv.ksh f_booting=$(gettext "failed to boot zone for install.") f_lofiadm=$(gettext "lofiadm -r %s failed.") f_zlogin=$(gettext "failed to install: console login failed.") f_install_failed=$(gettext "failed to complete install process.") f_mark=$(gettext "failed to mark auxiliary state.") f_mount_media=$(gettext "failed to mount media %s at %s") f_umount_media=$(gettext "failed to umount media from %s") f_copy_to_shared=$(gettext "failed to copy %s to shared filesystem") f_archive_mount=$(gettext "Could not mount archive %s at %s") m_booting=$(gettext "Booting zone for install.") m_usage=$(gettext "\n install -h\n install [-m manifest] [-c profile] [-C install-env-profile] -b isopath [-x no-auto-shutdown]\n") # Minimum image version that adds the auto-install-completion service # Kernel Zone media install with AI image at or above this level will halt # the zone automatically for a failed install image_version_supports_auto_shutdown=5 function clean_lofi { typeset dev=$1 if [[ -n "$dev" ]]; then zonecfg -z $ZONENAME remove device match=$dev lofiadm -d $dev fi } function cleanup { typeset root=$ZONEPATH/root if [[ -n $BRAND_SKIP_CLEANUP ]]; then vlog "Exiting with exit code $EXIT_CODE (skipping cleanup)" finish_log zone exit $EXIT_CODE fi state=$(zoneadm -z $ZONENAME list -p | awk -F: '{print $3}') if [[ $state == "running" ]]; then zoneadm -z $ZONENAME halt zoneadm -z $ZONENAME mark -A installing fi if [[ -d "$TMPDIR/media" ]] ; then umount -f $TMPDIR/media fi if [[ -n $uafs_mntpt ]]; then vlog "Unmounting Unified Archive from %s" "$uafs_mntpt" # If the zone halted properly this has already been done. # Error messages to that effect are nothing to worry about. umount -f "$uafs_mntpt" rmdir "$uafs_mntpt" fi if [[ -n $install_watcher_pid ]]; then kill -9 "$install_watcher_pid" 2>dev/null fi rm -f $root/shared/ai.xml rm -rf $root/shared/sysconfig/* 2>/dev/null if [[ -d "$root/shared/ie-sc" ]] ; then rm -rf $root/shared/ie-sc/ 2>/dev/null fi clean_lofi $media_lofi } function trap_cleanup { cleanup print "$f_interrupted" exit $EXIT_CODE } function trap_exit { vlog "Exiting with exit code $EXIT_CODE" finish_log zone exit $EXIT_CODE } function install_manifests { typeset root=$ZONEPATH/root typeset manifest=$1 typeset sc_config=$2 typeset ie_config=$3 if [[ -n $manifest ]]; then cp "$manifest" "$root/shared/ai.xml" || fatal "$f_copy_to_shared" "$manifest" fi if [[ -n $sc_config ]]; then if [[ ! -d $root/shared/sysconfig ]]; then mkdir "$root/shared/sysconfig" || fail_fatal "$f_mkdir" "$root/shared/sysconfig" fi if [[ -d "$sc_config" ]]; then cp -r $sc_config/* "$root/shared/sysconfig/" || fatal "$f_copy_to_shared" "$sc_config" else cp $sc_config "$root/shared/sysconfig/" || fatal "$f_copy_to_shared" "$sc_config" fi fi if [[ -n $ie_config ]]; then if [[ ! -d $root/shared/ie-sc ]]; then mkdir "$root/shared/ie-sc" || fail_fatal "$f_mkdir" \ "$root/shared/ie-sc" fi if [[ -d "$ie_config" ]]; then cp -r $ie_config/* \ "$root/shared/ie-sc/" || fatal "$f_copy_to_shared" "$ie_config" else cp $ie_config "$root/shared/ie-sc/" || fatal "$f_copy_to_shared" "$ie_config" fi fi } function add_lofi_device { typeset media=$1 typeset dev dev=$(lofiadm -r $media) if [[ $? != 0 ]]; then cleanup fail_fatal "$f_lofiadm" $media fi dev=${dev/lofi/rlofi} # # info returns 0 in the failure case too. # err=$(zonecfg -z $ZONENAME info device match=$dev 2>&1 >/dev/null) if [[ -z "$err" ]]; then lofi_dev=$dev return fi zonecfg -z $ZONENAME 2>&1 <<-EOF add device set match=$dev end EOF if [[ $? != 0 ]]; then lofiadm -d $dev cleanup fail_fatal "$f_configuring" fi lofi_dev=$dev } function get_media_info { typeset rdev=$1 typeset dev=${rdev/rlofi/lofi} # Mount the install media to determine its type mkdir "$TMPDIR/media" >/dev/null 2>&1 if ! mount -F hsfs "$dev" "$TMPDIR/media" >/dev/null 2>&1 ; then cleanup fail_fatal "$f_mount_media" "$dev" "$TMPDIR/media" fi if [[ -f "$TMPDIR/media/.image_info" ]] ; then install_media_type=$(nawk -F '=' \ '$1 == "IMAGE_TYPE" {print $2}' "$TMPDIR/media/.image_info") install_media_image_version=$(nawk -F '=' \ '$1 == "IMAGE_VERSION" {print $2}' "$TMPDIR/media/.image_info" | nawk -F '.' '{print $1}') fi if ! umount "$TMPDIR/media"; then cleanup fail_fatal "$f_umount_media" "$TMPDIR/media" fi } function get_cdrom_id { typeset dev=$1 id=$(zonecfg -z $ZONENAME info device match=$dev | grep id: | awk -F: '{print $2}') echo $id } function get_boot_args { typeset args="" typeset manifest=$1 typeset sc_config=$2 typeset ie_config=$3 typeset arch=$(uname -p) typeset dash_b="" # The boot arguments set below are only applicable for AI install # media. Return with nothing if this is not AI media. [[ $install_media_type == "AI" ]] || return # Compatibility: For AI install media with: # image version < 5.0, the "auto-shutdown" boot flag is set to halt the zone if # the install is successful # image version >= 5.0, the zone is halted by the global zone after installation # (success or failure), so there is no need to set the # "auto-shutdown" boot flag if [[ $arch == "i386" ]]; then args="$args -B install=true" shutdown=",auto-shutdown=true" dash_b="-B" else args="$args - install" shutdown=" auto-shutdown" fi if (( $install_media_image_version < $image_version_supports_auto_shutdown )) && [[ -z $no_auto_shutdown ]]; then args="$args$shutdown" fi if [[ -n $manifest ]] ; then args="$args $dash_b aimanifest=/system/shared/ai.xml" else args="$args $dash_b aimanifest=prompt" fi if [[ -n $sc_config ]]; then args="$args $dash_b profile=/system/shared/sysconfig/" fi if [[ -n $ie_config ]]; then args="$args $dash_b install-env-profile=/system/shared/ie-sc/" fi echo $args } EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN trap trap_cleanup INT # Used by start_log() set -A save_args "$0" "$@" ZONENAME="" ZONEPATH="" # Setup i18n output TEXTDOMAIN="SUNW_OST_OSCMD" export TEXTDOMAIN unset archive unset archive_aimedia unset archived_zone unset install_media unset install_media_type unset install_media_image_version unset sc_config unset ie_config unset manifest unset media_lofi unset uafs_mntpt unset debug unset no_auto_shutdown unset install_watcher_pid # brand specific list of -x suboptions and their suboption arguments typeset -A x_opts x_opts[cert]= x_opts[ca-cert]= x_opts[key]= while getopts "a:A:b:C:c:dhm:R:vx:z:Z:" opt; do case $opt in a) archive=$OPTARG ;; A) archive_aimedia=$OPTARG ;; b) install_media="$OPTARG";; C) ie_config="$OPTARG" ;; c) sc_config="$OPTARG" ;; d) debug=-d ;; h) fail_usage "";; m) manifest="$OPTARG" ;; R) ZONEPATH="$OPTARG" ;; v) OPT_V=1;; x) if [[ "$OPTARG" = "no-auto-shutdown" ]]; then no_auto_shutdown="$OPTARG" else # May call fail_usage. process_xopt x_opts "$OPTARG" fi ;; z) ZONENAME="$OPTARG" ;; Z) archived_zone="$OPTARG" ;; *) fail_usage "";; esac done shift $((OPTIND-1)) [[ -n $TMPDIR && -d $TMPDIR ]] || fail_internal "TMPDIR not set" zone= init_zone zone "$ZONENAME" "$ZONEPATH" eval $(bind_legacy_zone_globals zone) start_log zone install "${save_args[@]}" trap trap_exit EXIT if [[ -n $archive ]]; then uafs_mntpt=${zone.root}/shared/uafs mkdir -p "$uafs_mntpt" mntopts=vs=$archived_zone,daemon=/usr/lib/fs/uafs/uafs for param in key cert ca-cert; do [[ -n ${x_opts[$param]} ]] && mntopts+=,$param=${x_opts[$param]} done mount -F uvfs -q -o "$mntopts" "$archive" "$uafs_mntpt" || fatal "$f_archive_mount" "$archive" "$uafs_mntpt" [[ -z $install_media ]] && install_media=$uafs_mntpt/OVF/$archive_aimedia fi install_manifests "$manifest" "$sc_config" "$ie_config" add_lofi_device "$install_media" media_lofi=$lofi_dev get_media_info "$lofi_dev" vlog "$m_booting" cdrom_id=$(get_cdrom_id "$lofi_dev") boot_args=$(get_boot_args "$manifest" "$sc_config" "$ie_config") zoneadm -z $ZONENAME boot $debug -i -f -- cdrom$cdrom_id "$boot_args" if [[ $? != 0 ]]; then cleanup fail_fatal "$f_booting" fi # Call install_watcher in background only for AI install media # with image version >= 5 if [[ $install_media_type == "AI" ]] && (( $install_media_image_version >= $image_version_supports_auto_shutdown )); then set -A args -- -z "$ZONENAME" -R "$ZONEPATH" [[ -n $no_auto_shutdown ]] && a_push args -x "$no_auto_shutdown" /usr/lib/brand/solaris-kz/install_watcher "${args[@]}" & install_watcher_pid=$! fi zlogin -dDC $ZONENAME if [[ $? != 0 ]]; then cleanup fail_fatal "$f_zlogin" fi # # Determine success or failure. If the zone is not running, then check that # zoneadmd marked the state as installed (implying that the installer set the # "installed" auxiliary state when it was running). # If the zone is running check the underlying state in the index file instead. # state=$(zoneadm -z $ZONENAME list -p | awk -F: '{print $3}') sstate=$(grep ^$ZONENAME: /etc/zones/index | awk -F: '{print $2}') case $state in running|shutting_down|down) state=$sstate ;; *) ;; esac if [[ $state != "installed" ]]; then cleanup fail_fatal "$f_install_failed" fi printf "$m_complete\n\n" ${SECONDS} cleanup finish_log zone trap - EXIT exit $ZONE_SUBPROC_OK