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 # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23 # 24 25 # 0a Initialization. 26 27 [ -f /lib/svc/share/smf_include.sh ] || exit 1 28 29 . /lib/svc/share/smf_include.sh 30 31 activity=false 32 33 EMI_SERVICE="svc:/system/early-manifest-import:default" 34 PROFILE_DIR_SITE="/etc/svc/profile/site" 35 36 X= 37 ALT_REPOSITORY= 38 ALT_MFST_DIR= 39 early=false 40 [ "$SMF_FMRI" == "$EMI_SERVICE" ] && early=true 41 42 usage() 43 { 44 echo "Usage: /lib/svc/method/manifest-import [-n]" \ 45 "[-f repository-file -d manifest-directory]" 46 echo "\nOptions:" 47 echo "-n dryrun" 48 echo "-f and -d specify alternate repository and" \ 49 "manifest directory for import\n" 50 exit 2 51 } 52 53 while getopts "nd:f:" opt; do 54 case $opt in 55 n) X=echo;; 56 d) ALT_MFST_DIR=$OPTARG;; 57 f) ALT_REPOSITORY=$OPTARG;; 58 ?) usage;; 59 esac 60 done 61 62 # 63 # Both -f and -d options must be specified together or not specified at all 64 # 65 [ -n "$ALT_REPOSITORY" -a -z "$ALT_MFST_DIR" ] && usage 66 [ -n "$ALT_MFST_DIR" -a -z "$ALT_REPOSITORY" ] && usage 67 68 function svccfg_apply { 69 $X /usr/sbin/svccfg apply $1 70 if [ $? -ne 0 ]; then 71 echo "WARNING: svccfg apply $1 failed" | tee /dev/msglog 72 fi 73 } 74 75 # 76 # If the smf/manifest table has file entries that are missing 77 # then there is work to be done by the cleanup process. 78 # 79 function cleanup_needwork { 80 if [ "$early" == true ]; then 81 smfmfiles=`/usr/bin/svcprop smf/manifest | \ 82 awk '(/^lib_/ && /\/manifestfile /) {print $3}'` 83 else 84 smfmfiles=`/usr/bin/svcprop smf/manifest | \ 85 awk '/\/manifestfile / {print $3}'` 86 fi 87 88 nw=`/lib/svc/bin/mfstscan $smfmfiles 2>&1 1>/dev/null` 89 [ "$nw" ] && return 1 90 91 return 0 92 } 93 94 # 95 # Upon upgrading to early manifest import code, preserve hashes of system 96 # profiles which lived under /var/svc/profile so that svccfg apply would 97 # not re-apply the profiles and overwrite user customizations. Simply 98 # migrate manifestfile and hash values to new property groups named after 99 # profiles under /etc/svc/profile. If the profiles don't really exist, 100 # svccfg cleanup will remove the property groups in a later step. 101 # 102 # Existing generic.xml, inetd_services.xml, and name_service.xml symlinks 103 # need to be preserved. 104 # 105 # Don't process site.xml profile since it is still supported under 106 # /var/svc/profile directory. 107 # 108 function preserve_system_profiles { 109 110 # 111 # If /var is a separate fs, return and let Late Import 112 # preserves the hashes. 113 # 114 [ -d "/var/svc/profile" ] || return 1 115 116 # 117 # Preserve hashes for the following profiles: generic (two 118 # cases) and platform (uname -i, uname -m outputs). 119 # 120 gn="var_svc_profile_generic_open_xml" 121 gh=`/usr/bin/svcprop -p ${gn}/md5sum smf/manifest 2>/dev/null` 122 [ $? = 0 ] || gh="" 123 gn="etc_svc_profile_generic_open_xml" 124 125 gln="var_svc_profile_generic_limited_net_xml" 126 glh=`/usr/bin/svcprop -p ${gln}/md5sum smf/manifest 2>/dev/null` 127 [ $? = 0 ] || glh="" 128 gln="etc_svc_profile_generic_limited_net_xml" 129 130 LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _` 131 pln="var_svc_profile_platform_${pl}_xml" 132 plh=`/usr/bin/svcprop -p ${pln}/md5sum smf/manifest 2>/dev/null` 133 [ $? = 0 ] || plh="" 134 pln="etc_svc_profile_platform_${pl}_xml" 135 136 LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _` 137 if [ $plm != $pl ]; then 138 plmn="var_svc_profile_platform_${plm}_xml" 139 plmh=`/usr/bin/svcprop -p ${plmn}/md5sum smf/manifest \ 140 2>/dev/null` 141 [ $? = 0 ] || plmh="" 142 plmn="etc_svc_profile_platform_${plm}_xml" 143 else 144 plmh="" 145 fi 146 147 [ -n "$gh" ] && { 148 echo "Preserving generic hash ($gh)." 149 /usr/sbin/svccfg -s smf/manifest addpg ${gn} framework 150 /usr/sbin/svccfg -s smf/manifest setprop ${gn}/md5sum = \ 151 opaque: $gh 152 /usr/sbin/svccfg -s smf/manifest setprop ${gn}/manifestfile = \ 153 astring: "/etc/svc/profile/generic.xml" 154 } 155 [ -n "$glh" ] && { 156 echo "Preserving generic_limited hash ($glh)." 157 /usr/sbin/svccfg -s smf/manifest addpg ${gln} framework 158 /usr/sbin/svccfg -s smf/manifest setprop ${gln}/md5sum = \ 159 opaque: $glh 160 /usr/sbin/svccfg -s smf/manifest setprop ${gln}/manifestfile = \ 161 astring: "/etc/svc/profile/generic.xml" 162 } 163 [ -n "$plh" ] && { 164 echo "Preserving platform hash ($plh)." 165 /usr/sbin/svccfg -s smf/manifest addpg $pln framework 166 /usr/sbin/svccfg -s smf/manifest setprop $pln/md5sum = \ 167 opaque: $plh 168 /usr/sbin/svccfg -s smf/manifest setprop ${pln}/manifestfile = \ 169 astring: "/etc/svc/profile/platform_${pl}_xml" 170 } 171 [ -n "$plmh" ] && { 172 echo "Preserving platform hash ($plmh)." 173 /usr/sbin/svccfg -s smf/manifest addpg $plmn framework 174 /usr/sbin/svccfg -s smf/manifest setprop $plmn/md5sum = \ 175 opaque: $plmh 176 /usr/sbin/svccfg -s smf/manifest setprop \ 177 ${plmn}/manifestfile = \ 178 astring: "/etc/svc/profile/platform_${plm}_xml" 179 } 180 181 # 182 # Move symlinks from /var/svc/profile to /etc/svc/profile 183 # 184 generic_prof="/var/svc/profile/generic.xml" 185 ns_prof="/var/svc/profile/name_service.xml" 186 inetd_prof="/var/svc/profile/inetd_services.xml" 187 platform_prof="/var/svc/profile/platform.xml" 188 [ -L "$generic_prof" ] && mv $generic_prof /etc/svc/profile/ 189 [ -L "$ns_prof" ] && mv $ns_prof /etc/svc/profile/ 190 [ -L "$inetd_prof" ] && mv $inetd_prof /etc/svc/profile/ 191 [ -L "$platform_prof" ] && mv $platform_prof /etc/svc/profile/ 192 193 return 0 194 } 195 196 # 197 # 2. Manifest import. Application directories first, then 198 # site-specific manifests. 199 # 200 function import_manifests { 201 typeset basedir=$1 202 typeset console_print=$2 203 typeset logf="/etc/svc/volatile/manifest_import.$$" 204 205 rm -f $logf 206 207 nonsite_dirs=`/usr/bin/find $basedir/* -name site \ 208 -prune -o -type d -print -prune` 209 210 if [ -n "$_MFST_DEBUG" ]; then 211 nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs` 212 site_manifests=`/lib/svc/bin/mfstscan $basedir/site` 213 214 manifests="$nonsite_manifests $site_manifests" 215 216 echo "Changed manifests to import:" 217 for m in $manifests; do echo " $m"; done 218 fi 219 220 # 221 # Upon boot, attempt to move the repository to tmpfs. 222 # 223 if [ -z "$ALT_REPOSITORY" -a -z "$ALT_MFST_DIR" ]; then 224 /usr/sbin/svcadm _smf_repository_switch fast 225 fi 226 227 # 228 # Import the manifests while giving a running display of imports on 229 # console, and a final count in the logfile. 230 # 231 dirs="$nonsite_dirs" 232 [ -d "$basedir/site" ] && dirs="$dirs $basedir/site" 233 234 if [ "$console_print" = "true" ]; then 235 $X /usr/sbin/svccfg import -p /dev/msglog $dirs > $logf 2>&1 236 else 237 $X /usr/sbin/svccfg import $dirs > $logf 2>&1 238 fi 239 240 grep "Loaded .*. smf(5) service descriptions" $logf > /dev/null 2>&1 241 if [ $? -eq 0 ]; then 242 activity=true 243 fi 244 245 if [ -s $logf ]; then 246 grep "smf(5) service descriptions failed to load" $logf > /dev/null 2>&1 247 failures=$? 248 if [ $failures -eq 0 ]; then 249 echo "svccfg warnings:" 250 fi 251 cat $logf 252 253 if [ $failures -eq 0 -a "$console_print" = "true" ]; then 254 msg="svccfg import warnings. See" 255 msg="$msg /var/svc/log/system-manifest-import:default.log ." 256 echo $msg > /dev/msglog 257 fi 258 fi 259 rm -f $logf 260 } 261 262 # 263 # 3. Profile application. We must create the platform profile upon 264 # first boot, as we may be a diskless client of a platform or 265 # architecture distinct from our NFS server. 266 # 267 # Generic and platform profiles are only supported in /etc. 268 # 269 function apply_profile { 270 # 271 # If smf/manifest doesn't have any profile under /etc/var/profile, 272 # this is very likely an import after upgrade so call 273 # preserve_system_profiles in that case. 274 # 275 LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _` 276 pln="etc_svc_profile_platform_${pl}_xml" 277 278 LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _` 279 [ $plm != $pl ] && plmn="etc_svc_profile_platform_${plm}_xml" 280 281 preserve_profiles=1 282 for prof in $pln $plmn etc_svc_profile_platform_none_xml \ 283 etc_svc_profile_generic_limited_net_xml \ 284 etc_svc_profile_generic_open_xml; do 285 if /usr/bin/svcprop -p $prof smf/manifest >/dev/null 2>&1 286 then 287 preserve_profiles=0 288 break 289 fi 290 done 291 292 if [ $preserve_profiles -eq 1 ]; then 293 echo "/etc/svc system profiles not found: upgrade system profiles" 294 preserve_system_profiles || return 295 fi 296 297 typeset prefix="/etc/svc/profile" 298 svccfg_apply $prefix/generic.xml 299 if [ ! -f $prefix/platform.xml ]; then 300 this_karch=`uname -m` 301 this_plat=`uname -i` 302 303 if [ -f $prefix/platform_$this_plat.xml ]; then 304 platform_profile=platform_$this_plat.xml 305 elif [ -f $prefix/platform_$this_karch.xml ]; then 306 platform_profile=platform_$this_karch.xml 307 else 308 platform_profile=platform_none.xml 309 fi 310 311 ln -s $platform_profile $prefix/platform.xml 312 fi 313 314 svccfg_apply $prefix/platform.xml 315 } 316 317 # 318 # 4. Upgrade handling. The upgrade file generally consists of a series 319 # of svcadm(1M) and svccfg(1M) commands. 320 # 321 function handle_upgrade { 322 323 [ -f /var/svc/profile/upgrade ] && activity=true 324 325 ( 326 unset SVCCFG_CHECKHASH 327 328 if [ -f /var/svc/profile/upgrade ]; then 329 . /var/svc/profile/upgrade 330 331 /usr/bin/mv /var/svc/profile/upgrade \ 332 /var/svc/profile/upgrade.app.`date +\%Y\%m\%d\%H\%M\%S` 333 fi 334 335 # 336 # Rename the datalink upgrade script file. This script is used in the 337 # network/physical service to upgrade datalink configuration, but 338 # the file cannot be renamed until now (when the file system becomes 339 # read-write). 340 # 341 datalink_script=/var/svc/profile/upgrade_datalink 342 if [ -f "${datalink_script}" ]; then 343 /usr/bin/mv "${datalink_script}" \ 344 "${datalink_script}".app.`date +\%Y\%m\%d\%H\%M\%S` 345 fi 346 ) 347 } 348 349 # 350 # 5. Giving administrator the final say, apply site.xml profile and profiles 351 # under /etc/svc/profile/site directory. 352 # 353 function apply_site_profile { 354 typeset prefix="$1" 355 [ -f $prefix/site.xml ] && svccfg_apply $prefix/site.xml 356 357 if [ -d $PROFILE_DIR_SITE -a "$1" = "/etc/svc/profile" ]; then 358 svccfg_apply $PROFILE_DIR_SITE 359 fi 360 } 361 362 # 363 # 0b Cleanup deathrow 364 # 365 if [ "$early" = "false" ];then 366 deathrow=/etc/svc/deathrow 367 if [ -s $deathrow ];then 368 # 369 # svc.startd has unconfigured the services found in deathrow, 370 # clean them now. 371 # 372 while read fmri mfst pkgname; do 373 # Delete services and instances from the deathrow file. 374 /usr/sbin/svccfg delete -f $fmri >/dev/null 2>&1 375 # Remove deathrow manifest hash. 376 /usr/sbin/svccfg delhash -d $mfst >/dev/null 2>&1 377 done < $deathrow 378 /usr/bin/mv $deathrow $deathrow.old 379 fi 380 fi 381 382 SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH 383 384 # 385 # 0c Clean up repository 386 # 387 if [ "$early" = "false" ]; then 388 if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null | 389 /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null 390 then 391 set -- ` 392 /usr/bin/svcprop smf/manifest 2>/dev/null | 393 /usr/bin/grep '^ar_svc[^/]*/md5sum opaque ' | 394 /usr/bin/tr '/' ' ' | 395 while read pg prop type value; do 396 echo "$pg/$value" 397 done 398 ` 399 backup=`echo "$#/$#" | sed 's/.//g'` 400 fwidth=`echo "$#\c" | wc -c` 401 402 echo "Converting obsolete repository entries: \c" > /dev/msglog 403 i=1; n=$# 404 while [ $# -gt 0 ]; do 405 printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog 406 echo $1 | sed 's:/: :' | ( 407 read pg value 408 409 (echo "select /smf/manifest"; echo "delpg v$pg") | 410 /usr/sbin/svccfg 2>/dev/null >/dev/null 411 (echo "select /smf/manifest"; echo "delpg $pg") | 412 /usr/sbin/svccfg 2>/dev/null >/dev/null 413 (echo "select /smf/manifest"; 414 echo "addpg v$pg framework") | 415 /usr/sbin/svccfg 2>/dev/null >/dev/null 416 (echo "select /smf/manifest"; 417 echo "setprop v$pg/md5sum = opaque: $value") | 418 /usr/sbin/svccfg 2>/dev/null >/dev/null 419 ) 420 i=`expr $i + 1` 421 shift 422 echo "$backup\c" > /dev/msglog 423 done 424 echo > /dev/msglog 425 echo "Converted $n obsolete repository entries" 426 activity=true 427 fi 428 429 fi 430 431 # 432 # If the alternate repository and directory are specified, simply set 433 # SVCCFG_REPOSITORY env, run svccfg import on the given directory, and 434 # exit. 435 # 436 if [ -n "$ALT_REPOSITORY" -a -n "$ALT_MFST_DIR" ]; then 437 SVCCFG_REPOSITORY=$ALT_REPOSITORY export SVCCFG_REPOSITORY 438 import_manifests "$ALT_MFST_DIR" false 439 unset SVCCFG_REPOSITORY 440 exit 0 441 fi 442 443 # 444 # Call import and apply profiles here 445 # 446 if [ "$early" = "true" ]; then 447 import_manifests "/lib/svc/manifest" true 448 apply_profile 449 apply_site_profile "/etc/svc/profile" 450 else 451 # 452 # Process both /lib/svc/manifest and /var/svc/manifest 453 # during late manifest-import 454 # 455 # First import the manifests 456 # 457 import_manifests "/lib/svc/manifest" true 458 import_manifests "/var/svc/manifest" true 459 460 # 461 # Apply profiles 462 # 463 apply_profile 464 apply_site_profile "/etc/svc/profile" 465 466 # 467 # Run the upgrade script 468 # 469 handle_upgrade 470 apply_site_profile "/var/svc/profile" 471 fi 472 473 474 # 475 # 6. Final actions. 476 # 477 478 if $activity; then 479 /usr/sbin/svcadm _smf_backup "manifest_import" || true 480 fi 481 482 # 483 # If the filesystem is NOT read only then move the repo back to perm 484 # There is no care wether the switch was made or not, but just want 485 # to move it. If it is already perm this does not affect anything 486 # at least on the surface. REALLY want to improve on this... 487 # 488 touch /etc/svc/smf_rwtest.$$ > /dev/null 2>&1 489 if [ $? -eq 0 ]; then 490 rm -f /etc/svc/smf_rwtest.$$ 491 /usr/sbin/svcadm _smf_repository_switch perm || { \ 492 echo "Repository switch back operation failed, \c" 493 echo "please check the system log for the" 494 echo "possible fatal error messages." 495 exit $SMF_EXIT_ERR_FATAL 496 } 497 fi 498 499 if $activity; then 500 /usr/sbin/svccfg cleanup | /usr/bin/tee /dev/msglog 501 else 502 cleanup_needwork 503 if [ $? -ne 0 ]; then 504 /usr/sbin/svccfg cleanup -a | /usr/bin/tee /dev/msglog 505 fi 506 fi 507 508 exit 0