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