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 26 unset LD_LIBRARY_PATH 27 PATH=/usr/bin:/usr/sbin 28 export PATH 29 30 . /usr/lib/brand/shared/common.ksh 31 32 # Values for service tags. 33 STCLIENT=/usr/bin/stclient 34 ST_PRODUCT_NAME="Solaris 10 Containers" 35 ST_PRODUCT_REV="1.0" 36 ST_PRODUCT_UUID="urn:uuid:2f459121-dec7-11de-9af7-080020a9ed93" 37 38 w_sanity_detail=$(gettext " WARNING: Skipping image sanity checks.") 39 f_sanity_detail=$(gettext "Missing %s at %s") 40 f_sanity_sparse=$(gettext "Is this a sparse zone image? The image must be whole-root.") 41 f_sanity_vers=$(gettext "The image release version must be 10 (got %s), the zone is not usable on this system.") 42 f_not_s10_image=$(gettext "%s doesn't look like a Solaris 10 image.") 43 f_sanity_nopatch=$(gettext "Unable to determine the image's patch level.") 44 f_sanity_downrev=$(gettext "The image patch level is downrev for running in a solaris10 branded zone.\n(patchlist %s)") 45 f_need_newer_emul=$(gettext "The image requires a newer version of the solaris10 brand emulation.") 46 f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.") 47 f_no_ds=$(gettext "No zonepath dataset; the zonepath must be a ZFS dataset.") 48 f_multiple_ds=$(gettext "Multiple active datasets.") 49 f_no_active_ds=$(gettext "No active dataset; the zone's ZFS root dataset must be configured as\n\ta zone boot environment.") 50 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") 51 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.") 52 incompat_options=$(gettext "mutually exclusive options.\n%s") 53 54 sanity_ok=$(gettext " Sanity Check: Passed. Looks like a Solaris 10 image.") 55 sanity_fail=$(gettext " Sanity Check: FAILED (see log for details).") 56 57 e_badboot=$(gettext "Zone boot failed") 58 e_nosingleuser=$(gettext "ERROR: zone did not finish booting to single-user.") 59 e_unconfig=$(gettext "sys-unconfig failed") 60 v_unconfig=$(gettext "Performing zone sys-unconfig") 61 62 v_no_tags=$(gettext "Service tags facility not present.") 63 e_bad_uuid=$(gettext "Failed to get zone UUID") 64 v_addtag=$(gettext "Adding service tag: %s") 65 v_deltag=$(gettext "Removing service tag: %s") 66 e_addtag_fail=$(gettext "Adding service tag failed (error: %s)") 67 68 sanity_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 189 get_active_ds() { 190 ACTIVE_DS=$1/ROOT/zbe-0 191 } 192 193 # 194 # Make sure the active dataset is mounted for the zone. 195 # 196 mount_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 # 210 create_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 # 262 mk_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 # 298 sysunconfig_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 # 312 get_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 # 328 add_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 # 365 del_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 }