#!/bin/ash # ----------------------------------------------------------------------------- # # Copyright (c) 2007..2018 bwLehrpool-Projektteam # # This program/file is free software distributed under the GPL version 2. # See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html # # If you have any feedback please consult https://bwlehrpool.de and # send your feedback to bwlehrpool@hs-offenburg.de. # # General information about bwLehrpool can be found at https://bwlehrpool.de # # ----------------------------------------------------------------------------- # systemd-vmchooser_env # - This is the preparation script for the configuration of the virtuali- # zation tools used later on. # - This creates '$VMCHOOSER_CONF_DIR/virtualization.conf' that is later # evaluated by the runvirt script. ################################################################################ ################################################################################ ### Define default dirs / get configs ################################################################################ export PATH=$PATH:/opt/openslx/bin:/opt/openslx/sbin # source config file with vars (e.g. ipaddr, macaddr, HOSTNAME) . /opt/openslx/config # from plugins/vmchooser/XX_vmchooser.sh VMCHOOSER_DIR="/opt/openslx/vmchooser" VMCHOOSER_CONF_DIR="${VMCHOOSER_DIR}/config" VMCHOOSER_VIRT_CONF="${VMCHOOSER_CONF_DIR}/virtualization.conf" # Same as in service file for udhcpd DHCP_NAT_CONF="${VMCHOOSER_CONF_DIR}/udhcpd-nat1.conf" echo "# Generated $(date)" > "$VMCHOOSER_VIRT_CONF" # setup more scratch space for virtual machines, if configured for DIR in /tmp/virt /var/log/samba /run/samba; do if ! mkdir -p "$DIR"; then echo "Could not create '$DIR'!" exit 1 fi done # check if a fallback share is set as SLX_VM_TMP_SOURCE if [ -n "${SLX_VM_TMP_SOURCE}" ]; then LOG=$(mktemp) # use SLX_VM_TMP_TYPE and SLX_VM_TMP_OPTS, if set for TRY in 1 2 3 STOP; do [ "x$TRY" = "xSTOP" ] && break if [ -n "${SLX_VM_TMP_TYPE}" ] && [ -n "${SLX_VM_TMP_OPTS}" ]; then mount -t "${SLX_VM_TMP_TYPE}" -o "${SLX_VM_TMP_OPTS}" "${SLX_VM_TMP_SOURCE}" /tmp/virt elif [ -n "${SLX_VM_TMP_TYPE}" ]; then mount -t "${SLX_VM_TMP_TYPE}" "${SLX_VM_TMP_SOURCE}" /tmp/virt elif [ -n "${SLX_VM_TMP_OPTS}" ]; then mount -o "${SLX_VM_TMP_OPTS}" "${SLX_VM_TMP_SOURCE}" /tmp/virt else mount "${SLX_VM_TMP_SOURCE}" /tmp/virt fi RET=$? [ "$RET" = "0" ] && break sleep $TRY done > "$LOG" 2>&1 if [ "$RET" -ne "0" ]; then if [ -s "$LOG" ]; then slxlog --delete "mount-vm-tmp-fail" "Mounting of '${SLX_VM_TMP_SOURCE}' failed." "$LOG" else slxlog "mount-vm-tmp-fail" "Mounting of '${SLX_VM_TMP_SOURCE}' failed." rm -f -- "$LOG" fi fi fi chmod a+rwxt /tmp/virt # enable normal users to setup the extended virtual machine redo file space # and image source via network block device (NBD only at the moment) # allow to start/stop samba on virtual devices (latter one ignores multiple # independent daemons) #cat >> /mnt/etc/sudoers << EOF # allow to start and stop the special /tmp redo file space (RAM + NBD/NFS server RAID) #ALL ALL=NOPASSWD: /sbin/losetup /dev/loop* #ALL ALL=NOPASSWD: /sbin/mdadm -C /dev/md0 -l linear --raid-devices=2 /dev/loop* /dev/* #ALL ALL=NOPASSWD: /opt/openslx/rootfs/usr/sbin/nbd-client * * /dev/nbd* # allow to configure and start/stop samba services #ALL ALL=NOPASSWD: /opt/openslx/rootfs/bin/sed -i /etc/*/smb.conf -e * #ALL ALL=NOPASSWD: /usr/sbin/nmbd -s /etc/*/smb.conf #ALL ALL=NOPASSWD: /usr/sbin/smbd -s /etc/*/smb.conf #ALL ALL=NOPASSWD: /opt/openslx/rootfs/usr/bin/killall nmbd smbd #EOF ################################################################################ echo "Determine host's hardware configuration" ################################################################################ # general machine architecture (32/64bit) echo "HOST_ARCH=$(uname -m)" >> "${VMCHOOSER_VIRT_CONF}" # generated mac address parts from the host's mac address if [ -n "$SLX_PXE_MAC" ]; then HOSTMACADDR="${SLX_PXE_MAC}" else ## Fallback: HOSTMACADDR="$(ip a | grep ether | grep -o -E -i '([0-9a-f]{2}:){5}[0-9a-f]{2}' | head -n 1)" fi echo "HOSTMACADDR='$HOSTMACADDR'" >> "${VMCHOOSER_VIRT_CONF}" # NG: we define 10 fixed prefixes (00:FF:00 -> 00:FF:09) to use for VMs # First, check if the first 3 bytes of the host's mac address is # contained in our list. If it is, use the next one in the list. # If not, or the host's prefix is the last one in the list, use the first one. # This lays the groundwork to avoid mac addresses collisions in nested operations. MACADDRPREFIX= for i in 0 1 2 3 4 5 6 7 8; do if [ "x${HOSTMACADDR#00:FF:0$i}" != "x${HOSTMACADDR}" ]; then # current prefix is indeed part of the host's mac address # use the next prefix if != 9 MACADDRPREFIX="00:FF:0$(( i + 1 ))" break fi done # if it is still unset, then either the host's prefix did not match any in the list # or it matched the 9th. Either way, use the first prefix for this level of VMs. [ -n "${MACADDRPREFIX}" ] || MACADDRPREFIX='00:FF:00' # grab the last 2 bytes of the host's mac and prepend our VMID # placeholder (later replaced used by run-virt). MACADDRSUFFIX="$( printf "%s" "$HOSTMACADDR" | awk -F ":" '{print "%VMID%:" $(NF-1) ":" $NF}' | tr 'a-z' 'A-Z' )" { # ### stdout redirect start echo "MACADDRPREFIX='$MACADDRPREFIX'" echo "MACADDRSUFFIX='$MACADDRSUFFIX'" # read in ip address echo "HOSTIP=${SLX_PXE_CLIENT_IP}" # hostname echo "HOSTNAME='$( hostname -s )'" # get further hw information and check for traces of available optical and floppy drives j=0 for CDROM in $(dmesg|grep -i "Attached scsi CD-ROM sr" | sed "s,.*Attached scsi CD-ROM ,,"); do echo "CDROM_${j}=/dev/${CDROM}" j="$( j + 1 )" done j=0 for FLOPPY in $(dmesg|grep -i "Floppy drive"|sed "s,.*(s): ,,;s, is .*,,"); do echo "FLOPPY_${j}=/dev/${FLOPPY}" j="$( j + 1 )" done # Serial ports echo "SERIAL_PORTS='$(dmesg | grep -Eo 'ttyS[0-9]+' | sed 's,^,/dev/,' | tr '\n' ' ')'" } >> "${VMCHOOSER_VIRT_CONF}" # ### redirect end # Parallel ports modprobe parport_pc ################################################################################ echo "Setup VM networking" ################################################################################ # there will be three types of network interfaces for virtual machines available # all will be configured for every type of virtualization tool # a) br0 is the direct host bridge into the local LAN (br0 already exists) # vmnet0 for VMware # vboxnet0 for VirtualBox # kvmnet0* for Qemu/KVM # b) nat1 is an internal bridge which "NATes" into the local LAN (with DHCP) # vmnet1 for VMware # vboxnet1 for VirtualBox # kvmnet1* for Qemu/KVM # c) vsw2 is an internal host bridge to connect software defined LANs to # vmnet2 for VMware # vboxnet2 for VirtualBox # kvmnet2* for Qemu/KVM # creating and configuring nat0 # 192.168.101.0/24 is vm nat. If you ever change this there are a couple of other files # where you'd need to make changes, so think twice before doing so. ;) brctl addbr nat1 ip link set dev nat1 up ip addr add 192.168.101.1/24 dev nat1 echo "1" >/proc/sys/net/ipv4/conf/nat1/forwarding echo "1" >/proc/sys/net/ipv4/conf/br0/forwarding 2>/dev/null # iptables masquerade rule is now inserted by /opt/openslx/iptables/rules.d/50-virt-nat1-masquerading FALLBACK_DOMAIN="virtual.localnet" getips () { [ -z "$1" ] && return [ "$1" = "$FALLBACK_DOMAIN" ] && return # Output in one line by using echo without quotes echo $(timeout -t 2 nslookup "$1" 2>/dev/null | grep -A 4 '^Name:' | grep -E '^Address\s*[0-9]*: ' | awk -F': ' '{print $2}' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | awk '{print $1}') } # read the DNS configuration and configure the udhcpd [ -z "${SLX_DNS}" ] && SLX_DNS="8.8.8.8 8.8.4.4" [ -z "${SLX_NET_DOMAIN}" ] && SLX_NET_DOMAIN="$FALLBACK_DOMAIN" [ -z "${SLX_NET_SEARCH}" ] && SLX_NET_SEARCH="$FALLBACK_DOMAIN" # WINS - if not supplied, try to get it from the search base of our ldap config if [ -z "${SLX_NET_WINS}" ]; then DC=$(grep -m1 -i '^BASE\s*DC=' "/etc/ldap.conf" | grep -o -i 'DC=.*' | sed -r 's/\s*,\s*DC=/./gI;s/^\s*DC=//I') [ -z "$DC" ] && DC=$(grep -m1 -i '^ldap_search_base\s*=\s*DC=' "/etc/sssd/sssd.conf" | grep -o -i 'DC=.*' | sed -r 's/\s*,\s*DC=/./gI;s/^\s*DC=//I') [ -n "$DC" ] && SLX_NET_WINS=$(getips "$DC") fi # NTP - default to pool.ntp.org NTPSRV= [ -z "$SLX_NTP_SERVER" ] && SLX_NTP_SERVER="pool.ntp.org" for ips in $SLX_NTP_SERVER; do if ! printf "%s" "$ips" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then ips="$( getips "$ips" )" [ -z "$ips" ] && continue fi NTPSRV="$NTPSRV $ips" done [ -z "$NTPSRV" ] && NTPSRV="0.0.0.0" [ -z "${SLX_NET_WINS}" ] && SLX_NET_WINS=$(getips "$SLX_NET_DOMAIN") [ -z "${SLX_NET_WINS}" ] && SLX_NET_WINS="0.0.0.0" sed "s#%DNSSERVER%#${SLX_DNS}#;s#%DOMAIN%#${SLX_NET_DOMAIN}#;s#%SEARCH%#${SLX_NET_SEARCH}#;s#%WINS%#${SLX_NET_WINS}#;s#%NTPSERVER%#${NTPSRV}#" "${DHCP_NAT_CONF}.template" > "${DHCP_NAT_CONF}" # Make sure the primary vm running (we most likely never run more than one at a time anyways) always gets the same ip echo "static_lease $(echo "$MACADDRPREFIX:$MACADDRSUFFIX" | sed 's/%VMID%/01/') 192.168.101.20" >> "${DHCP_NAT_CONF}" mkdir -p /var/lib/udhcpd # creating and configuring vsw2 brctl addbr vsw2 ip link set dev vsw2 up echo "1" >/proc/sys/net/ipv4/conf/vsw2/forwarding # estimate free mem during clean boot # TODO: Does that even make sense? We determine available memory during bootup and then blindly use # this value to configure the VM's memory size later on. Shouldn't we query this right before starting the VM? MEM_TOTAL="$( awk '{if ($1 == "MemAvailable:") { print $2; exit; }}' /proc/meminfo )" [ -z "$MEM_TOTAL" ] && MEM_TOTAL=2048000 echo "HOST_MEM_TOTAL=$(( MEM_TOTAL / 1024 ))" >> "${VMCHOOSER_VIRT_CONF}" exit 0