1#!/bin/ksh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22# 23# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27# 0a Initialization. 28 29[ -f /lib/svc/share/smf_include.sh ] || exit 1 30 31. /lib/svc/share/smf_include.sh 32. /lib/svc/share/manifest_cleanup.ksh 33 34activity=false 35 36X= 37while getopts n opt; do 38 case $opt in 39 n) X=echo;; 40 ?) echo "Usage: /lib/svc/method/manifest-import [-n]\n" 41 exit 2;; 42 esac 43done 44 45function svccfg_apply { 46 $X /usr/sbin/svccfg apply $1 47 if [ $? -ne 0 ]; then 48 echo "WARNING: svccfg apply $1 failed" | tee /dev/msglog 49 fi 50} 51 52function svccfg_import { 53 $X /usr/sbin/svccfg import $1 2>>/tmp/manifest_import.$$ 54 if [ $? -ne 0 ]; then 55 echo > /dev/msglog 56 echo "WARNING: svccfg import $1 failed" | tee /dev/msglog 57 fi 58} 59 60function prophist_upgrade { 61 # 62 # A property has changed in the manifest that we wish to propagate into 63 # the repository during manifest import. We don't want to pollute 64 # manifests with overrides, so handle explicitly here. 65 # 66 fmri=$1 67 pgrp=$2 68 prop=$3 69 nval=$4 70 shift 4 71 72 /lib/svc/bin/prophist upgrade -e $fmri -g $pgrp -p $prop -n "$nval" \ 73 "$@" 74 [ $? = 0 ] && instance_refresh $fmri 75} 76 77function prophist_override { 78 # 79 # A property has changed in the manifest that we wish to propagate 80 # into the repository during manifest import. 81 # 82 fmri=$1 83 pgrp=$2 84 prop=$3 85 nval=$4 86 87 /lib/svc/bin/prophist overwrite -e $fmri -g $pgrp -p $prop -n "$nval" 88 [ $? = 0 ] && instance_refresh $fmri 89} 90 91function prophist_delete_svc_pg { 92 # 93 # Certain property groups have migrated from the service level to the 94 # instance level. We don't care if they are at both, as the instance 95 # level will trump. But having neither could be bad. So check and if 96 # the given pg exists at both levels, delete the service-level one only. 97 # 98 service=$1 99 instance=$2 100 property_group=$3 101 102 /usr/bin/svcprop -q -p $property_group $service 103 res1=$? 104 /usr/bin/svcprop -q -c -p $property_group $service:$instance 105 res2=$? 106 if [ $res1 -eq 0 -a $res2 -eq 0 ]; then 107 /lib/svc/bin/prophist delete -e $service -g $property_group 108 instance_refresh $service:$instance 109 fi 110} 111 112function prophist_delete_dependency { 113 # 114 # Some services have stale dependencies that need to be removed. 115 # This is done by removing the dependency property group. 116 # 117 fmri=$1 118 property_group=$2 119 120 /usr/bin/svcprop -q -c -p $property_group $fmri 121 if [ $? -eq 0 ]; then 122 /lib/svc/bin/prophist delete -e $fmri -g $property_group 123 else 124 [ -n "$_MFST_DEBUG" ] && \ 125 echo "Dependency $property_group not defined on $fmri" 126 fi 127} 128 129function prophist_delete_pg { 130 # Delete obsolete property groups from old manifests. Instances 131 # should be refreshed for changes to take effect. 132 fmri=$1 133 pg=$2 134 135 /usr/bin/svcprop -Cqp $pg $fmri && 136 /lib/svc/bin/prophist delete -e $fmri -g $pg 137} 138 139function prophist_addprop { 140 # 141 # If a property doesn't exist, create it. Instances should be 142 # refreshed for changes to take effect. 143 # 144 if [ $# -lt 6 ]; then 145 echo "prophist_addprop(): Insufficient arguments ($*)." 146 exit 1 147 fi 148 149 fmri=$1 150 /usr/bin/svcprop -q $fmri || return 151 152 pg=$2 153 pgtype=$3 154 prop=$4 155 156 /usr/bin/svcprop -Cqp $pg/$prop $fmri && return 157 158 shift 4 159 160 /usr/bin/svcprop -Cqp $pg $fmri || \ 161 /usr/sbin/svccfg -s $fmri addpg $pg $pgtype 162 /usr/sbin/svccfg -s $fmri setprop $pg/$prop = $* 163} 164 165function prophist_addmeth { 166 # 167 # If a method doesn't exist, create it. Instances should be refreshed 168 # for changes to take effect. 169 # 170 if [ $# -ne 4 ]; then 171 echo "prophist_addmeth(): Insufficient arguments ($*)" 172 exit 1 173 fi 174 175 fmri=$1 176 /usr/bin/svcprop -q $fmri || return 177 178 name=$2 179 /usr/bin/svcprop -Cqp $name $fmri && return 180 181 exec=$3 182 to=$4 183 184 /usr/sbin/svccfg -s $fmri <<END 185 addpg $name method 186 setprop $name/type = astring: method 187 setprop $name/exec = astring: "$exec" 188 setprop $name/timeout_seconds = count: $to 189END 190} 191 192function prophist_adddep { 193 # 194 # If a dependency doesn't exist, create it. Instances should be 195 # refreshed for changes to take effect. 196 # 197 if [ $# -lt 6 ]; then 198 echo "prophist_adddep(): Insufficient arguments ($*)" 199 exit 1 200 fi 201 202 fmri=$1 203 /usr/bin/svcprop -q $fmri || return 204 205 name=$2 206 /usr/bin/svcprop -Cqp $name $fmri && return 207 208 type=$3 209 group=$4 210 ro=$5 211 shift 5 212 213 /usr/sbin/svccfg -s $fmri <<END 214 addpg $name dependency 215 setprop $name/type = astring: $type 216 setprop $name/grouping = astring: $group 217 setprop $name/restart_on = astring: $ro 218 setprop $name/entities = fmri: $* 219END 220} 221 222function prophist_adddpt { 223 # 224 # If a dependent doesn't exist, create it. Instances should be 225 # refresh for changes to take effect. 226 # 227 if [ $# -ne 5 ]; then 228 echo "prophist_adddpt(): Incorrect arguments ($*).\n" 229 exit 1 230 fi 231 232 fmri=$1 233 /usr/bin/svcprop -q $fmri || return 234 235 name=$2 236 /usr/bin/svcprop -Cqp dependents/$name $fmri && return 237 238 group=$3 239 ro=$4 240 target=$5 241 242 prophist_addprop $fmri dependents framework $name fmri: $target 243 prophist_adddep $target $name service $group $ro $fmri 244} 245 246function instance_refresh { 247 echo $1 >> /etc/svc/volatile/refreshes 248} 249 250function refresh_instances { 251 [ -r /etc/svc/volatile/refreshes ] && { 252 sort -u /etc/svc/volatile/refreshes | xargs -l svcadm refresh 253 } 254} 255 256function instance_clear { 257 echo $1 >> /etc/svc/volatile/clears 258} 259 260function clear_conditionally { 261 [ "`/usr/bin/svcprop -p restarter/state $1`" = "maintenance" ] && \ 262 /usr/sbin/svcadm clear $1 263} 264 265function clear_instances { 266 [ -r /etc/svc/volatile/clears ] && { 267 for inst in `/usr/bin/sort -u /etc/svc/volatile/clears`; do 268 clear_conditionally $inst 269 done 270 } 271} 272 273function prepare_last_import { 274 # Preserve the five hashes for the profiles: generic (two 275 # cases), platform (uname -i, uname -m outputs), and site. 276 277 gn="var_svc_profile_generic_open_xml" 278 gh=`/usr/bin/svcprop -p ${gn}/md5sum smf/manifest 2>/dev/null` 279 [ $? = 0 ] || gh="" 280 281 gln="var_svc_profile_generic_limited_net_xml" 282 glh=`/usr/bin/svcprop -p ${gln}/md5sum smf/manifest 2>/dev/null` 283 [ $? = 0 ] || glh="" 284 285 LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _` 286 pln="var_svc_profile_platform_${pl}_xml" 287 plh=`/usr/bin/svcprop -p ${pln}/md5sum smf/manifest 2>/dev/null` 288 [ $? = 0 ] || plh="" 289 290 LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _` 291 if [ $plm != $pl ]; then 292 plmn="var_svc_profile_platform_${plm}_xml" 293 plmh=`/usr/bin/svcprop -p ${plmn}/md5sum smf/manifest \ 294 2>/dev/null` 295 [ $? = 0 ] || plmh="" 296 else 297 plmh="" 298 fi 299 300 sn="var_svc_profile_site_xml" 301 sh=`/usr/bin/svcprop -p $sn/md5sum smf/manifest 2>/dev/null` 302 [ $? = 0 ] || sh="" 303 304 # Remove all manifest hashes. 305 /usr/sbin/svccfg delete smf/manifest 306 307 # Restore smf/manifest and hash values. 308 /usr/sbin/svccfg add smf/manifest 309 [ -n "$gh" ] && { 310 echo "Preserving generic hash ($gh)." 311 /usr/sbin/svccfg -s smf/manifest addpg ${gn} framework 312 /usr/sbin/svccfg -s smf/manifest setprop ${gn}/md5sum = \ 313 opaque: $gh 314 } 315 [ -n "$glh" ] && { 316 echo "Preserving generic_limited hash ($glh)." 317 /usr/sbin/svccfg -s smf/manifest addpg ${gln} framework 318 /usr/sbin/svccfg -s smf/manifest setprop ${gln}/md5sum = \ 319 opaque: $glh 320 } 321 [ -n "$plh" ] && { 322 echo "Preserving platform hash ($plh)." 323 /usr/sbin/svccfg -s smf/manifest addpg $pln framework 324 /usr/sbin/svccfg -s smf/manifest setprop $pln/md5sum = \ 325 opaque: $plh 326 } 327 [ -n "$plmh" ] && { 328 echo "Preserving platform hash ($plmh)." 329 /usr/sbin/svccfg -s smf/manifest addpg $plmn framework 330 /usr/sbin/svccfg -s smf/manifest setprop $plmn/md5sum = \ 331 opaque: $plmh 332 } 333 [ -n "$sh" ] && { 334 echo "Preserving site hash ($sh)." 335 /usr/sbin/svccfg -s smf/manifest addpg $sn framework 336 /usr/sbin/svccfg -s smf/manifest setprop $sn/md5sum = \ 337 opaque: $sh 338 } 339} 340 341# 342# 0b Cleanup deathrow 343# 344deathrow=/etc/svc/deathrow 345if [ -s $deathrow ];then 346 # 347 # svc.startd has unconfigured the services found in deathrow, 348 # clean them now. 349 # 350 while read fmri mfst pkgname; do 351 # Delete services and instances from the deathrow file. 352 /usr/sbin/svccfg delete -f $fmri >/dev/null 2>&1 353 # Remove deathrow manifest hash. 354 /usr/sbin/svccfg delhash -d $mfst >/dev/null 2>&1 355 done < $deathrow 356 /usr/bin/mv $deathrow $deathrow.old 357fi 358SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH 359 360# 361# 0c Clean up repository 362# 363if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null | 364 /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null 365then 366 set -- ` 367 /usr/bin/svcprop smf/manifest 2>/dev/null | 368 /usr/bin/grep '^ar_svc[^/]*/md5sum opaque ' | 369 /usr/bin/tr '/' ' ' | 370 while read pg prop type value; do 371 echo "$pg/$value" 372 done 373 ` 374 backup=`echo "$#/$#" | sed 's/.//g'` 375 fwidth=`echo "$#\c" | wc -c` 376 377 echo "Converting obsolete repository entries: \c" > /dev/msglog 378 i=1; n=$# 379 while [ $# -gt 0 ]; do 380 printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog 381 echo $1 | sed 's:/: :' | ( 382 read pg value 383 384 (echo "select /smf/manifest"; echo "delpg v$pg") | 385 /usr/sbin/svccfg 2>/dev/null >/dev/null 386 (echo "select /smf/manifest"; echo "delpg $pg") | 387 /usr/sbin/svccfg 2>/dev/null >/dev/null 388 (echo "select /smf/manifest"; 389 echo "addpg v$pg framework") | 390 /usr/sbin/svccfg 2>/dev/null >/dev/null 391 (echo "select /smf/manifest"; 392 echo "setprop v$pg/md5sum = opaque: $value") | 393 /usr/sbin/svccfg 2>/dev/null >/dev/null 394 ) 395 i=`expr $i + 1` 396 shift 397 echo "$backup\c" > /dev/msglog 398 done 399 echo > /dev/msglog 400 echo "Converted $n obsolete repository entries" 401 activity=true 402fi 403 404# 405# If no last-import snapshots are present on critical services, then we are 406# creating the last-import snapshots for the first time post upgrade. 407# 408create_last_import=1 409for svc in single-user multi-user multi-user-server; do 410 if /usr/bin/svcprop -s last-import svc:/milestone/$svc:default \ 411 >/dev/null 2>&1 412 then 413 create_last_import= 414 break 415 fi 416done 417 418if [ $create_last_import ]; then 419 echo "Last import snapshots absent; preparing for re-import" 420 prepare_last_import 421 422 # 423 # Apply property history files. 424 # 425 echo "Upgrade detected; applying property history" 426 for phist in /var/svc/profile/prophist.*; do 427 /lib/svc/bin/prophist hash $phist 428 if [ $? = 3 ]; then 429 echo "Sourcing $phist" 430 . $phist 431 fi 432 done 433 434 /usr/bin/rm -f /var/svc/profile/.upgrade_prophist 435fi 436 437# 438# 2. Manifest import. Application directories first, then 439# site-specific manifests. 440# 441nonsite_dirs=`/usr/bin/find /var/svc/manifest/* -name site -prune -o -type d \ 442 -print -prune` 443 444nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs` 445site_manifests=`/lib/svc/bin/mfstscan /var/svc/manifest/site` 446 447manifests="$nonsite_manifests $site_manifests" 448 449[ -n "$_MFST_DEBUG" ] && { 450 echo "Changed manifests to import:" 451 for m in $manifests; do echo " $m"; done 452} 453 454# 455# 2b. Import the manifests while giving a running display of imports on 456# console, and a final count in the logfile. 457# 458if [ -n "$nonsite_manifests" -o -n "$site_manifests" ]; then 459 rm -f /tmp/manifest_import.$$ 460 461 set -- $manifests 462 cleanup="" 463 backup=`echo "$#/$#" | sed 's/.//g'` 464 fwidth=`echo "$#\c" | wc -c` 465 466 echo "Loading smf(5) service descriptions: \c" > /dev/msglog 467 468 # 469 # Attempt of moving the repository to tmpfs. If that doesn't 470 # work, reset doswitch so we don't attempt switching back. 471 # 472 /usr/sbin/svcadm _smf_repository_switch fast 473 doswitch=$? 474 475 i=1; n=$# 476 svcprop smf/manifest > /etc/svc/volatile/smf_manifest_svcprop 2>&1 477 while [ $# -gt 0 ]; do 478 printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog 479 grep $1 /etc/svc/volatile/smf_manifest_svcprop > /dev/null 2>&1 480 if [ $? -eq 0 ]; then 481 cleanup="$cleanup $1" 482 fi 483 svccfg_import $1 484 i=`expr $i + 1` 485 shift 486 echo "$backup\c" > /dev/msglog 487 done 488 rm -f /etc/svc/volatile/smf_manifest_svcprop 489 490 # 491 # If switch back fails, exit with the fatal error code. 492 # Normally the failure indicates that there is a serious 493 # problem on the root file system such as file operation 494 # failure or repository access failure. 495 # 496 if [ $doswitch -eq 0 ]; then 497 /usr/sbin/svcadm _smf_repository_switch perm || { \ 498 echo "Repository switch back operation failed, \c" 499 echo "please check the system log for the" 500 echo "possible fatal error messages." 501 exit $SMF_EXIT_ERR_FATAL 502 } 503 fi 504 505 echo > /dev/msglog 506 echo "Loaded $n smf(5) service descriptions" 507 activity=true 508 509 if [ -s /tmp/manifest_import.$$ ]; then 510 echo "svccfg warnings:" 511 cat /tmp/manifest_import.$$ 512 513 msg="svccfg import warnings. See" 514 msg="$msg /var/svc/log/system-manifest-import:default.log ." 515 echo $msg > /dev/msglog 516 fi 517 rm -f /tmp/manifest_import.$$ 518fi 519 520# 521# 3. Profile application. We must create the platform profile upon 522# first boot, as we may be a diskless client of a platform or 523# architecture distinct from our NFS server. 524# 525svccfg_apply /var/svc/profile/generic.xml 526 527if [ ! -f /var/svc/profile/platform.xml ]; then 528 this_karch=`uname -m` 529 this_plat=`uname -i` 530 531 if [ -f /var/svc/profile/platform_$this_plat.xml ]; then 532 platform_profile=platform_$this_plat.xml 533 elif [ -f /var/svc/profile/platform_$this_karch.xml ]; then 534 platform_profile=platform_$this_karch.xml 535 else 536 platform_profile=platform_none.xml 537 fi 538 539 ln -s $platform_profile /var/svc/profile/platform.xml 540fi 541 542svccfg_apply /var/svc/profile/platform.xml 543 544# 545# 4. Upgrade handling. The upgrade file generally consists of a series 546# of svcadm(1M) and svccfg(1M) commands. 547# 548( 549 unset SVCCFG_CHECKHASH 550 551 if [ -f /var/svc/profile/upgrade ]; then 552 . /var/svc/profile/upgrade 553 554 /usr/bin/mv /var/svc/profile/upgrade \ 555 /var/svc/profile/upgrade.app.`date +\%Y\%m\%d\%H\%M\%S` 556 activity=true 557 fi 558 559 # 560 # Rename the datalink upgrade script file. This script is used in the 561 # network/physical service to upgrade datalink configuration, but 562 # the file cannot be renamed until now (when the file system becomes 563 # read-write). 564 # 565 datalink_script=/var/svc/profile/upgrade_datalink 566 if [ -f "${datalink_script}" ]; then 567 /usr/bin/mv "${datalink_script}" \ 568 "${datalink_script}".app.`date +\%Y\%m\%d\%H\%M\%S` 569 fi 570) 571 572# 573# 5. Site profile is applied last to give administrator the final say. 574# 575if [ -f /var/svc/profile/site.xml ]; then 576 svccfg_apply /var/svc/profile/site.xml 577fi 578 579# 580# 6. Final actions. 581# 582refresh_instances 583clear_instances 584 585if $activity; then 586 svcadm _smf_backup "manifest_import" || true 587fi 588 589manifest_cleanup $activity $cleanup 590 591exit 0 592