blob: a011a0d10498bd85c9bbb3e2abe71a19423b948d (
plain) (
tree)
|
|
#!/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 [ "x$1" = "x--debug" ]; then
shift
DEBUG=true
elif [ "$SLX_DEBUG_MODE" = "ON" ] || grep -qE '\bdebug\b' "/proc/cmdline"; 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() {
# 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"
writelog "VM command: ${VIRTCMD} ${VIRTCMDOPTS[*]}"
# This will start the VM (no eval needed!)
writelog "---------- BEGIN VM command output ----------"
local retval
"${VIRTCMD}" "${VIRTCMDOPTS[@]}" >> "${LOGFILE}"
retval=${?}
writelog "---------- END VM command output ----------"
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
|