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