xref: /onnv-gate/usr/src/cmd/svc/configd/restore_repository.sh (revision 407:f4075c116450)
10Sstevel@tonic-gate#!/sbin/sh
20Sstevel@tonic-gate#
30Sstevel@tonic-gate# CDDL HEADER START
40Sstevel@tonic-gate#
50Sstevel@tonic-gate# The contents of this file are subject to the terms of the
60Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only
70Sstevel@tonic-gate# (the "License").  You may not use this file except in compliance
80Sstevel@tonic-gate# with the License.
90Sstevel@tonic-gate#
100Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
110Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
120Sstevel@tonic-gate# See the License for the specific language governing permissions
130Sstevel@tonic-gate# and limitations under the License.
140Sstevel@tonic-gate#
150Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
160Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
170Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
180Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
190Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
200Sstevel@tonic-gate#
210Sstevel@tonic-gate# CDDL HEADER END
220Sstevel@tonic-gate#
230Sstevel@tonic-gate#
24*407Sjwadams# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate# Use is subject to license terms.
260Sstevel@tonic-gate#
270Sstevel@tonic-gate#ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate
290Sstevel@tonic-gatePATH=/sbin:/usr/bin:/usr/sbin
30*407SjwadamsLC_ALL=C
31*407Sjwadamsexport PATH LC_ALL
320Sstevel@tonic-gate
330Sstevel@tonic-gate. /lib/svc/share/smf_include.sh
340Sstevel@tonic-gate. /lib/svc/share/fs_include.sh
350Sstevel@tonic-gate
360Sstevel@tonic-gateusage()
370Sstevel@tonic-gate{
380Sstevel@tonic-gate	echo "usage: $0 [-r rootdir]" >&2
39*407Sjwadams	echo "
40*407SjwadamsSee http://sun.com/msg/SMF-8000-MY for more information on the use of
41*407Sjwadamsthis script."
420Sstevel@tonic-gate	exit 2;
430Sstevel@tonic-gate}
440Sstevel@tonic-gate
450Sstevel@tonic-gaterepositorydir=etc/svc
460Sstevel@tonic-gaterepository=repository
470Sstevel@tonic-gate
480Sstevel@tonic-gatemyroot=/
490Sstevel@tonic-gatewhile getopts r: opt; do
500Sstevel@tonic-gate	case "$opt" in
510Sstevel@tonic-gate	    r)	myroot=$OPTARG
520Sstevel@tonic-gate		if [ ! -d $myroot ]; then
530Sstevel@tonic-gate			echo "$myroot: not a directory" >&2
540Sstevel@tonic-gate			exit 1
550Sstevel@tonic-gate		fi
560Sstevel@tonic-gate		# validate directory and make sure it ends in '/'.
570Sstevel@tonic-gate		case "$myroot" in
580Sstevel@tonic-gate		    //*) echo "$myroot: must begin with a single /" >&2
590Sstevel@tonic-gate			usage;;
600Sstevel@tonic-gate		    /)	echo "$myroot: alternate root cannot be /" >&2
610Sstevel@tonic-gate			usage;;
620Sstevel@tonic-gate
630Sstevel@tonic-gate		    /*/) ;;			# ends with /
640Sstevel@tonic-gate		    /*) myroot="$myroot/";;	# add final /
650Sstevel@tonic-gate
660Sstevel@tonic-gate		    *)	echo "$myroot: must be a full path" >&2
670Sstevel@tonic-gate			usage;;
680Sstevel@tonic-gate		esac;;
690Sstevel@tonic-gate	    ?)	usage;;
700Sstevel@tonic-gate	esac
710Sstevel@tonic-gatedone
720Sstevel@tonic-gate
730Sstevel@tonic-gateif [ $OPTIND -le $# ]; then
740Sstevel@tonic-gate	# getopts(1) didn't slurp up everything.
750Sstevel@tonic-gate	usage
760Sstevel@tonic-gatefi
770Sstevel@tonic-gate
78*407Sjwadams#
79*407Sjwadams# Note that the below test is carefully constructed to fail *open*;  if
80*407Sjwadams# anything goes wrong, it will drive onward.
81*407Sjwadams#
82*407Sjwadamsif [ -x /usr/bin/id -a -x /usr/bin/grep ] &&
83*407Sjwadams    /usr/bin/id 2>/dev/null | /usr/bin/grep -v '^[^=]*=0(' >/dev/null 2>&1; then
84*407Sjwadams	echo "$0: may only be invoked by root" >&2
85*407Sjwadams	exit 2
86*407Sjwadamsfi
87*407Sjwadams
88*407Sjwadamsecho >&2 "
89*407SjwadamsSee http://sun.com/msg/SMF-8000-MY for more information on the use of
90*407Sjwadamsthis script to restore backup copies of the smf(5) repository.
91*407Sjwadams
92*407SjwadamsIf there are any problems which need human intervention, this script will
93*407Sjwadamsgive instructions and then exit back to your shell."
94*407Sjwadams
950Sstevel@tonic-gateif [ "$myroot" -eq / ]; then
960Sstevel@tonic-gate	system="system"
970Sstevel@tonic-gate	[ "`/sbin/zonename`" != global ] && system="zone"
980Sstevel@tonic-gate	echo >&2 "
990Sstevel@tonic-gateNote that upon full completion of this script, the $system will be rebooted
1000Sstevel@tonic-gateusing reboot(1M), which will interrupt any active services.
1010Sstevel@tonic-gate"
1020Sstevel@tonic-gatefi
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate# check that the filesystem is as expected
1050Sstevel@tonic-gatecd "$myroot" || exit 1
1060Sstevel@tonic-gatecd "$myroot$repositorydir" || exit 1
1070Sstevel@tonic-gate
1080Sstevel@tonic-gatenouser=false
1090Sstevel@tonic-gaterootro=false
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate# check to make sure /usr is mounted
1120Sstevel@tonic-gateif [ ! -x /usr/bin/pgrep ]; then
1130Sstevel@tonic-gate	nouser=true
1140Sstevel@tonic-gatefi
115*407Sjwadams
1160Sstevel@tonic-gateif [ ! -w "$myroot" ]; then
1170Sstevel@tonic-gate	rootro=true
1180Sstevel@tonic-gatefi
1190Sstevel@tonic-gate
1200Sstevel@tonic-gateif [ "$nouser" = true -o "$rootro" = true ]; then
1210Sstevel@tonic-gate	if [ "$nouser" = true -a "$rootro" = true ]; then
1220Sstevel@tonic-gate		echo "The / filesystem is mounted read-only, and the /usr" >&2
1230Sstevel@tonic-gate		echo "filesystem has not yet been mounted." >&2
1240Sstevel@tonic-gate	elif [ "$nouser" = true ]; then
1250Sstevel@tonic-gate		echo "The /usr filesystem has not yet been mounted." >&2
1260Sstevel@tonic-gate	else
1270Sstevel@tonic-gate		echo "The / filesystem is mounted read-only." >&2
1280Sstevel@tonic-gate	fi
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate	echo >&2 "
1310Sstevel@tonic-gateThis must be rectified before $0 can continue.
1320Sstevel@tonic-gate
1330Sstevel@tonic-gateIf / or /usr are on SVM (md(7d)) partitions, first run
1340Sstevel@tonic-gate    /lib/svc/method/svc-metainit
1350Sstevel@tonic-gate
1360Sstevel@tonic-gateTo properly mount / and /usr, run:
1370Sstevel@tonic-gate    /lib/svc/method/fs-root
1380Sstevel@tonic-gatethen
1390Sstevel@tonic-gate    /lib/svc/method/fs-usr
1400Sstevel@tonic-gate
1410Sstevel@tonic-gateAfter those have completed successfully, re-run:
1420Sstevel@tonic-gate    $0 $*
1430Sstevel@tonic-gate
1440Sstevel@tonic-gateto continue.
1450Sstevel@tonic-gate"
1460Sstevel@tonic-gate	exit 1
1470Sstevel@tonic-gatefi
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate# at this point, we know / is mounted read-write, and /usr is mounted.
1500Sstevel@tonic-gateoldreps="`
1510Sstevel@tonic-gate	/bin/ls -1rt $repository-*-[0-9]*[0-9] | \
1520Sstevel@tonic-gate	    /bin/sed -e '/[^A-Za-z0-9_,.-]/d' -e 's/^'$repository'-//'
1530Sstevel@tonic-gate`"
1540Sstevel@tonic-gate
1550Sstevel@tonic-gateif [ -z "$oldreps" ]; then
1560Sstevel@tonic-gate	cat >&2 <<EOF
1570Sstevel@tonic-gateThere are no available backups of $myroot$repositorydir/$repository.db.
1580Sstevel@tonic-gateThe only available repository is "-seed-".  Note that restoring the seed
159*407Sjwadamswill lose all customizations, including those made by the system during
160*407Sjwadamsthe installation and/or upgrade process.
1610Sstevel@tonic-gate
1620Sstevel@tonic-gateEOF
1630Sstevel@tonic-gate	prompt="Enter -seed- to restore from the seed, or -quit- to exit: \c"
1640Sstevel@tonic-gate	default=
1650Sstevel@tonic-gateelse
1660Sstevel@tonic-gate	cat >&2 <<EOF
1670Sstevel@tonic-gateThe following backups of $myroot$repositorydir/$repository.db exist, from
1680Sstevel@tonic-gateoldest to newest:
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate$oldreps
1710Sstevel@tonic-gate
1720Sstevel@tonic-gateThe backups are named based on their type and the time what they were taken.
1730Sstevel@tonic-gateBackups beginning with "boot" are made before the first change is made to
1740Sstevel@tonic-gatethe repository after system boot.  Backups beginning with "manifest_import"
1750Sstevel@tonic-gateare made after svc:/system/manifest-import:default finishes its processing.
1760Sstevel@tonic-gateThe time of backup is given in YYYYMMDD_HHMMSS format.
1770Sstevel@tonic-gate
178*407SjwadamsPlease enter either a specific backup repository from the above list to
179*407Sjwadamsrestore it, or one of the following choices:
180*407Sjwadams
181*407Sjwadams	CHOICE		  ACTION
182*407Sjwadams	----------------  ----------------------------------------------
183*407Sjwadams	boot		  restore the most recent post-boot backup
184*407Sjwadams	manifest_import	  restore the most recent manifest_import backup
185*407Sjwadams	-seed-		  restore the initial starting repository  (All
186*407Sjwadams			    customizations will be lost, including those
187*407Sjwadams			    made by the install/upgrade process.)
188*407Sjwadams	-quit-		  cancel script and quit
1890Sstevel@tonic-gate
1900Sstevel@tonic-gateEOF
1910Sstevel@tonic-gate	prompt="Enter response [boot]: \c"
1920Sstevel@tonic-gate	default="boot"
1930Sstevel@tonic-gatefi
1940Sstevel@tonic-gate
1950Sstevel@tonic-gatecont=false
1960Sstevel@tonic-gatewhile [ $cont = false ]; do
1970Sstevel@tonic-gate	echo "$prompt"
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate	read x || exit 1
2000Sstevel@tonic-gate	[ -z "$x" ] && x="$default"
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate	case "$x" in
2030Sstevel@tonic-gate	    -seed-)
2040Sstevel@tonic-gate		if [ $myroot != / -o "`/sbin/zonename`" = global ]; then
2050Sstevel@tonic-gate			file="$myroot"lib/svc/seed/global.db
2060Sstevel@tonic-gate		else
2070Sstevel@tonic-gate			file="$myroot"lib/svc/seed/nonglobal.db
2080Sstevel@tonic-gate		fi;;
2090Sstevel@tonic-gate	    -quit-)
2100Sstevel@tonic-gate		echo "Exiting."
2110Sstevel@tonic-gate		exit 0;;
2120Sstevel@tonic-gate	    /*)
2130Sstevel@tonic-gate		file="$x";;
2140Sstevel@tonic-gate	    */*)
2150Sstevel@tonic-gate		file="$myroot$x";;
2160Sstevel@tonic-gate	    ?*)
2170Sstevel@tonic-gate		file="$myroot$repositorydir/repository-$x";;
2180Sstevel@tonic-gate	    *)	file= ;;
2190Sstevel@tonic-gate	esac
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate	if [ -f $file ]; then
2220Sstevel@tonic-gate		if [ -r $file ]; then
2230Sstevel@tonic-gate			checkresults="`echo PRAGMA integrity_check\; | \
2240Sstevel@tonic-gate			    /lib/svc/bin/sqlite $file >&1 | grep -v '^ok$'`"
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate			if [ -n "$checkresults" ]; then
2270Sstevel@tonic-gate				echo "$file: integrity check failed:" >&2
2280Sstevel@tonic-gate				echo "$checkresults" >&2
2290Sstevel@tonic-gate				echo
2300Sstevel@tonic-gate			else
2310Sstevel@tonic-gate				cont=true
2320Sstevel@tonic-gate			fi
2330Sstevel@tonic-gate		else
2340Sstevel@tonic-gate			echo "$file: not readable"
2350Sstevel@tonic-gate		fi
2360Sstevel@tonic-gate	elif [ -n "$file" ]; then
2370Sstevel@tonic-gate		echo "$file: not found"
2380Sstevel@tonic-gate	fi
2390Sstevel@tonic-gatedone
2400Sstevel@tonic-gate
2410Sstevel@tonic-gateerrors="$myroot"etc/svc/volatile/db_errors
2420Sstevel@tonic-gaterepo="$myroot$repositorydir/$repository.db"
2430Sstevel@tonic-gatenew="$repo"_old_"`date +%Y''%m''%d'_'%H''%M''%S`"
2440Sstevel@tonic-gate
2450Sstevel@tonic-gatesteps=
2460Sstevel@tonic-gateif [ "$myroot" = / ]; then
2470Sstevel@tonic-gate	steps="$steps
2480Sstevel@tonic-gatesvc.startd(1M) and svc.configd(1M) will be quiesced, if running."
2490Sstevel@tonic-gatefi
2500Sstevel@tonic-gate
2510Sstevel@tonic-gateif [ -r $repo ]; then
2520Sstevel@tonic-gate	steps="$steps
2530Sstevel@tonic-gate$repo
2540Sstevel@tonic-gate    -- renamed --> $new"
2550Sstevel@tonic-gatefi
2560Sstevel@tonic-gateif [ -r $errors ]; then
2570Sstevel@tonic-gate	steps="$steps
2580Sstevel@tonic-gate$errors
2590Sstevel@tonic-gate    -- copied --> ${new}_errors"
2600Sstevel@tonic-gatefi
2610Sstevel@tonic-gate
2620Sstevel@tonic-gatecat >&2 <<EOF
2630Sstevel@tonic-gate
2640Sstevel@tonic-gateAfter confirmation, the following steps will be taken:
2650Sstevel@tonic-gate$steps
2660Sstevel@tonic-gate$file
2670Sstevel@tonic-gate    -- copied --> $repo
2680Sstevel@tonic-gateEOF
2690Sstevel@tonic-gate
2700Sstevel@tonic-gateif [ "$myroot" = / ]; then
2710Sstevel@tonic-gate	echo "and the system will be rebooted with reboot(1M)."
2720Sstevel@tonic-gatefi
2730Sstevel@tonic-gate
2740Sstevel@tonic-gateecho
2750Sstevel@tonic-gatecont=false
2760Sstevel@tonic-gatewhile [ $cont = false ]; do
2770Sstevel@tonic-gate	echo "Proceed [yes/no]? \c"
2780Sstevel@tonic-gate	read x || x=n
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate	case "$x" in
2810Sstevel@tonic-gate	    [Yy]|[Yy][Ee][Ss])
2820Sstevel@tonic-gate		cont=true;;
2830Sstevel@tonic-gate	    [Nn]|[Nn][Oo])
2840Sstevel@tonic-gate		echo; echo "Exiting..."
2850Sstevel@tonic-gate		exit 0;
2860Sstevel@tonic-gate	esac;
2870Sstevel@tonic-gatedone
2880Sstevel@tonic-gate
2890Sstevel@tonic-gateumask 077		# we want files to be root-readable only.
2900Sstevel@tonic-gate
2910Sstevel@tonic-gatestartd_msg=
2920Sstevel@tonic-gateif [ "$myroot" = / ]; then
2930Sstevel@tonic-gate	zone="`zonename`"
2940Sstevel@tonic-gate	startd="`pgrep -z "$zone" -f svc.startd`"
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate	echo
2970Sstevel@tonic-gate	echo "Quiescing svc.startd(1M) and svc.configd(1M): \c"
2980Sstevel@tonic-gate	if [ -n "$startd" ]; then
2990Sstevel@tonic-gate		pstop $startd
3000Sstevel@tonic-gate		startd_msg=\
3010Sstevel@tonic-gate"To start svc.start(1M) running, do: /usr/bin/prun $startd"
3020Sstevel@tonic-gate	fi
3030Sstevel@tonic-gate	pkill -z "$zone" -f svc.configd
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate	sleep 1			# yes, this is hack
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate	echo "done."
3080Sstevel@tonic-gatefi
3090Sstevel@tonic-gate
3100Sstevel@tonic-gateif [ -r "$repo" ]; then
3110Sstevel@tonic-gate	echo "$repo"
3120Sstevel@tonic-gate	echo "    -- renamed --> $new"
3130Sstevel@tonic-gate	if mv $repo $new; then
3140Sstevel@tonic-gate		:
3150Sstevel@tonic-gate	else
3160Sstevel@tonic-gate		echo "Failed.  $startd_msg"
3170Sstevel@tonic-gate		exit 1;
3180Sstevel@tonic-gate	fi
3190Sstevel@tonic-gatefi
3200Sstevel@tonic-gate
3210Sstevel@tonic-gateif [ -r $errors ]; then
3220Sstevel@tonic-gate	echo "$errors"
3230Sstevel@tonic-gate	echo "    -- copied --> ${new}_errors"
3240Sstevel@tonic-gate	if cp -p $errors ${new}_errors; then
3250Sstevel@tonic-gate		:
3260Sstevel@tonic-gate	else
3270Sstevel@tonic-gate		mv -f $new $repo
3280Sstevel@tonic-gate		echo "Failed.  $startd_msg"
3290Sstevel@tonic-gate		exit 1;
3300Sstevel@tonic-gate	fi
3310Sstevel@tonic-gatefi
3320Sstevel@tonic-gate
3330Sstevel@tonic-gateecho "$file"
3340Sstevel@tonic-gateecho "    -- copied --> $repo"
3350Sstevel@tonic-gate
3360Sstevel@tonic-gateif cp $file $repo.new.$$ && mv $repo.new.$$ $repo; then
3370Sstevel@tonic-gate	:
3380Sstevel@tonic-gateelse
3390Sstevel@tonic-gate	rm -f $repo.new.$$ ${new}_errors
3400Sstevel@tonic-gate	mv -f $new $repo
3410Sstevel@tonic-gate	echo "Failed.  $startd_msg"
3420Sstevel@tonic-gate	exit 1;
3430Sstevel@tonic-gatefi
3440Sstevel@tonic-gate
3450Sstevel@tonic-gateecho
3460Sstevel@tonic-gateecho "The backup repository has been successfully restored."
3470Sstevel@tonic-gateecho
3480Sstevel@tonic-gate
3490Sstevel@tonic-gateif [ "$myroot" = / ]; then
3500Sstevel@tonic-gate	echo "Rebooting in 5 seconds."
3510Sstevel@tonic-gate	sleep 5
3520Sstevel@tonic-gate	reboot
3530Sstevel@tonic-gatefi
354