xref: /titanic_52/usr/src/cmd/svc/milestone/manifest-import (revision 9512fe850e98fdd448c638ca63fdd92a8a510255)
1#!/sbin/sh
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, Version 1.0 only
7# (the "License").  You may not use this file except in compliance
8# with the License.
9#
10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11# or http://www.opensolaris.org/os/licensing.
12# See the License for the specific language governing permissions
13# and limitations under the License.
14#
15# When distributing Covered Code, include this CDDL HEADER in each
16# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17# If applicable, add the following below this CDDL HEADER, with the
18# fields enclosed by brackets "[]" replaced with your own identifying
19# information: Portions Copyright [yyyy] [name of copyright owner]
20#
21# CDDL HEADER END
22#
23#
24# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27#ident	"%Z%%M%	%I%	%E% SMI"
28
29# 0.  Initialization.
30
31[ -f /lib/svc/share/smf_include.sh ] || exit 1
32
33activity=false
34
35X=
36while getopts n opt; do
37	case $opt in
38		n)	X=echo;;
39		?)	echo "Usage: /lib/svc/method/manifest-import [-n]\n"
40		exit 2;;
41	esac
42done
43
44svccfg_apply () {
45	$X /usr/sbin/svccfg apply $1
46	if [ $? -ne 0 ]; then
47		echo "WARNING: svccfg apply $1 failed" | tee /dev/msglog
48	fi
49}
50
51svccfg_import () {
52	$X /usr/sbin/svccfg import $1 2>>/tmp/manifest_import.$$
53	if [ $? -ne 0 ]; then
54		echo > /dev/msglog
55		echo "WARNING: svccfg import $1 failed" | tee /dev/msglog
56	fi
57}
58
59prophist_upgrade () {
60	#
61	# A property has changed in the manifest that we wish to propagate into
62	# the repository during manifest import.  We don't want to pollute
63	# manifests with overrides, so handle explicitly here.
64	#
65	fmri=$1
66	pgrp=$2
67	prop=$3
68	nval=$4
69	shift 4
70
71	/lib/svc/bin/prophist upgrade -e $fmri -g $pgrp -p $prop -n "$nval" \
72	    "$@"
73	[ $? = 0 ] && instance_refresh $fmri
74}
75
76prophist_override () {
77	#
78	# A property has changed in the manifest that we wish to propagate
79	# into the repository during manifest import.
80	#
81	fmri=$1
82	pgrp=$2
83	prop=$3
84	nval=$4
85
86	/lib/svc/bin/prophist overwrite -e $fmri -g $pgrp -p $prop -n "$nval"
87	[ $? = 0 ] && instance_refresh $fmri
88}
89
90prophist_delete_svc_pg () {
91	#
92	# Certain property groups have migrated from the service level to the
93	# instance level.  We don't care if they are at both, as the instance
94	# level will trump.  But having neither could be bad.  So check and if
95	# the given pg exists at both levels, delete the service-level one only.
96	#
97	service=$1
98	instance=$2
99	property_group=$3
100
101	/usr/bin/svcprop -q -p $property_group $service
102	res1=$?
103	/usr/bin/svcprop -q -c -p $property_group $service:$instance
104	res2=$?
105	if [ $res1 -eq 0 -a $res2 -eq 0 ]; then
106		/lib/svc/bin/prophist delete -e $service -g $property_group
107		instance_refresh $service:$instance
108	fi
109}
110
111prophist_delete_dependency () {
112	#
113	# Some services have stale dependencies that need to be removed.
114	# This is done by removing the dependency property group.
115	#
116	fmri=$1
117	property_group=$2
118
119	/usr/bin/svcprop -q -c -p $property_group $fmri
120	if [ $? -eq 0 ]; then
121		/lib/svc/bin/prophist delete -e $fmri -g $property_group
122	else
123		[ -n "$_MFST_DEBUG" ] && \
124		    echo "Dependency $property_group not defined on $fmri"
125	fi
126}
127
128prophist_delete_pg () {
129	# Delete obsolete property groups from old manifests.  Instances
130	# should be refreshed for changes to take effect.
131	fmri=$1
132	pg=$2
133
134	/usr/bin/svcprop -Cqp $pg $fmri &&
135	    /lib/svc/bin/prophist delete -e $fmri -g $pg
136}
137
138prophist_addprop () {
139	#
140	# If a property doesn't exist, create it.  Instances should be
141	# refreshed for changes to take effect.
142	#
143	if [ $# -lt 6 ]; then
144		echo "prophist_addprop(): Insufficient arguments ($*)."
145		exit 1
146	fi
147
148	fmri=$1
149	/usr/bin/svcprop -q $fmri || return
150
151	pg=$2
152	pgtype=$3
153	prop=$4
154
155	/usr/bin/svcprop -Cqp $pg/$prop $fmri && return
156
157	shift 4
158
159	/usr/bin/svcprop -Cqp $pg $fmri || \
160	    /usr/sbin/svccfg -s $fmri addpg $pg $pgtype
161	/usr/sbin/svccfg -s $fmri setprop $pg/$prop = $*
162}
163
164prophist_addmeth () {
165	#
166	# If a method doesn't exist, create it.  Instances should be refreshed
167	# for changes to take effect.
168	#
169	if [ $# -ne 4 ]; then
170		echo "prophist_addmeth(): Insufficient arguments ($*)"
171		exit 1
172	fi
173
174	fmri=$1
175	/usr/bin/svcprop -q $fmri || return
176
177	name=$2
178	/usr/bin/svcprop -Cqp $name $fmri && return
179
180	exec=$3
181	to=$4
182
183	/usr/sbin/svccfg -s $fmri <<END
184	    addpg $name method
185	    setprop $name/type = astring: method
186	    setprop $name/exec = astring: "$exec"
187	    setprop $name/timeout_seconds = count: $to
188END
189}
190
191prophist_adddep () {
192	#
193	# If a dependency doesn't exist, create it.  Instances should be
194	# refreshed for changes to take effect.
195	#
196	if [ $# -lt 6 ]; then
197		echo "prophist_adddep(): Insufficient arguments ($*)"
198		exit 1
199	fi
200
201	fmri=$1
202	/usr/bin/svcprop -q $fmri || return
203
204	name=$2
205	/usr/bin/svcprop -Cqp $name $fmri && return
206
207	type=$3
208	group=$4
209	ro=$5
210	shift 5
211
212	/usr/sbin/svccfg -s $fmri <<END
213	    addpg $name dependency
214	    setprop $name/type = astring: $type
215	    setprop $name/grouping = astring: $group
216	    setprop $name/restart_on = astring: $ro
217	    setprop $name/entities = fmri: $*
218END
219}
220
221prophist_adddpt () {
222	#
223	# If a dependent doesn't exist, create it.  Instances should be
224	# refresh for changes to take effect.
225	#
226	if [ $# -ne 5 ]; then
227		echo "prophist_adddpt(): Incorrect arguments ($*).\n"
228		exit 1
229	fi
230
231	fmri=$1
232	/usr/bin/svcprop -q $fmri || return
233
234	name=$2
235	/usr/bin/svcprop -Cqp dependents/$name $fmri && return
236
237	group=$3
238	ro=$4
239	target=$5
240
241	prophist_addprop $fmri dependents framework $name fmri: $target
242	prophist_adddep $target $name service $group $ro $fmri
243}
244
245instance_refresh () {
246	echo $1 >> /etc/svc/volatile/refreshes
247}
248
249refresh_instances () {
250	[ -r /etc/svc/volatile/refreshes ] && {
251		sort -u /etc/svc/volatile/refreshes | xargs -l svcadm refresh
252	}
253}
254
255instance_clear () {
256	echo $1 >> /etc/svc/volatile/clears
257}
258
259clear_conditionally () {
260	[ "`/usr/bin/svcprop -p restarter/state $1`" = "maintenance" ] && \
261	    /usr/sbin/svcadm clear $1
262}
263
264clear_instances () {
265	[ -r /etc/svc/volatile/clears ] && {
266		for inst in `/usr/bin/sort -u /etc/svc/volatile/clears`; do
267			clear_conditionally $inst
268		done
269	}
270}
271
272prepare_last_import () {
273	# Preserve the five hashes for the profiles: generic (two
274	# cases), platform (uname -i, uname -m outputs), and site.
275
276	gn="var_svc_profile_generic_open_xml"
277	gh=`/usr/bin/svcprop -p ${gn}/md5sum smf/manifest 2>/dev/null`
278	[ $? = 0 ] || gh=""
279
280	gln="var_svc_profile_generic_limited_net_xml"
281	glh=`/usr/bin/svcprop -p ${gln}/md5sum smf/manifest 2>/dev/null`
282	[ $? = 0 ] || glh=""
283
284	LC_ALL=C pl=`/usr/bin/uname -i | /usr/bin/tr , _`
285	pln="var_svc_profile_platform_${pl}_xml"
286	plh=`/usr/bin/svcprop -p ${pln}/md5sum smf/manifest 2>/dev/null`
287	[ $? = 0 ] || plh=""
288
289	LC_ALL=C plm=`/usr/bin/uname -m | /usr/bin/tr , _`
290	if [ $plm != $pl ]; then
291		plmn="var_svc_profile_platform_${plm}_xml"
292		plmh=`/usr/bin/svcprop -p ${plmn}/md5sum smf/manifest \
293		    2>/dev/null`
294		[ $? = 0 ] || plmh=""
295	else
296		plmh=""
297	fi
298
299	sn="var_svc_profile_site_xml"
300	sh=`/usr/bin/svcprop -p $sn/md5sum smf/manifest 2>/dev/null`
301	[ $? = 0 ] || sh=""
302
303	# Remove all manifest hashes.
304	/usr/sbin/svccfg delete smf/manifest
305
306	# Restore smf/manifest and hash values.
307	/usr/sbin/svccfg add smf/manifest
308	[ -n "$gh" ] && {
309		echo "Preserving generic hash ($gh)."
310		/usr/sbin/svccfg -s smf/manifest addpg ${gn} framework
311		/usr/sbin/svccfg -s smf/manifest setprop ${gn}/md5sum = \
312		    opaque: $gh
313	}
314	[ -n "$glh" ] && {
315		echo "Preserving generic_limited hash ($glh)."
316		/usr/sbin/svccfg -s smf/manifest addpg ${gln} framework
317		/usr/sbin/svccfg -s smf/manifest setprop ${gln}/md5sum = \
318		    opaque: $glh
319	}
320	[ -n "$plh" ] && {
321		echo "Preserving platform hash ($plh)."
322		/usr/sbin/svccfg -s smf/manifest addpg $pln framework
323		/usr/sbin/svccfg -s smf/manifest setprop $pln/md5sum = \
324		    opaque: $plh
325	}
326	[ -n "$plmh" ] && {
327		echo "Preserving platform hash ($plmh)."
328		/usr/sbin/svccfg -s smf/manifest addpg $plmn framework
329		/usr/sbin/svccfg -s smf/manifest setprop $plmn/md5sum = \
330		    opaque: $plmh
331	}
332	[ -n "$sh" ] && {
333		echo "Preserving site hash ($sh)."
334		/usr/sbin/svccfg -s smf/manifest addpg $sn framework
335		/usr/sbin/svccfg -s smf/manifest setprop $sn/md5sum = \
336		    opaque: $sh
337	}
338}
339
340SVCCFG_CHECKHASH=1 export SVCCFG_CHECKHASH
341
342#
343# 0. Clean up repository
344#
345if [ -z "$X" ] && /usr/bin/svcprop smf/manifest 2>/dev/null |
346    /usr/bin/grep '^ar_svc_[^/]*/md5sum opaque ' >/dev/null
347then
348	set -- `
349		/usr/bin/svcprop smf/manifest 2>/dev/null |
350		    /usr/bin/grep '^ar_svc[^/]*/md5sum opaque ' |
351		    /usr/bin/tr '/' ' ' |
352		    while read pg prop type value; do
353			echo "$pg/$value"
354		done
355	`
356	backup=`echo "$#/$#" | sed 's/.//g'`
357	fwidth=`echo "$#\c" | wc -c`
358
359	echo "Converting obsolete repository entries: \c" > /dev/msglog
360	i=1; n=$#
361	while [ $# -gt 0 ]; do
362		printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog
363		echo $1 | sed 's:/: :' | (
364			read pg value
365
366			(echo "select /smf/manifest"; echo "delpg v$pg") |
367			    /usr/sbin/svccfg 2>/dev/null >/dev/null
368			(echo "select /smf/manifest"; echo "delpg $pg") |
369			    /usr/sbin/svccfg 2>/dev/null >/dev/null
370			(echo "select /smf/manifest";
371			    echo "addpg v$pg framework") |
372			    /usr/sbin/svccfg 2>/dev/null >/dev/null
373			(echo "select /smf/manifest";
374			    echo "setprop v$pg/md5sum = opaque: $value") |
375			    /usr/sbin/svccfg 2>/dev/null >/dev/null
376		)
377		i=`expr $i + 1`
378		shift
379		echo "$backup\c" > /dev/msglog
380	done
381	echo > /dev/msglog
382	echo "Converted $n obsolete repository entries"
383	activity=true
384fi
385
386#
387# If no last-import snapshots are present on critical services, then we are
388# creating the last-import snapshots for the first time post upgrade.
389#
390create_last_import=1
391for svc in single-user multi-user multi-user-server; do
392	if /usr/bin/svcprop -s last-import svc:/milestone/$svc:default \
393	    >/dev/null 2>&1
394	then
395		create_last_import=
396		break
397	fi
398done
399
400if [ $create_last_import ]; then
401	echo "Last import snapshots absent; preparing for re-import"
402	prepare_last_import
403
404	#
405	# Apply property history files.
406	#
407	echo "Upgrade detected; applying property history"
408	for phist in /var/svc/profile/prophist.*; do
409		/lib/svc/bin/prophist hash $phist
410		if [ $? = 3 ]; then
411			echo "Sourcing $phist"
412			. $phist
413		fi
414	done
415
416	/usr/bin/rm -f /var/svc/profile/.upgrade_prophist
417fi
418
419#
420# 2.  Manifest import.  Application directories first, then
421# site-specific manifests.
422#
423nonsite_dirs=`/usr/bin/find /var/svc/manifest/* -name site -prune -o -type d \
424	-print -prune`
425
426nonsite_manifests=`/lib/svc/bin/mfstscan $nonsite_dirs`
427site_manifests=`/lib/svc/bin/mfstscan /var/svc/manifest/site`
428
429manifests="$nonsite_manifests $site_manifests"
430
431[ -n "$_MFST_DEBUG" ] && {
432	echo "Changed manifests to import:"
433	for m in $manifests; do echo "  $m"; done
434}
435
436#
437# 2b.  Import the manifests while giving a running display of imports on
438# console, and a final count in the logfile.
439#
440if [ -n "$nonsite_manifests" -o -n "$site_manifests" ]; then
441	rm -f /tmp/manifest_import.$$
442
443	set -- $manifests
444	backup=`echo "$#/$#" | sed 's/.//g'`
445	fwidth=`echo "$#\c" | wc -c`
446
447	echo "Loading smf(5) service descriptions: \c" > /dev/msglog
448
449	i=1; n=$#
450	while [ $# -gt 0 ]; do
451		printf "%${fwidth}s/%${fwidth}s" $i $n > /dev/msglog
452		svccfg_import $1
453		i=`expr $i + 1`
454		shift
455		echo "$backup\c" > /dev/msglog
456	done
457
458	echo > /dev/msglog
459	echo "Loaded $n smf(5) service descriptions"
460	activity=true
461
462	if [ -s /tmp/manifest_import.$$ ]; then
463		echo "svccfg warnings:"
464		cat /tmp/manifest_import.$$
465
466		msg="svccfg import warnings.  See"
467		msg="$msg /var/svc/log/system-manifest-import:default.log ."
468		echo $msg > /dev/msglog
469	fi
470	rm -f /tmp/manifest_import.$$
471fi
472
473#
474# 3.  Profile application.  We must create the platform profile upon
475# first boot, as we may be a diskless client of a platform or
476# architecture distinct from our NFS server.
477#
478svccfg_apply /var/svc/profile/generic.xml
479
480if [ ! -f /var/svc/profile/platform.xml ]; then
481	this_karch=`uname -m`
482	this_plat=`uname -i`
483
484	if [ -f /var/svc/profile/platform_$this_plat.xml ]; then
485		platform_profile=platform_$this_plat.xml
486	elif [ -f /var/svc/profile/platform_$this_karch.xml ]; then
487		platform_profile=platform_$this_karch.xml
488	else
489		platform_profile=platform_none.xml
490	fi
491
492	ln -s $platform_profile /var/svc/profile/platform.xml
493fi
494
495svccfg_apply /var/svc/profile/platform.xml
496
497#
498# 4.  Upgrade handling.  The upgrade file generally consists of a series
499# of svcadm(1M) and svccfg(1M) commands.
500#
501(
502	unset SVCCFG_CHECKHASH
503
504	if [ -f /var/svc/profile/upgrade ]; then
505		. /var/svc/profile/upgrade
506
507		/usr/bin/mv /var/svc/profile/upgrade \
508		    /var/svc/profile/upgrade.app.`date +\%Y\%m\%d\%H\%M\%S`
509		activity=true
510	fi
511)
512
513#
514# 5.  Site profile is applied last to give administrator the final say.
515#
516if [ -f /var/svc/profile/site.xml ]; then
517	svccfg_apply /var/svc/profile/site.xml
518fi
519
520#
521# 6.  Final actions.
522#
523refresh_instances
524clear_instances
525
526if $activity; then
527	svcadm _smf_backup "manifest_import" || true
528fi
529
530exit 0
531