2N/A#! /bin/ksh
2N/A
2N/A#
2N/A# CDDL HEADER START
2N/A#
2N/A# The contents of this file are subject to the terms of the
2N/A# Common Development and Distribution License (the "License").
2N/A# You may not use this file except in compliance with the License.
2N/A#
2N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A# or http://www.opensolaris.org/os/licensing.
2N/A# See the License for the specific language governing permissions
2N/A# and limitations under the License.
2N/A#
2N/A# When distributing Covered Code, include this CDDL HEADER in each
2N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A# If applicable, add the following below this CDDL HEADER, with the
2N/A# fields enclosed by brackets "[]" replaced with your own identifying
2N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2N/A#
2N/A# CDDL HEADER END
2N/A#
2N/A
2N/A#
2N/A# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A#
2N/A
2N/A
2N/Aexport PATH=/usr/bin:/usr/sbin
2N/A
2N/A. /usr/lib/brand/shared/common.ksh
2N/A. /usr/lib/brand/shared/uninstall.ksh
2N/A
2N/Afunction get_zone_state {
2N/A typeset -n z=$1
2N/A typeset fields
2N/A
2N/A zoneadm -z ${z.name} list -p | IFS=: read -A fields
2N/A if (( ${#fields[@]} < 6 )); then
2N/A error "%s: unknown data returned from zoneadm list -p" \
2N/A "${zone.name}"
2N/A return 1
2N/A fi
2N/A z.state=${fields[2]}
2N/A z.brand=${fields[5]}
2N/A
2N/A return 0
2N/A}
2N/A
2N/A#
2N/A# run cmd undo rollback
2N/A#
2N/A# Runs the command given in the cmd array. If all goes well, it adds the
2N/A# command in the undo array to the rollback array (of arrays) and returns 0.
2N/A# If the command does not return 0, the commands that exist in the rollback
2N/A# array are executed in the reverse of the order that they were added.
2N/A#
2N/A# In all cases, the exit value from the command in cmd is returned.
2N/A#
2N/Afunction run {
2N/A typeset -n cmd=$1
2N/A typeset -n undo=$2
2N/A typeset -n rollback=$3
2N/A
2N/A if (( dryrun )); then
2N/A print " " ${cmd[@]}
2N/A return 0
2N/A fi
2N/A (( verbose )) && log "Running <%s>" "${cmd[*]}"
2N/A ( eval "${cmd[@]}" )
2N/A typeset -i rv=$?
2N/A if (( rv == 0 )); then
2N/A # Push the undo array onto the rollback stack
2N/A typeset -i rbsize=${#rollback[@]}
2N/A typeset -a rollback[rbsize]
2N/A set -A rollback[$rbsize] -- "${undo[@]}"
2N/A return 0
2N/A fi
2N/A
2N/A error "Command <%s> failed with exit status %d. Rolling back." \
2N/A "${cmd[*]}" $rv
2N/A
2N/A typeset -i i
2N/A for (( i = ${#rollback[@]} - 1; i >= 0; i-- )); do
2N/A log "Executing rollback command <%s>" "${rollback[i][*]}"
2N/A ( eval "${rollback[i][@]}" )
2N/A done
2N/A return $rv
2N/A}
2N/A
2N/A#
2N/A# get_active_be zone
2N/A#
2N/A# Overrides shared get_active_be. Is used instead of brand-specific
2N/A# get_active_be because they know about the new layout, not the old.
2N/A#
2N/Afunction get_active_be {
2N/A typeset -n zone=$1
2N/A typeset -A uuid2gzbe
2N/A typeset -i needs_selection=0
2N/A
2N/A #
2N/A # solaris10 only supports a single for those that need to be converted.
2N/A #
2N/A if [[ ${zone.brand} == "solaris10" ]]; then
2N/A zone.active_ds="${zone.path.ds}/ROOT/zbe-0"
2N/A return 0
2N/A fi
2N/A
2N/A #
2N/A # The rest is solaris brand or something that uses the solaris brand
2N/A #
2N/A
2N/A #
2N/A # Load an associative array of global zone BEs. Store current uuid
2N/A # of GZBE in $active_gzbe.
2N/A #
2N/A # Initially the gzbes associative array is one dimensional. The
2N/A # following loop (beginning with zfs list) will add a second
2N/A # dimension. The fully populated uiid2gzbe structure will look like:
2N/A #
2N/A # uuid2gzbe[<gzbe uuid>]=<gzbe name>
2N/A # uuid2gzbe[<gzbe uuid>][ngzbe name]=<ngz active>
2N/A #
2N/A typeset be uuid active junk
2N/A typeset active_gzbe
2N/A beadm list -H | while IFS=\; read be uuid active junk ; do
2N/A uuid2gzbe[$uuid]=$be
2N/A [[ $active == *N* ]] && active_gzbe=$uuid
2N/A done
2N/A if [[ -z $active_gzbe ]]; then
2N/A error "%s: unable to get global zone BE UUID" "${zone.name}"
2N/A return 1
2N/A fi
2N/A
2N/A #
2N/A # Look for the best match of zone BEs
2N/A #
2N/A typeset name parent active tab=$(printf "\t")
2N/A typeset prop_parent="org.opensolaris.libbe:parentbe"
2N/A typeset prop_active="org.opensolaris.libbe:active"
2N/A
2N/A typeset -A ngzbe
2N/A zfs list -H -r -d 1 -t filesystem -o name,$prop_parent,$prop_active \
2N/A "${zone.path.ds}/ROOT" | while IFS=$tab read name parent active ; do
2N/A
2N/A # skip the non-BE top-level dataset
2N/A [[ $name == "${zone.path.ds}/ROOT" ]] && continue
2N/A
2N/A if [[ -z ${uuid2gzbe[$parent]} ]]; then
2N/A uuid2gzbe[$parent]='Missing Global Zone Boot Env'
2N/A fi
2N/A ngzbe[$(basename $name)].parent=$parent
2N/A ngzbe[$(basename $name)].active=$active
2N/A
2N/A [[ $parent == "$active_gzbe" ]] || continue
2N/A [[ $active == on ]] || continue
2N/A vlog "Found active dataset %s" "$name"
2N/A if [[ -n "$active_ds" ]]; then
2N/A error "$f_multiple_ds"
2N/A error "%s: Multiple active datasets" "${zone.name}"
2N/A (( needs_selection=1 ))
2N/A continue
2N/A fi
2N/A active_ds=$name
2N/A done
2N/A if [[ -n $active_ds ]]; then
2N/A zone.active_ds=$active_ds
2N/A return 0
2N/A fi
2N/A
2N/A #
2N/A # Active dataset was not found by property. See if something is mounted
2N/A # on the zone root.
2N/A #
2N/A active_ds=$(zfs list -H -o name ${zone.root})
2N/A if [[ $active_ds == "${zone.path.ds}"/ROOT/* ]]; then
2N/A zone.active_ds=$active_ds
2N/A return 0
2N/A fi
2N/A
2N/A #
2N/A # If no active boot environment was found, offer a table of available
2N/A # boot environments
2N/A #
2N/A error "%s: No active dataset" "${zone.name}"
2N/A
2N/A print "\nThe following unconverted boot environments exist this zone.\n"
2N/A print -- "Boot Environment NGZ Active Global Zone Boot Environment" \
2N/A "GZ Active"
2N/A print -- "----------------- ----------- ----------------------------" \
2N/A "---------"
2N/A typeset be gzbe gzactive
2N/A for be in ${!ngzbe[@]} ; do
2N/A gzbe="${uuid2gzbe[${ngzbe[$be].parent}]}"
2N/A if [[ $gzbe == "$active_gzbe" ]]; then
2N/A gzactive=yes
2N/A else
2N/A gzactive=no
2N/A fi
2N/A printf "%-17s %-11s %-28s %s\n" "$be" "${ngzbe[$be].active}" \
2N/A "$gzbe" "$gzactive"
2N/A done
2N/A
2N/A
2N/A print "\nUse:\n"
2N/A print "\tdsconvert -b <bootenv> ...\n"
2N/A print "to specify the boot environment to activate during conversion.\n"
2N/A
2N/A return 1
2N/A}
2N/A
2N/Afunction usage {
2N/A print "Usage: dsconvert [-hnv] [-b <BE>] zone\n\n" \
2N/A " -h\t\tShow this help message\n" \
2N/A " -n\t\tDry run - make no changes\n" \
2N/A " -v\t\tVerbose\n" \
2N/A " -b <BE>\tActivate the specified zone boot environment\n"
2N/A}
2N/A
2N/A#
2N/A# main
2N/A#
2N/A
2N/A
2N/Atypeset -i dryrun=0
2N/Abootenv=
2N/Am_conversion_complete="%s: Conversion complete"
2N/Awhile getopts :b:hnv opt ; do
2N/A case $opt in
2N/A b) bootenv=$OPTARG
2N/A ;;
2N/A h) usage
2N/A exit 0
2N/A ;;
2N/A n) (( dryrun = 1 ))
2N/A m_conversion_complete="%s: Dryrun complete"
2N/A function nopfn { echo " " "$*"; }
2N/A nop=nopfn
2N/A ;;
2N/A v) (( verbose = 1 )) ;; # used in this script
2N/A ?) usage 1>&2
2N/A exit 1
2N/A ;;
2N/A esac
2N/Adone
2N/Ashift $(( OPTIND - 1 ))
2N/Aif (( $# != 1 )); then
2N/A usage 1>&2
2N/A exit 1
2N/Afi
2N/Azonename=$1
2N/A
2N/Azoneadm -z "$zonename" list >/dev/null 2>&1 || {
2N/A error "%s: %s: No such zone configured" "$(basename "$0")" "$zonename"
2N/A exit 1
2N/A}
2N/A
2N/Ainit_zone zone "$zonename"
2N/Atypeset -a cmd undo rollback
2N/Atypeset -i has_bes=0
2N/Atypeset active_ds=
2N/A
2N/Ainit_dataset old_ROOT_ds "${zone.path.ds}/ROOT" >/dev/null 2>&1 || {
2N/A error "%s: zone has no old style ROOT dataset." "$zonename"
2N/A exit 1
2N/A}
2N/A
2N/Aget_zone_state zone || exit 1
2N/A
2N/A#
2N/A# This check is used for the brief window where people may be trying to use
2N/A# an ON build with a build of the solaris brand that is too old. Since the
2N/A# sysboot script was introduced with the dataset layout change, it makes for
2N/A# an easy check.
2N/A#
2N/Aif [[ ${zone.brand} != solaris10 && ! -f /usr/lib/brand/solaris/sysboot ]]
2N/Athen
2N/A error "%s: %s must be updated before converting\n\t%s branded zones" \
2N/A "${zone.name}" pkg:/system/zones/brand/solaris "${zone.brand}"
2N/A exit 1
2N/Afi
2N/A
2N/Acase "${zone.state}" in
2N/A installed) : ;;
2N/A configured|unavailable)
2N/A # Be sure that there's a dataset under the old ROOT
2N/A typeset be_datasets
2N/A set -A be_datasets $(zfs list -H -o name -d 1 -r \
2N/A "${zone.path.ds}/ROOT")
2N/A if (( ${#be_datasets[@]} < 2 )); then
2N/A log "%s: zone has no boot environments" "$zonename"
2N/A (( hasbes=0 ))
2N/A else
2N/A get_ds_from_path "${zone.root}" active_ds || {
2N/A log "%s: configured but no BE mounted at %s" \
2N/A "$zonename" "${zone.root}"
2N/A (( hasbes=0 ))
2N/A }
2N/A fi
2N/A ;;
2N/A *) error "%s: Unable to convert zone in state %s" "${zonename}" \
2N/A "${zone.state}"
2N/A exit 1
2N/A ;;
2N/Aesac
2N/A
2N/Aif [[ -n $bootenv ]]; then
2N/A if [[ ${zone.brand} == "solaris10" ]]; then
2N/A error "%s: The -b option is not supported with the %s brand" \
2N/A "$zonename" "${zone.brand}"
2N/A exit 1
2N/A fi
2N/A zone.active_ds="${zone.path.ds}/ROOT/$bootenv"
2N/A if ! zfs list "${zone.active_ds}" >/dev/null 2>&1 ; then
2N/A error "%s: Zone has no boot environment named %s" \
2N/A "$zonename" "$bootenv"
2N/A exit 1
2N/A fi
2N/Aelse
2N/A get_active_be zone || exit 1
2N/Afi
2N/A
2N/A#
2N/A# Look at zonecfg fs and dataset resources to see if anything under /export
2N/A# is added. The message that comes out of zonecfg_has_export is not helpful
2N/A# in this particular case, so we ignore it.
2N/A#
2N/Atypeset -i skip_export=0
2N/Azonecfg_has_export zone >/dev/null 2>&1 && (( skip_export = 1 ))
2N/A
2N/Alog "%s: Creating zone rpool dataset" "$zonename"
2N/Aset -A cmd zfs create -o mountpoint=/rpool -o zoned=on "${zone.rpool_ds}"
2N/Aset -A undo zfs destroy "${zone.rpool_ds}"
2N/Arun cmd undo rollback || exit 1
2N/A
2N/Aif (( skip_export == 0 )); then
2N/A log "%s: Creating zone export dataset" "$zonename"
2N/A set -A cmd zfs create -o mountpoint=/export "${zone.rpool_ds}/export"
2N/A set -A undo zfs destroy "${zone.rpool_ds}/export"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A log "%s: Creating zone export/home dataset" "$zonename"
2N/A set -A cmd zfs create "${zone.rpool_ds}/export/home"
2N/A set -A undo zfs destroy "${zone.rpool_ds}/export/home"
2N/A run cmd undo rollback || exit 1
2N/Afi
2N/A
2N/Aset -A props -- -o mountpoint=legacy -o canmount=noauto
2N/Aif [[ ${zone.brand} != solaris10 ]]; then
2N/A a_push props -o "com.oracle.libbe:nbe_handle=on"
2N/Afi
2N/Alog "%s: Creating zone ROOT dataset" "$zonename"
2N/Aset -A cmd zfs create "${props[@]}" "${zone.ROOT_ds}"
2N/Aset -A undo zfs destroy "${zone.ROOT_ds}"
2N/Arun cmd undo rollback || exit 1
2N/A
2N/A#
2N/A# Moving the dataset hierarchy is problematic when clones are involved.
2N/A# The easiest way to avoid the problem with clones is to use more of them.
2N/A#
2N/Alog "%s: Cloning datasets from ROOT to rpool/ROOT" "$zonename"
2N/Aset -A cmd zfs set -r canmount=off "${zone.path.ds}/ROOT"
2N/Aset -A undo zfs set -r canmount=${old_ROOT_ds.props[canmount].value} \
2N/A "${zone.path.ds}/ROOT"
2N/Arun cmd undo rollback || exit 1
2N/A
2N/A#
2N/A# Unconventional quoting of date format string is to silence SCCS keyword
2N/A# warnings.
2N/A#
2N/Asnapname=$(basename $0)-$(TZ=UTC date "+%Y""%m%dT%H""%M""%SZ")
2N/Aset -A cmd zfs snapshot -r "${zone.path.ds}/ROOT@$snapname"
2N/Aset -A undo zfs destroy -rd "${zone.path.ds}/ROOT@$snapname"
2N/Arun cmd undo rollback || exit 1
2N/A
2N/A#
2N/A# Get a list of all the old datasets and their properties. Once we
2N/A# have that, use that information to create clones.
2N/A#
2N/Atypeset -a dslist
2N/Aget_datasets -p ${zone.path.ds}/ROOT dslist || {
2N/A error "%s: Unable to get list of datasets under %s" \
2N/A "${zone.name}" "${zone.path.ds}/ROOT"
2N/A exit 1
2N/A}
2N/A
2N/A#
2N/A# Go through the list and be sure they are all unmounted and won't become
2N/A# mounted. This is needed because the clones that get created will need to use
2N/A# the mount points currently used by the originals. Ignore the first item in
2N/A# the array because that is the ROOT dataset.
2N/A#
2N/Atypeset -i i
2N/Afor (( i = ${#dslist[@]} - 1; i > 1; i-- )); do
2N/A
2N/A # Before this conversion multiple datasets in the BE were broken.
2N/A # Therefore, we don't deal with them here either.
2N/A if [[ ${dslist[i].name} == ${zone.path.ds}/ROOT/*/* ]]; then
2N/A # Force a rollback and exit
2N/A set -A cmd error \
2N/A "%s: Unsupported non-root dataset %s in boot environment" \
2N/A "${zone.name}" "${dslist[i].name}" \; false
2N/A set -A undo echo "this command will never run"
2N/A run cmd undo rollback
2N/A exit 1
2N/A fi
2N/A
2N/A if [[ ${dslist[i].props[canmount].value} != no ]]; then
2N/A set -A cmd zfs set canmount=off "${dslist[i].name}"
2N/A set -A undo zfs set canmount=${dslist[i].props[canmount].value} \
2N/A "${dslist[i].name}"
2N/A run cmd undo rollback || exit 1
2N/A fi
2N/A if [[ ${dslist[i].props[mounted].value} == yes ]]; then
2N/A set -A cmd unmount "${dslist[i].name}"
2N/A if [[ ${dslist[i].props[mountpoint].value} == legacy ]]; then
2N/A # Create undo using existing mountpoint
2N/A set -A undo mount -F zfs "${dslist[i].name}" \
2N/A "$(nawk -F '\t' -v "dev=${dslist[i].name}" \
2N/A '$1 == dev {print $2; exit}' /etc/mnttab)"
2N/A else
2N/A # This conversion process assumes no one uses temporary
2N/A # mount points for zones before this conversion is
2N/A # necessary.
2N/A set -A undo zfs mount "${dslist[i].name}"
2N/A fi
2N/A run cmd undo rollback || exit 1
2N/A fi
2N/Adone
2N/A
2N/A#
2N/A# The sources are all unmounted and along the way we verified that it is only
2N/A# root datasets. Create clones.
2N/A#
2N/Afor (( i = 1; i < ${#dslist[@]}; i++ )); do
2N/A set -A props -- -o mountpoint=/ -o canmount=noauto
2N/A
2N/A # preserve user properties
2N/A for prop in "${!dslist[i].props[@]}" ; do
2N/A # Skip non-user properties and inherited user properties
2N/A [[ $prop == *:* ]] || continue
2N/A [[ ${dslist[i].props[$prop].source} == @(local|received) ]] ||
2N/A continue
2N/A
2N/A a_push props -o "$prop=${dslist[i].props[$prop].value}"
2N/A done
2N/A
2N/A src=${dslist[i].name}@$snapname
2N/A new=${dslist[i].name/${zone.path.ds}/${zone.rpool_ds}}
2N/A
2N/A set -A cmd zfs clone "${props[@]}" "$src" "$new"
2N/A set -a undo destroy_zone_dataset "$new"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A (( has_bes=1 ))
2N/Adone
2N/A
2N/Aif (( has_bes )); then
2N/A #
2N/A # The layout is now correct, except for datasets that need to be
2N/A # deleted. Load the brand-specific common functions. Note that
2N/A # all of the non-solaris10 brands that this script support use
2N/A # the solaris common.ksh.
2N/A #
2N/A if [[ ${zone.brand} == "solaris10" ]]; then
2N/A . /usr/lib/brand/solaris10/common.ksh
2N/A else
2N/A . /usr/lib/brand/solaris/common.ksh
2N/A fi
2N/A
2N/A # Clean up boot environment properties as needed
2N/A (( dryrun )) || set_active_be zone "$(basename "${zone.active_ds}")"
2N/A
2N/A #
2N/A # If we started this exercise with a zone that was attached, just run
2N/A # the rough equivalent of the sysboot hook to mount it. If it wasn't
2N/A # attached, then we need to remount the active dataset at the zone
2N/A # root.
2N/A #
2N/A log "%s: Remounting zone at %s" "$zonename" "${zone.root}"
2N/A if [[ ${zone.state} == installed ]]; then
2N/A set -A cmd mount_active_be -c zone
2N/A set -A undo umount "${zone.root}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A if [[ ${zone.brand} != solaris10 ]]; then
2N/A log "\n%8s: zone %s needs to be updated with attach -u" \
2N/A NOTICE "$zonename"
2N/A
2N/A log "%8s: \"zoneadm -z %s detach\" to detach, then" \
2N/A Run "$zonename"
2N/A log "%8s: \"zoneadm -z %s attach -u\" to attach.\n" \
2N/A Run "$zonename"
2N/A fi
2N/A elif [[ ${zone.state} == unavailable ]]; then
2N/A set -A cmd mount_active_be -c zone
2N/A set -A undo umount "${zone.root}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A if [[ ${zone.brand} == solaris10 ]]; then
2N/A log "\n%8s: zone %s needs to be attached." NOTICE \
2N/A "$zonename"
2N/A log "%8s: \"zoneadm -z %s attach\" to attach.\n" \
2N/A Run "$zonename"
2N/A else
2N/A log "\n%8s: zone %s needs to be updated with attach -u" \
2N/A NOTICE "$zonename"
2N/A log "%8s: \"zoneadm -z %s attach -u\" to attach.\n" \
2N/A Run "$zonename"
2N/A fi
2N/A
2N/A else # detached
2N/A
2N/A #
2N/A # Before the dataset revision, each BE only supported a single
2N/A # (root) dataset. As such, we can use a rather simplistic
2N/A # approach to mounting the active BE.
2N/A #
2N/A set -A cmd zfs set canmount=off "${zone.active_ds}"
2N/A set -A undo zfs set canmount="$(/usr/sbin/zfs get -H \
2N/A -o value canmount "${zone.active_ds}")" "${zone.active_ds}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A set -A cmd zfs set zoned=off "${zone.active_ds}"
2N/A set -A undo zfs inherit zoned "${zone.active_ds}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A set -A cmd zfs set mountpoint="${zone.root}" "${zone.active_ds}"
2N/A set -A undo zfs set mountpoint=$(/usr/sbin/zfs get -H \
2N/A -o value mountpoint "${zone.active_ds}") \
2N/A "${zone.active_ds}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A set -A cmd zfs set canmount=on "${zone.active_ds}"
2N/A set -A undo zfs set canmount=off "${zone.active_ds}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A set -A cmd zfs mount "${zone.active_ds}"
2N/A set -A undo zfs unmount "${zone.active_ds}"
2N/A run cmd undo rollback || exit 1
2N/A
2N/A log "\n%8s: zone %s converted, but is still detached" \
2N/A NOTICE "$zonename"
2N/A if [[ ${zone.brand} == solaris10 ]]; then
2N/A log "%8s: \"zoneadm -z %s attach\" to attach.\n" \
2N/A Run "$zonename"
2N/A else
2N/A log "%8s: \"zoneadm -z %s attach -u\" to attach.\n" \
2N/A Run "$zonename"
2N/A fi
2N/A fi
2N/Afi
2N/A
2N/A#
2N/A# Clean up old datasets
2N/A#
2N/Alog "%s: Removing obsolete datasets" "${zone.name}"
2N/Afor (( i = ${#dslist[@]} - 1; i >= 0; i-- )); do
2N/A (( verbose )) && log "%s: Destroying dataset %s" "${zone.name}" \
2N/A "${dslist[i].name}"
2N/A (( dryrun )) || destroy_zone_dataset "${dslist[i].name}"
2N/Adone
2N/A
2N/Aif (( skip_export == 0 )) && [[ -d ${zone.root}/export ]]; then
2N/A log "%s: Migrating /export from the active boot environent" \
2N/A "${zone.name}"
2N/A (( dryrun )) || migrate_export zone
2N/A (( dryrun )) || migrate_rpool zone
2N/Afi
2N/A
2N/A#
2N/A# Convert for dataset aliases
2N/A#
2N/A# If there are no delegated datasets, this does nothing. If there are
2N/A# delegated datasets that don't have aliases defined (none should have
2N/A# aliases yet), the default aliases get populated into the zone configuration.
2N/A#
2N/Atypeset -i errors=0
2N/Alog "%s: Converting dataset aliases\n" "$zonename"
2N/Azonecfg -z "$zonename" "$(zonecfg -z $zonename info dataset | \
2N/A nawk '$1 == "name:" { printf "select dataset name=%s; end;", $2 }')"
2N/Aif (( $? != 0 )); then
2N/A (( errors++ ))
2N/A cat <<-NOMORE
2N/A
2N/A The automated conversion process is complete.
2N/A
2N/A Before the zone will boot zone configuration problems need to be
2N/A corrected. Run 'zonecfg -z $zonename' then use the verify subcommand
2N/A within zonecfg to get a list of configuration problems that must be
2N/A corrected within zonecfg.
2N/A
2N/A NOMORE
2N/Afi
2N/A
2N/Alog "%s: Verifying zone with zoneadm\n" "$zonename"
2N/Azoneadm -z "$zonename" verify
2N/Aif (( $? != 0 )); then
2N/A if (( errors == 0 )); then
2N/A print "\nThe automated conversion process is complete."
2N/A fi
2N/A (( errors++ ))
2N/A cat <<-NOMORE
2N/A
2N/A As displayed above, system configuration problems exist that must
2N/A be corrected befor the zone will boot. Before booting $zonename you
2N/A will need to manually correct those problems.
2N/A
2N/A You may run 'zoneadm -z $zonename verify' at any time to re-verify the
2N/A system configuration related to this zone.
2N/A
2N/A NOMORE
2N/Afi
2N/A
2N/A#
2N/A# Check for potential /dev/zvol conflicts. While this may emit warnings, it
2N/A# it should not cause the exit code to change from 0.
2N/A#
2N/Alog "%s: Checking for potential configuration conflicts\n" "$zonename"
2N/Azonecfg -z "$zonename" verify -v
2N/Aif (( $? != 0 )); then
2N/A cat <<-NOMORE
2N/A
2N/A With Zone Dataset Aliasing, ZFS datasets that are delegated to
2N/A $zonename appear within the zone as virtual ZFS pools. One or more
2N/A of the device resources that appears in the configuration for
2N/A $zonename may hide the existence of similarly named ZFS volumes
2N/A within these virtual pools. See zonecfg(1M) and dev(7FS) for
2N/A details.
2N/A
2N/A You may run 'zonecfg -z $zonename verify -v' at any time to perform
2N/A this check again.
2N/A
2N/A NOMORE
2N/Afi
2N/A
2N/Aif (( errors != 0 )); then
2N/A exit 1
2N/Afi
2N/A
2N/Alog "$m_conversion_complete" "$zonename"
2N/Aexit 0