1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21# 22# Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23# Use is subject to license terms. 24# 25 26unset LD_LIBRARY_PATH 27PATH=/usr/bin:/usr/sbin 28export PATH 29 30. /usr/lib/brand/shared/common.ksh 31 32# Values for service tags. 33STCLIENT=/usr/bin/stclient 34ST_PRODUCT_NAME="Solaris 10 Containers" 35ST_PRODUCT_REV="1.0" 36ST_PRODUCT_UUID="urn:uuid:2f459121-dec7-11de-9af7-080020a9ed93" 37 38w_sanity_detail=$(gettext " WARNING: Skipping image sanity checks.") 39f_sanity_detail=$(gettext "Missing %s at %s") 40f_sanity_sparse=$(gettext "Is this a sparse zone image? The image must be whole-root.") 41f_sanity_vers=$(gettext "The image release version must be 10 (got %s), the zone is not usable on this system.") 42f_not_s10_image=$(gettext "%s doesn't look like a Solaris 10 image.") 43f_sanity_nopatch=$(gettext "Unable to determine the image's patch level.") 44f_sanity_downrev=$(gettext "The image patch level is downrev for running in a solaris10 branded zone.\n(patchlist %s)") 45f_need_newer_emul=$(gettext "The image requires a newer version of the solaris10 brand emulation.") 46f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.") 47f_no_ds=$(gettext "No zonepath dataset; the zonepath must be a ZFS dataset.") 48f_multiple_ds=$(gettext "Multiple active datasets.") 49f_no_active_ds=$(gettext "No active dataset; the zone's ZFS root dataset must be configured as\n\ta zone boot environment.") 50f_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") 51f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.") 52incompat_options=$(gettext "mutually exclusive options.\n%s") 53 54sanity_ok=$(gettext " Sanity Check: Passed. Looks like a Solaris 10 image.") 55sanity_fail=$(gettext " Sanity Check: FAILED (see log for details).") 56 57e_badboot=$(gettext "Zone boot failed") 58e_nosingleuser=$(gettext "ERROR: zone did not finish booting to single-user.") 59e_unconfig=$(gettext "sys-unconfig failed") 60v_unconfig=$(gettext "Performing zone sys-unconfig") 61 62v_no_tags=$(gettext "Service tags facility not present.") 63e_bad_uuid=$(gettext "Failed to get zone UUID") 64v_addtag=$(gettext "Adding service tag: %s") 65v_deltag=$(gettext "Removing service tag: %s") 66e_addtag_fail=$(gettext "Adding service tag failed (error: %s)") 67 68sanity_check() 69{ 70 typeset dir="$1" 71 res=0 72 73 # 74 # Check for some required directories and make sure this isn't a 75 # sparse zone image. 76 # 77 checks="etc etc/svc var var/svc" 78 for x in $checks; do 79 if [[ ! -e $dir/$x ]]; then 80 log "$f_sanity_detail" "$x" "$dir" 81 res=1 82 fi 83 done 84 # Files from SUNWcsr and SUNWcsu that are in sparse inherit-pkg-dirs. 85 checks="lib/svc sbin/zonename usr/bin/chmod" 86 for x in $checks; do 87 if [[ ! -e $dir/$x ]]; then 88 log "$f_sanity_detail" "$x" "$dir" 89 log "$f_sanity_sparse" 90 res=1 91 fi 92 done 93 94 if (( $res != 0 )); then 95 log "$sanity_fail" 96 fatal "$install_fail" "$ZONENAME" 97 fi 98 99 if [[ "$SANITY_SKIP" == 1 ]]; then 100 log "$w_sanity_detail" 101 return 102 fi 103 104 # 105 # Check image release to be sure its S10. 106 # 107 image_vers="unknown" 108 if [[ -f $dir/var/sadm/system/admin/INST_RELEASE ]]; then 109 image_vers=$(nawk -F= '{if ($1 == "VERSION") print $2}' \ 110 $dir/var/sadm/system/admin/INST_RELEASE) 111 fi 112 113 if [[ "$image_vers" != "10" ]]; then 114 log "$f_sanity_vers" "$image_vers" 115 res=1 116 fi 117 118 # 119 # Make sure we have the minimal KU patch we support. These are the 120 # KUs for S10u8. 121 # 122 if [[ $(uname -p) == "i386" ]]; then 123 req_patch="141445-09" 124 else 125 req_patch="141444-09" 126 fi 127 128 for i in $dir/var/sadm/pkg/SUNWcakr* 129 do 130 if [[ ! -d $i || ! -f $i/pkginfo ]]; then 131 log "$f_sanity_nopatch" 132 res=1 133 fi 134 done 135 136 # 137 # Check the core kernel pkg for the required KU patch. 138 # 139 found=0 140 for i in $dir/var/sadm/pkg/SUNWcakr*/pkginfo 141 do 142 patches=$(nawk -F= '{if ($1 == "PATCHLIST") print $2}' $i) 143 for patch in $patches 144 do 145 if [[ $patch == $req_patch ]]; then 146 found=1 147 break 148 fi 149 done 150 151 if (( $found == 1 )); then 152 break 153 fi 154 done 155 156 if (( $found != 1 )); then 157 log "$f_sanity_downrev" "$patches" 158 res=1 159 fi 160 161 # 162 # Check the S10 image for a required version of the emulation. 163 # 164 VERS_FILE=/usr/lib/brand/solaris10/version 165 s10vers_needs=0 166 if [[ -f $dir/$VERS_FILE ]]; then 167 s10vers_needs=$(/usr/bin/egrep -v "^#" $dir/$VERS_FILE) 168 fi 169 170 # Now get the current emulation version. 171 emul_vers=$(/usr/bin/egrep -v "^#" $VERS_FILE) 172 173 # Verify that the emulation can run this version of S10. 174 if (( $s10vers_needs > $emul_vers )); then 175 log "$f_need_newer_emul" 176 res=1 177 fi 178 179 if (( $res != 0 )); then 180 log "$sanity_fail" 181 fatal "$install_fail" "$ZONENAME" 182 fi 183 184 vlog "$sanity_ok" 185} 186 187# Find the active dataset under the zonepath dataset to mount on zonepath/root. 188# $1 ZONEPATH_DS 189get_active_ds() { 190 ACTIVE_DS=$1/ROOT/zbe-0 191} 192 193# 194# Make sure the active dataset is mounted for the zone. 195# 196mount_active_ds() { 197 get_zonepath_ds $zonepath 198 get_active_ds $ZONEPATH_DS 199 200 # If already mounted then we're done. 201 mnted=`zfs get -H mounted $ACTIVE_DS | cut -f3` 202 [[ $mnted = "yes" ]] && return 203 204 mount -F zfs $ACTIVE_DS $zonepath/root || fail_fatal "$f_zfs_mount" 205} 206 207# 208# Set up ZFS dataset hierarchy for the zone root dataset. 209# 210create_active_ds() { 211 # Find the zone's current dataset. This should have been created by 212 # zoneadm (or the attach hook). 213 get_zonepath_ds $zonepath 214 215 # 216 # We need to tolerate errors while creating the datasets and making the 217 # mountpoint, since these could already exist from an attach scenario. 218 # 219 220 /usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1 221 if (( $? != 0 )); then 222 /usr/sbin/zfs create -o mountpoint=legacy -o zoned=on \ 223 $ZONEPATH_DS/ROOT 224 if (( $? != 0 )); then 225 fail_fatal "$f_zfs_create" 226 fi 227 else 228 /usr/sbin/zfs set mountpoint=legacy $ZONEPATH_DS/ROOT \ 229 >/dev/null 2>&1 230 /usr/sbin/zfs set zoned=on $ZONEPATH_DS/ROOT \ 231 >/dev/null 2>&1 232 fi 233 234 get_active_ds $ZONEPATH_DS 235 zfs list -H -o name $ACTIVE_DS >/dev/null 2>&1 236 if (( $? != 0 )); then 237 zfs create -o canmount=noauto $ACTIVE_DS 238 (( $? != 0 )) && fail_fatal "$f_zfs_create" 239 else 240 zfs set canmount=noauto $ACTIVE_DS >/dev/null 2>&1 241 zfs inherit mountpoint $ACTIVE_DS >/dev/null 2>&1 242 zfs inherit zoned $ACTIVE_DS >/dev/null 2>&1 243 fi 244 245 if [ ! -d $ZONEROOT ]; then 246 /usr/bin/mkdir -m 0755 -p $ZONEROOT || \ 247 fail_fatal "$f_mkdir" "$ZONEROOT" 248 fi 249 /usr/bin/chmod 700 $ZONEPATH || fail_fatal "$f_chmod" "$ZONEPATH" 250 251 mount -F zfs $ACTIVE_DS $ZONEROOT || fail_fatal "$f_zfs_mount" 252} 253 254# 255# Before booting the zone we may need to create a few mnt points, just in 256# case they don't exist for some reason. 257# 258# Whenever we reach into the zone while running in the global zone we 259# need to validate that none of the interim directories are symlinks 260# that could cause us to inadvertently modify the global zone. 261# 262mk_zone_dirs() { 263 vlog "$v_mkdirs" 264 if [[ ! -f $ZONEROOT/tmp && ! -d $ZONEROOT/tmp ]]; then 265 mkdir -m 1777 -p $ZONEROOT/tmp || exit $EXIT_CODE 266 fi 267 if [[ ! -f $ZONEROOT/var/run && ! -d $ZONEROOT/var/run ]]; then 268 mkdir -m 1755 -p $ZONEROOT/var/run || exit $EXIT_CODE 269 fi 270 if [[ ! -f $ZONEROOT/var/tmp && ! -d $ZONEROOT/var/tmp ]]; then 271 mkdir -m 1777 -p $ZONEROOT/var/tmp || exit $EXIT_CODE 272 fi 273 if [[ ! -h $ZONEROOT/etc && ! -f $ZONEROOT/etc/mnttab ]]; then 274 /usr/bin/touch $ZONEROOT/etc/mnttab || exit $EXIT_CODE 275 /usr/bin/chmod 444 $ZONEROOT/etc/mnttab || exit $EXIT_CODE 276 fi 277 if [[ ! -f $ZONEROOT/proc && ! -d $ZONEROOT/proc ]]; then 278 mkdir -m 755 -p $ZONEROOT/proc || exit $EXIT_CODE 279 fi 280 if [[ ! -f $ZONEROOT/dev && ! -d $ZONEROOT/dev ]]; then 281 mkdir -m 755 -p $ZONEROOT/dev || exit $EXIT_CODE 282 fi 283 if [[ ! -h $ZONEROOT/etc && ! -h $ZONEROOT/etc/svc && \ 284 ! -d $ZONEROOT/etc/svc ]]; then 285 mkdir -m 755 -p $ZONEROOT/etc/svc/volatile || exit $EXIT_CODE 286 fi 287} 288 289# 290# We're sys-unconfig-ing the zone. This will normally halt the zone, however 291# there are problems with sys-unconfig and it can hang when the zone is booted 292# to milestone=none. Sys-unconfig also sometimes hangs halting the zone. 293# Thus, we take some care to workaround these sys-unconfig limitations. 294# 295# On entry we expect the zone to be booted. We use sys-unconfig -R to make it 296# think its working on an alternate root and let the caller halt the zone. 297# 298sysunconfig_zone() { 299 /usr/sbin/zlogin -S $ZONENAME /usr/sbin/sys-unconfig -R /./ \ 300 >/dev/null 2>&1 301 if (( $? != 0 )); then 302 error "$e_unconfig" 303 return 1 304 fi 305 306 return 0 307} 308 309# 310# Get zone's uuid for service tag. 311# 312get_inst_uuid() 313{ 314 typeset ZONENAME="$1" 315 316 ZONEUUID=`zoneadm -z $ZONENAME list -p | nawk -F: '{print $5}'` 317 [[ $? -ne 0 || -z $ZONEUUID ]] && return 1 318 319 INSTANCE_UUID="urn:st:${ZONEUUID}" 320 return 0 321} 322 323# 324# Add a service tag for a given zone. We use two UUIDs-- the first, 325# the Product UUID, comes from the Sun swoRDFish ontology. The second 326# is the UUID of the zone itself, which forms the instance UUID. 327# 328add_svc_tag() 329{ 330 typeset ZONENAME="$1" 331 typeset SOURCE="$2" 332 333 if [ ! -x $STCLIENT ]; then 334 vlog "$v_no_tags" 335 return 0 336 fi 337 338 get_inst_uuid "$ZONENAME" || (error "$e_bad_uuid"; return 1) 339 340 vlog "$v_addtag" "$INSTANCE_UUID" 341 $STCLIENT -a \ 342 -p "$ST_PRODUCT_NAME" \ 343 -e "$ST_PRODUCT_REV" \ 344 -t "$ST_PRODUCT_UUID" \ 345 -i "$INSTANCE_UUID" \ 346 -P "none" \ 347 -m "Sun" \ 348 -A `uname -p` \ 349 -z "$ZONENAME" \ 350 -S "$SOURCE" >/dev/null 2>&1 351 352 err=$? 353 354 # 226 means "duplicate record," which we can ignore. 355 if [[ $err -ne 0 && $err -ne 226 ]]; then 356 error "$e_addtag_fail" "$err" 357 return 1 358 fi 359 return 0 360} 361 362# 363# Remove a service tag for a given zone. 364# 365del_svc_tag() 366{ 367 typeset ZONENAME="$1" 368 369 if [ ! -x $STCLIENT ]; then 370 vlog "$v_no_tags" 371 return 0 372 fi 373 374 get_inst_uuid "$ZONENAME" || (error "$e_bad_uuid"; return 1) 375 376 vlog "$v_deltag" "$INSTANCE_UUID" 377 $STCLIENT -d -i "$INSTANCE_UUID" >/dev/null 2>&1 378 return 0 379} 380