src/brand/common.ksh
changeset 2391 90c532b69592
parent 2367 49e71b6682c7
parent 2390 f1c659f5c28e
equal deleted inserted replaced
2389:30ea7b982e91 2391:90c532b69592
    21 
    21 
    22 #
    22 #
    23 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    23 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    24 #
    24 #
    25 
    25 
    26 #
       
    27 # Only change PATH if you give full consideration to GNU or other variants
       
    28 # of common commands having different arguments and output.  Setting PATH is
       
    29 # and not using the full path to executables provides a performance improvement
       
    30 # by using the ksh builtin equivalent of many common commands.
       
    31 #
       
    32 export PATH=/usr/bin:/usr/sbin
       
    33 unset LD_LIBRARY_PATH
    26 unset LD_LIBRARY_PATH
       
    27 PATH=/usr/bin:/usr/sbin
       
    28 export PATH
    34 
    29 
    35 . /usr/lib/brand/shared/common.ksh
    30 . /usr/lib/brand/shared/common.ksh
    36 
    31 
    37 PROP_PARENT="org.opensolaris.libbe:parentbe"
    32 PROP_PARENT="org.opensolaris.libbe:parentbe"
    38 PROP_ACTIVE="org.opensolaris.libbe:active"
    33 PROP_ACTIVE="org.opensolaris.libbe:active"
    39 PROP_BE_HANDLE="com.oracle.libbe:nbe_handle"
       
    40 
    34 
    41 f_incompat_options=$(gettext "cannot specify both %s and %s options")
    35 f_incompat_options=$(gettext "cannot specify both %s and %s options")
    42 f_sanity_detail=$(gettext  "Missing %s at %s")
    36 f_sanity_detail=$(gettext  "Missing %s at %s")
    43 f_sanity_sparse=$(gettext  "Is this a sparse zone image?  The image must be whole-root.")
    37 f_sanity_sparse=$(gettext  "Is this a sparse zone image?  The image must be whole-root.")
    44 sanity_ok=$(gettext     "  Sanity Check: Passed.  Looks like a Solaris system.")
    38 sanity_ok=$(gettext     "  Sanity Check: Passed.  Looks like a Solaris system.")
    45 sanity_fail=$(gettext   "  Sanity Check: FAILED (see log for details).")
    39 sanity_fail=$(gettext   "  Sanity Check: FAILED (see log for details).")
    46 sanity_fail_vers=$(gettext  "  Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.")
    40 sanity_fail_vers=$(gettext  "  Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.")
    47 install_fail=$(gettext  "        Result: *** Installation FAILED ***")
    41 install_fail=$(gettext  "        Result: *** Installation FAILED ***")
    48 f_zfs_in_root=$(gettext "Installing a zone inside of the root pool's 'ROOT' dataset is unsupported.")
    42 f_zfs_in_root=$(gettext "Installing a zone inside of the root pool's 'ROOT' dataset is unsupported.")
       
    43 f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.")
    49 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.")
    44 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.")
    50 f_no_gzbe=$(gettext "unable to determine global zone boot environment.")
    45 f_no_gzbe=$(gettext "unable to determine global zone boot environment.")
       
    46 f_no_ds=$(gettext "the zonepath must be a ZFS dataset.\nThe parent directory of the zonepath must be a ZFS dataset so that the\nzonepath ZFS dataset can be created properly.")
    51 f_multiple_ds=$(gettext "multiple active datasets.")
    47 f_multiple_ds=$(gettext "multiple active datasets.")
    52 f_no_active_ds=$(gettext "no active dataset.")
    48 f_no_active_ds=$(gettext "no active dataset.")
    53 f_zfs_unmount=$(gettext "Unable to unmount the zone's root ZFS dataset (%s).\nIs there a global zone process inside the zone root?\nThe current zone boot environment will remain mounted.\n")
    49 f_zfs_unmount=$(gettext "Unable to unmount the zone's root ZFS dataset (%s).\nIs there a global zone process inside the zone root?\nThe current zone boot environment will remain mounted.\n")
    54 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.")
    50 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.")
    55 
    51 
    75 
    71 
    76 m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
    72 m_complete=$(gettext    "        Done: Installation completed in %s seconds.")
    77 m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console (zlogin -C)")
    73 m_postnote=$(gettext    "  Next Steps: Boot the zone, then log into the zone console (zlogin -C)")
    78 m_postnote2=$(gettext "              to complete the configuration process.")
    74 m_postnote2=$(gettext "              to complete the configuration process.")
    79 
    75 
       
    76 fail_incomplete() {
       
    77 	printf "ERROR: " 1>&2
       
    78 	printf "$@" 1>&2
       
    79 	printf "\n" 1>&2
       
    80 	exit $ZONE_SUBPROC_NOTCOMPLETE
       
    81 }
       
    82 
       
    83 fail_usage() {
       
    84 	printf "$@" 1>&2
       
    85 	printf "\n" 1>&2
       
    86 	printf "$m_brnd_usage" 1>&2
       
    87 	printf "$m_usage\n" 1>&2
       
    88 	exit $ZONE_SUBPROC_USAGE
       
    89 }
       
    90 
    80 is_brand_labeled() {
    91 is_brand_labeled() {
    81 	if [[ -z $ALTROOT ]]; then
    92 	if [ -z $ALTROOT ]; then
    82 		AR_OPTIONS=""
    93 		AR_OPTIONS=""
    83 	else
    94 	else
    84 		AR_OPTIONS="-R $ALTROOT"
    95 		AR_OPTIONS="-R $ALTROOT"
    85 	fi
    96 	fi
    86 	brand=$(/usr/sbin/zoneadm $AR_OPTIONS -z $ZONENAME \
    97 	brand=$(/usr/sbin/zoneadm $AR_OPTIONS -z $ZONENAME \
   133 	fi
   144 	fi
   134 	
   145 	
   135 	vlog "$sanity_ok"
   146 	vlog "$sanity_ok"
   136 }
   147 }
   137 
   148 
   138 function get_current_gzbe {
   149 get_current_gzbe() {
   139 	#
   150 	#
   140 	# If there is no alternate root (normal case) then set the
   151 	# If there is no alternate root (normal case) then set the
   141 	# global zone boot environment by finding the boot environment
   152 	# global zone boot environment by finding the boot environment
   142 	# that is active now.
   153 	# that is active now.
   143 	# If a zone exists in a boot environment mounted on an alternate root,
   154 	# If a zone exists in a boot environment mounted on an alternate root,
   144 	# then find the boot environment where the alternate root is mounted.
   155 	# then find the boot environment where the alternate root is mounted.
   145 	#
   156 	#
   146 	CURRENT_GZBE=$(beadm list -H | nawk -v alt=$ALTROOT -F\; '{
   157 	if [ -x /usr/sbin/beadm ]; then
   147 		if (length(alt) == 0) {
   158 		CURRENT_GZBE=`/usr/sbin/beadm list -H | /usr/bin/nawk \
   148 		    # Field 3 is the BE status.  'N' is the active BE.
   159 				-v alt=$ALTROOT -F\; '{
   149 		    if ($3 !~ "N")
   160 			if (length(alt) == 0) {
   150 			next
   161 			    # Field 3 is the BE status.  'N' is the active BE.
   151 		} else {
   162 			    if ($3 !~ "N")
   152 		    # Field 4 is the BE mountpoint.
   163 				next
   153 		    if ($4 != alt)
   164 			} else {
   154 		next
   165 			    # Field 4 is the BE mountpoint.
       
   166 			    if ($4 != alt)
       
   167 				next
       
   168 			}
       
   169 			# Field 2 is the BE UUID
       
   170 			print $2
       
   171 		}'`
       
   172 	else
       
   173 		# If there is no beadm command then the system doesn't really
       
   174 		# support multiple boot environments.  We still want zones to
       
   175 		# work so simulate the existence of a single boot environment.
       
   176 		CURRENT_GZBE="opensolaris"
       
   177 	fi
       
   178 
       
   179 	if [ -z "$CURRENT_GZBE" ]; then
       
   180 		fail_fatal "$f_no_gzbe"
       
   181 	fi
       
   182 }
       
   183 
       
   184 # Find the active dataset under the zonepath dataset to mount on zonepath/root.
       
   185 # $1 CURRENT_GZBE
       
   186 # $2 ZONEPATH_DS
       
   187 get_active_ds() {
       
   188 	ACTIVE_DS=`/usr/sbin/zfs list -H -r -t filesystem \
       
   189 	    -o name,$PROP_PARENT,$PROP_ACTIVE $2/ROOT | \
       
   190 	    /usr/bin/nawk -v gzbe=$1 ' {
       
   191 		if ($1 ~ /ROOT\/[^\/]+$/ && $2 == gzbe && $3 == "on") {
       
   192 			print $1
       
   193 			if (found == 1)
       
   194 				exit 1
       
   195 			found = 1
   155 		}
   196 		}
   156 		# Field 2 is the BE UUID
   197 	    }'`
   157 		print $2
   198 
   158 	    }')
   199 	if [ $? -ne 0 ]; then
   159 	if [ -z "$CURRENT_GZBE" ]; then
   200 		fail_fatal "$f_multiple_ds"
   160 		return 1
   201 	fi
   161 	fi
   202 
   162 	return 0
   203 	if [ -z "$ACTIVE_DS" ]; then
   163 }
   204 		fail_fatal "$f_no_active_ds"
   164 
   205 	fi
   165 #
   206 }
   166 # get_active_be zone
   207 
   167 #
   208 # Check that zone is not in the ROOT dataset.
   168 # Finds the active boot environment for the given zone.
   209 fail_zonepath_in_rootds() {
   169 #
   210 	case $1 in
   170 # Arguments:
   211 		rpool/ROOT/*)
   171 #
   212 			fail_fatal "$f_zfs_in_root"
   172 #  zone		zone structure initialized with init_zone
   213 			break;
   173 #
   214 			;;
   174 # Globals:
   215 		*)
   175 #
   216 			break;
   176 #  CURRENT_GZBE	Current global zone boot environment.  If not already set,
   217 			;;
   177 #		it will be set.
   218 	esac
   178 #
   219 }
   179 # Returns:
   220 
   180 #
   221 #
   181 #  0 on success, else 1.
   222 # Make sure the active dataset is mounted for the zone.  There are several
   182 #
   223 # cases to consider:
   183 function get_active_be {
   224 # 1) First boot of the zone, nothing is mounted
   184 	typeset -n zone=$1
   225 # 2) Zone is halting, active dataset remains the same.
   185 	typeset active_ds=
   226 # 3) Zone is halting, there is a new active dataset to mount.
   186 	typeset tab=$(printf "\t")
   227 #
   187 
   228 mount_active_ds() {
   188 	[[ -z "$CURRENT_GZBE" ]] && get_current_gzbe
   229 	mount -p | cut -d' ' -f3 | egrep -s "^$ZONEPATH/root$"
   189 
   230 	if (( $? == 0 )); then
   190 	typeset name parent active
   231 		# Umount current dataset on the root (it might be an old BE).
   191 	zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \
   232 		umount $ZONEPATH/root
   192 	    ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do
   233 		if (( $? != 0 )); then
   193 		[[ $parent == "$CURRENT_GZBE" ]] || continue
   234 			# The umount failed, leave the old BE mounted.
   194 		[[ $active == on ]] || continue
   235 			# Warn about gz process preventing umount.
   195 		vlog "Found active dataset %s" "$name"
   236 			printf "$f_zfs_unmount" "$ZONEPATH/root"
   196 		if [[ -n "$active_ds" ]] ; then
   237 			return
   197 			error "$f_multiple_ds"
       
   198 			return 1
       
   199 		fi
   238 		fi
   200 		active_ds=$name
   239 	fi
       
   240 
       
   241 	# Mount active dataset on the root.
       
   242 	get_current_gzbe
       
   243 	get_zonepath_ds $ZONEPATH
       
   244 	get_active_ds $CURRENT_GZBE $ZONEPATH_DS
       
   245 
       
   246 	mount -F zfs $ACTIVE_DS $ZONEPATH/root || fail_fatal "$f_zfs_mount"
       
   247 }
       
   248 
       
   249 #
       
   250 # Set up ZFS dataset hierarchy for the zone root dataset.
       
   251 #
       
   252 create_active_ds() {
       
   253 	get_current_gzbe
       
   254 
       
   255 	#
       
   256 	# Find the zone's current dataset.  This should have been created by
       
   257 	# zoneadm.
       
   258 	#
       
   259 	get_zonepath_ds $zonepath
       
   260 
       
   261 	# Check that zone is not in the ROOT dataset.
       
   262 	fail_zonepath_in_rootds $ZONEPATH_DS
       
   263 
       
   264 	#
       
   265 	# From here on, errors should cause the zone to be incomplete.
       
   266 	#
       
   267 	int_code=$ZONE_SUBPROC_FATAL
       
   268 
       
   269 	#
       
   270 	# We need to tolerate errors while creating the datasets and making the
       
   271 	# mountpoint, since these could already exist from some other BE.
       
   272 	#
       
   273 
       
   274 	/usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1
       
   275 	if (( $? != 0 )); then
       
   276 		/usr/sbin/zfs create -o mountpoint=legacy \
       
   277 		    -o zoned=on $ZONEPATH_DS/ROOT
       
   278 		if (( $? != 0 )); then
       
   279 			fail_fatal "$f_zfs_create"
       
   280 		fi
       
   281 	fi
       
   282 
       
   283 	BENAME=zbe
       
   284 	BENUM=0
       
   285 	# Try 100 different names before giving up.
       
   286 	while [ $BENUM -lt 100 ]; do
       
   287        		/usr/sbin/zfs create -o $PROP_ACTIVE=on \
       
   288 		    -o $PROP_PARENT=$CURRENT_GZBE \
       
   289 		    -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME >/dev/null 2>&1
       
   290 		if (( $? == 0 )); then
       
   291 			break
       
   292 		fi
       
   293 		BENUM=`expr $BENUM + 1`
       
   294 		BENAME="zbe-$BENUM"
   201 	done
   295 	done
   202 	if [[ -z $active_ds ]]; then
   296 
   203 		error "$f_no_active_ds"
   297 	if [ $BENUM -ge 100 ]; then
   204 		return 1
   298 		fail_fatal "$f_zfs_create"
   205 	fi
   299 	fi
   206 
   300 
   207 	zone.active_ds=$active_ds
   301 	if [ ! -d $ZONEROOT ]; then
   208 }
   302 		/usr/bin/mkdir $ZONEROOT
   209 
   303 	fi
   210 function set_active_be {
   304 
   211 	typeset -n zone="$1"
   305 	/usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $ZONEROOT || \
   212 	typeset be="$2"
   306 	    fail_incomplete "$f_zfs_mount"
   213 
       
   214 	[[ -z "$CURRENT_GZBE" ]] && get_current_gzbe
       
   215 
       
   216 	#
       
   217 	# Turn off the active property on BE's with the same GZBE
       
   218 	#
       
   219 	zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \
       
   220 	    ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do
       
   221 		[[ $parent == "$CURRENT_GZBE" ]] || continue
       
   222 		[[ $active == on ]] || continue
       
   223 		[[ $name ==  "${zone.ROOT_ds}/$be" ]] && continue
       
   224 		vlog "Deactivating active dataset %s" "$name"
       
   225 		zfs set $PROP_ACTIVE=off "$name" || return 1
       
   226 	done
       
   227 
       
   228 	zone.active_ds="${zone.ROOT_ds}/$be"
       
   229 
       
   230 	zfs set "$PROP_PARENT=$CURRENT_GZBE" ${zone.active_ds} \
       
   231 	    || return 1
       
   232 	zfs set "$PROP_ACTIVE=on" ${zone.active_ds} || return 1
       
   233 
       
   234 	zfs set "$PROP_BE_HANDLE=on" "${zone.rpool_ds}" || return 1
       
   235 
       
   236 	return 0
       
   237 }
   307 }
   238 
   308 
   239 #
   309 #
   240 # Run sys-unconfig on the zone.
   310 # Run sys-unconfig on the zone.
   241 #
   311 #