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