#!/bin/bash
################################################################################
# Filename: ./src/plugins/vmware/bin/qrm-vmware-manage
# 
# The contents of this file are subject to the Qlusters Public License
# Version 1.1 (the License); you may not use this file except in compliance
# with the License.
# You may obtain a copy of the License at
# http://www.openqrm.org/content/view/33/69/.
# 
# Software distributed under the License is distributed on an AS IS basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
# the specific language governing rights and limitations under the License.
# 
# The Original Code is openQRM.
# 
# The Initial Developer of the Original Code is Qlusters Corporation. Portions
# created by Qlusters Corporation are Copyright (C) 2003-2005. All Rights
# Reserved.
# 
# Contributor(s):
# 
# Description:
# 
# Comments:
################################################################################
# 
# This script will manage vmware partitions
# It is intended to be called from the partitioning engine.
#
# The config file for a given VM guest will be $remote_config_dir/$vm_mac/$vm_mac.vmx
# A directory is created for each VM
#
# TODO:
#   Add check to see if there are needed answers on start()
#   Add qrm_events sends
#   Add qrmexecd wget of the parameter file so we don't write locally
#   Add reboot (qrmexecd)
#   Get qrm_base_dir from actual qrm config
#   Add the other guestOS types

# defaults
vm_port=902
vm_type="other24xlinux"
vm_mem=256
err_key="VirtualMachine.State.Operation.Error.Action.Failed"
# powerop_mode can be "hard", "soft", or "trysoft"
vm_powerop_mode="hard"

# local base path for the image
# qrm_base_dir=/mnt/usb/images/gsx2
qrm_base_dir="$QRM_NODES_BASE_DIR/qrm/plugins/vmware"

# This is the directory to put the configuration directory for each VM into.
# It is relative to the $qrm_base_dir, and should be the path within the image
# right now this is written locally (See TODOs)
remote_config_dir="/var/lib/vmware/VirtualMachines"

# template from which to create each vm config file
# (absolute path)
vm_template_conf="$QRM_NODES_BASE_DIR/qrm/plugins/vmware/etc/template.vmx"


###############################################################################
##### functions
################################################################################
function usage() {
	echo "usage: $0 (start|stop|create|remove|getstate|getallstate|list|reboot) {options}..."
	#echo -e "\t-h {host}" 
	#echo -e "\t-u {user}" 
	#echo -e "\t-p {password}"
	echo -e "\t-m {mac address}"
	echo -e "\t[-P {port}]"
	echo -e "\t[-M {Memory Size}] (default is 256M)"
	echo -e "\t[-t {guest OS type}]"
	echo -e "\t[-e {event key to send in case of error}]"
	echo -e "\ttype is (other24xlinux|other26xlinux) default is other24xlinux"
	exit 1
}

# args: vm_mac
function start() {
	vm_config="$1"

	state=$(getstate $vm_config)
	if [ "$state" != "on" ] ; then
		$vmwarecmd $vm_config start
		if [ $? -ne 0 ] ; then
			#TODO send some qrm error
			echo "ERROR: \"$vmwarecmd $vm_config start\" did not finish successfully"
			exit 1
		fi

		# TODO check for required user input
		state="$(getstate $vm_config)"
		if [ "$state" != "on" ] ; then
			#TODO send some qrm error
			echo "ERROR: vmware partition did not start successfully"
			exit 1
		else
			exit 0
		fi
	fi
}

# args: vm_mac
function stop() {
	vm_config="$1"

	state=$(getstate $vm_config)
	if [ "$state" != "off" ] ; then
		$vmwarecmd $vm_config stop $vm_powerop_mode
		if [ $? -ne 0 ] ; then
			#TODO send some qrm error
			echo "ERROR: \"$vmwarecmd $vm_config stop $vm_powerop_mode\" did not finish successfully"
			exit 1
		fi

		state="$(getstate $vm_config)"
		if [ "$state" != "off" ] ; then
			#TODO send some qrm error
			echo "ERROR: vmware partition did not stop successfully"
			exit 1
		else
			exit 0
		fi
	fi 
}

function list() {
	vm_list=$($vmwarecmd -l)
	if [ $? -ne 0 ] ; then
		#TODO send qrm error
		echo "ERROR: \"$vmwarecmd -l\" was not successful"
	fi
	echo "$vm_list"
		
}

function remove() {
  vm_config="$1"

  state=$(getstate $vm_config)
  if [ "$state" == "off" ] ; then
    $vmwarecmd -s unregister $vm_config 
    if [ $? -ne 0 ] ; then
      #TODO send some qrm error
      echo "ERROR: \"$vmwarecmd $vm_config start\" did not finish successfully"
      exit 1
	  else
  	 list=$(list)
	    # check the registered list to verify it was removed
  	  if echo $list | grep $vm_mac > /dev/null 2>&1 ; then
				# TODO add error
				echo "ERROR: vmware partition did not register successfully"
    	  exit 1
	    else
				#it is not in the list, then remove config file
				#echo its was successfully removed from vmware, removing file ${qrm_base_dir}${vm_config}
				echo its was successfully removed from vmware, removing file ${vm_config}
				#rm -rf $(dirname ${qrm_base_dir}${vm_config})
				rm -rf $(dirname ${vm_config})
      	exit 0
			fi
    fi


  fi
}

# args: vm_mac vm_mem vm_type
function create() {
	vm_mac="$1"
	vm_config="$2"
	#vm_config_local=${qrm_base_dir}${vm_config}
	vm_config_local=${vm_config}
	vm_mem="$3"
	vm_type="$4"

	if [ ! -f $vm_template_conf ] ; then
		#TODO send qrm error
		echo "ERROR: Template file does not exist"
		exit 1	
	fi
	if [ ! -f $vm_config_local ] ; then
		if [ ! -d "$(dirname $vm_config_local)" ] ; then
			mkdir -p "$(dirname $vm_config_local)"
		fi
		cat $vm_template_conf |\
			sed -e "s/@@MEM@@/$vm_mem/"   |\
			sed -e "s/@@TYPE@@/$vm_type/" |\
			sed -e "s/@@NAME@@/$vm_mac/"  |\
			sed -e "s/@@MACADDRESS@@/$vm_mac/" > $vm_config_local
	fi
	if [ ! -x $vm_config ] ; then
		chmod a+x $vm_config_local
	fi

	#TODO send qrmexecd command to wget file to local.
	echo creating local file in $vm_config_local
	echo creating remote file in $vm_config

	$vmwarecmd -s register $vm_config
	# return of 20 indicates the VM was already registered
	if [ $? -ne 0 ] && [ $? -ne "20" ] ; then
		#TODO send error	
		echo "ERROR: \"$vmwarecmd -s register $vm_config\" did not finish successfully"
		exit 1
	else
		list=$(list)
		# check the registered list to verify it was added.
		if echo $list | grep $vm_mac > /dev/null 2>&1 ; then
			exit 0
		else
			# TODO add error
			echo "ERROR: vmware partition did not register successfully"
			exit 1
		fi
	fi
}

function getstate() {
	state=$($vmwarecmd "$1" getstate)
	if [ $? -ne 0 ] ; then
		#TODO send some qrm error
		echo "ERROR: \"$vmwarecmd $1 getstate\" did not finish successfully"
		# exit 1??
		return 1
	else 
		echo $state
		return 0
	fi
}

function getallstate() {
	for i in $(list) ; do 
		state=$(getstate "$i")
		echo "VM $i has state \"$state\""
	done
}

################################################################################
##### inital validation
################################################################################
if [ ! -z "$1" ] ; then
	vm_command=$1
	shift
else
	usage
fi 

vmwarecmd="`which vmware-cmd`"
if [ -z "$vmwarecmd" ] ; then
	# TODO check qrm error messages
	echo "ERROR: can't find vmware-cmd in $PATH"
	# TODO check qrm error codes
	exit 1
fi

################################################################################
##### option parsing
################################################################################

#while getopts "h:u:p:m:P:M:t:e:" option ; do
while getopts "m:P:M:t:e:" option ; do
  case $option in
#		 h) vm_host=$OPTARG;;
#		u) vm_user=$OPTARG;;
#		p) vm_pass=$OPTARG;;
		m) vm_mac=$(echo $OPTARG | tr a-z A-Z);;
		P) vm_port=$OPTARG;;
		M) vm_mem=$OPTARG;;
		t) vm_type=$OPTARG;;
		e) err_key=$OPTARG;;
		*) usage;;
  esac
done

#if [ -z "$vm_host" ] || [ -z "$vm_user" ] || [ -z "$vm_pass" ] || [ -z "$vm_mac" ] ; then
if [ -z "$vm_mac" ] ; then
	usage
fi

# vmware-cmd -q -H host -U user -P port
#vmwarecmd="$vmwarecmd -q -H $vm_host -U $vm_user -P $vm_pass"
vmwarecmd="$vmwarecmd -q "

vm_config_local="${qrm_base_dir}${remote_config_dir}/$vm_mac/$vm_mac.vmx"
vm_config_remote="${remote_config_dir}/$vm_mac/$vm_mac.vmx"

case "$vm_command" in
	start) start "$vm_config_remote";;

	stop) stop "$vm_config_remote";;

	list) list;;

	create)
		create $vm_mac $vm_config_remote $vm_mem $vm_type
	;;

	remove)
    remove $vm_config_remote
  ;;


	getstate)
		# returns (echos) state: 
		# can be: "on" "off" "suspended" "stuck" "unknown"
		getstate $vm_config_remote
	;;

	getallstate) getallstate;;

	reboot)
		#TODO implement me!
		echo "Not implemented yet"
		exit 1
	;;

	*)
	usage
esac
exit 0
# vim:ts=2:sw=2:sts=0
