Home | History | Annotate | Download | only in milestone
      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 
     34 activity=false
     35 
     36 X=
     37 while 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
     43 done
     44 
     45 function 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 
     52 function 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 
     60 function 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 
     77 function 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 
     91 function 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 
    112 function 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 
    129 function 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 
    139 function 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 
    165 function 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
    189 END
    190 }
    191 
    192 function 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: $*
    219 END
    220 }
    221 
    222 function 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 
    246 function instance_refresh {
    247 	echo $1 >> /etc/svc/volatile/refreshes
    248 }
    249 
    250 function refresh_instances {
    251 	[ -r /etc/svc/volatile/refreshes ] && {
    252 		sort -u /etc/svc/volatile/refreshes | xargs -l svcadm refresh
    253 	}
    254 }
    255 
    256 function instance_clear {
    257 	echo $1 >> /etc/svc/volatile/clears
    258 }
    259 
    260 function clear_conditionally {
    261 	[ "`/usr/bin/svcprop -p restarter/state $1`" = "maintenance" ] && \
    262 	    /usr/sbin/svcadm clear $1
    263 }
    264 
    265 function 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 
    273 function 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 #
    344 deathrow=/etc/svc/deathrow
    345 if [ -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
    357 fi
    358 SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH
    359 
    360 #
    361 # 0c Clean up repository
    362 #
    363 if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null |
    364     /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null
    365 then
    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
    402 fi
    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 #
    408 create_last_import=1
    409 for 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
    416 done
    417 
    418 if [ $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
    435 fi
    436 
    437 #
    438 # 2.  Manifest import.  Application directories first, then
    439 # site-specific manifests.
    440 #
    441 nonsite_dirs=`/usr/bin/find /var/svc/manifest/* -name site -prune -o -type d \
    442 	-print -prune`
    443 
    444 nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs`
    445 site_manifests=`/lib/svc/bin/mfstscan /var/svc/manifest/site`
    446 
    447 manifests="$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 #
    458 if [ -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.$$
    518 fi
    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 #
    525 svccfg_apply /var/svc/profile/generic.xml
    526 
    527 if [ ! -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
    540 fi
    541 
    542 svccfg_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 #
    575 if [ -f /var/svc/profile/site.xml ]; then
    576 	svccfg_apply /var/svc/profile/site.xml
    577 fi
    578 
    579 #
    580 # 6.  Final actions.
    581 #
    582 refresh_instances
    583 clear_instances
    584 
    585 if $activity; then
    586 	svcadm _smf_backup "manifest_import" || true
    587 fi
    588 
    589 manifest_cleanup $activity $cleanup
    590 
    591 exit 0
    592