#!/bin/sh
#
#
# @(#)$Id: bconvert.sh,v 1.1.2.3.6.1 1998/09/10 13:38:19 cvsusr Exp $
#
# Copyright 1997 Dynamic Software AB
# This is unpublished proprietary source code.
#
# Description:
#	BoKS convert script. Convert master, server or client
#	to master server or client after some sanity checks.
#
# Usage:
#	convert [-v] master | server | client
#
USAGE="`basename $0` [-v] master | server | client"
trap 'exit 3' 1 2 3 15


umask 022

verbose=false

if [ x"$1" = x"-v" ]; then
    verbose=true
    shift
fi


case $1 in
    master|server|client) to_type=$1 ;;
    *) echo "$USAGE" >&2; exit 1 ;;
esac

# complain if not root
case `id` in
    uid=0*) ;;
    *) echo "You must be root to run `basename $0`" >&2
       exit 1
       ;;
esac

# setup paths

for f in /etc/opt/SUNWssmi/ENV /etc/boksenv; do
    if [ -f $f ]; then
	eval `grep '^BOKS_lib' $f`
	eval `grep '^BOKS_sbin' $f`
	eval `grep '^BOKS_etc' $f`
	eval `grep '^BOKS_var' $f`
	eval `grep '^BOKS_data' $f`
	PATH=$BOKS_lib:$BOKS_sbin:$PATH
	export PATH
	break
    fi
done

if [ -z "$BOKS_lib" ]; then
    echo "Cannot setup paths for SSMI" >&2
    echo "Is it properly installed and setup?" >&2
    echo "If it is, try running smadm -S `basename $0`" >&2
    exit 1
fi

from_type=
if [ -f $BOKS_etc/ENV ]; then
    BOKSINIT=
    eval `grep '^BOKSINIT=' $BOKS_etc/ENV`
    from_type=$BOKSINIT
fi

if [ -z "$from_type" ]; then
    echo "Cannot determine if machine is master, server or client" >&2
    echo "Have you run setup?" >&2
    exit 1
fi

case $from_type in
    master|server|client) ;;
    *) echo "Cannnot convert type $from_type to $to_type" >&2
       exit 1
       ;;
esac

# Some conversions are not possible
if [ $from_type = $to_type ]; then
    echo "Machine already installed as $to_type" >&2
    exit 1
fi
if [ $from_type = client -a $to_type = master ]; then
    echo "Cannot convert $from_type to $to_type" >&2
    exit 1
fi


# Now check for error conditions

# if converting to master first check that there is no master reachable,
# then check that there is no $BOKS_data/.download
if [ $to_type = master ]; then
    $verbose && echo "Checking to see that there is no master running elsewhere..."
    xx="`showmaster`"
    if [ -n "$xx" ]; then
	hostip="`echo $xx | sed -e 's/\([^ ]*\)  *\(.*\)/\1 (\2)/'`"
	if [ -n "$hostip" ]; then
	    hostip="$xx"
	fi
	echo "There is already a master running. $hostip." >&2
	echo "Will not convert to master" >&2
	exit 1
    fi
    if [ -f $BOKS_data/.download ]; then
	echo "This server was downloading, and the database may not be valid" >&2
	echo "Please find another server to convert!" >&2
	echo
	echo "If you must convert this one, remove the file" >&2
	echo "      $BOKS_data/.download" >&2
	echo "then restart SSMI and run `basename $0` again." >&2
	echo "After conversion, restore a backup database." >&2
	exit 1
    fi
    if [ ! -f $BOKS_data/sys.dat -o ! -s $BOKS_data/sys.dat ]; then
	echo "This server does not have a database downloaded from master." >&2
	echo "Please find another server to convert!" >&2
	exit 1
    fi
fi

# If converting to server from anything else than master,
# check that a master is reachable
if [ $from_type != master -a $to_type = server ]; then
    $verbose && echo "Checking to see if a master can be found..."
    xx="`showmaster`"
    if [ -z "$xx" ]; then
	echo "Cannot find a master to communicate with." >&2
	echo "You may want to edit $BOKS_etc/bcastaddr" >&2
        echo '(see bcastaddr(4B))' "then restart SSMI" >&2
	echo "and try `basename $0` again." >&2
	exit 1
    fi
fi


# If converting from master always ask for a nodekey
# to store on disk.
if [ $from_type = master ]; then
    echo "You must now enter the nodekey for this machine."
    echo "Make sure it is the same one as you entered when"
    echo "installing this machine."
    echo
    hostkey -f
    if [ $? != 0 ]; then
	echo "Failed to get nodekey." >&2
	echo "Conversion not done." >&2
	exit 1
    fi
fi



# Now do actual conversion

# Make backup copies of some files for emergency recovery

# Save a backup copy of the ENV file
envbck=$BOKS_etc/ENV.convbck
cp $BOKS_etc/ENV $envbck
if [ $? -ne 0 ]; then
    echo "Failed to make backup copy $envbck of $BOKS_etc/ENV" >&2
    echo "Possibly disk is full." >&2
    echo "Conversion not done." >&2
    exit 1
fi

# routine to restore backup files and restarting daemons on fail
conv_fail () {
    if [ -n "$envbck" -a -s "$envbck" ]; then
	if cp $envbck $BOKS_etc/ENV; then
	    rm -f $envbck
	fi
    fi
    echo "Conversion failed" >&2
    echo "Reverted to $from_type" >&2
    $verbose && echo "Restarting daemons"
    Boot
    exit 1
}


# Stop daemons
$verbose && echo "Stopping daemons..."
Boot -k


# Change BOKSINIT in $BOKS_etc/ENV file
$verbose && echo "Setting BOKSINIT=$to_type in ENV file..."

# make sure we have space to convert file by making two copies of it
tmpfile1=/tmp/ENV_1.$$
tmpfile2=/tmp/ENV_2.$$

cp $BOKS_etc/ENV $tmpfile1
if [ $? -ne 0 ]; then
    echo "Failed to update ENV file" >&2
    echo "No space on /tmp?" >&2
    conv_failed
fi
cp $BOKS_etc/ENV $tmpfile2
if [ $? -ne 0 ]; then
    echo "Failed to update ENV file" >&2
    echo "No space on /tmp?" >&2
    conv_failed
fi

grep -v '^BOKSINIT=' $tmpfile1 > $tmpfile2
echo "BOKSINIT=$to_type" >> $tmpfile2
cp $tmpfile2 $BOKS_etc/ENV
if [ $? -ne 0 ]; then
    echo "Failed to update ENV file" >&2
    conv_failed
fi

# if -> master we want to add ISMASTER=on to ENV file
# if master -> we want to remove it.
if [ $to_type = master -o $from_type = master ]; then
    cp $BOKS_etc/ENV $tmpfile1
    if [ $? -ne 0 ]; then
	echo "Failed to update ENV file" >&2
	echo "No space on /tmp?" >&2
	conv_failed
    fi
    cp $BOKS_etc/ENV $tmpfile2
    if [ $? -ne 0 ]; then
	echo "Failed to update ENV file" >&2
	echo "No space on /tmp?" >&2
	conv_failed
    fi

    grep -v '^ISMASTER=' $tmpfile1 > $tmpfile2
    if [ $to_type = master ]; then
        echo "ISMASTER=on" >> $tmpfile2
    fi
    cp $tmpfile2 $BOKS_etc/ENV
    if [ $? -ne 0 ]; then
	echo "Failed to update ENV file" >&2
	conv_failed
    fi
fi
rm -f $tmpfile1 $tmpfile2

# Now we can restart daemons
$verbose && echo "Restarting daemons..."
Boot

# weird routine to try to check if a root exists for machine
# and in that case echo back the full boks name
find_root () {
    h=$1
    r=`lsbks -l $h:root`
    if [ -n "$r" ]; then
	echo $r
	return
    fi
    # here is the weirdest part, check all hostgroups that
    # h is memeber of...
    hgrpadm -l | while read g m; do
	if [ -n "$m" ]; then
	    regexp=`echo "$m" | sed -e 's/\*/\.*/g'`
	    if expr "$h" : "^$regexp$" > /dev/null 2>&1; then
		r=`lsbks -l $g:root`
		if [ -n "$r" ]; then
		    echo "$r"
		    break
		fi
	    fi
	fi
    done
}


if [ $to_type = master ]; then
    # Try to determine name of root user on this machine
    host=`/usr/bin/uname -n`
    ip=`lh -I $host`
    if [ -z "$ip" ]; then
	# try stripping domain part if any
	host=`echo $host | sed -e 's/\..*//'`
	ip=`lh -I $host`
    fi
    if [ -n "$ip" ]; then
	found_hostname=true
    else
	found_hostname=false
    fi
    found_root=false
    if $found_hostname; then
	# try to find name of root user on this host
	root=`find_root $host`
	if [ -n "$root" ]; then
	   found_root=true
	fi
    fi

    # if we found a root, put him into the admins file unless already there
    if $found_root; then
	if grep "^$host:root$" $BOKS_etc/admins > /dev/null 2>&1; then
	    :
	else
	    echo "$host:root" >> $BOKS_etc/admins
	fi
    else
	echo "Unsuccessful in trying to determine the SSMI username" >&2
	echo "of root on this machine" >&2
	echo "The SSMI root username for this machine" >&2
	echo "must be added to the $BOKS_etc/admins file" >&2
	echo "to allow administration using the GUI." >&2
    fi
fi
$verbose && echo "Conversion from $from_type to $to_type done."

if [ $to_type = master ]; then
    echo
    $verbose || echo "Conversion from $from_type to $to_type done."
    echo "You must now make sure all the servers are able to talk"
    echo "to this new master."
    echo "You can test this by running $BOKS_lib/showmaster on each"
    echo "server. It should respond with the name and ip-address of"
    echo "this new master."
    echo "If it does not respond, the server is probably on another"
    echo "subnet, and you must add the ip-address of this machine"
    echo "to the $BOKS_etc/bcastaddr file on the server and restart"
    echo "SSMI on the server" '(see bcastaddr(4B)).'
    echo
    echo "If you are using soft PSD's you must now restore special"
    echo "PSD's from a backup to be able to create new PSD's with"
    echo "the CA you used previously. If not, you must create a new"
    echo "CA to use when creating new PSD's."
fi

if [ $from_type = master ]; then
    echo
    $verbose || echo "Conversion from $from_type to $to_type done."
    echo "This SSMI domain will now be left without a master."
    echo "You should now convert one of the servers to be a master as"
    echo "soon as possible."
    echo
    echo "If you are using soft PSD's, you should make a backup copy"
    echo "of the directories"
    echo "   $BOKS_data/sso_creds/ca_creds/keypkgs"
    echo "and"
    echo "   $BOKS_data/sso_creds/user_creds/keypkgs"
    echo "and install on the new master if you want to be able"
    echo "to create new PSD's using the CA you are now using."
fi
