summaryrefslogtreecommitdiffstats
path: root/core/modules/hardware-stats/data/opt/openslx/scripts/cron-system_usage_update
blob: 1e82acbee438a88fdedb0a9b95d1e4129f965689 (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
#!/bin/bash
# Use bash not ash for >32bit arithmetic

touch /run/openslx || exit 1
full=false
[ "$1" = "--full" ] && full=true

[ -r "/etc/system-uuid" ] || exit 0

. /opt/openslx/config
[ -z "$SLX_REMOTE_LOG" ] && exit 0

UUID=$(cat "/etc/system-uuid")

[ -z "$UUID" ] && exit 1

USED=0
Name=

# detect if we need '--no-legend' or not...
LEGEND=
loginctl --help 2>&1 | grep -q -- '--no-legend' && LEGEND="--no-legend"
for SESSION in $(loginctl $LEGEND | awk '{print $1}'); do
	unset Display Remote State Class
	eval "$(loginctl -p Display -p Remote -p State -p Class -p Name show-session "$SESSION")"
	if [ "$Display" = ":0" ] && [ "$Remote" = "no" ] && [[ "$State" = "active" || "$State" = "online" ]] && [ "$Class" = "user" ]; then
		USED=1 # We only consider sessions on the primary display, which should always be the case
		break # keeps $Name set!
	fi
	unset Name
done

. "$( which slx-tools )"

# Also report usage of /tmp and swap
TMP="$( fs_path_space /tmp )"
TMP_FREE="${TMP% *}"
TMP_SIZE="${TMP#* }"
PERSISTENT_SIZE=0
PERSISTENT_FREE=0
if fs_path_ismountpoint /opt/openslx/persistent; then
	TMP="$( fs_path_space /opt/openslx/persistent )"
	ID45_FREE="${TMP% *}"
	ID45_SIZE="${TMP#* }"
fi

SWAP_SIZE=$( awk '{if ($1 == "SwapTotal:") { print $2; exit; }}' /proc/meminfo )
SWAP_FREE=$( awk '{if ($1 == "SwapFree:") { print $2; exit; }}' /proc/meminfo )
MEM_SIZE=$( awk '{if ($1 == "MemTotal:") { print $2; exit; }}' /proc/meminfo )
MEM_FREE=$( awk '{if ($1 == "MemAvailable:") { print $2; exit; }}' /proc/meminfo )
if [ -z "$MEM_FREE" ]; then
	MEM_FREE=$( awk 'BEGIN{n=0}{if ($1 == "MemFree:" || $1 == "Buffers:" || $1 == "Cached:") n += $2}END{print n}' /proc/meminfo )
fi
# CPU temp and load
set --
if $full; then
	current="$( awk '$1 == "cpu" {printf "%.0f %.0f", ($5+$6), ($2+$3+$4+$5+$6+$7+$8)}' /proc/stat )"
	c_count=${current#* }
	write=false
	if [ -s "/run/openslx/usage.state" ]; then
		old="$( cat "/run/openslx/usage.state" )"
		l_count="${old#* }"
		# sloppy way to prevent rapid updates; counter speed varies depending on HZ and core count
		if [ "$(( c_count - l_count ))" -gt 12000 ]; then
			write=true
			set -- "$@" "--data-urlencode" "cpuload=$( echo "$current $old" | awk '{ print (100 - ($1 - $3)/($2 - $4) * 100) }' )"
		fi
	else
		write=true
	fi
	if $write; then
		echo "$current" > "/run/openslx/usage.state"
	fi
	if command -v sensors > /dev/null; then
		# TODO JSON support arrived recently, port after base system is updated from 18.04
		# Try to get the package id reading, use core temps as fallback
		set -- "$@" "--data-urlencode" "cputemp=$( sensors | tr 'A-Z' 'a-z' \
			| awk 'BEGIN{p=0;pc=0;c=0;cc=0;tctl=0} {
					if ($1 == "package" && substr($4, 1, 1) == "+") {
						gsub("[^0-9.]", "", $4);
						p += $4;
						pc++;
					} else if ($1 ~ /^core/ && substr($3, 1, 1) == "+") {
						gsub("[^0-9.]", "", $3);
						c += $3;
						cc++;
					} else if ($1 ~ /^tctl:/ && substr($2, 1, 1) == "+") {
						gsub("[^0-9.]", "", $2);
						tctl = $2;
					}
			} END {
				if (pc > 0) print (p / pc);
				else if (cc > 0) print (c / cc);
				else if (tctl > 0) print (tctl);
			}' )"
	fi
fi

# Bail out if we already sent the shutdown event to server
# or if the cron-job hasn't been set up yet.
# Do this right before the curl call to minimize odds for a race condition
if [ -e "/etc/cron.d/usage_stats" ] && ! [ -e "/run/openslx/shutdown.mutex" ]; then
	curl --retry 3 --retry-connrefused --connect-timeout 3 --max-time 15 --retry-max-time 20 -sS \
		--data-urlencode "type=~runstate" --data-urlencode "uuid=$UUID" \
		--data-urlencode "used=$USED" \
		--data-urlencode "user=$Name" --data-urlencode "tmpsize=$TMP_SIZE" --data-urlencode "tmpfree=$TMP_FREE" \
		--data-urlencode "id45size=$ID45_SIZE" --data-urlencode "id45free=$ID45_FREE" \
		--data-urlencode "swapsize=$SWAP_SIZE" --data-urlencode "swapfree=$SWAP_FREE" \
		--data-urlencode "memsize=$MEM_SIZE" --data-urlencode "memfree=$MEM_FREE" \
		"$@" \
		"$SLX_REMOTE_LOG" | grep -v 'RESULT=0'
fi

# Warn user if tmp or swap usage is high; system might crash soon

# ..but not if flag to shut up is present
[ -e "/run/openslx/no-ram-warning" ] && exit 0

WARN=
memfreep=$(( MEM_FREE / (MEM_SIZE / 100) ))
swapratio=$(( (SWAP_SIZE - SWAP_FREE) * 100 / MEM_FREE ))
if (( SWAP_SIZE > 0 && SWAP_FREE < 500000 && (memfreep < 10 || swapratio > 100) )) || # less than 500MB swap free and (memfree < 10% or more swap usage than free memory)
	(( SWAP_SIZE == 0 && MEM_FREE < 1200000 )); then # no swap and less than 1.2GB available
	WARN="$WARN
Der Arbeitsspeicher des Computers ist fast voll.
The computer is running out of RAM."
fi
if [ -n "$TMP_FREE" ] && [ "$TMP_FREE" -lt 500000 ]; then
	WARN="$WARN
Es verbleibt wenig temporärer Speicher für die Arbeitsdaten der laufenden VM.
Little temporary storage is left for the current VM."
fi

if [ -n "$WARN" ]; then
	WARN="$WARN

Bitte sichern Sie Ihre Arbeit und starten Sie den PC neu.
Please save your work and reboot this machine.

Sie können einen bwLehrpool-Admin bitten, eine größere ID-44-Partition einzurichten.
You could ask a bwLehrpool administrator to create a larger ID-44 partition."
	idle-daemon --send "warn $WARN"
fi

exit 0