#!/usr/bin/ksh93

#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# =============================================================================
# post_install_vm_config : Perform post-installation Virtual Machine Config
# =============================================================================
#

#
# Establish PATH for non-built in commands
#
export PATH=/usr/xpg4/bin:/bin:/usr/bin:/usr/sbin

#
# Source in shared common VMC code.
# All variable and functions defined in vmc_common are named with
# prifix "vmc" or VMC.
#
. /usr/share/distro_const/vmc/vmc_common

#
# Make sure all math stuff runs in the "C" locale
#
vmc_set_locale

#######################################################################
# cleanup
#	This function attempts to clean up any resources this script
#	could generate. Depending on where in the script this function
#	is involved some resources may not be there to cleanup, but
#	that will not adversely effect anything.
#
#	This function is not defined using the function keyword
#	to avoid an exit loop.
#
# Input: none
# Returns: none
#
#######################################################################
cleanup ()
{

	#
	# It is not necessary to process errors.
	#
	{
		trap "" ERR INT
		set +o errexit

		#
		# Attempt to reconfigure the VM to it's original settings.
		#
		VBoxManage -q modifyvm ${DIST_NAME} \
		    --memory ${orig_ram_size} --cpus ${orig_cpus} \
		    --hwvirtex ${orig_virt_hw}

	} > /dev/null 2>&1

}

#######################################################################
# main
#
# Args:
#	MFEST_SOCKET: Socket needed to get manifest data via ManifestRead object
#	PKG_IMG_PATH: Package image area
#	TMP_DIR: Temporary directory to contain the bootroot file
#	BR_BUILD: Area where bootroot is put together (not used)
#	MEDIA_DIR: Area where the media is put. (Not used)

# Additional arguments passed as arguments to this finalizer script
#	from the VMC Manifest:
#	<CPUS> - desired number of virtual CPUs
#	<hw> - desired hardware VT-x/AMD-V
#	<RAM_SIZE> - Size (in MB) of the VM RAM
#
# Inputs to be taken from the VMC Manifest:
#	<DIST_NAME> - "name" tag from VMC Manifest
#
# Output:
#
#	No formal output. (Result is a reconfigured VM instance.)
#
# Diagnostic Output:
#
#	Message written to standard output (print -u1) will go to
#	the distro constructor log file.
#
#	Message written to standard error (print -u2) will go to
#	the distro constructor log file and the screen where the
#	distro constructor is being run.
#
# Description:
#
#	This finalizer script will configure the VM settings desired
#	for exporting of the final image. The VM settings used for
#	installation are probably not what the deployer wants when
#	distributing the final image to their users. This Finalizer
#	script will reset some settings from their install time
#	settings to what is set in the VMC DC manifest. At the moment,
#	this is the VM's RAM setting.  
#
# Returns:
#	1 on failure
#	0 on success
#
#######################################################################

builtin cp
builtin mkdir
builtin mv
builtin rm

#
# Variable which act as constants are in CAPs
# Variable which can be modified are in lower case
#
typeset -i cmdsts
typeset    vbox_cmd
typeset -r MANIFEST_READ=/usr/bin/ManifestRead
typeset    is_running="" # Used for testing if the VM is already running.
typeset    orig_ram_size=""
typeset    orig_cpus=""
typeset    orig_virt_hw=""

#
# Process command line arguments
#
if (( $# != 8 )) ; then
	print -u2 "\nWrong number of arguments provided by Distro Constructor."
	print -u2 "The arguments \"ram size\", \"cpus\" and " \
	    "\"virtual hw\" must be specified in the manifest."
	exit 1
fi

typeset -r MFEST_SOCKET="$1"

#
# A non-integer value accidently passed by the user would be converted
# to "0" when assigned to an interger type.
#
# Expected integer arguements are assigned to temp. non-integer variables
# so validation can be done in the validation section and the error message
# can reflect what the user passed instead of "0".
#
typeset -r TMP_RAM_SIZE=$6  # VM RAM size
typeset -r TMP_CPUS=$7  # Number of CPUS
typeset -r VIRT_HW="$8"   # "on", "off" hardware virtualization enabled

typeset -r DIST_NAME="$(${MANIFEST_READ} ${MFEST_SOCKET} "name")"

#
# Validate the arguments
#

#
# If the argument is numeric assign its value to RAM_SIZE
#
if [[ ${TMP_RAM_SIZE} != +([0-9]) ]]
then
        print -u2 "\nImproper argument."
        print -u2 "\nThe ram size of ${TMP_RAM_SIZE} is invalid."
        print -u2 "\"ram size\" must be an integer, min \"1000\" (MB)."
        exit 1
fi
typeset -i RAM_SIZE=${TMP_RAM_SIZE}  # VM RAM size

if ((${RAM_SIZE} < 1000 || ${RAM_SIZE} > 16384)) ; then
        print -u2 "\nThe ram size of ${RAM_SIZE} is invalid. It must" \
	    " be in range [1000, 16384] (MB)"
        exit 1
fi

#
# If the argument is numeric assign its value to CPUS
#
if [[ ${TMP_CPUS} != +([0-9]) ]]
then
        print -u2 "\nImproper argument."
        print -u2 "\ncpus of ${TMP_CPUS} is invalid."
        print -u2 "\"cpus\" must be an integer in the range [1,32]"
        exit 1
fi
typeset -i CPUS=${TMP_CPUS}  # Number of CPUS

if ((${CPUS} < 1 || ${CPUS} > 32)) ; then
	print -u2 "\nThe number of CPUS ${CPUS} is invalid. It must" \
            " be in range [1,32]"
	exit 1
fi

if [[ "${VIRT_HW}" != "on" && "${VIRT_HW}" != "off" ]] ; then
	print -u2 "\nThe hardware virtualization setting" \
	    "${VIRT_HW} is not valid. It must be \"on\" or \"off\"."
	exit 1
fi

if [[ "XX${DIST_NAME}" == "XX" ]] ; then
	print -u2 "\nThe distribution name ${DIST_NAME}" \
	    "is not valid."
	exit 1
fi

#
# Set up error handling.
# Use set -o errexit to trap errors. However, where possible,
# explicitly check command return status for errors.
#
trap "vmc_error_handler_trap" INT
set +o errexit

#
# Check if Virtual Box is installed
#
vmc_is_vbox_installed
cmdsts=$?
vmc_error_handler ${cmdsts} \
    "\nError: Required VirtualBox version is not installed"

#
# Check if the VM is running. Issue a warning if it is.
#
is_running=$(VBoxManage -q showvminfo ${DIST_NAME} | grep State)
if [[ "${is_running}"  == ~(E)^State:[ ]*running.* ]]; then
	print -u2 "\nVirtual Machine ${DIST_NAME} is running."
	print -u2 "\tNo action will be taken. Shutdown the Virtual"
	print -u2 "\tMachine then restart this script."
	print -u2 "\tTo shutdown the VM issue:"
	print -u2 "\tpfexec VBoxManage controlvm ${DIST_NAME} poweroff"
	exit 1
fi

#
# Save the current settings so they can be reset in the cleanup routine
#
vbox_cmd="VBoxManage -q showvminfo ${DIST_NAME}"
orig_ram_size=$(${vbox_cmd} | grep "^Memory size:" | awk '{print $NF}')
orig_cpus=$(${vbox_cmd} | grep "^Number of CPUs:" | awk '{print $NF}')
orig_virt_hw=$(${vbox_cmd} | grep "^VT-x VPID:" | awk '{print $NF}')

#
# Configure Virtual Machine to the user supplied settings.
#
vbox_cmd="VBoxManage -q modifyvm ${DIST_NAME} --memory ${RAM_SIZE} \
    --cpus ${CPUS} --hwvirtex ${VIRT_HW}"
print -u1 "\nInvoking: ${vbox_cmd}"
${vbox_cmd}
cmdsts=$?
vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."


#
# exit with success status
#
exit 0

