summaryrefslogtreecommitdiffstats
path: root/modules-available/vmstore/inc/vmstorebenchmark.inc.php
blob: 10c55431109d99584067b216c5a4eb15bf1a5e22 (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
<?php

class VmStoreBenchmark
{

	const PROP_LIST_KEY = 'vmstore.benchmark';

	/**
	 * @param string[] $machineUuids List of UUIDs
	 * @return void
	 */
	public static function prepareSelectDialog(array $uuids)
	{
		Module::isAvailable('rebootcontrol');
		User::assertPermission('.vmstore.benchmark');
		$uuids = array_values(Request::post('uuid', Request::REQUIRED, 'array'));
		$machines = RebootUtils::getFilteredMachineList($uuids, '.vmstore.benchmark');
		if ($machines === false)
			return;
		$machines = array_column($machines, 'machineuuid');
		$id = Property::addToList(self::PROP_LIST_KEY,
			json_encode(['machines' => $machines]), 60);
		Util::redirect('?do=vmstore&show=benchmark&action=select&id=' . $id);
	}

	/**
	 * @param array $machineUuids
	 * @param string $image
	 * @param bool $nfs
	 * @param int $start timestamp when the clients should start
	 * @return ?string taskId, or null on error
	 */
	public static function start(string $id, array $machineUuids, string $image, bool $nfs, int &$start)
	{
		Module::isAvailable('rebootcontrol');
		$clients = Database::queryAll('SELECT machineuuid, clientip FROM machine WHERE machineuuid IN (:uuids)',
			['uuids' => $machineUuids]);
		if (empty($clients)) {
			ErrorHandler::traceError('Cannot start benchmark: No matching clients');
		}
		// The more clients we have, the longer it takes to SSH into all of them.
		// As of 2022, RemoteExec processes 4 clients in parallel
		$start = ceil(count($clients) / 4 + 5 + time());
		$nfsOpt = $nfs ? '--nfs' : '';
		// We fork off the benchmark into the background, and collect the results with another RemoteExec job
		// when we're done. This is because RemoteExec only does four concurrent SSH connections, so if we wanted to
		// do this the easy, synchronous way, we never could run more than four tests at the same time.
		$command = <<<COMMAND
(
exec &> /dev/null < /dev/null
setsid
image_speedcheck --start $start --console $nfsOpt --file "$image" > "/tmp/speedcheck-$id"
) &
COMMAND;
		$task = RebootControl::runScript($clients, $command);
		return $task['id'] ?? null;
	}

	public static function parseBenchLine(string $line): array
	{
		$out = ['cpu' => [], 'net' => []];
		foreach (explode(',', $line) as $elem) {
			$elem = explode('+', $elem);
			$out['net'][] = ['x' => (int)$elem[0], 'y' => (int)$elem[1]];
			//$out['cpu'][] = ['x' => $elem[0], 'y' => $elem[2]];
		}
		return $out;
	}

}