summaryrefslogtreecommitdiffstats
path: root/core/modules/run-virt/data/opt/openslx/vmchooser/run-virt-includes/set_runvirt_hardware_variables.inc
blob: 414c654a997da8b4f7300324acc1f58904e4febf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/bin/bash
###########################################
# 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 ;)

## Functions ##
# Import /run/hwinfo variables
import_hwinfo() {
	$(safesource "/run/hwinfo")
}
# 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"
}
# 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

	# Calculare amount of memory for the VM. Be generous if diff is written to HDD.
	# First, determine how much should be left to the host system. Minimum is 1GB.
	local min=1024
	local reserve max
	if $TMPDIR_IN_RAM; then
		# tmp in RAM, so reserve a lot for the system since that is where the HDD diff goes.
		reserve=65
		max=8192 # But max. 8GB
	else
		# We have a backing store for the HDD diff, be generous
		if lsmod | grep -q '^nvidia'; then
			# With nvidia cards, the host needs a bit more RAM.
			max=2800
			reserve=28
		else
			max=1800
			reserve=21
		fi
	fi

	# Calculate absulute amount of RAM that should stay available to the host
	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... 
}

# 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() {
	local i mac byte
	# 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"
	isset MACADDRPREFIX || writelog "No MAC address prefix was defined in ${VMCHOOSER_CONF_DIR}/virtualizer.conf"

	# 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"
	declare -g OTHER_NICS=
	# Set up additional NICs if enabled
	if [ "$SLX_BRIDGE_OTHER_NICS" = "yes" ]; then
		for i in /sys/class/net/br-nic-*/address; do
			[ -s "$i" ] || continue
			mac=$(tr '[a-f]' '[A-F]' < "$i")
			# Calc checksum of mac by summing the bytes mod 256
			byte=$(( $(<<<$mac sed 's/^/ ( 0x/;s/:/ + 0x/g;s/$/ ) % 256/') ))
			byte=$(printf "%02X" "$byte")
			# (PR:EF:IX):LA:ST:CH - use general prefix for VMs, then last two octets of source mac, plus the checksum
			mac="${MACADDRPREFIX}:${mac:12:5}:${byte}"
			OTHER_NICS+=" $mac"
		done
	fi
}

# Virtual fd/cd/dvd and drive devices, floppy b: for configuration
# If the variables in virtualization.conf is set, "TRUE" is assigned,
# "FALSE" otherwise.
check_optical_drives() {
	# TODO This should only handle exam mode here, maybe even have one function
	# that prepares all exam mode related stuff. Then create the TRUE/FALSE
	# variables somewhere in the vmware plugin, since it's specific to that
	# plugin.
	FLOPPY0="FALSE"
	CDROM0="FALSE"
	CDROM1="FALSE"
	if [ -z "$SLX_EXAM" ]; then
		if [ -n "$FLOPPY_0" ]; then
			FLOPPY0="TRUE"
		fi
		if [ -n "$CDROM_0" ]; then
			CDROM0="TRUE"
		fi
		if [ -n "$CDROM_1" ]; then
			CDROM1="TRUE"
		fi
	fi
	readonly FLOPPY0 CDROM0 CDROM1
}

# 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
set_serial_ports() {
	declare -g SERIAL0=
	#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
		SERIAL0="$PORT"
		break
	done

	declare -g PARALLEL0=
	for PORT in /dev/parport*; do
		[ -c "$PORT" ] || continue
		PARALLEL0="$PORT"
		break
	done

	readonly SERIAL0 PARALLEL0
}

## MAIN ##
call_post_source \
	import_hwinfo \
	set_virt_memory \
	set_virt_mac \
	set_virt_hostname \
	set_serial_ports \
	check_optical_drives