#!/bin/ksh -p # # # # # # # # # # # # # # # # # # # # # # Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. # # # common shell script functions # . /usr/lib/brand/shared/common.ksh . /usr/lib/brand/solaris/common.ksh . /usr/lib/brand/shared/uninstall.ksh f_zfs_mount=$(gettext "Failed to mount dataset %s.") trap_exit() { finish_log zone exit $EXIT_CODE } EXIT_CODE=$ZONE_SUBPROC_USAGE # # options processing # # If we weren't passed at least two arguments, exit now. (( $# < 2 )) && fail_fatal "$f_abort" # used by start_log() set -A save_args "$0" "$@" # This block of code must run before init_zone() otherwise it will fail to # initialize various dataset variables when zonepath is unmounted. # If a previous install failure left zonepath unmounted, attempt to mount it so # uninstall can properly destroy it. Zonepath is unmounted if the mountpoint # for the zonepath doesn't match zonepath. typeset zp_mountpoint zp_dsn zp_basename /usr/sbin/zfs list -H -o name,mountpoint "$2" 2>/dev/null | IFS=$'\t' read zp_dsn zp_mountpoint if [[ -n $zp_mountpoint ]] && [[ $zp_mountpoint != legacy ]] && \ [[ $zp_mountpoint != $2 ]] && [[ -n $zp_dsn ]] ; then zp_basename=$(basename "$2") # Now see if expected dataset has the zonepath as mountpoint /usr/sbin/zfs list -H -o mountpoint "$zp_dsn/$zp_basename" \ 2>/dev/null | IFS=$'\t' read zp_mountpoint if [[ $zp_mountpoint == $2 ]]; then zfs mount "$zp_dsn/$zp_basename" || { # If the mount failed, continue the uninstall, but # give an error message. log "$f_zfs_mount" "$zp_dsn/$zp_basename" log "Unable to destroy dataset $zp_dsn/$zp_basename" } fi fi typeset zone init_zone zone "$1" "$2" eval $(bind_legacy_zone_globals zone) shift 2 trap trap_exit EXIT options="FhHnvx:" options_repeat="" options_seen="" opt_F="" opt_n="" opt_v="" # check for bad or duplicate options OPTIND=1 while getopts $options OPT ; do case $OPT in x) ;; # zoneadm only \? ) uninstall_usage_err ;; # invalid argument : ) uninstall_usage_err ;; # argument expected * ) opt=`echo $OPT | sed 's/-\+//'` if [ -n "$options_repeat" ]; then echo $options_repeat | grep $opt >/dev/null [ $? = 0 ] && break fi ( echo $options_seen | grep $opt >/dev/null ) && uninstall_usage_err options_seen="${options_seen}${opt}" ;; esac done # check for a help request OPTIND=1 while getopts :$options OPT ; do case $OPT in h|H ) uninstall_usage esac done # process options OPTIND=1 while getopts :$options OPT ; do case $OPT in F) opt_F="-F" ;; n) opt_n="-n" ;; v) opt_v="-v" ;; esac done shift `expr $OPTIND - 1` [ $# -gt 0 ] && uninstall_usage_err # # main # EXIT_CODE=$ZONE_SUBPROC_TRYAGAIN start_log zone uninstall "${save_args[@]}" nop="" if [[ -n "$opt_n" ]]; then nop="echo" # # in '-n' mode we should never return success (since we haven't # actually done anything). so override ZONE_SUBPROC_OK here. # ZONE_SUBPROC_OK=$ZONE_SUBPROC_FATAL fi get_current_gzbe # find all the zone BEs associated with this global zone BE. typeset -a belist if [[ -n "$CURRENT_GZBE" ]]; then zfs list -H -t filesystem -r -d 1 -o \ $PROP_PARENT,$PROP_ACTIVE,$PROP_CANDIDATE,name "${zone.ROOT_ds}" \ 2>/dev/null | while IFS=$'\t' read parent active candidate fs; do # Skip the ROOT dataset [[ "$fs" == "${zone.ROOT_ds}" ]] && continue zbe=$(basename "$fs") # # match by PROP_PARENT uuid. If the uuid is not set ("-"), the # BE is invalid (interrupted install?) and should be deleted. # if [[ $parent == "-" || $parent == "${CURRENT_GZBE}" ]]; then a_push belist "$zbe" continue fi # # If 'install -a' or 'attach -a' extracted multiple ZBEs and # could not figure out which one to attach, the multiple ZBEs # may have been left behind. In such a case, the zone will # be in the "unavailable" state. # if [[ $candidate == "$CURRENT_GZBE" ]]; then a_push belist "$zbe" continue fi done fi destroy_zone_datasets zone -b belist finish_log zone # Set exit code for trap handler EXIT_CODE=$ZONE_SUBPROC_OK exit $ZONE_SUBPROC_OK