#!/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.
#

#
# =============================================================================
# export_vm : Export a Virtual Machine in VMWare ESX format or in OVF format
# =============================================================================
#

#
# 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
# prefix "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

		#
		# Cleanup output area
		#
		rm -rf ${MEDIA_OUT}/${EXPORT_FORMAT}

		#
		# Restore the boot from ISO setting.
		#
		if [[ "${vm_iso}" != "empty"  ]]; then
			VBoxManage -q modifyvm ${DIST_NAME} --dvd ${vm_iso} \
			    --boot1 dvd 
		fi

	} > /dev/null 2>&1

}

#######################################################################
# main
#
# Name: export_vm
#	
# Args:
#	MFEST_SOCKET: Socket 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:
#	<export_format> = Forat type to export either ESX or OVF
#
# Inputs to be taken from the VMC Manifest:
#	<DIST_NAME> - "name" tag from VMC Manifest
#	
# Output:
#	Exported VM in supported formats currently either ESX or OVF.
#
# Description:
#
#	This finalizer script will export the VM in a format that
#	can be consumed by VMWare ESX.
#	or
#	can be consumed by hypervisors which support OVF VMs
#
#	Exported network will not be reconfigured and will remain NAT
#	
# Returns:
#	1 on failure
#	0 on success
#
#######################################################################

#
# Define built-in commands
#
builtin cp
builtin mkdir
builtin mv
builtin rm

typeset -i cmdsts
typeset    vbox_cmd
typeset -r MANIFEST_READ=/usr/bin/ManifestRead

#
# Process command line arguments
#
if (( $# != 6 )) ; then
	print -u2 "\nWrong number of arguments provided by Distro Constructor."
	exit 1
fi

#
# Arguments
#
typeset -r MFEST_SOCKET="$1"
typeset -r MEDIA_OUT="$5"
typeset -ru EXPORT_FORMAT="$6" # export format, ESX or OVF, in uppercase

# "name" tag from VMC Manifest
typeset -r DIST_NAME="$(${MANIFEST_READ} ${MFEST_SOCKET} "name")"


#
# Validate the arguments
#
if [[ ! -d ${MEDIA_OUT} ]] ; then
        print -u2 "\nMedia output area ${MEDIA_OUT} does not exist"
        exit 1
fi

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

if [[ "${EXPORT_FORMAT}" != "ESX" && "${EXPORT_FORMAT}" != "OVF" ]]; then
        print -u2 "\nThe export format specified: ${EXPORT_FORMAT}" \
	    " is invalid. It must be either \"esx\"  or \"ovf\" "
        exit 1
fi

#
# Need an all lowercase equivalent to EXPORT_FORMAT
#
typeset -rl EXPORT_FORMAT_LC=${EXPORT_FORMAT}

#
# variables
#
typeset    vm_iso=""        # The ISO loaded in the VM DVD
typeset    vm_disk=""       # The VM disk image
typeset    is_running=""    # Used for testing if the VM is already running.

#
# 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"

#
# If the Virtual Machine is already running issue a warning
# and exit.
#
vbox_cmd="VBoxManage -q showvminfo ${DIST_NAME}"
is_running=$(${vbox_cmd} | grep "^State")
if [[ "${is_running}"  == ~(E)^State:[ ]*running.* ]]; then
        print -u2 "\nVirtual Machine ${DIST_NAME} is running."
        print -u2 "\tNo action will be taken."
        print -u2 "\tShutdown the Virtual Machine then resume"
        print -u2 "\tthe Distribution Constructor run via:"
        print -u2 "\tpfexec distro_const build -r " \
	    "export_${EXPORT_FORMAT_LC} <name of manifest>"
        print -u2 "\tTo shutdown the VM issue:"
        print -u2 "\tpfexec VBoxManage controlvm ${DIST_NAME} poweroff"
        exit 1
fi

#
# Save VM's iso image loaded in the DVD
#
vm_iso=$(${vbox_cmd} | grep ^DVD: | awk '{print $2}')
if [[ "${vm_iso}" == "empty"  ]]; then
	vmc_error_handler 1 "\nError: no ISO found in CD/DVD."
fi

#
# Save VM's disk
#
vm_disk=$(${vbox_cmd} | grep "^Primary master:" | awk '{print $3}')

#
# Remove any possible legacy bits from a prior run.
#
rm -rf ${MEDIA_OUT}/${EXPORT_FORMAT} > /dev/null 2>&1

#
# Create the destination directories if it does not already exist.
#
mkdir -p -m 777 ${MEDIA_OUT}/${EXPORT_FORMAT}
cmdsts=$?
vmc_error_handler ${cmdsts} \
    "\nError: mkdir ${MEDIA_OUT}/${EXPORT_FORMAT} failed."

#
# Configure Virtual Machine to boot from hard disk
#
vbox_cmd="VBoxManage -q modifyvm ${DIST_NAME} --dvd none --boot1 disk"
print -u1 "\nInvoking: ${vbox_cmd}"
${vbox_cmd}
cmdsts=$?
vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."

if [[ ${EXPORT_FORMAT} == "ESX" ]] ; then
	#
	# Create a clone of the installed virtual machine in
	# a format usable by VMWare ESX
	#
	vbox_cmd="VBoxManage -q clonehd ${vm_disk} \
	    ${MEDIA_OUT}/${EXPORT_FORMAT}/${DIST_NAME}.vmdk \
	    --variant ${EXPORT_FORMAT},fixed"
	print -u1 "\nInvoking: ${vbox_cmd}"
	${vbox_cmd}
	cmdsts=$?
	vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."
else
	#
	# Assume EXPORT_FORMAT == OVF since this is the only other format
	# and EXPORT_FORMAT has already been validated.
	#
	#
	# Export OVF:
	# Export the VM in OVF format
	#
	vbox_cmd="VBoxManage -q export ${DIST_NAME} \
	    -o ${MEDIA_OUT}/${EXPORT_FORMAT}/${DIST_NAME}.${EXPORT_FORMAT}"
	print -u1 "\nInvoking: ${vbox_cmd}"
	${vbox_cmd}
	cmdsts=$?
	vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."
fi


#
# Display the export VM configuration details
#
vbox_cmd="VBoxManage -q showvminfo ${DIST_NAME}"
print -u1 "\nInvoking: ${vbox_cmd}"
${vbox_cmd} > ${MEDIA_OUT}/${EXPORT_FORMAT}/${DIST_NAME}_config.txt
cmdsts=$?
vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."

#
# Restore the boot from ISO setting.
#
vbox_cmd="VBoxManage -q modifyvm ${DIST_NAME} --dvd ${vm_iso} --boot1 dvd"
print -u1 "\nInvoking: ${vbox_cmd}"
${vbox_cmd}
cmdsts=$?
vmc_error_handler ${cmdsts} "\nError: ${vbox_cmd} failed."

#
# exit with success status
#
exit 0

