#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. # . /usr/lib/brand/solaris/common.ksh # To use destroy_zone_datasets zone to destroy orphan ZBE on attach. . /usr/lib/brand/shared/uninstall.ksh # Allows developer to override some things like PATH and PYTHONPATH . /usr/lib/brand/solaris/developerenv.ksh # m_usage is used by fail_usage() m_usage=$(gettext "Usage:\n\t attach [-uv] [-a archive | -d directory | -z zbe]\n\t\t[-c profile.xml | dir] [-x attach-last-booted-zbe|\n\t\t\tforce-zbe-clone|deny-zbe-clone|destroy-orphan-zbes]\n\n\t-u\tUpdate the software in the attached zone boot environment to\n\t\tmatch the sofware in the global zone boot environment.\n\t-v\tVerbose.\n\t-c\tUpdate the zone configuration with the sysconfig profile\n\t\tspecified in the given file or directory.\n\t-a\tExtract the specified archive into the zone then attach the\n\t\tactive boot environment found in the archive. The archive\n\t\tmay be a zfs, cpio, or tar archive. It may be compressed with\n\t\tgzip or bzip2.\n\t-d\tCopy the specified directory into a new zone boot environment\n\t\tthen attach the zone boot environment.\n\t-z\tAttach the specified zone boot environment.\n\t-x\tattach-last-booted-zbe\t: Attach the last booted zone boot\n\t\t\t\t\t environment.\n\t\tforce-zbe-clone\t\t: Clone zone boot environment\n\t\t\t\t\t on attach.\n\t\tdeny-zbe-clone\t\t: Do not clone zone boot environment\n\t\t\t\t\t on attach.\n\t\tdestroy-orphan-zbes\t: Destroy all orphan zone boot\n\t\t\t\t\t environments. (not associated with\n\t\t\t\t\t any global BE)") m_use_install=$(gettext "Warning: The -a and -d options to the attach subcommand may be removed in a\nfuture release of Solaris. Use of the install subcommand is recommended.") m_failed=$(gettext " Result: Attach Failed.") e_dataset_not_in_be=$(gettext "Dataset %s mountpoint %s is not under zone root %s") f_multiple_extractions=$(gettext "Zone already has one or more extracted zone boot environments.\nUse 'zoneadm -z attach -z ' to attach an existing zbe.\n") f_bad_opt_combo=$(gettext "incompatible options -%s and %-s") f_repeated_opt=$(gettext "repeated option -%s") # Clean up on interrupt trap_cleanup() { trap - INT log "$m_interrupt" # umount any mounted file systems umnt_fs trap_exit } # If the attach failed then clean up the ZFS datasets we created. trap_exit() { # # Since trap_int calls trap_exit we need to cancel the exit # handler so that we don't do two passes. # trap - INT EXIT if [[ -n $EXIT_NOEXECUTE ]]; then # dryrun mode, nothing to do here; exit with whatever # EXIT_CODE is set to. ; elif [[ $EXIT_CODE == $ZONE_SUBPROC_USAGE ]]; then # Usage message printed, nothing to do here. ; elif [[ $EXIT_CODE == @($ZONE_SUBPROC_OK|$ZONE_SUBPROC_UNAVAILABLE) ]] then # unmount the zoneroot if labeled brand is_brand_labeled && ( umount $ZONEROOT || \ log "$f_zfs_unmount" "$ZONEPATH/root" ) unpin_datasets "${zone.path.ds}" || error "$f_unpin" elif [[ $EXIT_CODE == $ZONE_SUBPROC_TRYAGAIN ]]; then unpin_datasets "${zone.path.ds}" || error "$f_unpin" log "$m_failed" else # Remove datasets that shouldn't exist delete_unpinned_datasets "${zone.path.ds}" && EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN unpin_datasets "${zone.path.ds}" || error "$f_unpin" log "$m_failed" fi vlog "Exiting with exit code $EXIT_CODE" finish_log zone exit $EXIT_CODE } EXIT_CODE=$ZONE_SUBPROC_USAGE install_media="-" # Will be used by start_log after option processing set -A save_args "$0" "$@" # If we weren't passed at least two arguments, exit now. (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE zone= init_zone zone "$1" "$2" # Set ZONEPATH, etc. eval $(bind_legacy_zone_globals zone) shift; shift # remove ZONENAME and ZONEPATH from arguments array allow_update=none noexecute=0 typeset -A opts # Used in option compatibility checks. unset inst_type unset sc_config # Get publisher information for global zone. These structures are used # to store information about the global zone publishers and # incorporations. typeset gz_incorporations="" # Valid -x options for attach operation typeset -A zone.xopts=([$ATTACH_LAST_BOOTED_ZBE]= [$DENY_ZBE_CLONE]= [$FORCE_ZBE_CLONE]= [$DESTROY_ORPHAN_ZBES]= [$FORCE_ZPOOL_IMPORT]=) # # If extracting an archive that contains multiple zbes, it is possible that # we won't be able to automatically select which zbe to set as the active # zbe. In such a case, discover_active_be() will suggest the use of this # command. It may be augmented in getopts processing. # set -A ATTACH_Z_COMMAND zoneadm -z "${zone.name}" attach -z "" # Other brand attach options are invalid for this brand. verbose= while getopts "a:c:d:n:Uuvz:x:" opt; do opts[$opt]=1 case $opt in a) # If the path is automounted, [[ -f ... ]] does not # trigger a mount so we may get a false error. ls "$OPTARG" >/dev/null 2>&1 [[ -f $OPTARG ]] || fatal "$f_arg_not_file" "$OPTARG" inst_type="archive" install_media="$OPTARG" ;; c) ls "$OPTARG" >/dev/null 2>&1 [[ -f $OPTARG ]] || [[ -d $OPTARG ]] || fatal "$f_arg_not_file_or_dir" "$OPTARG" sc_config="$OPTARG" a_push ATTACH_Z_COMMAND -c "$OPTARG" ;; d) # If the path is automounted, [[ -d ... ]] does not # trigger a mount so we may get a false error. ls "$OPTARG" >/dev/null 2>&1 [[ -d $OPTARG ]] || fatal "$f_arg_not_dir" "$OPTARG" inst_type="directory" install_media="$OPTARG" ;; n) noexecute=1 EXIT_NOEXECUTE=1 dryrun_mfst=$OPTARG ;; u) [[ $allow_update == all ]] && \ fatal "$f_bad_opt_combo" u U [[ $allow_update == min ]] && \ fatal "$f_repeated_opt" u allow_update=min a_push ATTACH_Z_COMMAND -u ;; U) [[ $allow_update == min ]] && \ fatal "$f_bad_opt_combo" u U [[ $allow_update == all ]] && \ fatal "$f_repeated_opt" U allow_update=all a_push ATTACH_Z_COMMAND -U ;; v) verbose=-v OPT_V=1 # used for vlog() ;; z) inst_type=zbe install_media="$OPTARG" ;; x) process_xopt zone.xopts "$OPTARG" # Check if valid x opts used. [[ -n ${zone.xopts[$FORCE_ZBE_CLONE]} ]] && \ [[ -n ${zone.xopts[$DENY_ZBE_CLONE]} ]] && \ fail_usage "$f_invalid_xopt" $FORCE_ZBE_CLONE $DENY_ZBE_CLONE ;; ?) fail_usage "" ;; esac done shift $((OPTIND-1)) # Configuration profile file must have .xml suffix if [[ -f $sc_config && $sc_config != *.xml ]]; then fail_usage "$f_scxml" "$sc_config" fi if [[ -n ${opts[a]} && -n ${opts[d]} ]]; then fail_usage "$f_incompat_options" a d fi if [[ -n ${opts[a]} && -n ${opts[z]} ]]; then fail_usage "$f_incompat_options" a z fi if [[ -n ${opts[d]} && -n ${opts[z]} ]]; then fail_usage "$f_incompat_options" d z fi get_current_gzbe # # Be sure that a previous attach -a didn't leave zbes behind. # if [[ $inst_type == archive || $inst_type == directory ]]; then /usr/sbin/zfs list -Hro name,$PROP_CANDIDATE "${zone.ROOT_ds}" \ 2>/dev/null | while IFS='$\t' read name candidate ; do if [[ $candidate == "$CURRENT_GZBE" ]]; then fatal "$f_multiple_extractions" fi done # Advise that install is the better choice these days. log "$m_use_install" fi [[ -z "$inst_type" ]] && inst_type="directory" if [[ $noexecute == 1 ]]; then # # the zone doesn't have to exist when the -n option is used, so do # this work early. # # LIXXX There is no sw validation for IPS right now, so just pretend # everything will be ok. # Exit handler not yet active, so no need to worry about it. exit $ZONE_SUBPROC_OK fi trap trap_cleanup INT trap trap_exit EXIT EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN start_log zone attach "${save_args[@]}" pin_datasets "${zone.path.ds}" || fatal "$f_pin" enable_zones_services 1 || exit $EXIT_CODE # Create a ZBE and transfer data into it. attach_datasets -t "$inst_type" -m "$install_media" zone || exit $EXIT_CODE log "$m_active_zbe" "${zone.active_ds}" # Attach the image, perhaps with updates. attach_image zone "$allow_update" # Be sure that shared data that shouldn't be in in the ZBE isn't in the ZBE. if [[ -n ${opts[a]} || -n ${opts[d]} ]]; then migrate_export zone migrate_rpool zone fi # Apply the sysconfig profile, if needed [[ -n $sc_config ]] && reconfigure_zone "$sc_config" mark_orphan_zbes zone # Delete orphan zbe (if option set). [[ -n ${zone.xopts[$DESTROY_ORPHAN_ZBES]} ]] && destroy_orphan_zbes zone trap - EXIT unpin_datasets "${zone.path.ds}" || error "$f_unpin" finish_log zone exit $ZONE_SUBPROC_OK