#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2013, 2015, 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 m_usage=$(gettext "\n install -h\n install [-a archive | -m manifest] [-c profile] [-C install-env-profile] [-b isopath ] [-x no-auto-shutdown] [-x install-size=] [-x force-zpool-create=]\n") f_ai_pub_proxy=$(gettext "publisher %s: proxy URI not supported for install") f_ai_pub_badtype=$(gettext "publisher %s: unknown type") f_aimanifest_load=$(gettext "Unable to aimanifest load.") f_aimanifest_uar_missing=$(gettext "ARCHIVE specified in manifest, not found.") f_cp_failed=$(gettext "Failed to copy %s to %s") f_pkg_no_incs=$(gettext "unable to find installed incorporations") f_bad_opt_no_auto_shutdown=$(gettext "Option -x no-auto-shutdown is only valid with -a or -b option") f_bad_opt_combo=$(gettext "Options -%s and -%s are mutually exclusive") f_bad_opt_ie_config=$(gettext "Option -C is only valid with -a or -b") f_no_uar_media=$(gettext "Archived zone %s has no AI media") f_uar_nonroot=$(gettext "Archive contains non-root data, please use [-m manifest]") f_uar_nonroot_err=$(gettext "Unable to determine archived data streams") f_initialize_hostdata=$(gettext "Failed to initialize host data") f_rootpool_from_manifest=$(gettext "Failed to get root zpool name from manifest") f_unknown_arch=$(gettext "Unknown arch %s") m_ai_pub_disabled=$(gettext "skipping publisher %s: disabled") m_ai_pub_offline=$(gettext "skipping publisher %s: offline") m_ai_pub_no_origin=$(gettext "skipping publisher %s: no origin") m_cache=$(gettext "pkg cache: Using %s.") e_zpool_export=$(gettext "failed to export zpool %s.") e_zfs_mount=$(gettext "failed to mount zpool filesystem %s.") function cleanup { if [[ -z $EXIT_CODE ]]; then fail_internal "EXIT_CODE not set" fi if [[ -n $BRAND_SKIP_CLEANUP ]]; then vlog "Exiting with exit code $EXIT_CODE (skipping cleanup)" finish_log zone exit $EXIT_CODE fi if [[ $EXIT_CODE == $ZONE_SUBPROC_OK ]]; then typeset destroy=false else typeset destroy=true fi cleanup_storage zone $destroy if (( $? == 0 )) && [[ $EXIT_CODE == $ZONE_SUBPROC_FATAL ]]; then EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN fi fini_tmpdir vlog "Exiting with exit code $EXIT_CODE" finish_log zone } function trap_cleanup { log "$f_interrupted" cleanup exit $EXIT_CODE } function trap_exit { vlog "Performing cleanup on exit" cleanup exit $EXIT_CODE } function aim_precheck_manifest { typeset t_manifest=$1 export AIM_MANIFEST=$t_manifest # If manifest has any disk specified, fail. if aimanifest get "auto_install/ai_instance/target/disk[1]" \ >/dev/null 2>&1; then fatal "$f_ai_manifest_has_disk" fi } # # Creates a given node (or attribute if $node@attr) if missing and ensures the # value matches the optional second argument. If the second argument is not # specified, the value is not compared. # function aim_add_set { export AIM_MANIFEST typeset path=$1 typeset value=$2 # Optional typeset curval curval=$(aimanifest get -- "$path" 2>&1) if (( $? == 0 )); then if (( $# > 1 )) && [[ $curval != "$value" ]]; then aimanifest set -- "$path" "$value" >/dev/null || fatal "$f_ai_manifest_set" "$path" fi return fi # If it is a property that's being added and the parent element does not # exist, add the parent element first. if [[ "$path" == *@* ]]; then typeset elem=${path%@*} if ! aimanifest get -- "$elem" >/dev/null 2>&1; then typeset newelem newelem=$(aimanifest add -r -- \ "${elem%\[@([0-9]*)\]}" "") if (( $? != 0 )) || [[ $elem == *\[@([0-9]*)\] && $newelem != "$elem" ]]; then error "$f_ai_manifest_add" "$elem" fatal "$f_ai_manifest_set" "$path" fi fi aimanifest set -- "$path" "$value" >/dev/null 2>&1 || fatal "$f_ai_manifest_add" "$path" else aimanifest add -- "$path" "$value" >/dev/null 2>&1 || fatal "$f_ai_manifest_add" "$path" fi } function aim_setpub { typeset pubno=$1 publisher=$2 origin=$3 element=$4 instance=$5 sticky=$6 # These are files in the global zone. Their contents get added to the # manifest. typeset key=$7 cert=$8 set -- $(aimanifest get -r \ /auto_install/ai_instance/software[@type=IPS]/source) typeset sw_src=$2 typeset sw_pub=$sw_src/publisher[$pubno] # # Add publisher node # aim_add_set "$sw_pub@name" "$publisher" # # Add instance node # aim_add_set "$sw_pub/${element}[$instance]@name" "$origin" # # Add credentials, credentials/key, and credentials/cert # if [[ $origin == ~(i:https:*) ]] && [[ -n $key || -n $cert ]]; then typeset cred=$sw_pub/credentials aim_add_set "$cred" [[ -n $key ]] && aim_add_set "$cred/key" "$(cat "$key")" [[ -n $cert ]] && aim_add_set "$cred/cert" "$(cat "$cert")" fi # # Add cmd_options # if [[ $sticky != true ]]; then aim_add_set "$sw_pub/cmd_options" --non-sticky fi } function aim_addpkg { typeset pkgno=$1 pkg=$2 set -- $(aimanifest get -r \ /auto_install/ai_instance/software/software_data) typeset sw_data=$2 typeset sw_pkg_num=$sw_data/name[$pkgno] if aimanifest get "$sw_pkg_num" >/dev/null 2>&1; then aimanifest set "$sw_pkg_num" "$pkg" >/dev/null || fatal "$f_ai_manifest_set" "$sw_pkg_num" else aimanifest add "$sw_data/name" "$pkg" >/dev/null || fatal "$f_ai_manifest_add" "$sw_pkg_num" fi } function aim_setfacet { typeset facet=$1 value=$2 set -- $(aimanifest get -r \ /auto_install/ai_instance/software/destination/image) typeset sw_image=$2 typeset path path=$(aimanifest add -r "$sw_image/facet" "$facet" 2>/dev/null) || fatal "$f_ai_manifest_add" "$sw_image/facet" aimanifest set "$path@set" "$value" >/dev/null || fatal "$f_ai_manifest_set" "$path@set" } # Add disk and disk elements. For example: # # # # # # # # function aim_add_disk { typeset t_manifest=$1 typeset rpoolname=$2 typeset id disk typeset disk_elem dev name_type export AIM_MANIFEST=$t_manifest for id in ${!zone.boot_disks[@]}; do disk_elem=$(aimanifest add -r target/disk@whole_disk "true" \ 2>/dev/null) || fatal "$f_ai_manifest_add" "target/disk@whole_disk" dev= name_type= # Specify that disk as part of a mirrored root pool. aimanifest set "$disk_elem@in_zpool" "$rpoolname" >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/disk_name" aimanifest set "$disk_elem@in_vdev" mirrored >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/disk_name" if [[ -n ${zone.boot_disks[$id][lofi]} ]]; then dev=${zone.boot_disks[$id][lofi]} else dev=${zone.boot_disks[$id][dev]} fi if [[ $dev == /dev/*dsk/c*d* ]]; then dev=$(basename "$dev") name_type=ctd fi aimanifest add "$disk_elem/disk_name@name" "$dev" >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/disk_name" if [[ -n $name_type ]]; then aimanifest set "$disk_elem/disk_name@name_type" \ "$name_type" >/dev/null || fatal "$f_ai_manifest_add" \ "$disk_elem/disk_name@name_type" fi # Set the vdev_label for this disk so that the installer updates # the metadata in the zpool created from this disk with values # the guest will see it as. aimanifest add "$disk_elem/vdev_label@ctd" "c1d$id" \ >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/vdev_label@ctd" aimanifest set "$disk_elem/vdev_label@devid" "" >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/vdev_label@devid" case $(uname -p) in i386) disk="/zvnex/zvblk@$id" ;; sparc) disk="/kz-devices@ff/disk@$id" ;; *) fatal "$f_unknown_arch" $(uname -p) ;; esac aimanifest set "$disk_elem/vdev_label@devpath" \ "$disk" >/dev/null || fatal "$f_ai_manifest_add" "$disk_elem/vdev_label@devpath" done typeset vdev_elem vdev_elem=$(aimanifest add -r target/logical[1]/zpool[1]/vdev@name \ mirrored 2>/dev/null) || fatal "$f_ai_manifest_add" "target/logical/zpool/vdev" aimanifest set "$vdev_elem@redundancy" mirror >/dev/null || fatal "$f_ai_manifest_add" "$vdev_elem@redundancy" } function aim_set_boot_mods { typeset t_manifest=$1 typeset arch=$(uname -p) export AIM_MANIFEST=$t_manifest typeset boot_mods_elem=$(aimanifest get -r "boot_mods" 2>/dev/null) if [[ -z $boot_mods_elem ]] ; then boot_mods_elem=$(aimanifest add -r "boot_mods" "" \ 2>/dev/null) || fatal "$f_ai_manifest_add" "boot_mods" else set -- $boot_mods_elem boot_mods_elem=$2 fi # Set guest's firmware type into boot_mods element # On x86 we have zvboot for kernel zone but on SPARC we just use OBP # as usual if [[ $arch == "i386" ]]; then aimanifest set "$boot_mods_elem@firmware" "zvmm" >/dev/null || \ fatal "$f_ai_manifest_set" "$boot_mods_elem@firmware" fi } function aim_set_swap_dump { typeset t_manifest=$1 export AIM_MANIFEST=$t_manifest # Add a swap zvol if manifest does not specify 'noswap' or if 'noswap' # is false, and explicit swap zvol not already specified. typeset noswap=$(aimanifest get target/logical@noswap 2>/dev/null) if [[ -z $noswap || $noswap == false ]] ; then if ! aimanifest get \ "logical/zpool/zvol[@use=swap]@name" >/dev/null 2>&1; then swap_zvol=$(aimanifest add -r \ "logical/zpool[@is_root=true]/zvol@name" swap \ 2>/dev/null) || fatal "$f_ai_manifest_add" "swap zvol" aimanifest set "$swap_zvol@use" "swap" >/dev/null || fatal "$f_ai_manifest_set" "$swap_zvol@use" aimanifest add "$swap_zvol/size@val" "1G" >/dev/null || fatal "$f_ai_manifest_add" "$swap_zvol/size" fi fi # Add a dump zvol if manifest does not specify 'nodump' or if 'nodump' # is false, and explicit dump zvol not already specified. typeset nodump=$(aimanifest get target/logical@nodump 2>/dev/null) if [[ -z $nodump || $nodump == false ]] ; then if ! aimanifest get \ "logical/zpool/zvol[@use=dump]@name" >/dev/null 2>&1; then dump_zvol=$(aimanifest add -r \ "logical/zpool[@is_root=true]/zvol@name" dump \ 2>/dev/null) || fatal "$f_ai_manifest_add" "dump zvol" aimanifest set "$dump_zvol@use" "dump" >/dev/null || fatal "$f_ai_manifest_set" "$dump_zvol@use" aimanifest add "$dump_zvol/size@val" "1G" >/dev/null || fatal "$f_ai_manifest_add" "$dump_zvol/size" fi fi } # # There is a maximum of one cert and one key set per publisher. This function # looks for them and returns the file names that contain the cert and key. # function get_ssl_params { typeset publisher=$1 typeset -n key=$2 typeset -n cert=$3 key= cert= typeset var val LC_ALL=C $PKG publisher "$publisher" 2>/dev/null | while IFS=: read var val; do var=${var// } val=${val// } [[ $var == @(SSLKey|SSLCert) ]] || continue [[ $val == None ]] && continue if [[ $var == SSLKey ]]; then key=$val else cert=$val fi [[ -n $key && -n $cert ]] && return done } # # Add all of the global zone's publishers to the AI manifest. If the second # argument is "true", the global zone publishers are added if and only if there # are no publishers defined. # function add_gz_publishers { typeset manifest=$1 typeset add_only=${2:-false} [[ -z $manifest || ! -f $manifest ]] && fail_internal "invalid manifest: (%s)" "$manifest" [[ $manifest == /usr/share/auto_install/* ]] && fail_internal "trying to modify system manifest (%s)" "$manifest" [[ $add_only == @(true|false) ]] || fail_internal "invalid add_only (%s)" "$add_only" # If the manifest lacks a node, add it. typeset swnode=/auto_install/ai_instance/software AIM_MANIFEST=$manifest aimanifest get $swnode[@type=IPS] >/dev/null 2>&1 if (( $? != 0 )); then typeset ipsnode ipsnode=$(AIM_MANIFEST=$manifest aimanifest add -r "$swnode" "") [[ -z $ipsnode ]] && fatal "$f_ai_manifest_add" "$swnode" AIM_MANIFEST=$manifest aimanifest set "$ipsnode@type" IPS \ >/dev/null || fatal "$f_ai_manifest_set" "$ipsnode@type" fi AIM_MANIFEST=$manifest aimanifest get $swnode[@type=IPS]/source \ >/dev/null 2>&1 if (( $? != 0 )); then AIM_MANIFEST=$manifest aimanifest add \ "$swnode[@type=IPS]/source" "" >/dev/null || fatal "$f_ai_manifest_add" "$swnode[@type=IPS]/source" fi if [[ $add_only == true ]]; then # If any publishers are defined, do not add the global zone # publishers. aimanifest get \ '/auto_install/ai_instance/software[@type=IPS]/source/publisher[1]' \ >/dev/null 2>&1 if (( $? == 0 )); then return 0 fi fi # In XML, lists are indexed with first element 1, not 0. typeset -i i=1 # For keeping track of publishers with multiple origins, mirrors. typeset -A publishers typeset publisher sticky syspub enabled type status origin proxy junk LC_ALL=C $PKG publisher -HnF tsv | while IFS=$'\t' read publisher sticky syspub enabled type status \ origin proxy junk; do # # Sanity check the publishers, taking into account that AI # isn't able to cope with all of pkg(5)'s publisher settings. # # - Reject any type other than origin and mirror # - Reject any proxy configuration, whether through # the system repository or a per-origin proxy. # - Skip any disabled publishers # - Skip any offline publishers # - Skip any publishers with no origin # # Extra fields are ignored. # if [[ $origin == @(|-) ]]; then vlog "$m_ai_pub_no_origin" "$publisher" continue fi if [[ $type != @(origin|mirror) ]]; then fail_fatal "$f_ai_pub_badtype" "$publisher" "$type" continue fi if [[ $origin == proxy://* || $proxy != @(|-) ]]; then fail_fatal "$f_ai_pub_proxy" "$publisher" continue fi if [[ $enabled != true ]]; then vlog "$m_ai_pub_disabled" "$publisher" continue fi if [[ $status != online ]]; then vlog "$m_ai_pub_offline" "$publisher" continue fi # # Keep track of the number of origins and mirrors seen for this # publisher. # if [[ -z ${publishers[$publisher]} ]]; then typeset -i publishers[$publisher].index=$i typeset -i publishers[$publisher].origin=0 typeset -i publishers[$publisher].mirror=0 # Next publisher index in the AI manifest (( i++ )) fi typeset -n instance=publishers[$publisher].$type (( instance++ )) if [[ -z ${publishers[$publisher].key} ]]; then typeset key cert get_ssl_params "$publisher" key cert publishers[$publisher].key=$key publishers[$publisher].cert=$cert fi # Update the AI manifest AIM_MANIFEST="$manifest" aim_setpub \ ${publishers[$publisher].index} "$publisher" \ "$origin" "$type" "$instance" "$sticky" \ "${publishers[$publisher].key}" \ "${publishers[$publisher].cert}" done return 0 } function create_manifest { typeset in_manifest=$1 typeset -n out_manifest=$2 new_manifest=$TMPDIR/devel-ai-manifest.xml export AIM_MANIFEST=$new_manifest # Load in the default manifest aimanifest load "$in_manifest" || fatal "$f_aimanifest_load" # Set publishers in manifest to match global zone. add_gz_publishers "$new_manifest" || fail_internal "add_gz_publishers failed" # # Set packages in manifest. The default manifest has entire and # solaris-large-server, which will be overwritten by these # updates. We update the auto-install manifest to install any # package in the global zone which has a core-os* install-hold, # this normally includes entire and all incorporation packages. # typeset -a incs set -A incs $($PKG search -Ho pkg.fmri -l \ ":set:pkg.depend.install-hold:core-os*") [[ -z "$incs" ]] && fail_fatal "$f_pkg_no_incs" i=1 aim_addpkg $i pkg:/group/system/solaris-small-server typeset fmri junk $PKG list -Hv "${incs[@]}" | while read fmri junk; do (( i++ )) aim_addpkg $i $fmri done # # Propagate any version locks that are relevant to installed # incorporations. # typeset -A facets typeset facet pkg typeset -l value $PKG facet -HF tsv | while IFS=$'\t' read facet value junk; do facets[$facet]=$value done for pkg in ${incs[@]//@(pkg:\/|@*)/}; do facet=facet.version-lock.$pkg [[ -z ${facets[$facet]} ]] && continue aim_setfacet "$facet" "${facets[$facet]}" done out_manifest=$AIM_MANIFEST } function auto_install { typeset manifest=$1 typeset config=$2 # If there is a cache, use it. if [[ -f /var/pkg/pkg5.image && -d /var/pkg/publisher ]]; then # respect PKG_CACHEROOT if the caller has it set. [[ -z "$PKG_CACHEROOT" ]] && export PKG_CACHEROOT=/var/pkg/publisher log "$m_cache" "$PKG_CACHEROOT" fi /usr/bin/auto-install -L -m "$manifest" -c "$config" || fatal "$f_ai" } function export_zpool { typeset pool=$1 # # A zpool that was just imported will often be busy on the first export # try. While zfs`spa_export_common() tries to force a sync to clear # refs to the pool, it's not always sufficient. Other things can cause # a pool to be transiently busy too - for instance 'zfs list' briefly # takes a hold on each dataset, which in turn takes a hold on the pool. # Enlightenment may come from stacks leading to zfs`spa_open_ref(). # typeset -i try for (( try=1; try <= 5; try++ )); do zpool export "$pool" && break vlog "Failed to export zpool %s on try %d." "$pool" $try if (( try == 5 )); then error "$e_zpool_export" "$pool" return 1 else sleep $try fi done return 0 } function build_dev_tree { typeset rpool_dir=$1 find $(cat /usr/lib/brand/solaris-kz/dev.filelist) \ -print 2> /dev/null | cpio -pdum "$rpool_dir" } # Set to ZONE_SUBPROC_TRYAGAIN so that usage error doesn't force uninstall. 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 PKG=/usr/bin/pkg unset archive unset install_media unset sc_config unset ie_config unset manifest unset uafs_mntpt # brand specific list of -x suboptions and their suboption arguments typeset -A x_opts=([install-size]= [cert]= [ca-cert]= [key]= [force-zpool-create]= [storage-create-missing]=) # See init_tmpdir() and fini_tmpdir() cleanup_tmpdir=false unset debug unset no_auto_shutdown umask 0022 while getopts "a:b:C:c:dhm:R:vx:Z:z:" opt; do case $opt in a) archive=$(mk_abs_path $OPTARG) ;; b) install_media=$(mk_abs_path $OPTARG) ;; C) ie_config=$(mk_abs_path $OPTARG) ;; c) sc_config=$(mk_abs_path $OPTARG) ;; d) debug=-d ;; h) fail_usage "";; m) manifest=$(mk_abs_path $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)) if [[ -z ${x_opts[install-size]} ]]; then zvol_size="16G" else zvol_size=${x_opts[install-size]} fi if [[ -n "$@" ]]; then fail_usage "" fi if [[ -z $ZONEPATH || -z $ZONENAME ]]; then fail_usage "Brand error: No zone path or name" fi if [[ -n $archive && -n $install_media ]]; then fail_usage "$f_bad_opt_combo" a b fi if [[ -n $archive && -n $manifest ]]; then fail_usage "$f_bad_opt_combo" a m fi if [[ -n "$install_media" ]] && [[ ! -r "$install_media" ]]; then fail_usage "$e_not_found" "$install_media" fi if [[ -n "$manifest" ]] && [[ ! -r "$manifest" ]]; then fail_usage "$e_not_found" "$manifest" fi if [[ -n $no_auto_shutdown && -z $archive && -z $install_media ]]; then fail_usage "$f_bad_opt_no_auto_shutdown" fi if [[ -n "$ie_config" ]] && [[ -z "$archive" ]] && [[ -z "$install_media" ]]; then fail_usage "$f_bad_opt_ie_config" fi check_sc_config "$sc_config" check_sc_config "$ie_config" EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN zone= init_zone zone "$ZONENAME" "$ZONEPATH" typeset -A zone.xopts for key in "${!x_opts[@]}"; do zone.xopts[$key]=${x_opts[$key]} done eval $(bind_legacy_zone_globals zone) # Sets TMPDIR to a safe directory specific to this script. init_tmpdir start_log zone install "${save_args[@]}" export AIM_LOGFILE=$ZONEADM_LOGFILE trap trap_exit EXIT # If a manifest was passed, check to see if it points at a unified # archive. If it does, set our $archive so that it gets handled # properly below. We will ultimately mount and install it as with any # other archive. if [[ -n $manifest ]] ; then typeset -i i=1 # In XML, lists are indexed with first element 1, not 0 typeset ai_inst="auto_install/ai_instance" typeset sw_type="$ai_inst/software@type" export AIM_MANIFEST=$manifest aimanifest get "$sw_type" 2>/dev/null | while read transfer_type; do if [[ $transfer_type == ARCHIVE ]] ; then uri="$ai_inst/software[$i]/source/file@uri" archive=$(aimanifest get "$uri" 2>/dev/null) if (($? != 0)) || [[ -z $archive ]] ; then fatal "$f_aimanifest_uar_missing" fi break fi let i++ done fi # For non-media/non-archive installs where an AI manifest is provided, # precheck the manifest. It must not contain target specification(s). if [[ -n $manifest && -z $install_media && -z $archive ]]; then aim_precheck_manifest "$manifest" fi # When installing from a unified archive, the boot media is found in the # archive. uafs, a uvfs file system module, is used to mount the archive into # the guest's shared folder. if [[ -n $archive ]]; then typeset -A uarinfo read_uar_info "$archive" x_opts uarinfo if [[ -z $archived_zone ]]; then if (( ${#uarinfo[system][@]} != 1 )); then fatal "$e_specify_zone" "${!uarinfo[system][*]}" fi archived_zone=${!uarinfo[system][@]} fi archive_aimedia=${uarinfo[system][$archived_zone][ai_media]} if [[ -z $archive_aimedia ]]; then # In the future this should trigger looking at Live Install fatal "$f_no_uar_media" "$archived_zone" fi # When deploying from an archive, ensure that we've been # passed a manifest if the archive contains non-root data. AI # requires a target specification in the manifest in this case; # we will not automate the selection of non-root targets. if [[ -z $manifest ]] ; then root_only=${uarinfo[system][$archived_zone][root_only]} if [[ $root_only == No ]] ; then fatal "$f_uar_nonroot" elif [[ $root_only != Yes ]] ; then # Unexpected value in output fatal "$f_uar_nonroot_err" fi fi # The guest requires an AI manifest that references the OVA # file from its perspective. Either update the manifest passed # in or create a new one. Since zone.ua_archived_zone is set, # prep_ua_manifest will not try to open the archive. if [[ -z $manifest ]] ; then # If no manifest was passed in, work from a default manifest="/usr/share/auto_install/manifest/default_archive.xml" fi zone.ua_archived_zone=$archived_zone prep_ua_manifest -m "$manifest" \ -g /system/shared/uafs/OVA zone "$archive" manifest || exit aim_set_swap_dump "$manifest" # If this is a nonglobal-to-global deployment, set the host gz # publishers in the manifest for the transformed image to use. brand=${uarinfo[system][$archived_zone][brand]} if [[ $brand == solaris && $archived_zone != global ]] ; then add_gz_publishers "$manifest" true fi fi if [[ -z "$install_media" && -z $archive ]]; then # Any value (including not set) other than true means false zone.direct_install=true fi get_install_disks zone # If "-x force-zpool-create=" is not used, ensure that the boot disks # are not already in use. typeset rootpool if [[ -n $manifest ]]; then rootpool=$(env AIM_MANIFEST="$manifest" \ aimanifest get 'target/logical/zpool[@is_root="true"]@name') || fatal "$f_rootpool_from_manifest" fi [[ -z $rootpool ]] && rootpool=rpool if [[ ${x_opts[force-zpool-create]} == $rootpool ]]; then zone.force_create_rootpool=true else check_bootdisks_inuse zone "$rootpool" fi # By default, kernel zones use storage from # /VARSHARE/zones/. If this zone needs anything from there, # set it up. create_storage zone if [[ ${zone.direct_install} != true ]]; then set -A args -- -z "$ZONENAME" -R "$ZONEPATH" [[ -n $install_media ]] && a_push args -b "$install_media" [[ -n $archive ]] && a_push args -a "$archive" [[ -n $archive_aimedia ]] && a_push args -A "$archive_aimedia" [[ -n $archived_zone ]] && a_push args -Z "$archived_zone" [[ -n $manifest ]] && a_push args -m "$manifest" [[ -n $sc_config ]] && a_push args -c "$sc_config" [[ -n $ie_config ]] && a_push args -C "$ie_config" [[ -n $OPT_V ]] && a_push args -v [[ -n $debug ]] && a_push args -d [[ -n $no_auto_shutdown ]] && a_push args -x "$no_auto_shutdown" for param in key cert ca-cert; do [[ -n ${x_opts[$param]} ]] && a_push args -x "$param=${x_opts[$param]}" done # Call media_install in a way that cleanup happens properly. Note # that if this were exec'd, cleanup() wouldn't be called and we may # leave behind temporary files. In the case of failure, we may want # cleanup to remove datasets created above as well. /usr/lib/brand/solaris-kz/media_install "${args[@]}" EXIT_CODE=$? exit $EXIT_CODE fi # When testing the device creation aspects of install, there's no real need # to do the install. Save a bunch of time and bail before doing long-running # tasks. if [[ -n $DEBUG_SKIP_INSTALL ]]; then log "WARNING: DEBUG_SKIP_INSTALL=%s; installation not performed" \ "$DEBUG_SKIP_INSTALL" EXIT_CODE=$ZONE_SUBPROC_OK cleanup finish_log zone trap - EXIT exit $ZONE_SUBPROC_OK fi if [[ -z $manifest ]]; then create_manifest /usr/share/auto_install/manifest/default.xml manifest [[ -n $manifest && -f $manifest ]] || fail_internal "manifest not created" [[ -z "${zone.boot_disks[*]}" ]] && fatal "No bootable disks in zone configuration" aim_add_disk "$manifest" "$rootpool" else cp "$manifest" $TMPDIR/devel-ai-manifest.xml || fatal "$f_cp_failed" "$manifest" $TMPDIR/devel-ai-manifest.xml manifest=$TMPDIR/devel-ai-manifest.xml add_gz_publishers "$manifest" true aim_add_disk "$manifest" "$rootpool" fi aim_set_boot_mods "$manifest" aim_set_swap_dump "$manifest" vlog "Updated manifest %s" "$manifest" vlog "-------------------------\n%s\n-------------------------" \ "$(cat "$manifest")" if [[ -z $sc_config ]]; then sc_config=/usr/share/auto_install/sc_profiles/enable_sci.xml fi auto_install "$manifest" "$sc_config" # Initialize hostdata. zoneadm -z "$ZONENAME" attach -x initialize-hostdata-incomplete || fatal "$f_initialize_hostdata" EXIT_CODE=$ZONE_SUBPROC_OK log "$m_complete\n\n" ${SECONDS} cleanup finish_log zone trap - EXIT exit $ZONE_SUBPROC_OK