#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. # . /usr/lib/brand/solaris/common.ksh # Allows developers to override some things like PATH and PYTHONPATH . /usr/lib/brand/solaris/developerenv.ksh f_a_obs=$(gettext "-a publisher=uri option is obsolete.") f_mktemp=$(gettext "Unable to make temporary filename.") f_aimanifest_add=$(gettext "Unable to aimanifest add.") f_aimanifest_get=$(gettext "Unable to aimanifest get.") f_autoinstall=$(gettext "auto-install failed.") f_nolabel=$(gettext "A label must be assigned before installing.") m_ai_running=$(gettext "Running auto-install: '%s'") m_image=$(gettext " Image: Preparing at %s.") m_mannote=$(gettext " Note: Man pages can be obtained by installing pkg:/system/manual") m_usage=$(gettext "\n install [-h]\n install [-m manifest] [-c profile.xml | dir]\n install {-a archive|-d path} {-p|-u} [-U] [-s|-v] [-c profile.xml | dir]") m_done=$(gettext " done.") trap_cleanup() { print "$m_interrupt" exit $EXIT_CODE } trap_exit() { vlog "Exiting with exit code $EXIT_CODE" finish_log zone exit $EXIT_CODE } EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN trap trap_cleanup INT # Used by start_log() set -A save_args "$0" "$@" manifest="" profile_dir="" ZONENAME="" ZONEPATH="" # Setup i18n output TEXTDOMAIN="SUNW_OST_OSCMD" export TEXTDOMAIN PKG=pkg unset install_archive unset source_dir unset silent_mode unset verbose_mode unset sc_config unset OPT_C unset temp_manifest unset temp_scprofile unset update_all unset archived_zone typeset -a xopts while getopts "a:c:d:hm:pR:suUx:vz:Z:" opt; do case $opt in a) OPTARG=$(mk_abs_path $OPTARG) # We're expecting a path to an archive if [[ ! -f $OPTARG ]]; then # If old style 'pub=uri' parameter then error. echo $OPTARG | egrep -s = if (( $? == 0 )); then fail_usage "$f_a_obs" fi fi install_archive="-a $OPTARG";; c) OPTARG=$(mk_abs_path $OPTARG) ls "$OPTARG" >/dev/null 2>&1 [[ -f $OPTARG ]] || [[ -d $OPTARG ]] || fatal "$f_arg_not_file_or_dir" "$OPTARG" sc_config="$OPTARG" OPT_C="-c $OPTARG" ;; d) source_dir="-d `mk_abs_path $OPTARG`";; h) fail_usage "";; m) manifest="$(mk_abs_path $OPTARG)" ;; p) preserve_zone="-p";; R) ZONEPATH="$OPTARG" ;; s) silent_mode=1;; x) a_push xopts -x "$OPTARG";; u) unconfig_zone="-u";; U) update_all="-U";; v) verbose_mode="-v";; Z) if [[ -n $ZONENAME ]]; then # If 'install -a archive -z archived_zone' is # fat-fingered to use -Z rather than -z, we will end # up here. fail_usage "" fi ZONENAME="$OPTARG" ;; z) archived_zone="-z $OPTARG" ;; *) fail_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 zone= init_zone zone "$ZONENAME" "$ZONEPATH" eval $(bind_legacy_zone_globals zone) # Check whether the zone has been detached from this system and if so, suggest # either trying to re-attach the zone or marking it incomplete and uninstalling # it first. if has_bootable_bes zone; then log "$f_reattach_or_uninstall" "(re)install" EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN exit $EXIT_CODE fi is_brand_labeled brand_labeled=$? if (( $brand_labeled == 0 )); then . /usr/lib/brand/labeled/common.ksh fi check_sc_config "$sc_config" # An image install can't use both -a AND -d... [[ -n "$install_archive" && -n "$source_dir" ]] && fail_usage "$f_incompat_options" "-a" "-d" # The install can't be both verbose AND silent... [[ -n $silent_mode && -n $verbose_mode ]] && \ fail_usage "$f_incompat_options" "-s" "-v" # The install can't both preserve and unconfigure [[ -n $unconfig_zone && -n $preserve_zone ]] && \ fail_usage "$f_incompat_options" "-u" "-p" # AI zone manifest option isn`t allowed when installing from a system image. if [[ -n "$install_archive" || -n "$source_dir" ]]; then [[ -n "$manifest" ]] && fail_usage \ "$f_incompat_options" "-a|-d" "-m" fi # p2v options aren't allowed when installing from a repo. if [[ -z $install_archive && -z $source_dir ]]; then [[ -n $preserve_zone || -n $unconfig_zone || -n $update_all ]] && \ fail_usage "$f_incompat_options" "default" "-p|-u|-U" fi start_log zone install "${save_args[@]}" trap trap_exit EXIT # # 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. # It's ok to not find entire in the current image, since this means the user # can install pre-release development bits for testing purposes. # entire_fmri=$(get_entire_incorp) # # If we're installing from an image, branch off to that installer. # Set up ZFS dataset hierarchy for the zone root dataset. # if [[ -n $install_archive || -n $source_dir ]]; then /usr/lib/brand/solaris/image_install $ZONENAME $ZONEPATH \ $install_archive $source_dir $verbose_mode $silent_mode \ $unconfig_zone $preserve_zone $OPT_C $update_all "${xopts[@]}" \ $archived_zone EXIT_CODE=$? exit $EXIT_CODE fi # Only image_install expects -x options (( ${#xopts[*]} == 0 )) || fail_usage "" log "$m_image\n" $ZONEROOT enable_zones_services 1 if (( $? != 0 )); then EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN exit $EXIT_CODE fi integer ua_deployment=0 if [[ -n $manifest ]]; then AIM_MANIFEST=$manifest \ aimanifest get /auto_install/ai_instance/software[@type=ARCHIVE] \ >/dev/null 2>&1 if (( $? == 0 )); then ua_deployment=1 fi if (( ua_deployment == 1 )); then # If the software type is ARCHIVE, read the archive information. # It will be needed later to determine what type of archive # is being deployed. typeset -A uar_props export AIM_MANIFEST=$manifest typeset archive_loc=$(aimanifest get \ "/auto_install/ai_instance/software[@type=ARCHIVE]/source/file@uri") if [[ -z $archive_loc ]]; then print "$f_aimanifest_get: No archive source found in" print "$manifest" exit $ZONE_SUBPROC_TRYAGAIN fi typeset -A zone.xopts=([cert]= [ca-cert]= [key]=) read_uar_info "$archive_loc" zone.xopts uar_props || exit $ZONE_SUBPROC_TRYAGAIN uar_creator=${!uar_props[archive][*]} fi else # Use default AI zone manifest if none is given manifest=/usr/share/auto_install/manifest/zone_default.xml fi # # So long as this is not a unified archive deployment: # - Add packages to AI zone manifest for TX zones if appropriate. # - Add entire package if installed in GZ # # The environment variable AIM_MANIFEST contains the file where all the # aimanifest changes will be made. The load operation loads that manifest # into the working file. The add operation adds the entries to the # working file. # if (( ua_deployment == 0 )) && ( (( brand_labeled == 0 )) || [[ -n $entire_fmri ]] ); then temp_manifest=$(mktemp -t manifest.xml.XXXXXX) if [[ -z $temp_manifest ]]; then print "$f_mktemp" exit $ZONE_SUBPROC_TRYAGAIN fi export AIM_MANIFEST=$temp_manifest aimanifest load $manifest if (( $? != 0 )); then print "$f_aimanifest_load" exit $ZONE_SUBPROC_TRYAGAIN fi if (( $brand_labeled == 0 )); then primary=$(tncfg -z $ZONENAME info primary 2>/dev/null) if [ $? != 0 ]; then print "$f_nolabel" exit $ZONE_SUBPROC_NOTCOMPLETE elif [ $primary = "primary=yes" ]; then labeled_pkg=pkg:/group/feature/trusted-desktop else labeled_pkg=pkg:/system/trusted fi aimanifest add \ /auto_install/ai_instance/software/software_data[@action="install"]/name \ $labeled_pkg if (( $? != 0 )); then print "$f_aimanifest_add" exit $ZONE_SUBPROC_TRYAGAIN fi fi if [[ -n $entire_fmri ]]; then aimanifest add \ /auto_install/ai_instance/software/software_data[@action="install"]/name \ pkg:///$entire_fmri if (( $? != 0 )); then print "$f_aimanifest_add" exit $ZONE_SUBPROC_TRYAGAIN fi fi manifest=$temp_manifest fi # # Before installing the zone, set up ZFS dataset for the zone root dataset, # but don't create rpool/ROOT or rpool/export hierarchies since installer # will create them. Sets EXIT_CODE if datasets are created. # create_active_ds -r zone || fatal "$f_no_ds" # # Set up the AI install. Check to see if the installation includes # a recovery archive, and do not use enable_sci.xml if it is. # If it is a clone archive, then including enable_sci.xml is appropriate. # # If unconfig service is online, then call auto-install with the default # profile or with the caller supplied profile. # If unconfig service is offline or doesn't exist, then don't pass # any profile to auto-install since this will cause SCI tool to start in # zone on boot. Previous sysconfig method handled below after install. # SC_ONLINE=$(svcprop -p restarter/state \ svc:/milestone/unconfig:default 2> /dev/null) set -A aicmd /usr/bin/auto-install -z "$ZONENAME" -Z "${zone.rpool_ds}" \ -m "$manifest" if (( $? == 0 )) && [[ $SC_ONLINE == "online" ]]; then if [[ -n $sc_config ]]; then # Do not quote $OPT_C as it should be "-c " a_push aicmd $OPT_C elif (( $brand_labeled == 0 )); then labeled_makeSCprofile a_push aicmd -c $temp_scprofile elif (( ua_deployment == 0 )) || [[ ${uar_props[archive][$uar_creator][recovery]} == No ]]; then a_push aicmd -c \ /usr/share/auto_install/sc_profiles/enable_sci.xml fi fi # # Run auto-install, saving the output in the log file. Tricks are needed # so that we can check the exit value from auto-install rather than the exit # value from tee. # vlog "$m_ai_running" "${aicmd[*]}" "${aicmd[@]}" || fail_fatal "$f_autoinstall" if [[ -n $temp_manifest ]]; then rm $temp_manifest fi if [[ -n $temp_scprofile ]]; then rm $temp_scprofile fi log "\n$m_mannote\n" log "$m_done\n" # # If unconfig service is offline or doesn't exist, then use # previous sysconfig method since that is still being used by the # zone. Copy sysidcfg file if given, but only copy if it isn't the # new SC file enable_sci.xml. The enable_sci.xml file causes # sysid to generate warnings in a zone. # mount_active_be -c zone || fail_fatal "$f_mount_active_be" if [[ $SC_ONLINE != "online" ]]; then touch $ZONEROOT/etc/.UNCONFIGURED if [[ -n $sc_config ]] && [[ $sc_config != \ "/usr/share/auto_install/sc_profiles/enable_sci.xml" ]]; then cp $sc_config $ZONEROOT/etc/sysidcfg fi fi # # Labeled zones need to be able to modify /etc/gconf files, when gnome # packages are installed in the zone. Set up links in the zone to the # global zone files -- this will provide default versions from the global # zone, which can be modified by the zone, breaking the link. if (( $brand_labeled == 0 )); then if [ -d /etc/gconf ]; then cd /etc/gconf for i in $(find .); do if [ ! -e $ZONEROOT/etc/gconf/$i ]; then if [ -d $i ]; then mkdir $ZONEROOT/etc/gconf/$i else ln -s /etc/gconf-global/$i \ $ZONEROOT/etc/gconf/$i fi fi done fi fi log "$m_complete_seconds\n\n" ${SECONDS} if (( $brand_labeled != 0 )); then log "$m_postnote\n" log "$m_postnote2\n" else labeled_configure fi finish_log zone trap - EXIT exit $ZONE_SUBPROC_OK