summaryrefslogblamecommitdiffstats
path: root/core/modules/run-virt/data/opt/openslx/vmchooser/vmchooser-run_virt
blob: dfebebe7a812d651c5aa375f20b345500e249109 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                                                                               
 
                                                 
 



                                                                         
                                              

                                                                            
 






                                                                                









                                            
                                                    
                                                




                                                      








                                                         
             
                             

                  
                   



                   
              
 
















                                                                                 

                                                                              
 
                                                       
                       
                                                                       
                                                          
                                               
  
                
 
        
                                      

                                 
                                                                                        
                                                                             




                                                                                                            



                                    
 


                                                                                           
 


                                                                           
 


                                                                                   


                                                                                         

                                                                                           
 

                                                                                 
 

                                                                               
 

                                                                             
 
 
                                               
                                                                                         
                                                                                    
 

                                                                       
 


























                                                                                                                         
                  
            


                                                    













                                                                                                       

                                                    























                                                                                                        
                                                           
                                
                                                                




                                                           

                                                              
 



                                                
                                                     
 
                                                          


                   








                                                                                                                  
          

  

                   
 








                                                                                                 
 
      
 
#!/bin/bash
# Full bash required
# -----------------------------------------------------------------------------
#
# Copyright (c) 2007..2018 bwLehrpool-Projektteam
#
# This program/file is free software distributed under the GPL version 2.
# See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
#
# If you have any feedback please consult https://bwlehrpool.de and
# send your feedback to support@bwlehrpool.de.
#
# General information about bwLehrpool can be found at https://bwlehrpool.de
#
# -----------------------------------------------------------------------------
# run-virt.sh
#    - This is the generic wrapper for the several virtualization solutions.
#      The idea is to setup a set of variables used by at least two different
#      tools and then include the specific plugin which configures the speci-
#      fied virtualization tool.
################################################################################
SELF="$( readlink -f "${BASH_SOURCE[0]}" )"
if [ -z "$SELF" ] || ! [ -f "$SELF" ]; then
	SELF="$( readlink -f "$0" )"
fi
if [ -z "$SELF" ] || ! [ -f "$SELF" ]; then
	slxlog "run-virt" "Cannot find SELF"
	exit 1
fi
readonly SELF

# Global variables needed for the core functionality
declare -rg VMCHOOSER_DIR="$( dirname "$SELF" )"
declare -rg VMCHOOSER_CONF_DIR="$VMCHOOSER_DIR/config"
declare -rg USER="$(whoami)"
declare -rg TMPDIR="/tmp/virt/${USER}/$$"
declare -rg CONFDIR="${TMPDIR}/metadata"

if ! [ -d "$VMCHOOSER_DIR" ]; then
	slxlog "run-virt" "$SELF is not in a directory!?"
	exit 1
fi

# Useless without this
. /opt/openslx/config
. /opt/openslx/bin/slx-tools

# Debug mode?
if [ "$1" = "--debug" ]; then
	shift
	DEBUG=true
elif is_debug; then
	DEBUG=true
else
	DEBUG=false
fi
readonly DEBUG

# Check for existence of plugin
if [ "x$1" = "x--query" ]; then
	PLUGIN_ID="${2//[^a-z_\-]/}"
	if [ -z "$PLUGIN_ID" ]; then
		echo "Error: No plugin name given" >&2
		exit 1
	fi
	if ! [ -f "$VMCHOOSER_DIR/plugins/$PLUGIN_ID/run-virt.include" ]; then
		echo "Plugin '$PLUGIN_ID' does not exist." >&2
		exit 1
	fi
	# Maybe in the future we want to output information about the plugin here
	# to stdout in a simple to parse format like key=value....
	echo "Plugin '$PLUGIN_ID' found" >&2
	exit 0
fi

# This script expects the path to the xml file describing the VM to be started
declare -rg XML_FILE="$1"

# A path to the logfile can be given as second argument
declare -g LOGFILE="$2"
if [ -z "$LOGFILE" ] || ! touch "$LOGFILE" || ! [ -f "$LOGFILE" ]; then
	LOGFILE="/var/log/openslx/run-virt.${USER}.$$.log"
	touch "$LOGFILE" || LOGFILE="$(mktemp)"
fi
readonly LOGFILE

main() {
	declare -rg MAINPID="$BASHPID"
	# Don't have writelog yet
	echo "MAINPID: $MAINPID"
	# Functions needed by vmchooser-run_virt (writelog(), cleanexit(), safesource())
	declare -rg RUN_VIRT_INCLUDE_DIR="${VMCHOOSER_DIR}/run-virt-includes"
	if ! source "${RUN_VIRT_INCLUDE_DIR}/vmchooser_runvirt_functions.inc"; then
		slxlog "run-virt" "Could not source ${RUN_VIRT_INCLUDE_DIR}/vmchooser_runvirt_functions.inc"
		exit 1
	fi

	trap 'cleanexit $?' EXIT
	trap 'cleanexit 129' SIGHUP
	trap 'cleanexit 130' SIGINT
	trap 'cleanexit 143' SIGTERM

	# Starting sourcing the includes files. Note that the critical ones should use
	# the '--exit' option of safesource to trigger cleanexit in case of a corrupted/bad
	# include file.

	# Set core runvirt variables and directories
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/init_core.inc")
	writelog "#################### Initialization ####################"

	# Read vmchooser.conf, (generated) virtualization.conf and slx config files
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/load_configs.inc")

	# Declaration of hardware related variables
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/set_runvirt_hardware_variables.inc")

	# Window manager required early for user feedback through popups (e.g. errors) etc.
	$(safesource "${RUN_VIRT_INCLUDE_DIR}/start_windowmanager.inc")

	# Read needed variables from XML file
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/get_xml_file_variables.inc")

	# Download metadata from server (e.g. vmx for vmware)
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/download_vm_metadata.inc")

	# Try to use dnbd3 to access the image, nfs/cifs fallback
	$(safesource --exit "${RUN_VIRT_INCLUDE_DIR}/setup_image_access.inc")


	# Mark the end of generic run-virt part
	writelog "Done with generic run-virt. Now loading virtualizer-specific includes."
	writelog "#################### Plugin init: $PLUGIN_ID ####################"

	# NG: first include the hypervisor includes
	$(safesource "${RUN_VIRT_INCLUDE_DIR}/setup_vm_hypervisor.inc")

	# It must declare PLUGIN_FEATURES to set which features are needed.
	# Features are those defined by run-virt.d include files.
	# After sourcing the plugin, check that it defined both PLUGIN_FEATURES and
	# the main function 'run_plugin' which will be called later by the main scripts.
	if ! isset PLUGIN_FEATURES || ! is_function run_plugin; then
		writelog "Bad plugin '$PLUGIN_ID': either it did not set PLUGIN_FEATURES or did not define 'run_plugin'."
		EXIT_TYPE="internal" EXIT_REASON="Fehlerhaftes vmchooser plugin: '$PLUGIN_ID'." cleanexit 1
	fi
	writelog "Requested features:\t${PLUGIN_FEATURES}"

	# Source the *.inc files in run-virt.d
	for FILE in ${VMCHOOSER_DIR}/run-virt.d/*.inc; do
		$(safesource "$FILE")
	done

	# Now look which features were requested and call the handler if one is defined.
	for FEAT in $PLUGIN_FEATURES; do
		if notempty FEATURE_HANDLERS["${FEAT}"]; then
			writelog "Initialising '${FEAT}'..."
			if ! ${FEATURE_HANDLERS["$FEAT"]}; then
				writelog "\tFailed to run '${FEATURE_HANDLERS["$FEAT"]}'."
				error_user "Konnte Feature namens '$FEAT' nicht initialisieren!
	Diese Funktion wird nicht verfügbar sein!" # not critical, do not exit!
			fi
		else
			writelog "\tFeature '$FEAT' has no handler! This function will be unavailable."
			notify_user "Feature '$FEAT' nicht unterstützt"
		fi
	done
	# Prepare array for the command line options
	unset VIRTCMDOPTS
	declare -a VIRTCMDOPTS
	# The features should now be initialized, call the main 'run_plugin' function of the hypervisor
	writelog "#################### Plugin run: $PLUGIN_ID ####################"
	writelog "Calling 'run_plugin' of '$PLUGIN_ID'..."
	run_plugin || writelog "Failed to run 'run_plugin' of '$PLUGIN_ID'."

	# It should have set this variable if all went well
	if isempty VIRTCMD; then
		error_user "Fehler beim Starten der VM-Sitzung" "
	Das Start-Script für den Virtualisierer $PLUGIN_ID hat kein Kommando
	zum Starten der Sitzung definiert. Kann Sitzung nicht initialisieren."
		slxlog "virt-plugin-error" "run-virt.include for $PLUGIN_ID did not set VIRTCMD"
		cleanexit 1
	fi

	run_hooks "pre-exec" "$PLUGIN_ID" "$IMGUUID"

	# Launch COWGUI in CoW-Edit-Mode
	local cowpid cowurl vmpidfile
	cowpid=
	vmpidfile=
	if [ -n "$DMSD_COW_SESSION" ]; then
		vmpidfile="$( mktemp -p "/run/user/$( id -u )" )"
		cowurl="${SLX_VMCHOOSER_BASE_URL//"/vmchooser/"/"/cow/"}"
		(
		cntr=0
		while true; do
			cowgui --session "$DMSD_COW_SESSION" --url "$cowurl" --pid "$DNBD3_PID" && break
			# Unclean exit, let's see if it's worth relaunching
			state="$( curl -m 3 -sS -L "$cowurl/status/$DMSD_COW_SESSION" | jq -r .state )"
			[ -z "$state" ] && break
			[ "$state" = "PROCESSING" ] && break
			[ "$state" = "ERROR" ] && break
			[ "$state" = "COMPLETELY_DONE" ] && break
			(( cntr++ > 10 )) && break
		done
		[ -n "$vmpidfile" ] && kill "$( cat "$vmpidfile" )"
		) &
		cowpid=$!
	fi

	writelog "VM command: ${VIRTCMD} ${VIRTCMDOPTS[*]}"
	# This will start the VM
	writelog "---------- BEGIN VM command output ----------"
	local retval vmpid
	"${VIRTCMD}" "${VIRTCMDOPTS[@]}" &>> "${LOGFILE}" &
	vmpid=$!
	[ -n "$vmpidfile" ] && echo "$vmpid" > "$vmpidfile"
	wait "$vmpid"
	retval=${?}
	writelog "---------- END VM command output ----------"

	[ -n "$DNBD3_PID" ] && kill "$DNBD3_PID"
	# If cow, wait for GUI
	[ -n "$cowpid" ] && wait "$cowpid"

	run_hooks "post-exec" "$PLUGIN_ID" "$IMGUUID"

	writelog "Virtualizer exited with '$retval'. Bye."

	cleanexit 0
}
# Detach
main &
RUNVIRT_PID="$!"

# Give some time
usleep 100000
if ! kill -0 "${RUNVIRT_PID}"; then
	if [ -n "${LOGFILE}" ] && [ -f "${LOGFILE}" ]; then
		echo "Failed to start runvirt main function. Seems that it exited early (<100ms)." >> "${LOGFILE}"
	fi
fi

wait "$RUNVIRT_PID"
RUNVIRT_RET="$?"

if [ "${RUNVIRT_RET}" -ne 0 ]; then
	if [ "${RUNVIRT_RET}" -eq 141 ]; then
		# 141 happens on alt + print screen + k or upon automatic logout via systemd
		# just sleep here to avoid these annoying (and misleading) slxlogs....
		sleep 2 ; sleep 2
	fi
	[ -s "${LOGFILE}" ] && slxlog "run-virt-wrapper" "Failed to launch runvirt!" "${LOGFILE}"
	exit "$RUNVIRT_RET"
fi

exit 0