summaryrefslogtreecommitdiffstats
path: root/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes
diff options
context:
space:
mode:
authorJonathan Bauer2017-01-25 18:32:35 +0100
committerJonathan Bauer2017-01-25 18:32:35 +0100
commiteea5898961a40fc50f01356f90c42904a73a3f74 (patch)
tree52c19d11efc2d7d904ac89e36ff271de305cfc5a /core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes
parent[pam] Include cifs.upcall for DFS support (diff)
downloadmltk-eea5898961a40fc50f01356f90c42904a73a3f74.tar.gz
mltk-eea5898961a40fc50f01356f90c42904a73a3f74.tar.xz
mltk-eea5898961a40fc50f01356f90c42904a73a3f74.zip
major run-virt restructure, only vmware plugin tested!
Diffstat (limited to 'core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes')
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/download_vm_metadata.inc52
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc122
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/init_core.inc18
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/load_configs.inc19
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc213
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc26
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc12
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc130
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc46
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc79
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc101
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc40
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc53
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc77
-rw-r--r--core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc388
15 files changed, 727 insertions, 649 deletions
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/download_vm_metadata.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/download_vm_metadata.inc
index 974a5626..818896fc 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/download_vm_metadata.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/download_vm_metadata.inc
@@ -1,32 +1,46 @@
########################################################
# Include: Detect, whether runvirt runs in legacy mode #
########################################################
-
+## Functions ##
# Legacy mode: As runvirt has been before.
# New mode: uuid in xml _and_ vmx given via http.
+download_metadata() {
+ # Sanity checks
+ if ! check_dep wget; then
+ writelog "Could not find 'wget' in PATH: $PATH"
+ EXIT_TYPE="internal" EXIT_REASON="Fehlendes Dienstprogramm 'wget'!" cleanexit 1
+ fi
-writelog "Detecting current/legacy mode ..."
+ if ! isset SLX_VMCHOOSER_BASE_URL; then
+ writelog "SLX_VMCHOOSER_BASE_URL is not set! Was /opt/openslx/config sourced?"
+ EXIT_TYPE="internal" EXIT_REASON="Keine URL zur Schnittstelle des bwLehrpool-Satelliten gefunden!" cleanexit 1
+ fi
-declare -rg TMPCONFIG="$TMPDIR/vmconfig.tmp"
+ writelog "Detecting current/legacy mode..."
+ declare -rg TMPCONFIG="$TMPDIR/vmconfig.tmp"
-# Assume legacy mode by default, only trigger "current" mode if everything else below worked
-LEGACY=yes
-if [ -z "$IMGUUID" ]; then # Keine uuid: Abbruch, Legacy
- writelog "Could not extract a uuid param from ${xmlfile}. Triggering legacy mode."
-else
- # Now getting template file:
- if ! wget -T 6 -O "$TMPCONFIG" "${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID}" 2>/dev/null >&2; then
- writelog "wget ${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID}. Triggering legacy mode."
- else
- writelog "wget ${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID} successful."
- if [ ! -s "$TMPCONFIG" ]; then
- writelog "Server sent zero byte virtual machine description file. Triggering legacy mode."
+ if wget -T 6 -O "$TMPCONFIG" "${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID}" 2>/dev/null >&2; then
+ writelog "Downloaded VM description from '${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID}' successfully."
+ if [ -s "$TMPCONFIG" ]; then
+ # Downloaded a non-zero VM description file, all good
+ return 0
else
- writelog "Triggering current (non-legacy) mode."
- LEGACY= # everything worked - clear legacy mode variable (so we use the "current" mode)
+ writelog "Server sent zero byte virtual machine description file. Triggering legacy mode."
fi
fi
-fi
-readonly LEGACY
+ # Seems we are in legacy mode, which is no longer supported. Warn user and exit
+ EXIT_TYPE="user" EXIT_REASON="
+Die gewählte VM ist eine 'Legacy VM', für die unvollständige
+Metadaten auf dem bwLehrpool-Server hinterlegt sind. Diese
+werden nicht mehr unterstützt. Um diese VM weiterhin nutzen
+zu können, muss sie mittels der bwLehrpool-Suite heruntergeladen,
+einmal gebootet, und wieder hochgeladen werden.
+(Bei der Gelegenheit könnten z.B. auch gleich anfallende Updates
+eingespielt werden.)
+" cleanexit 1
+}
+
+## Main ##
+call_post_source download_metadata
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc
index fdacc69c..a6543c76 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc
@@ -1,63 +1,69 @@
############################################
# Include: Get needed values from XML file #
############################################
-
-writelog "Parsing XML..."
-
-declare -rg VMSTORE_PATH=/mnt/vmstore
-
-get_xml () {
- xmlextract "//settings/eintrag/${1}/@param" "${xmlfile}"
+## Functions ##
+parse_xml() {
+ # Sanity checks
+ if ! check_dep get_xml; then
+ writelog "Could not find 'get_xml'"
+ EXIT_TYPE="internal" EXIT_REASON="Keine XML-Unterstützung!" cleanexit 1
+ fi
+
+ writelog "Parsing XML..."
+ declare -rg VMSTORE_PATH=/mnt/vmstore
+ declare -rg IMGUUID=$(get_xml "uuid")
+ if isempty IMGUUID; then
+ writelog "Error parsing XML: No value for 'uuid'."
+ EXIT_TYPE="user" EXIT_REASON="Konnte keine ID für das ausgewählte Image ermitteln!" cleanexit 1
+ fi
+
+ # Relative / Absolute path to image
+ declare -rg SRC_IMG_RELATIVE=$(get_xml "image_name")
+ declare -g SRC_IMG_ABSOLUTE=$(get_xml "image_path")
+
+ if isempty SRC_IMG_ABSOLUTE SRC_IMG_RELATIVE; then
+ writelog "Error parsing XML: Neither relative nor absolute path for image found!"
+ EXIT_TYPE="user" EXIT_REASON="Konnte kein Pfad zur ausgewählten virtuellen Maschine ermitteln!" cleanexit 1
+ fi
+
+ if isempty SRC_IMG_ABSOLUTE && [ "${SRC_IMG_ABSOLUTE:0:1}" != "/" ]; then
+ writelog "Error parsing XML: Parsed value for absolute path doesn't start with '/': '$SRC_IMG_ABSOLUTE'"
+ EXIT_TYPE="user" EXIT_REASON="Ungültiger asboluter Pfad zur virtuellen Maschine!" cleanexit 1
+ fi
+
+ notempty SRC_IMG_ABSOLUTE || SRC_IMG_ABSOLUTE="${VMSTORE_PATH}/${SRC_IMG_RELATIVE}"
+ readonly SRC_IMG_ABSOLUTE
+
+ declare -rg IMG_BASENAME=$(basename "$SRC_IMG_ABSOLUTE")
+
+ VM_DISPLAYNAME=$(get_xml "short_description")
+ notempty VM_DISPLAYNAME || VM_DISPLAYNAME="${IMG_BASENAME}"
+ readonly VM_DISPLAYNAME
+
+ # Define VM_CLEANNAME since VM_DISPLAYNAME can be long and contain weird characters
+ declare -rg VM_CLEANNAME=$(echo "${VM_DISPLAYNAME:0:32}" | sed -r 's/[^0-9a-zA-Z_-\.]+/_/g')
+
+ # image is for the following virtual machine
+ declare -rg PLUGIN_ID=$(get_xml "virtualmachine")
+ if isempty PLUGIN_ID; then
+ writelog "Error parsing XML: No value for 'virtualmachine'."
+ EXIT_TYPE="user" EXIT_REASON="Konnte kein Virtualisierer für das ausgewählte Image ermitteln." cleanexit 1
+ fi
+
+ # Extracting OS type (VM_OS_TYPE) from xml file. We don't care here whether VM_OS_TYPE is empty, as then
+ # it will yield the default entries later on.
+ declare -g VM_OS_TYPE=$(get_xml "os")
+
+ # Print summary to log
+ writelog "\tVirtualization plugin: $PLUGIN_ID"
+ writelog "\tVM filename: $IMG_BASENAME"
+ writelog "\tVM UUID: $IMGUUID"
+ writelog "\tVM name: $VM_DISPLAYNAME"
+ writelog "\tVM short name: $VM_CLEANNAME"
+ writelog "\tVM OS: $VM_OS_TYPE"
+ writelog "Done parsing XML."
+ return 0
}
-IMGUUID=$(get_xml "uuid")
-
-# # Name of the virt image
-SRC_IMG_ABSOLUTE=$(get_xml "image_path")
-SRC_IMG_RELATIVE=$(get_xml "image_name")
-
-if [ -z "${SRC_IMG_ABSOLUTE}${SRC_IMG_RELATIVE}" ]; then
- writelog "Neither relative nor absolute path for image found in xml"
- cleanexit 1
-fi
-
-if [ -n "$SRC_IMG_ABSOLUTE" ] && [ "${SRC_IMG_ABSOLUTE:0:1}" != "/" ]; then
- writelog "Error parsing XML for absolute image path: given value doesn't start with '/': '$SRC_IMG_ABSOLUTE'"
- cleanexit 1
-fi
-
-if [ -z "$SRC_IMG_ABSOLUTE" ]; then
- SRC_IMG_ABSOLUTE="${VMSTORE_PATH}/${SRC_IMG_RELATIVE}"
-fi
-
-IMG_BASENAME=$(basename "$SRC_IMG_ABSOLUTE")
-writelog "Virtual image file name: $IMG_BASENAME"
-
-VM_DISPLAYNAME=$(get_xml "short_description")
-[ -z "$VM_DISPLAYNAME" ] && VM_DISPLAYNAME="${IMG_BASENAME}"
-
-# Define VM_NAME_CLEAN since VM_DISPLAYNAME can be long and contain weird characters
-VM_NAME_CLEAN=$(echo "${VM_DISPLAYNAME:0:32}" | sed -r 's/[^0-9a-zA-Z_-\.]+/_/g')
-
-# image is for the following virtual machine
-PLUGIN_ID=$(grep -o 'virtualmachine param=.*"' "${xmlfile}" \
- | sed -e "s/&.*;/; /g" | awk -F '"' '{print $2}')
-
-# Extracting OS type (VM_OS_TYPE) from xml file. We don't care here whether VM_OS_TYPE is empty, as then
-# it will yield the default entries later on.
-VM_OS_TYPE=$(get_xml "os")
-
-readonly IMGUUID
-readonly SRC_IMG_ABSOLUTE SRC_IMG_RELATIVE
-readonly IMG_BASENAME
-readonly VM_DISPLAYNAME VM_NAME_CLEAN
-readonly PLUGIN_ID
-readonly VM_OS_TYPE
-
-writelog "VM UUID: $IMGUUID"
-writelog "Virtualization plugin: $PLUGIN_ID"
-writelog "VM name: $VM_DISPLAYNAME"
-writelog "VM short name: $VM_NAME_CLEAN"
-writelog "VM OS: $VM_OS_TYPE"
-writelog "Done parsing XML."
-
+## MAIN ##
+call_post_source parse_xml
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/init_core.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/init_core.inc
new file mode 100644
index 00000000..8e83811c
--- /dev/null
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/init_core.inc
@@ -0,0 +1,18 @@
+################################################
+# Include: Sets core variables and directories #
+################################################
+# Global variables needed for the core functionality
+declare -rg VMCHOOSER_DIR="/opt/openslx/vmchooser"
+declare -rg VMCHOOSER_CONF_DIR="$VMCHOOSER_DIR/config"
+declare -rg USER="$(whoami)"
+declare -rg LOGFILE="/var/log/openslx/run-virt.${USER}.$$.log"
+declare -rg TMPDIR="/tmp/virt/${USER}/$$"
+
+# Create temporary directory for current invocation
+if check_dep mkdir && ! mkdir -p "$TMPDIR"; then
+ writelog "Could not create temporary directory '$TMPDIR' for session"
+ EXIT_TYPE="internal" EXIT_REASON="Konnte kein Arbeitsverzeichnis für die VM-Sitzung anlegen." cleanexit 1
+fi
+
+# Get a unique VM_ID for the current invocation
+get_vm_id
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/load_configs.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/load_configs.inc
new file mode 100644
index 00000000..bd205816
--- /dev/null
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/load_configs.inc
@@ -0,0 +1,19 @@
+###################################################
+# Include: Declaration of run-virt core variables #
+###################################################
+## Functions ##
+load_configs() {
+ writelog "Loading configs..."
+
+ # Include general configuration from vmchooser
+ $(safesource --exit "$VMCHOOSER_CONF_DIR/vmchooser.conf")
+
+ # Load general virtualization information
+ $(safesource --exit "$VMCHOOSER_CONF_DIR/virtualization.conf")
+
+ # Load general openslx config
+ $(safesource --exit "/opt/openslx/config")
+}
+
+## MAIN ##
+call_post_source load_configs
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc
index 508c9efe..5fb14806 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc
@@ -1,113 +1,124 @@
###########################################
# Include: Set hardware related variables #
###########################################
+# New way of handling MAC address prefixes to support
+# nested and concurrent run-virt invocations.
+# Using a list of predefined MAC prefixes to use for VMs,
+# check if the host's MAC address prefix is in that list.
+# If not, use the first prefix in the list. If it is
+# use the next prefix in the list. If the host's prefix
+# is the last in the list, use the first one again.
+# This way we support up to 10 nested/concurrent VMs.
+# Use: 00:FF:00 for firtual machines ;)
+declare -gA MAC_PREFIXES
+for i in {0..9}; do
+ # make an associate array, it will make our life easier later
+ MAC_PREFIXES["00:FF:0$i"]="$i"
+done
-get_vm_id() {
- local script=${BASH_SOURCE[-1]}
- [ -z "$script" ] && script="$0"
- if [ -n "$script" ]; then
- script=$(readlink -f "$script")
- if [ -n "$script" ] && [ -s "$script" ]; then
- #bingo
- VM_ID=$(ps ax | grep -F "$script" | grep -v 'grep' | grep -o -- "${script}.*\$" | sort -u | wc -l)
- if [ "$VM_ID" -gt 0 ]; then
- [ "${#VM_ID}" -eq 1 ] && VM_ID="0${VM_ID}"
- [ "${#VM_ID}" -gt 2 ] && VM_ID="${VM_ID:0:2}"
- [ "${#VM_ID}" -eq 2 ] && return
- fi
- fi
- fi
- # fallback: take last two digits of current pid...
- VM_ID=$(expr substr $$ $(expr ${#$} - 1) 2)
- [ "${#VM_ID}" -eq 1 ] && VM_ID="0${VM_ID}"
-}
-
-get_vm_id
-
-# Make sure cpu_cores is not empty
-cpu_cores=${cpu_cores:-"1"}
-
-# Amount of memory for the VM. Be generous if diff is written to HDD
-if mount | grep -q '^/dev/sd.*on.*/tmp'; then
- reserve=20
- min=768
- max=1800
-else
- reserve=65
- min=768
- max=8192
-fi
-# Calculate absulute amount of RAM that should stay available to the host
-reserve="$(( ( totalmem * reserve ) / 100 ))"
-# Respect some upper and lower bounds for the host amount
-[ "$reserve" -lt "$min" ] && reserve="$min"
-[ "$reserve" -gt "$max" ] && reserve="$max"
+## Functions ##
+# Sets the VM's hostname to the original hostname prefixed with a fixed string and its ID
+set_virt_hostname() {
+ declare -rg HOSTNAME="virt${VM_ID}-$(hostname)"
+ writelog "\tVM Hostname:\t\t$HOSTNAME"
+}
+set_virt_cpu() {
+ # Make sure CPU_CORES is not empty
+ declare -g CPU_CORES=${CPU_CORES:-"1"}
+}
+# Derives the amount of memory allocated to the VM from the
+# host's total memory (previously determined by systemd-run_virt_env)
+set_virt_memory() {
+ # Make sure we have a VM_ID and HOST_MEM_TOTAL (read from virtualization.conf)
+ if isempty HOST_MEM_TOTAL; then
+ writelog "HOST_MEM_TOTAL is empty! Was '$VMCHOOSER_CONF_DIR/virtualization.conf' sourced?"
+ EXIT_TYPE="internal" EXIT_REASON="Konnte die Größe des Arbeitsspeichers nicht ermitteln!" cleanexit 1
+ fi
-# Get a result which can be divided by 4
-mem="$(( ( ( totalmem - reserve ) / 4 ) * 4 ))"
-if [ -n "$mainvirtmem" ]; then
- forcemem="$(( mainvirtmem / 4 * 4 ))"
- mem="$forcemem"
-fi
-hostmem="$(( totalmem - mem ))"
+ # Amount of memory for the VM. Be generous if diff is written to HDD
+ local min=768
+ local reserve max
+ if mount | grep -q '^/dev/sd.*on.*/tmp'; then
+ reserve=20
+ max=1800
+ else
+ reserve=65
+ max=8192
+ fi
-# Fill in VMID
-macaddrsuffix=$(echo "$macaddrsuffix" | sed "s/%VMID%/${VM_ID}/")
+ # Calculate absulute amount of RAM that should stay available to the host
+ local reserve="$(( ( HOST_MEM_TOTAL * reserve ) / 100 ))"
+ # Respect some upper and lower bounds for the host amount
+ [ "$reserve" -lt "$min" ] && reserve="$min"
+ [ "$reserve" -gt "$max" ] && reserve="$max"
+
+ # Get a result which can be divided by 4
+ declare -g VM_MEM="$(( ( ( HOST_MEM_TOTAL - reserve ) / 4 ) * 4 ))"
+ declare -g HOST_MEM_REMAINING="$(( HOST_MEM_TOTAL - VM_MEM ))"
+ # NOTE: removed old code that evaluated 'mainvirtmem'
+ # as it did nothing and we don't know what the idea was...
+}
-if ! echo "$macaddrprefix" | grep -q -E '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$'; then
- slxlog "virt-mac" "Could not properly generate mac address prefix (got $macaddrprefix)"
-fi
-if ! echo "$macaddrsuffix" | grep -q -E '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$'; then
- slxlog "virt-mac" "Could not properly generate mac address suffix (got $macaddrsuffix)"
-fi
-macaddr="$macaddrprefix:$macaddrsuffix"
+# New way to generate MAC addresses:
+# MAC_PREFIXES is a statically declared list of prefixes which
+# can be used for VMs. To support nested VMs, we just look for
+# the MAC prefix of the host and if it is present in the list,
+# we just take the next one in the list. Currently support up to 10.
+# If none are found, we just take the first prefix.
+# Suffix template is taken from /opt/openslx/vmchooser/config/virtualization.conf
+# and will have the VMID inserted as first byte.
+set_virt_mac() {
+ # First, determine prefix of the host's MAC address
+ isset HOSTMACADDR || writelog "Host's MAC address was not defined in ${VMCHOOSER_CONF_DIR}/virtualizer.conf"
+ local HOST_MAC_PREFIX=$(echo "$HOSTMACADDR" | tr '[a-z]' '[A-Z]' | grep -o -E '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}')
+ unset MACADDRPREFIX
+ if notempty HOST_MAC_PREFIX && notempty MAC_PREFIXES[${HOST_MAC_PREFIX}]; then
+ # the host's prefix was in our list, so use the next one in the list
+ local -i HOST_MAC_PREFIX_INDEX="${MAC_PREFIXES[${HOST_MAC_PREFIX}]}" # this will be at least 0
+ # increment if its between 0 and 8
+ if [[ $HOST_MAC_PREFIX_INDEX =~ ^[0-8]$ ]]; then
+ declare -g MACADDRPREFIX="${HOST_MAC_PREFIX%?}$(( ++HOST_MAC_PREFIX_INDEX ))"
+ fi
+ fi
+ # host's mac prefix could not be determined (practically this should never happen)
+ # or the prefix is not in our mac address list or we reached the end of the list.
+ # Either way, use first mac prefix in the list
+ notempty MACADDRPREFIX || declare -g MACADDRPREFIX="$(echo ${!MAC_PREFIXES[@]} | awk '{print $1}')"
+
+ # Fill in VM_ID
+ local MACADDRSUFFIX=${MACADDRSUFFIX//%VMID%/"${VM_ID}"}
+
+ if ! echo "$MACADDRPREFIX" | grep -q -E '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$'; then
+ slxlog "virt-mac" "Could not properly generate mac address prefix (got $MACADDRPREFIX)"
+ fi
+ if ! echo "$MACADDRSUFFIX" | grep -q -E '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$'; then
+ slxlog "virt-mac" "Could not properly generate mac address suffix (got $MACADDRSUFFIX)"
+ fi
+ declare -g VM_MAC_ADDR="$MACADDRPREFIX:$MACADDRSUFFIX"
+}
# Virtual fd/cd/dvd and drive devices, floppy b: for configuration
-# if $floppy_0 from virtualization.conf set then fdtest="TRUE"
-fdtest=${floppy_0:+"TRUE"}
-# if $fdtest not set floppy0="FALSE", else "TRUE"
-floppy0=${fdtest:-"FALSE"}
-# if $cdrom_0 from virtualization.conf set then cdtest="TRUE"
-cdtest=${cdrom_0:+"TRUE"}
-# if $cdtest not set cdrom0="FALSE", else "TRUE"
-cdrom0=${cdtest:-"FALSE"}
-# if $cdrom_1 from virtualization.conf set then cdtest="TRUE"
-cdtest=${cdrom_1:+"TRUE"}
-# if $cdtest not set cdrom1="FALSE", else "TRUE"
-cdrom1=${cdtest:-"FALSE"}
-
-# Dynamically detect serial ports here instead of at boot time
-# (virtualization.conf), since USB serial ports get quite common
-# and might not be plugged in at boot time yet
-serial_0=
-#for port in $(awk '{ if ($1 ~ /^[0-9]+:/ && $2 != "uart:unknown") print "/dev/ttyS" sub(/:\$/, "", $1) }' /proc/tty/driver/serial); do
-for port in $serial_ports /dev/ttyUSB*; do
- [ -c "$port" ] || continue
- serial_0="$port"
- break
-done
-
-parallel_0=
-for port in /dev/parport*; do
- [ -c "$port" ] || continue
- parallel_0="$port"
- break
-done
-
-# RDP/VNC port (59001 - 59099)
-remotedesktopport="590${VM_ID}"
-
-# Add rw share for home dir
-homesharepath="${HOME}/PERSISTENT"
-homesharename="home"
-
-# Add common share
-commonsharepath="${HOME}/SHARE"
-commonsharename="share"
-
-# Set hostname: using original hostname and adding string
-hostname="virt-$(hostname)"
+# NOTE: This uses bash's variable expansion magic to set
+# CDROM/FLOPPY variables evaluated later by the virtualizers...
+# If the variables in virtualization.conf is set, "TRUE" is assigned,
+# "FALSE" otherwise.
+check_optical_drives() {
+ local TESTVAR=${FLOPPY_0:+"TRUE"}
+ declare -rg FLOPPY0=${TESTVAR:-"FALSE"}
+
+ TESTVAR=${CDROM_0:+"TRUE"}
+ declare -rg CDROM0=${TESTVAR:-"FALSE"}
+
+ TESTVAR=${CDROM_1:+"TRUE"}
+ declare -rg CDROM1=${TESTVAR:-"FALSE"}
+}
-writelog "\tVM Hostname:\t\t$hostname"
+## MAIN ##
+call_post_source \
+ set_virt_cpu \
+ set_virt_memory \
+ set_virt_mac \
+ set_virt_hostname \
+ check_optical_drives
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc
deleted file mode 100644
index cd9a573a..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc
+++ /dev/null
@@ -1,26 +0,0 @@
-######################################################
-# Include: Declaration of run-virt default variables #
-######################################################
-
-VMCHOOSER_DIR="/opt/openslx/vmchooser"
-VMCHOOSER_CONF_DIR="$VMCHOOSER_DIR/config"
-USER="$(whoami)"
-LOGFILE="/var/log/openslx/run-virt.${USER}.$$.log"
-TMPDIR="/tmp/virt/${USER}/$$"
-
-readonly VMCHOOSER_DIR VMCHOOSER_CONF_DIR LOGFILE TMPDIR USER
-
-# include general configuration from vmchooser
-[ -f "$VMCHOOSER_CONF_DIR/vmchooser.conf" ] && . "$VMCHOOSER_CONF_DIR/vmchooser.conf"
-# load general virtualization information
-[ -f "$VMCHOOSER_CONF_DIR/virtualization.conf" ] && . "$VMCHOOSER_CONF_DIR/virtualization.conf"
-# Load general openslx config
-[ -f "/opt/openslx/config" ] && . "/opt/openslx/config"
-# Create temp dir
-if ! mkdir -p "$TMPDIR"; then
- slxlog "virt-tmpdir" "Could not create temporary directory '$TMPDIR' for session"
- error_user "Konnte kein temporäres Arbeitsverzeichnis für die VM-Sitzung anlegen. Ein Computer-Neustart könnte das Problem lösen."
- cleanexit 1
- exit 1
-fi
-
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc
deleted file mode 100644
index f0820ed7..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc
+++ /dev/null
@@ -1,12 +0,0 @@
-
-setup_firewall () {
- local LOGF="${TMPDIR}/firewall.log"
- local RET
- [ "$DISPLAY" = ":0" ] || return 0 # For now, to avoid conflicts, we only do this on display :0
- slxfwtool "$IMGUUID" > "$LOGF" 2>&1
- RET=$?
- if [ "$RET" != "0" ]; then
- slxlog "runvirt-firewall" "Error setting up firewall rules for lecture $IMGUUID (Exit code $RET)" "$LOGF"
- fi
- return 0
-}
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc
index 4240d9ca..a41c1055 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc
@@ -1,7 +1,6 @@
###########################################################
# Include: Setup dnbd for image access, nfs/cifs fallback #
###########################################################
-
# This will currently make sure that the variable
# VM_DISKFILE_RO is set which will contain the
# absolute path to the disk image to use for the vm
@@ -14,85 +13,112 @@
# indicate to the virt plugin that it doesn't need to
# handle creating a temporary CoW layer itself.
-writelog "Setting up disk access for virtualizer/emulator ..."
-# Try to use dnbd3 to access the image
-unset VM_DISKFILE_RO
-unset dnbd3_fuse_mount_point
+# Helper to cleanup the image mounted with dnbd3-fuse
+cleanup_dnbd3() {
+ if ! isset DNBD3_MOUNT_POINT; then
+ writelog "'DNBD3_MOUNT_POINT' is not set! Aborting DNBD3 cleanup."
+ return 1
+ fi
+ # try to umount it now
+ for timeout in 1 1 1 FAIL; do
+ fusermount -u "${DNBD3_MOUNT_POINT}" && break
+ writelog "dnbd3 still busy...."
+ [ "$timeout" = "FAIL" ] && break
+ sleep "$timeout"
+ done
+}
setup_dnbd3 () {
# Mount path for images mounted with dnbd3-fuse
- dnbd3_fuse_mount_point="$TMPDIR/dnbd3fuse.mnt"
- mkdir -p "${dnbd3_fuse_mount_point}"
+ declare -rg DNBD3_MOUNT_POINT="${TMPDIR}/dnbd3fuse.mnt"
+ mkdir -p "${DNBD3_MOUNT_POINT}"
# start dnbd3-fuse in subshell
- local dnbd3_tmplog="$TMPDIR/dnbd3fuse.log"
- local dnbd3_exitflag="$TMPDIR/dnbd3exit$RANDOM"
- local TIMEOUT vm_revision
- rm -f -- "$dnbd3_exitflag"
+ local DNBD3_TMPLOG="${TMPDIR}/dnbd3fuse.log"
+ local DNBD3_EXITFLAG="${TMPDIR}/dnbd3exit$RANDOM"
+ local TIMEOUT VM_DISKFILE_REVISION
+ rm -f -- "${DNBD3_EXITFLAG}"
(
- dnbd3-fuse -f -o allow_other,max_readahead=262144 -h "$SLX_DNBD3_SERVERS" -i "${SRC_IMG_RELATIVE}" "${dnbd3_fuse_mount_point}" > "$dnbd3_tmplog" 2>&1
+ dnbd3-fuse -f -o allow_other,max_readahead=262144 -h "${SLX_DNBD3_SERVERS}" -i "${SRC_IMG_RELATIVE}" "${DNBD3_MOUNT_POINT}" > "${DNBD3_TMPLOG}" 2>&1
RET=$?
- touch "$dnbd3_exitflag"
+ touch "${DNBD3_EXITFLAG}"
if [ "$RET" != "0" ]; then
writelog "dnbd3-fuse stopped working (Exit code $RET)"
- slxlog "virt-dnbd3-fuse" "dnbd3-fuse stopped/refused serving '${SRC_IMG_RELATIVE}' from '${SLX_DNBD3_SERVERS}' with error code: $RET" "${dnbd3_tmplog}"
+ slxlog "virt-dnbd3-fuse" "dnbd3-fuse stopped/refused serving '${SRC_IMG_RELATIVE}' from '${SLX_DNBD3_SERVERS}' with error code: $RET" "${DNBD3_TMPLOG}"
fi
) &
# give it a bit of time
usleep 250000
# check if we have the image
for TIMEOUT in 0.5 1 1 OUT; do
- if [ -r "${dnbd3_fuse_mount_point}/img" ]; then
- vm_revision="$(grep -m 1 "^Revision:" "${dnbd3_fuse_mount_point}/status" | cut -d" " -f2)"
- VM_DISKFILE_RO="${dnbd3_fuse_mount_point}/img"
- writelog "DNBD3: $SRC_IMG_RELATIVE on $VM_DISKFILE_RO with rid $vm_revision"
+ if [ -r "${DNBD3_MOUNT_POINT}/img" ]; then
+ VM_DISKFILE_REVISION="$(grep -m 1 "^Revision:" "${DNBD3_MOUNT_POINT}/status" | cut -d" " -f2)"
+ VM_DISKFILE_RO="${DNBD3_MOUNT_POINT}/img"
+ writelog "DNBD3: ${SRC_IMG_RELATIVE} on ${VM_DISKFILE_RO} with rid ${VM_DISKFILE_REVISION}"
+ add_cleanup "cleanup_dnbd3"
break
fi
- [ "$TIMEOUT" = "OUT" -o -e "$dnbd3_exitflag" ] && break
+ [ "$TIMEOUT" = "OUT" -o -e "$DNBD3_EXITFLAG" ] && break
sleep "$TIMEOUT"
done
- if [ -z "$VM_DISKFILE_RO" ]; then
- slxlog "virt-dnbd3" "No dnbd3 server for ${SRC_IMG_RELATIVE} found, trying NFS/CIFS..." "$dnbd3_tmplog"
+ if isempty VM_DISKFILE_RO; then
+ slxlog "virt-dnbd3" "No dnbd3 server for ${SRC_IMG_RELATIVE} found, trying NFS/CIFS..." "$DNBD3_TMPLOG"
writelog "No working dnbd3 server found :-("
+ else
+ readonly VM_DISKFILE_RO
fi
}
-# See if we should setup dnbd3 image access at all
-if ! which dnbd3-fuse; then
- writelog "Can't use dnbd3 as dnbd3-fuse binary is not in PATH"
-elif [ -z "$SRC_IMG_RELATIVE" ]; then
- writelog "Can't use dnbd3 as SRC_IMG_RELATIVE is not set"
-elif [ -z "$SLX_DNBD3_SERVERS" ] || [ "x$SLX_VM_DNBD3" != "xyes" ]; then
- writelog "Can't use dnbd3 as no servers are given in config, or SLX_VM_DNBD3 is not set to yes"
-else
- setup_dnbd3
-fi
-
-# VM_DISKFILE_RO will be empty if dnbd3 is not used or failed to connect.
-# Let's try to fall back to NFS/CIFS via file system
-if [ -z "$VM_DISKFILE_RO" ]; then
+setup_fallback() {
# Maybe we're reading a dnbd3 directory with RIDs encoded into the filename - use latest one
- rid_suffix=$(ls -1 "${SRC_IMG_ABSOLUTE}.r"* | grep -E -o '\.r[0-9]+$' | grep -o -E '[0-9]+$' | sort -n | tail -n 1)
- if [ -n "$rid_suffix" ]; then
+ unset VM_DISKFILE_REVISION
+ local VM_DISKFILE_REVISION=$(ls -1 "${SRC_IMG_ABSOLUTE}.r"* | grep -E -o '\.r[0-9]+$' | grep -o -E '[0-9]+$' | sort -n | tail -n 1)
+ if notempty VM_DISKFILE_REVISION; then
# found
- VM_DISKFILE_RO="${SRC_IMG_ABSOLUTE}.r${rid_suffix}"
- elif [ -e "$SRC_IMG_ABSOLUTE" ]; then
+ VM_DISKFILE_RO="${SRC_IMG_ABSOLUTE}.r${VM_DISKFILE_REVISION}"
+ elif [ -e "${SRC_IMG_ABSOLUTE}" ]; then
# try name we got from xml in the first place
- VM_DISKFILE_RO="$SRC_IMG_ABSOLUTE"
+ VM_DISKFILE_RO="${SRC_IMG_ABSOLUTE}"
fi
-fi
-
-# Check if virtual machine container file exists
-if [ -z "$VM_DISKFILE_RO" ] || ! [ -e "${VM_DISKFILE_RO}" ]; then
- slxlog "virt-image-missing" "VM image $VM_DISKFILE_RO not found!"
- writelog "Virtual machine image ${VM_DISKFILE_RO} not found!"
- error_user "Das Image für die gewählte Virtuelle Maschine konnte nicht gefunden werden.
-Versuchen Sie zunächst, den Computer komplett neu zu starten. Sollte das Problem bestehen bleiben, wenden Sie sich bitte an den Support."
- cleanexit 1
-fi
+ readonly VM_DISKFILE_RO
+}
-readonly VM_DISKFILE_RO
-writelog "Disk file to use: $VM_DISKFILE_RO"
+## MAIN PART / Sanity checks ##
+setup_image_access() {
+ writelog "Setting up virtual hard disk access for virtualizer/emulator ..."
+
+ unset VM_DISKFILE_RO
+ declare -g VM_DISKFILE_RO
+
+ # See if we should setup dnbd3 image access at all
+ if ! check_dep dnbd3-fuse fusermount; then
+ writelog "\tCan't use dnbd3 as dnbd3-fuse/fusermount binaries are not in PATH"
+ elif ! isset SRC_IMG_RELATIVE; then
+ writelog "\tCan't use dnbd3 as SRC_IMG_RELATIVE is not set"
+ elif ! isset SLX_DNBD3_SERVERS || [ "x${SLX_VM_DNBD3}}" != "xyes" ]; then
+ writelog "\tCan't use dnbd3 as no servers are given in config, or SLX_VM_DNBD3 is not set to yes"
+ else
+ # register setup_dnbd3 as start hook after sourcing this include
+ writelog "Trying image access via DNBD3..."
+ setup_dnbd3
+ fi
+
+ # VM_DISKFILE_RO will be empty if dnbd3 is not used or failed to connect.
+ if isempty VM_DISKFILE_RO; then
+ # try to fallback to access the image via NFS/CIFS filesystem
+ writelog "Trying fallback image access via NFS/CIFS..."
+ setup_fallback
+ fi
+
+ # Check if we finally found a valid, readable container
+ if isempty VM_DISKFILE_RO || [ ! -r "${VM_DISKFILE_RO}" ]; then
+ writelog "Virtual machine image ${VM_DISKFILE_RO} not found!"
+ EXIT_TYPE="user" EXIT_REASON="Konnte virtuelle Festplatte des gewählten Image nicht finden!" cleanexit 1
+ fi
+
+ writelog "\tVM disk file:\t\t${VM_DISKFILE_RO}"
+}
+call_post_source setup_image_access
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc
deleted file mode 100644
index 2fb9310a..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc
+++ /dev/null
@@ -1,46 +0,0 @@
-#####################################
-# Include: Setup printer daemon LPD #
-#####################################
-
-QUEUE="STANDARD" # This has to match the queue you configured in your VM
-SPOOLDIR=
-
-### Disabled: 100megs is not enough, some jobs are HUGE, try to use temp which should be on disk
-## Try using user's tmpfs home first, as it gets wiped on logout
-#if [ -n "${HOME}" ] && [ -w "${HOME}" ]; then
-# SPOOLDIR="${HOME}/.spool"
-# mkdir -p "${SPOOLDIR}/${QUEUE}"
-#fi
-# If failed, try to fall back to /tmp
-
-if [ -z "${SPOOLDIR}" ] || [ ! -w "${SPOOLDIR}/${QUEUE}" ]; then
- SPOOLDIR="${TMPDIR}/printergui-${RANDOM}"
- rm -rf -- "${SPOOLDIR}"
- if ! mkdir -p "${SPOOLDIR}/${QUEUE}"; then
- slxlog "virt-spooldir" "Could not create spool directory ($SPOOLDIR) for $USER - printing will not work!"
- # TODO: Warn user
- fi
- chmod 0700 "${SPOOLDIR}/${QUEUE}"
-fi
-
-# Start the lpdaemon listening on the given port
-# TODO: externalize with something like runvirt.d (other parts might benefit from that too)
-tcpsvd -E 192.168.101.1 5515 \
- lpd "$SPOOLDIR" \
- ash -c "/opt/openslx/scripts/run-virt_print '${USER}' \"${SPOOLDIR}/${QUEUE}/\$DATAFILE\"" &
-
-# PID to kill the process
-PID_LPD="$!"
-
-{
- sleep 2
- # Check if tcpsvd is running. Do this a little delayed so we do not check
- # immediately after trying to spawn it, as this could result in
- # success even if it's not really working.
-
- if ! kill -0 "$PID_LPD"; then
- slxlog "virt-lpd" "Could not start tcpsvd/lpd for virtual machine session"
- notify_user "Durcksystem" "Das Drucksystem konnte nicht initialisiert werden. Druckfunktion nicht verfügbar."
- fi
-} &
-
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc
deleted file mode 100644
index c6cece3d..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-# ^-- Add shebang even though it's sourced so vim highlights bash specific features properly
-########################
-# Include: Setup sound #
-########################
-
-writelog "Starting sound setup ..."
-
-unset VOL
-if [ -r "/run/hwinfo" ] && source "/run/hwinfo"; then
- # On startup, the volume of Master, PCM, Speaker, etc. will be set to 100%
- # Some hardware with builtin speakers might be a bit too loud then, so you can
- # define an exception table here. Array key is "Manufacturer//Model"
- declare -A VOLUME_EXCEPTIONS
- VOLUME_EXCEPTIONS["Hewlett-Packard//HP Compaq 8200 Elite CMT PC"]="85%" # This is bwPC3
- # Read
- VOL=${VOLUME_EXCEPTIONS["${HW_MANUF}//${HW_MODEL}"]}
-fi
-
-# Default to maximum volume
-if [ -z "$VOL" ]; then
- VOL="100%"
-fi
-
-if true; then
- # detecting which card is to be used
- writelog --quiet "Detecting which sound card to use ..."
- PROC="/proc/asound/cards"
- if [ ! -r "$PROC" ]; then
- writelog --quiet "'${PROC}' not found or not readable."
- SOUND_CARD_INDEX=0
- SOUND_CARD_COUNT=1
- else
- # Try to filter HDMI cards first
- SOUND_CARD_INDEX=$(grep -v -i 'HDMI' "${PROC}" | grep -E -o '^[[:space:]]{0,2}[0-9]+[[:space:]]+' | head -n 1)
- # If empty, try again with all
- [ -z "${SOUND_CARD_INDEX}" ] && SOUND_CARD_INDEX=$(cat "${PROC}" | grep -E -o '^[[:space:]]{0,2}[0-9]+[[:space:]]+' | head -n 1)
- if [ -z "${SOUND_CARD_INDEX}" ]; then
- writelog --quiet "No sound card found."
- SOUND_CARD_INDEX=0
- fi
- SOUND_CARD_COUNT=$(grep -E '^[[:space:]]{0,2}[0-9]+[[:space:]]+' "${PROC}" | wc -l)
- fi
-
- SOUND_CARD_INDEX="$(grep -E -o '[0-9]+' <<<$SOUND_CARD_INDEX)"
- writelog --quiet "Detected sound card index is: $SOUND_CARD_INDEX"
- writelog --quiet "Sound card count: $SOUND_CARD_COUNT"
-
- # Adjust sound volume (playback)... Random mixer names we have encountered during testing
- writelog --quiet "Setting up volume..."
- (
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Master' "$VOL" unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'PCM' "100%" unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'CD' "100%" unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Headphone' "100%" unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Front' "100%" unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Speaker' "100%" unmute
- # Recording. It seems that (most) devices need the volume set to 0, so you
- # don't hear your own mic input, but should be unmuted. Also on some cards,
- # you need to set the cap option on the mic you want to use, while other cards
- # will just ignore that option.
- # Plus, most cards have a Capture mixer, which needs to be set to cap too, and
- # have its volume turned up. (There'll probably be some cards that need yet
- # another setup, but this works for now on 4 tested cards)
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Rear Mic Boost' "50%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Rear Mic' "0%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Front Mic Boost' "50%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Front Mic' "0%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Mic Boost' "50%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Mic' "0%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Capture' "100%" cap unmute
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Input Source' 'Mic'
- amixer -q -c "$SOUND_CARD_INDEX" sset 'Input Source' 'Front Mic' # Let's hope nobody uses rear mic...
- # fix random static noise when starting vmplayer when module snd_pcsp (not pcspkr) is loaded
- amixer -q -c pcsp sset Master "0%" mute 2>/dev/null >&2
- ) 2>&1 | grep -v 'amixer: Unable to find'
- writelog --quiet "Done setting up volume."
-fi >> "${LOGFILE}" 2>&1 # Don't pipe here since it would spawn a subshell so all variable modifications would be lost
-
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc
deleted file mode 100644
index d9ae052c..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/bin/bash
-##############################################
-# Include: Setup virtual floppy for drive b: #
-##############################################
-
-declare -rg FLOPPYIMG="${TMPDIR}/floppy.img"
-declare -rg TMPHOME="${HOME}"
-declare -rg RUNSCRIPT="${TMPDIR}/runscript.tmp"
-
-wget -T 6 -O "${RUNSCRIPT}" "${SLX_VMCHOOSER_BASE_URL}/lecture/${IMGUUID}/runscript" > /dev/null &
-WGET=$!
-
-dd "if=/dev/zero" "of=${FLOPPYIMG}" count=1440 bs=1024
-chmod 0600 "${FLOPPYIMG}"
-mkfs.fat "${FLOPPYIMG}" || mkfs.vfat "${FLOPPYIMG}" || mkdosfs "${FLOPPYIMG}"
-
-# Create file with resolution information etc.
-. "/opt/openslx/inc/shares"
-if [ -z "$SHARE_REMAP_MODE" ]; then
- SHARE_REMAP_MODE_INI="0"
- SHARE_REMAP_MODE="3"
-else
- SHARE_REMAP_MODE_INI="$SHARE_REMAP_MODE"
-fi
-[ -z "$SHARE_CREATE_MISSING_REMAP" ] && SHARE_CREATE_MISSING_REMAP="1"
-declare -rg RESOLUTION=$(xrandr | grep -o -E 'connected\s*(primary)?\s*[0-9]+x[0-9]+\+0\+0' \
- | grep -o -E -m1 '[0-9]+x[0-9]+')
-
-# Legacy: HOSTRES.TXT
-cat > "${TMPDIR}/HOSTRES.TXT" <<-HIER
-${RESOLUTION}
-HIER
-
-# Create file for network shares to mount
-declare -rg SHARES="${TMPDIR}/shares.dat"
-touch "${SHARES}"
-chmod 0600 "${SHARES}"
-if ! pwdaemon --query "${TMPHOME}/.pwsocket" > "${SHARES}"; then
- slxlog "virt-pwdaemon" "Could not start pwdaemon"
-else
- sed -i 's/^/192.168.101.1\t/' "${SHARES}" # TODO: Depending on nettype (in case we have != nat some day)
- if [ "${SHARE_REMAP_MODE}" = 1 -o "${SHARE_REMAP_MODE}" = 2 ] && [ -e "${TMPHOME}/.home" ]; then
- NETHOME=$(cat "${TMPHOME}/.home")
- [ -z "$SHARE_HOME_DRIVE" ] && SHARE_HOME_DRIVE="H:"
- # Tab between items, so spaces can be used!
- echo "${NETHOME} ${SHARE_HOME_DRIVE} Home-Verzeichnis" >> "${SHARES}"
- fi
- for VAR in ${!SHARE_LINE_*}; do
- echo "${!VAR}" >> "${SHARES}"
- done
-fi
-
-wait "$WGET"
-
-# Check downloaded runscript, handle extension marker
-EXT=
-if [ -s "$RUNSCRIPT" ]; then
- EXT=$(head -n 1 "$RUNSCRIPT" | grep -o -i '^EXT=.*$' | cut -d '=' -f 2-)
- [ -n "$EXT" ] && [ "x${EXT:0:1}" != "x." ] && EXT=".$EXT"
-fi
-
-# Write info file
-UNAME=
-[ -s "${HOME}/.account" ] && UNAME=$(cat "${HOME}/.account")
-[ -z "${UNAME}" ] && UNAME=$(whoami)
-cat > "${TMPDIR}/openslx.ini" <<-HIER
-[openslx]
-username=${UNAME}
-resolution=${RESOLUTION}
-createMissingRemap=${SHARE_CREATE_MISSING_REMAP}
-remapMode=${SHARE_REMAP_MODE_INI}
-homeDrive=${SHARE_HOME_DRIVE}
-scriptExt=${EXT}
-
-[remap]
-documents=${SHARE_DOCUMENTS}
-downloads=${SHARE_DOWNLOADS}
-desktop=${SHARE_DESKTOP}
-media=${SHARE_MEDIA}
-other=${SHARE_OTHER}
-HIER
-
-# Copy all them there filez into floppy image
-mcopy -i "${FLOPPYIMG}" "${TMPDIR}/openslx.ini" "${TMPDIR}/HOSTRES.TXT" "${SHARES}" "::/"
-mcopy -i "${FLOPPYIMG}" "$VMCHOOSER_DIR/data/openslx.exe" "::/"
-# Copy guest configuration (with added information) config.xml to be accessed
-# via virtual floppy
-mcopy -i "${FLOPPYIMG}" "$xmlfile" "::/config.xml"
-
-# Copying linux directory:
-mcopy -s -i "${FLOPPYIMG}" "$VMCHOOSER_DIR/data/linux" "::/"
-
-# User supplied runscript
-if [ -n "$EXT" ]; then
- sed -i '1d' "${RUNSCRIPT}"
- mcopy -i "${FLOPPYIMG}" "${RUNSCRIPT}" "::/runscript${EXT}"
-fi
-
-rm -f -- "${SHARES}" "${TMPDIR}/openslx.ini" "${TMPDIR}/HOSTRES.TXT"
-unset SHARES VAR NETHOME UNAME
-
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc
index 7709a85d..80b7dbb9 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc
@@ -1,34 +1,18 @@
##########################################################################
# Include: Setup virtual machine hypervisor via vm-specific include file #
##########################################################################
-
-# Get all virtual machine specific stuff from the respective include file
-if [ ! -e "$VMCHOOSER_DIR/$PLUGIN_ID/run-virt.include" ] ; then
- slxlog "virt-plugin-missing" "Could not find run-virt.include for $PLUGIN_ID ($VMCHOOSER_DIR/$PLUGIN_ID/run-virt.include)"
- writelog "Failed because of missing ${PLUGIN_ID} plugin."
- error_user "Konnte den Virtualisierer '$PLUGIN_ID' nicht finden. Starten der Virtuellen Maschine fehlgeschlagen.
- Starten Sie den Computer neu und wenden Sie sich an den Support, wenn das Problem weiterhin besteht."
- cleanexit 1
-fi
-
-self="${PLUGIN_ID}"
-
-if ! bash -n "$VMCHOOSER_DIR/$PLUGIN_ID/run-virt.include"; then
- slxlog "virt-plugin-syntax" "run-virt.include for $PLUGIN_ID contains syntax errors (bash -n run-virt.include failed)"
- writelog "Erroneous run-virt.include for $PLUGIN_ID (syntax check)"
- error_user "Das Start-Script für den Virtualisierer '$PLUGIN_ID' ist fehlerhaft.
- Starten Sie den Computer neu und wenden Sie sich an den Support, wenn das Problem weiterhin besteht."
- cleanexit 1
-fi
-
-setup_vm_commandline () {
- # Now including the hypervisor specific include file:
- if ! source "$VMCHOOSER_DIR/$PLUGIN_ID/run-virt.include"; then
- slxlog "virt-plugin-error" "run-virt.include for $PLUGIN_ID could not be sourced properly."
- writelog "Erroneous run-virt.include for ${PLUGIN_ID}? Source returned != 0"
- error_user "Das Start-Script für den Virtualisierer '$PLUGIN_ID' hat einen fehlercode zurückgegeben.
- Starten Sie den Computer neu, falls es beim Ausführen der VM zu Problemen kommt
- und wenden Sie sich an den Support, wenn das Problem weiterhin besteht."
+## Functions ##
+setup_vm_commandline() {
+ # Sanity checks
+ if ! isset PLUGIN_ID; then
+ writelog "Sanity check failed: PLUGIN_ID is not set."
+ EXIT_TYPE="internal" EXIT_REASON="Konnte kein Virtualisierer für das gewählte Image ermitteln!" cleanexit 1
+ fi
+ if ! $(safesource "$VMCHOOSER_DIR/plugins/$PLUGIN_ID/run-virt.include"); then
+ # safesource logs errors on its own
+ EXIT_TYPE="internal" EXIT_REASON="Konnte Virtualisierungsplugin '$PLUGIN_ID' nicht initialisieren!" cleanexit 1
fi
}
+## Main ##
+call_post_source setup_vm_commandline
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc
index da43f341..37d88ab4 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc
@@ -1,27 +1,42 @@
####################################################
# Include: Start windowmanager for easier handling #
####################################################
-
+## Functions ##
# Some problems may arise with windows opening in background when
# using eg. vmware without a window manager.
-
-FOUND_WM=
-for dm in openbox kwin xfwm4 metacity blackbox twm fvwm2 ; do
- if which $dm >/dev/null 2>&1 ; then
- if [ "$dm" = "fvwm2" ] ; then
- echo "EdgeScroll 0 0" > ${redodir}/fvwm
- writelog "Starting fvwm2."
- fvwm2 -f ${redodir}/fvwm >/dev/null 2>&1 &
- else
- writelog "Starting ${dm}."
- $dm >/dev/null 2>&1 &
+start_wm() {
+ # Sanity checks
+ unset RUNVIRT_DM
+ for DM in openbox kwin xfwm4 metacity blackbox twm fvwm2 ; do
+ if type "${DM}" >/dev/null 2>&1 ; then
+ declare -rg RUNVIRT_DM="${DM}"
+ break
fi
- FOUND_WM=1
- break
+ done
+ if ! isset RUNVIRT_DM; then
+ # not fatal, so do not exit but report via slxlog
+ slxlog "runvirt-wm" "Could not find any window manager to use!"
+ notify_user "Konnte keinen Window Manager finden. (Das ist schlecht!)"
+ return 1
+ fi
+
+ # start RUNVIRT_DM determined above
+ writelog "Starting ${RUNVIRT_DM}."
+ if [ "${RUNVIRT_DM}" = "fvwm2" ]; then
+ # fvwm2 is not even in the minilinux, so this might be obsolete...
+ echo "EdgeScroll 0 0" > ${TMPDIR}/fvwm
+ fvwm2 -f ${TMPDIR}/fvwm >/dev/null 2>&1 &
+ else
+ ${RUNVIRT_DM} >/dev/null 2>&1 &
+ fi
+ local RUNVIRT_DM_PID="$$"
+ if ! kill -0 ${RUNVIRT_DM_PID} ; then
+ # not fatal, just warn user
+ notify_user "$RUNVIRT_VM stoppte unerwartet."
+ return 1
fi
-done
+ return 0
+}
-if [ -z "$FOUND_WM" ]; then
- slxlog "virt-windowmanager" "Could not find any window manager to use!"
- notify_user "Konnte keinen Window Manager finden. (Das ist schlecht!)"
-fi
+## MAIN ##
+call_post_source start_wm
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc
deleted file mode 100644
index a2d442e4..00000000
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc
+++ /dev/null
@@ -1,77 +0,0 @@
-# Helper function that will scan /dev/bus/usb for devices matching specific classes
-# and then output the corresponding device ids. This can be used for selective
-# handover of devices to a virtual machine
-
-declare -rg PASSTHROUGH_USB_DEVICES="2 0:5 0:6 0:7 0:14 0:16 0:17 239"
-
-# $1: expression to fill with device information.
-# valid placeholders are:
-# %VENDOR% - device vendor id
-# %PRODUCT% - device product id
-# $2-n: device classes to include in output
-get_usb_devices_int() {
- [ -z "$TMPDIR" ] && TMPDIR="/tmp"
- local EXP=$1
- shift
- if [ -z "$EXP" ]; then
- writelog --quiet "No ouput expression template passed to get_usb_devices"
- cleanexit 1
- fi
- if [ $# -eq 0 ]; then
- writelog --quiet "No device classes given to get_usb_devices"
- cleanexit 1
- fi
- local MATCH=';'
- while [ $# -gt 0 ]; do
- MATCH+="$1;"
- [[ "$1" != *:* ]] && MATCH+="0:$1;"
- shift
- done
- local dev=
- local key value trailing
- trailing=
- local tmp="${TMPDIR}/lsusb.$$.$RANDOM"
- for dev in /dev/bus/usb/*/*; do
- if ! lsusb -D "$dev" > "$tmp" 2>/dev/null; then
- writelog --quiet "Cannot lsusb $dev"
- continue
- fi
- local DC=
- local OK=
- local VENDOR=
- local PRODUCT=
- while read -r key value trailing || [ -n "$key" ]; do
- if [[ "$key" == "idVendor" ]]; then
- [[ "$value" == 0x* ]] && VENDOR="${value:2}"
- elif [[ "$key" == "idProduct" ]]; then
- [[ "$value" == 0x* ]] && PRODUCT="${value:2}"
- elif [ -z "$DC" ]; then
- # No bDeviceClass seen yet
- if [[ "$key" == "bDeviceClass" ]]; then
- DC="$value"
- [[ "$MATCH" == *";${DC};"* ]] && OK=yo
- fi
- else
- # #DeviceClass is generic, look at sub class
- if [[ "$key" == "bInterfaceClass" ]]; then
- [[ "$MATCH" == *";${DC}:${value};"* ]] && OK=yo
- fi
- fi
- if [ -n "$OK" -a -n "$VENDOR" -a -n "$PRODUCT" ]; then
- echo "$EXP" | sed "s/%VENDOR%/${VENDOR}/g;s/%PRODUCT%/${PRODUCT}/g"
- break
- fi
- done < "$tmp"
- done
- rm -f -- "$tmp"
-}
-
-get_usb_devices() {
- if which lsusb 2>/dev/null >&2 && lsusb --help 2>&1 | grep -q -- '-D' 2>/dev/null; then
- [ $# -eq 1 ] && set -- "$1" $PASSTHROUGH_USB_DEVICES # no quotes here!
- get_usb_devices_int "$@" | sort -u
- else
- writelog --quiet "Cannot scan usb bus: lsusb not found or doesn't support -D"
- fi
-}
-
diff --git a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc
index ca475da0..d09f6a75 100644
--- a/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc
+++ b/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc
@@ -1,8 +1,32 @@
#######################################################
# Include: Set functions needed by vmchooser-run_virt #
#######################################################
+## Assigns an ID to the currently starting VM to support
+# multiple instances running simultaneously.
+# Note that VM_ID will always have two digits.
+get_vm_id() {
+ local script=${BASH_SOURCE[-1]}
+ [ -z "$script" ] && script="$0"
+ if [ -n "$script" ]; then
+ script=$(readlink -f "$script")
+ if [ -n "$script" ] && [ -s "$script" ]; then
+ #bingo
+ declare -g VM_ID=$(ps ax | grep -F "$script" | grep -v 'grep' | grep -o -- "${script}.*\$" | sort -u | wc -l)
+ if [ "$VM_ID" -gt 0 ]; then
+ [ "${#VM_ID}" -eq 1 ] && VM_ID="0${VM_ID}"
+ [ "${#VM_ID}" -gt 2 ] && VM_ID="${VM_ID:0:2}"
+ [ "${#VM_ID}" -eq 2 ] && readonly VM_ID && return
+ fi
+ fi
+ fi
+ # fallback: take last two digits of current pid...
+ VM_ID=$(expr substr $$ $(expr ${#$} - 1) 2)
+ [ "${#VM_ID}" -eq 1 ] && VM_ID="0${VM_ID}"
+ readonly VM_ID
+}
-# function to write to stdout and logfile
+################# LOGGING FUNCTIONS ##################
+# Helper function to write to stdout and logfile
writelog() {
local DATE=$(date +%Y-%m-%d-%H-%M-%S)
# write to stdout?
@@ -12,9 +36,11 @@ writelog() {
echo -e "$DATE: $@"
fi
# log into file
- echo -e "$DATE: $@" >> "${LOGFILE}"
+ echo -e "$DATE: ${SLX_DEBUG:+(${FUNCNAME[1]}) }$@" >> "${LOGFILE}"
}
+# Helper function to notify the user.
+# This directly returns and do not wait for a user confirmation.
notify_user() {
local TOPIC="$1"
shift
@@ -22,6 +48,8 @@ notify_user() {
writelog "Notify: **${TOPIC}**: $*"
}
+# Helper to display an error message box to the user.
+# Only returns when the user dismisses the message.
error_user() {
local TOPIC="$1"
shift
@@ -37,47 +65,246 @@ $*"
BODY="$TOPIC"
fi
# Zenity should yield the nicest result
- zenity --error --title "$TITLE" --text "$BODY" && return
+ # TODO the title is only set as the window name,
+ # which cannot be seen without a window manager
+ zenity --error --title "$TITLE" --text "$BODY"
+ local RET=$?
+ [ $RET -le 1 ] && return
# QnD abuse printergui for error message as it's blocking
/opt/openslx/cups/printergui --error "$MSG" && return
# printergui might not exist, try fallback here
- # unfortunately, i can only think of notify+sleep right now
+ # unfortunately, I can only think of notify+sleep right now
notify-send -u critical "$TITLE" "$BODY"
sleep 10
}
-# Clean exit will be called at the end of vmchooser-run_virt
+################## CLEANUP FUNCTIONS ##################
+# Registers functions to be called when cleanexit is called.
+# Only accepts functions that were not previously registered.
+# This kinda detects when a cleanup function was overriden,
+# or at least that something is fishy.
+declare -ag CLEANUP_TASKS
+add_cleanup() {
+ [ $# -lt 1 ] && writelog "'${FUNCNAME[0]}' needs at least one argument! $# given." && return
+ # check if the given function name is already used
+ while [ $# -ne 0 ]; do
+ if array_contains CLEANUP_TASKS "$1"; then
+ writelog "Cleanup function '$1' already registered! Are there multiple definitions of this function?"
+ writelog "This might suggest that a previously defined cleanup function was overriden!"
+ return 1
+ fi
+ CLEANUP_TASKS+=("$1")
+ shift
+ done
+ return 0
+}
+# This function will be called at the end of vmchooser-run_virt
+# or upon critical errors during the runtime.
+# It will call the cleanup functions registered through 'add_cleanup'
+# and clean TMPDIR if appropriate. Further, it will evaluate and
+# process the EXIT_{TYPE,REASON} variables that hold information
+# on why we are about to exit.
+#
+# EXIT_TYPE should be either:
+# - 'internal' for critical internal errors, this will
+# automatically send the logfile via slxlog.
+# - 'user' for errors related to the user's choice
+# Others could be thought of like 'external' for failures
+# with remote services (e.g. slx apis, external image repo, ...)
+#
+# EXIT_REASON should contain a user-friendly message to print to the user.
cleanexit() {
+ writelog "Cleanexit '$1' triggered by '${BASH_SOURCE[1]}:${FUNCNAME[1]}'"
sleep 1
- # Ummount dnbd3-fuse
- if [ -n "$dnbd3_fuse_mount_point" ] && [ -e "$dnbd3_fuse_mount_point/img" ]; then
- for timeout in 1 1 1 FAIL; do
- fusermount -u "$dnbd3_fuse_mount_point" && break
- writelog "dnbd3 still busy...."
- [ "$timeout" = "FAIL" ] && break
- sleep "$timeout"
- done
- fi
- # Kill LPD
- [ -n "${PID_LPD}" ] && kill "${PID_LPD}"
+ while isset CLEANUP_TASKS; do
+ local TASK=${CLEANUP_TASKS[-1]}
+ unset -v CLEANUP_TASKS[-1]
+ if ! is_function $TASK; then
+ writelog "Registered cleanup function '$TASK' is not a function. This should not be..."
+ continue
+ fi
+ if ! ${TASK}; then
+ writelog "Failed to run cleanup function '$TASK'! Exit code: $RET"
+ fi
+ done
# If we're not in debug mode, remove all temporary files
- if [ -n "${TMPDIR}" -a -z "$SLX_DEBUG" ]; then
+ if notempty SLX_DEBUG && isset TMPDIR; then
rm -rf -- "${TMPDIR}"
fi
- [ $# -gt 0 ] && exit "$1"
- exit 129 # No exit code was given :/
-}
+ # Now see if we need to do the catch all error stuff
+ # no exit code given, return 129
+ [ $# -eq 0 ] && exit 129
+ # if 0 given, exit 0
+ [ "x$1" = "x0" ] && exit 0
-rv_clean_string() {
- if [ "$#" -ge 1 ]; then
- echo "$@" | tr '[A-Z]' '[a-z]' | tr -d -c '[a-z0-9\-]'
+ # given exit code is set and not 0, handle the error now
+ # now evaluate the EXIT_{TYPE,REASON} variables and generate error title/text
+ local ERR_TITLE ERR_TEXT ERR_FOOTER
+ # default error footer
+ ERR_FOOTER="Versuchen Sie den Computer neuzustarten und falls das Problem bestehen bleibt, kontaktieren Sie den Support."
+ if notempty EXIT_TYPE; then
+ case "${EXIT_TYPE}" in
+ user)
+ ERR_TITLE="Auswahlfehler"
+ ERR_FOOTER="Beim Start Ihrer Veranstaltung sind Fehler aufgetretten. Versuchen Sie es mit einer anderen Veranstaltung."
+ ;;
+ internal)
+ ERR_TITLE="Interner Fehler"
+ ;;
+ *)
+ ERR_TITLE="Unbekannter Fehler"
+ writelog "Unknown EXIT_TYPE: '${EXIT_TYPE}'."
+ ;;
+ esac
+ fi
+ if notempty EXIT_REASON; then
+ ERR_TEXT="${EXIT_REASON}"
else
- tr '[A-Z]' '[a-z]' | tr -d -c '[a-z0-9\-]'
+ # this should never happen if EXIT_REASON is properly
+ # used when calling cleanexit !
+ ERR_TEXT="Unbekannter Fehler"
+ fi
+
+ # first send the logfile (in case the user does not close the error before using magic keys e.g.)
+ # for any other error types besides 'user'.
+ [ "x${EXIT_TYPE}" != "xuser" ] && \
+ slxlog "runvirt-exit-${EXIT_TYPE}" "Critical error happened in '${BASH_SOURCE[1]}:${FUNCNAME[1]}', see logs." "${LOGFILE}"
+
+ # finally display the error
+ error_user "${ERR_TITLE}" "
+${ERR_TEXT}
+
+${ERR_FOOTER}
+"
+ writelog "All done. Exiting."
+ exit "$1"
+}
+
+################# SOURCING FUNCTIONS #################
+# Wrapped 'source' that first checks for existence and
+# syntax before actually sourcing the given file.
+# The option '--exit' triggers cleanexit upon syntax errors.
+# Without it, it returns 0 when tests passed, 1 otherwise.
+# Usage:
+# safesource [--exit] <files>
+safesource() {
+ declare -i EXIT_ON_FAILURE=0
+ [ "x$1" = "x--exit" ] && EXIT_ON_FAILURE=1 && shift
+ while [ $# -gt 0 ]; do
+ # sanitze filename just to be sure as it is part of the eval coming later
+ # alphanumeric and - _ . should be enough for common file naming scheme
+ if [[ ! "$1" =~ ^[a-zA-Z0-9./_-]+$ ]]; then
+ writelog "'$1' is a weird filename to source! Ignoring."
+ return 1
+ fi
+ local FILE="$1"
+ shift
+ bash -n "${FILE}"
+ local -i RET=$?
+ if [ $RET -ne 0 ]; then
+ case $RET in
+ 1) writelog --quiet "Bad file to source: ${FILE}" ;;
+ 2) writelog --quiet "Bad syntax: ${FILE}" ;;
+ 126) writelog --quiet "Could not access: ${FILE}" ;;
+ 127) writelog --quiet "File not found: ${FILE}" ;;
+ *) writelog --quiet "Syntax check (bash -n) returned unknown error code '${RET}' for: ${FILE}" ;;
+ esac
+ if [ $EXIT_ON_FAILURE -eq 1 ]; then
+ echo "eval EXIT_REASON=\"internal:source:${FILE}\" cleanexit 1 ;"
+ else
+ echo "eval writelog \"Could not safesource '${FILE}'.\" ;"
+ fi
+ return 1
+ fi
+ echo "eval source ${FILE} ;"
+ echo "run_post_source ${FILE} ;"
+
+ done
+ return 0
+}
+
+# Registers functions to be called after sourcing an include.
+# Includes should only define functions and register them
+# to be called after successfully sourcing.
+declare -Ag RUN_POST_SOURCE
+call_post_source() {
+ while [ $# -gt 0 ]; do
+ if ! is_function "$1"; then
+ writelog "Tried to register a non-function: '$1'"
+ continue
+ fi
+ if notempty BASH_SOURCE[1]; then
+ RUN_POST_SOURCE[${BASH_SOURCE[1]}]+="$1 "
+ shift
+ else
+ writelog "Could not determine the sourced file calling ${FUNCNAME[0]}"
+ fi
+ done
+}
+# Helper called after sourcing the file via safesource. It just calls the
+# functions in the same order they were registered.
+run_post_source() {
+ [ $# -ne 1 ] && writelog "'${FUNCNAME[0]}' expects one argument only! $# given." && return 1
+ for TASK in ${RUN_POST_SOURCE["${1}"]}; do
+ # sanity checks
+ if ! is_function $TASK; then
+ writelog "\tRegistered function '$TASK' is not a function!"
+ return 1 # TODO maybe even cleanexit here as this seems very bad...
+ fi
+ # remove from stack before running it
+ RUN_POST_SOURCE["${1}"]="${RUN_POST_SOURCE[${1//${TASK}\ /\ }]}"
+ ${TASK}
+ local -i RET=$?
+ if [ $RET -ne 0 ]; then
+ writelog "\tFailed to run post source '${TASK}' (Exit code: $RET)"
+ return $RET
+ fi
+ done
+ return 0
+}
+
+################# FEATURE FUNCTIONS ##################
+# Helper to register feature handlers, read run-virt.d/README
+declare -Ag FEATURE_HANDLERS
+reg_feature_handler() {
+ if [ $# -ne 2 ]; then
+ writelog "'${FUNCNAME[0]}' expects 2 arguments! $# given."
+ return 1
+ fi
+ if notempty FEATURE_HANDLERS["$1"]; then
+ writelog "'${BASH_SOURCE[1]}' tried to overwrite feat handler '$1'! Ignoring."
+ # maybe allow overwritting?
+ return 1
fi
+ if ! is_function "$2"; then
+ writelog "'${BASH_SOURCE[1]}' tried to register a non-function as feat handler!"
+ writelog "\t'$2' is a '$(type -t $2 2>&1)'."
+ return 1
+ fi
+ # all good, save it
+ FEATURE_HANDLERS["$1"]="$2"
+ return 0
}
+
+################### XML FUNCTIONS ####################
+# Extract given xpath from given xml file
+# e.g.: xmlextract '//node/nestednode/@attribute' "$file"
+# @param
+# @return Plain text, UTF-8
+xmlextract() {
+ xmlstarlet sel -T -E utf-8 -t -v "$1" "$2"
+}
+
+# Wrapper for convenience
+get_xml () {
+ xmlextract "//settings/eintrag/${1}/@param" "${XML_FILE}"
+}
+
+
+################## HELPER FUNCTIONS ##################
# Check if the given variables are set (empty or not)
isset() {
while [ $# -gt 0 ]; do
@@ -96,12 +323,111 @@ notempty() {
return 0
}
-##
-# Extract given xpath from given xml file
-# e.g.: xmlextract '//node/nestednode/@attribute' "$file"
-# @param
-# @return Plain text, UTF-8
-xmlextract() {
- xmlstarlet sel -T -E utf-8 -t -v "$1" "$2"
+# Convenience function
+isempty() {
+ ! notempty $@
+}
+
+# Helper to test if given arguments are declared as functions
+is_function() {
+ while [ $# -gt 0 ]; do
+ local TYPE="$(type -t "$1" 2>/dev/null)"
+ if [ "x${TYPE}" != "xfunction" ]; then
+ writelog "'$1' not a function but a '${TYPE}'."
+ return 1
+ fi
+ shift
+ done
+ return 0
}
+# Helper to test if given arguments are declared as arrays
+is_array() {
+
+ # -ne 1 ] && writelog "is_array: Expects 1 argument! $# given." && return 1
+ while [ $# -gt 0 ]; do
+ local ARRAY_DEF="$(declare -p ${1} 2>/dev/null)"
+ if [[ ! "${ARRAY_DEF}" =~ "declare -a" ]] && [[ ! "${ARRAY_DEF}" =~ "declare -A" ]]; then
+ return 1
+ fi
+ shift
+ done
+ return 0
+}
+
+# Helper to test is the given array contains given value
+# Usage:
+# array_contains ARRAY_TO_TEST <values...>
+array_contains() {
+ if [ $# -lt 2 ]; then
+ writelog "${FUNCNAME[0]}: Expects at least 2 arguments, $# given."
+ return 1
+ fi
+ # is $1 even defined?
+ local ARRAY_DEF="$(declare -p $1 2>/dev/null)"
+ if isempty ARRAY_DEF; then
+ writelog "${FUNCNAME[0]}: '$1' not defined!"
+ return 1
+ fi
+ local ARRAY_NAME="$1"
+ shift
+
+ # sanity check on $ARRAY_DEF being either indexed or associative array
+ if ! is_array "${ARRAY_NAME}"; then
+ writelog "${FUNCNAME[0]}: '${ARRAY_NAME}' not an array! Declared as:\t${ARRAY_DEF}"
+ return 1
+ fi
+
+ # now test if array contains the given values in $2+
+ while [ $# -gt 0 ]; do
+ # check if ARRAY_DEF contains '"<value>"'
+ if [[ ! "${ARRAY_DEF}" =~ '="'${1}'"'[^\]]+ ]]; then
+ writelog "${FUNCNAME[0]}: '${1}' not in '${ARRAY_NAME}'"
+ return 1
+ fi
+ shift
+ done
+ return 0
+}
+
+# Helper to check if the given arguments are valid command names.
+# This uses 'type -t' thus supports notably binaries, functions
+# and aliases (might need these one day).
+# By default, only 0 is returned if all arguments are found.
+# Use '--oneof' to return 0 if any one of the arguments are found.
+check_dep() {
+ [ $# -lt 1 ] && return 1
+ unset ONEOF
+ if [ "x$1" = "x--oneof" ]; then
+ local ONEOF="1"
+ shift
+ fi
+ while [ $# -gt 0 ]; do
+ if ! type -t "$1" >/dev/null 2>&1 ; then
+ writelog "Dependency check failed! Could not find '$1'."
+ isset ONEOF || return 1
+ else
+ isset ONEOF && return 0
+ fi
+ shift
+ done
+ isset ONEOF && return 1 || return 0
+}
+
+
+
+# TODO: This is only used once in the whole script:
+# to cleanup the os string stored in the xml
+# Since the rework of this script, the os strings come from
+# the satellite server which already gives us a sanitized string
+# thus this function might not be needed anymore, as calling it on
+# new gen os strings effectively does nothing.
+# Removes any non-alphanumerical and non-hyphen chars
+# from the given parameters.
+clean_string() {
+ if [ "$#" -ge 1 ]; then
+ echo "$@" | tr '[A-Z]' '[a-z]' | tr -d -c '[a-z0-9\-]'
+ else
+ tr '[A-Z]' '[a-z]' | tr -d -c '[a-z0-9\-]'
+ fi
+}