diff options
author | Jonathan Bauer | 2017-01-25 18:32:35 +0100 |
---|---|---|
committer | Jonathan Bauer | 2017-01-25 18:32:35 +0100 |
commit | eea5898961a40fc50f01356f90c42904a73a3f74 (patch) | |
tree | 52c19d11efc2d7d904ac89e36ff271de305cfc5a /core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes | |
parent | [pam] Include cifs.upcall for DFS support (diff) | |
download | mltk-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')
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 +} |