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