diff options
Diffstat (limited to 'remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes')
14 files changed, 830 insertions, 0 deletions
diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/check_runvirt_needed_files.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/check_runvirt_needed_files.inc new file mode 100644 index 00000000..fbb0bc70 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/check_runvirt_needed_files.inc @@ -0,0 +1,53 @@ +################################################################# +# Include: Check for important files used by vmchooser_run-virt # +################################################################# + +# WARNING: This is perhaps vestigial! + +filecheck() { + filecheck=$(LANG=us ls -lh ${diskfile} 2>&1) + writelog "Filecheck:\n${filecheck}\n" + noimage=$(echo ${filecheck} | grep -i "no such file or directory" | wc -l) + rightsfile=${diskfile} + + # check if link + if [ -L "${diskfile}" ]; then + # take link target + rightsfile=$(ls -lh ${diskfile} 2>&1 | awk -F '-> *' '{print $2}') + rightsfile=${vmdir}/${rightsfile} + filecheck=$(LANG=us ls -lh ${rightsfile} 2>&1) + fi + + # does file exist + if [ "${noimage}" -ge "1" ]; then + writelog "Virtual Machine Image Problem:\c " + writelog "\tThe image you've specified doesn't exist." + writelog "Filecheck says:\c " + writelog "\t\t${diskfile}:\n\t\t\tNo such file or directory" + writelog "Hint:\c " + writelog "\t\t\tCompare spelling of the image with your options.\n" + exit 1 + fi + # readable by calling user + if ! [ -r "${diskfile}" >/dev/null 2>&1 \ + -o -r "${diskfile}" >/dev/null 2>&1 ]; then + writelog "Vmware Image Problem:\c " + writelog "\tThe image you've specified has wrong rights." + writelog "Filecheck says:\t\t$(echo ${filecheck} \ + | awk '{print $1" "$3" "$4}') ${rightsfile}" + writelog "Hint:\t\t\tChange rights with: chmod a+r ${rightsfile}\n" + exit 1 + fi + + # writable (for persistent-mode)? + if ! [ -w "${diskfile}" >/dev/null 2>&1 \ + -o -w "${diskfile}" >/dev/null 2>&1 ] \ + && [ "${np}" = "independent-persistent" ]; then + writelog "Vmware Image Problem:\c " + writelog "\tThe image you have specified has wrong rights." + writelog "Filecheck says:\t\t$(echo ${filecheck} \ + | awk '{print $1" "$3" "$4}') ${rightsfile}" + writelog "Hint:\t\t\tUse nonpersistent-mode or change rights to rw\n" + exit 1 + fi +} diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/detect_legacy.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/detect_legacy.inc new file mode 100644 index 00000000..8bdfd8b1 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/detect_legacy.inc @@ -0,0 +1,34 @@ +######################################################## +# Include: Detect, whether runvirt runs in legacy mode # +######################################################## + +# Legacy mode: As runvirt has been before. +# New mode: uuid in xml _and_ vmx given via http. + +writelog "Detecting current/legacy mode ..." + +# First, let's try to extract an imguuid from xmlfile: +declare -rg IMGUUID=$(grep -i -o '<uuid param=.*"' "${xmlfile}" | sed -e "s/&.*;/; /g" | awk -F '"' '{ print $2 }') +declare -rg TMPCONFIG="$TMPDIR/vmconfig.tmp" + +writelog "IMGUUID extracted: $IMGUUID" + +# 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." + else + writelog "Triggering current (non-legacy) mode." + LEGACY= # everything worked - clear legacy mode variable (so we use the "current" mode) + fi + fi +fi + diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc new file mode 100644 index 00000000..b7ed648c --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/get_xml_file_variables.inc @@ -0,0 +1,103 @@ +########################################### +# Include: Set hardware related variables # +########################################### + +writelog "Starting configuration..." +writelog "\tLogfile:\t\t${LOGFILE}" +writelog "\t/tmp info:\t\t$(df -h | grep " /tmp$" | awk '{print $2}') \c" +writelog "$(grep "/tmp " /proc/mounts | awk '{print $1" "$2" "$3" "$4}')" +writelog "\tVM XML dir:\t\t$(dirname "${xmlfile}")" +writelog "\tXML file:\t\t${xmlfile}" +writelog "Enable 3D:\t\t${enable3d}" +writelog "VM config:" + +# # Name of the virt image +imgname=$(grep -io '<image_path param=.*"' "${xmlfile}" | sed -e "s/&.*;/; /g" | awk -F '"' '{ print $2 }') +imgrelpath=$(grep -io '<image_name param=.*"' "${xmlfile}" | sed -e "s/&.*;/; /g" | awk -F '"' '{ print $2 }') +# [ -z "$imgname" ] && imgname="${imgrelpath}" +imgrelpath=${imgrelpath#/mnt/vmstore/} + +writelog "Virtual image file name: $imgname" + +# Imagename w/ full path +if echo "${imgname}" | grep -q '^/'; then + imgpath="$(dirname "${imgname}")" + imgname="$(basename "${imgname}")" + vmpath="${imgpath}/${imgname}" + # If old vmchooser binary stuff + # We do not need folder name as it is already included by vmchooser +elif echo "${xmlfile}" | grep -q '^/tmp/'; then + vmpath="$imgname" + imgname="$(basename "${imgname}")" + ## Added for persistent support. +else + # Else use same path as xml + imgpath="${xmlpath}" + vmpath="${imgpath}/${imgname}" +fi + +# If ${vm_name} not defined use ${xmlfile} +vm_name="${vm_name:-${xmlfile%.xml}}" + +# Define vm_shortname since vm_name can be very long +vm_shortname="$(basename "${xmlfile%.xml}" | sed -e "s, ,-,g")" + +# vm_name = displayname, define for old scripts +displayname="${vm_name}" + +# image is for the following virtual machine +xmlvirt=$(grep -o 'virtualmachine param=.*"' "${xmlfile}" \ + | sed -e "s/&.*;/; /g" | awk -F '"' '{print $2}') + +# choose the proper virtualization/emulator plugin +[ "x${xmlvirt}" != "x" -a "x${xmlvirt}" != "xqemukvm" -a "x${xmlvirt}" != "xvirtualbox" -a "x${xmlvirt}" != "xvmware" ] && xmlvirt="emufe" + +# Extracting OS type (vmostype) from xml file. We don't care here whether vmostype is empty, as then +# it will yield the default entries later on. +vmostype=$(grep -io '<os param=.*"' "${xmlfile}" | sed -e "s/&.*;/; /g" | awk -F '"' '{ print $2 }') + +# make a guess from the filename extension if ${xmlvirt} is empty +# (not set within the XML file) +# TODO: implement possibility to submit own configuration files +if [ -z "${xmlvirt}" ] && [ -n "${additional_config}" ]; then + writelog "No virtual machine parameter defined in ${xmlfile}" + writelog "Trying to guess VM...\c" + case "$(cat ${additional_config} | tr \"[A-Z]\" \"[a-z]\")" in + *config.version*|*virtualhw.version*|*independent-nonpersistent*|*vmdk*) + xmlvirt="vmware" + ;; + *innotek*|*virtualbox*) + xmlvirt="virtualbox" + ;; + *qemu*|*kvm*) + xmlvirt="qemukvm" + ;; + *) + xmlvirt="none" + ;; + esac + elif [ -z "${xmlvirt}" ]; then + case "$(echo ${imgname##*.} | tr \"[A-Z]\" \"[a-z]\")" in + vmdk) + xmlvirt="vmware" + ;; + vbox|vdi) + xmlvirt="virtualbox" + ;; + qcow*) + xmlvirt="qemukvm" + ;; + *) + xmlvirt="emufe" + ;; + esac + writelog "result:\t${xmlvirt}" +fi + +# Set redirects to 0, see vmgrid if you want to define some +redirects=0 + +writelog "\tVirtualization:\t\t$xmlvirt" +writelog "\tVM name:\t\t$vm_name" +writelog "\tVM short name:\t\t$vm_shortname" +writelog "\tVM OS:\t\t$vmostype" diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc new file mode 100644 index 00000000..9a46bc88 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc @@ -0,0 +1,102 @@ +########################################### +# Include: Set hardware related variables # +########################################### + +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) +} + +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" + +# 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 ]" + +# Fill in VMID +macaddrsuffix=$(echo "$macaddrsuffix" | sed "s/%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 +macaddr="$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"} +# IDE is expected default, test for the virtual disk image type should +# be done while creating the runscripts ... +# TODO enable SCSI support instead of just disabling it. +ide="TRUE" +scsi="FALSE" +hddrv="ide" +audio="true" +remotedesktopport="590${VM_ID}" + +# Enable 3D +enable3d=$(grep -i -o "<enable3d param=.*" "${xmlfile}" | awk -F '"' '{print $2}' | rv_clean_string) + +# 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)" + +writelog "\tVM Hostname:\t\t$hostname" + diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc new file mode 100644 index 00000000..4c4ccf1d --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_variables.inc @@ -0,0 +1,26 @@ +###################################################### +# Include: Declaration of run-virt default variables # +###################################################### + +VMCHOOSER_DIR="/opt/openslx/vmchooser" +VMCHOOSER_CONF_DIR="$VMCHOOSER_DIR/config" +LOGFILE="/var/log/openslx/run-virt.${USER}.$$.log" +USER="$(whoami)" +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/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc new file mode 100644 index 00000000..f0820ed7 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_firewall.inc @@ -0,0 +1,12 @@ + +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/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc new file mode 100644 index 00000000..3c4ed330 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_image_access.inc @@ -0,0 +1,71 @@ +########################################################### +# Include: Setup dnbd for image access, nfs/cifs fallback # +########################################################### + +writelog "Now in setup_image_access.inc ..." + +# Try to use dnbd3 to access the image +unset vm_diskfile +unset vm_revision +unset dnbd3_fuse_mount_point +unset dnbd3_tmplog +if ! which dnbd3-fuse; then + writelog "Can't use dnbd3 as dnbd3-fuse binary is not in PATH" +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 + # Mount path for images mounted with dnbd3-fuse + dnbd3_fuse_mount_point="$TMPDIR/dnbd3fuse.mnt" + mkdir -p "${dnbd3_fuse_mount_point}" + # start dnbd3-fuse in subshell + dnbd3_tmplog="$TMPDIR/dnbd3fuse.log" + dnbd3_exitflag="$TMPDIR/dnbd3exit$RANDOM" + rm -f -- "$dnbd3_exitflag" + ( + dnbd3-fuse -f -o allow_other,max_readahead=262144 -h "$SLX_DNBD3_SERVERS" -i "${imgrelpath}" "${dnbd3_fuse_mount_point}" > "$dnbd3_tmplog" 2>&1 + RET=$? + touch "$dnbd3_exitflag" + if [ "$RET" != "0" ]; then + writelog "dnbd3-fuse stopped working (Exit code $RET)" + slxlog "virt-dnbd3-fuse" "dnbd3-fuse stopped/refused serving '${imgrelpath}' 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="${dnbd3_fuse_mount_point}/img" + writelog "DNBD3: $imgrelpath on $vm_diskfile with rid $vm_revision" + vmpath="$vm_diskfile" + break + fi + [ "$TIMEOUT" = "OUT" -o -e "$dnbd3_exitflag" ] && break + sleep "$TIMEOUT" + done + + if [ -z "$vm_diskfile" ]; then + slxlog "virt-dnbd3" "No dnbd3 server for ${imgrelpath} found, trying NFS/CIFS..." "$dnbd3_tmplog" + writelog "No working dnbd3 server found :-(" + fi +fi + +# $vm_diskfile will be empty if dnbd3 is not used or failed. Let's try to fall back to NFS/CIFS via file system +if [ -z "$vm_diskfile" ]; then + new_vmpath=$(ls "${vmpath}.r"* | grep -E -o '\.r[0-9]+$' | grep -o -E '[0-9]+' | sort -n | tail -n 1) + [ -n "$new_vmpath" ] && vmpath="${vmpath}.r${new_vmpath}" + vm_diskfile="$vmpath" +fi + +# Check if virtual machine container file exists +if ! [ -e "${vmpath}" ]; then + slxlog "virt-image-missing" "VM image $vmpath not found!" + writelog "Virtual machine image ${vmpath} 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 + +writelog "Virtual machine disk file: $vm_diskfile" + diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc new file mode 100644 index 00000000..2fb9310a --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_printer_lpd.inc @@ -0,0 +1,46 @@ +##################################### +# 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/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc new file mode 100644 index 00000000..6230aa3a --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_sound.inc @@ -0,0 +1,65 @@ +#!/bin/bash <-- Add shebang even though it's sourced so vim highlights bash specific features properly +######################## +# Include: Setup sound # +######################## +# 8086:1e20: Sound card in bwPX4 + +writelog "Starting sound setup ..." + +if lspci -n | grep -E -i '8086:1e20( |$)'; then + VOL="100%" # bwPC 4: Speaker too quiet :-( +else + VOL="85%" +fi + +if true; then + # detecting which card is to be used + writelog "Detecting which sound card to use ..." + PROC="/proc/asound/cards" + if [ ! -r "$PROC" ]; then + writelog "'${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 "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 "Detected sound card index is: $SOUND_CARD_INDEX" + writelog "Sound card count: $SOUND_CARD_COUNT" + + # Adjust sound volume (playback)... Random mixer names we have encountered during testing + writelog "Setting up volume..." + amixer -q -c "$SOUND_CARD_INDEX" sset 'Master' "$VOL" unmute + amixer -q -c "$SOUND_CARD_INDEX" sset 'PCM' "$VOL" unmute + amixer -q -c "$SOUND_CARD_INDEX" sset 'CD' "$VOL" unmute + amixer -q -c "$SOUND_CARD_INDEX" sset 'Headphone' "$VOL" unmute + amixer -q -c "$SOUND_CARD_INDEX" sset 'Front' "$VOL" unmute + amixer -q -c "$SOUND_CARD_INDEX" sset 'Speaker' "$VOL" 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' '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 + writelog "Done setting up volume." +fi >> "${LOGFILE}" 2>&1 diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc new file mode 100644 index 00000000..d9ae052c --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_virtual_floppy.inc @@ -0,0 +1,101 @@ +#!/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/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc new file mode 100644 index 00000000..ce15524f --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/setup_vm_hypervisor.inc @@ -0,0 +1,34 @@ +########################################################################## +# 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/$xmlvirt/run-virt.include" ] ; then + slxlog "virt-plugin-missing" "Could not find run-virt.include for $xmlvirt ($VMCHOOSER_DIR/$xmlvirt/run-virt.include)" + writelog "Failed because of missing ${xmlvirt} plugin." + error_user "Konnte den Virtualisierer '$xmlvirt' 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="${xmlvirt}" + +if ! bash -n "$VMCHOOSER_DIR/$xmlvirt/run-virt.include"; then + slxlog "virt-plugin-syntax" "run-virt.include for $xmlvirt contains syntax errors (bash -n run-virt.include failed)" + writelog "Erroneous run-virt.include for $xmlvirt (syntax check)" + error_user "Das Start-Script für den Virtualisierer '$xmlvirt' 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/$xmlvirt/run-virt.include"; then + slxlog "virt-plugin-error" "run-virt.include for $xmlvirt could not be sourced properly." + writelog "Erroneous run-virt.include for ${xmlvirt}? Source returned != 0" + error_user "Das Start-Script für den Virtualisierer '$xmlvirt' 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." + fi +} + diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc new file mode 100644 index 00000000..da43f341 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/start_windowmanager.inc @@ -0,0 +1,27 @@ +#################################################### +# Include: Start windowmanager for easier handling # +#################################################### + +# 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 & + fi + FOUND_WM=1 + break + fi +done + +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 diff --git a/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc new file mode 100644 index 00000000..a2d442e4 --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/usb_detector.inc @@ -0,0 +1,77 @@ +# 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/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc new file mode 100644 index 00000000..c0d17dbe --- /dev/null +++ b/remote/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/vmchooser_runvirt_functions.inc @@ -0,0 +1,79 @@ +####################################################### +# Include: Set functions needed by vmchooser-run_virt # +####################################################### + +# function to write to stdout and logfile +writelog() { + local DATE=$(date +%Y-%m-%d-%H-%M-%S) + # write to stdout? + if [ "x$1" = "x--quiet" ]; then + shift + else + echo -e "$DATE: $@" + fi + # log into file + echo -e "$DATE: $@" >> "${LOGFILE}" +} + +notify_user() { + local TOPIC="$1" + shift + notify-send -u normal "$TOPIC" "$@" + writelog "Notify: **${TOPIC}**: $*" +} + +error_user() { + local TOPIC="$1" + shift + local MSG TITLE BODY + if [ $# -gt 0 ]; then + MSG=" $TOPIC +$*" + TITLE="$TOPIC" + BODY="$*" + else + MSG="$TOPIC" + TITLE="ERROR" + BODY="$TOPIC" + fi + # Zenity should yield the nicest result + zenity --error --title "$TITLE" --text "$BODY" && 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 + notify-send -u critical "$TITLE" "$BODY" + sleep 10 +} + +# Clean exit will be called at the end of vmchooser-run_virt +cleanexit() { + 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}" + + # If we're not in debug mode, remove all temporary files + if [ -n "${TMPDIR}" -a -z "$SLX_DEBUG" ]; then + rm -rf -- "${TMPDIR}" + fi + + [ $# -gt 0 ] && exit "$1" + exit 129 # No exit code was given :/ +} + +rv_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 +} |