diff options
Diffstat (limited to 'modules-available/dozmod/api.inc.php')
-rw-r--r-- | modules-available/dozmod/api.inc.php | 107 |
1 files changed, 70 insertions, 37 deletions
diff --git a/modules-available/dozmod/api.inc.php b/modules-available/dozmod/api.inc.php index d9f7354c..b5030cc5 100644 --- a/modules-available/dozmod/api.inc.php +++ b/modules-available/dozmod/api.inc.php @@ -10,6 +10,8 @@ **/ +use JetBrains\PhpStorm\NoReturn; + if (!Module::isAvailable('locations')) { die('require locations module'); } @@ -17,27 +19,30 @@ if (!Module::isAvailable('locations')) { define('LIST_URL', CONFIG_DOZMOD_URL . '/vmchooser/list'); define('VMX_URL', CONFIG_DOZMOD_URL . '/vmchooser/lecture'); -$availableRessources = ['list', 'vmx', 'netrules', 'runscript', 'metadata', 'netshares']; +$availableRessources = ['list', 'netrules', 'metadata', 'imagemeta']; /* BEGIN: A simple caching mechanism ---------------------------- */ -function cache_hash($obj) +function cache_hash($obj): string { return md5(serialize($obj)); } -function cache_key_to_filename($key) +function cache_key_to_filename(string $key): string { return "/tmp/bwlp-slxadmin-cache-$key"; } -function cache_put($key, $value) +function cache_put(string $key, string $value): void { $filename = cache_key_to_filename($key); - file_put_contents($filename, $value); + // Try to avoid another client concurrently accessing the cache seeing an empty file + $tmp = $filename . '-' . mt_rand(); + file_put_contents($tmp, $value); + rename($tmp, $filename); } -function cache_has($key) +function cache_has(string $key): bool { $filename = cache_key_to_filename($key); $mtime = @filemtime($filename); @@ -46,21 +51,18 @@ function cache_has($key) return false; // cache miss } $now = time(); - if ($now < $mtime || $now - $mtime > CONFIG_DOZMOD_EXPIRE) { - return false; - } else { - return true; - } + return $now >= $mtime && $now - $mtime <= CONFIG_DOZMOD_EXPIRE; } -function cache_get($key) +function cache_get(string $key): string { $filename = cache_key_to_filename($key); return file_get_contents($filename); } /* good for large binary files */ -function cache_get_passthru($key) +#[NoReturn] +function cache_get_passthru(string $key): void { $filename = cache_key_to_filename($key); $fp = fopen($filename, "r"); @@ -68,7 +70,7 @@ function cache_get_passthru($key) fpassthru($fp); exit; } - error_log('Cannot passthrough cache file ' . $filename); + error_log('DMSD-cache: Cannot passthrough cache file ' . $filename); } /* END: Cache ---------------------------------------------------- */ @@ -76,7 +78,7 @@ function cache_get_passthru($key) /* this script requires 2 (3 with implicit client ip) parameters * -* resource = vmx,... +* resource = list,metadata,... * lecture_uuid = client can choose **/ @@ -85,11 +87,16 @@ function cache_get_passthru($key) * Takes raw lecture list xml, returns array of uuids. * * @param string $responseXML XML from dozmod server - * @return array list of UUIDs, false on error + * @return array list of UUIDs */ -function xmlToLectureIds($responseXML) +function xmlToLectureIds(string $responseXML): array { - $xml = new SimpleXMLElement($responseXML); + try { + $xml = new SimpleXMLElement($responseXML); + } catch (Exception $e) { + EventLog::warning('Error parsing XML response data from DMSD: ' . $e->getMessage(), $responseXML); + return []; + } if (!isset($xml->eintrag)) return []; @@ -102,7 +109,8 @@ function xmlToLectureIds($responseXML) return $uuids; } -function sendExamModeMismatch() +#[NoReturn] +function sendExamModeMismatch(): void { Header('Content-Type: text/xml; charset=utf-8'); echo @@ -112,8 +120,8 @@ function sendExamModeMismatch() <image_name param="null"/> <priority param="100"/> <creator param="Ernie Esslingen"/> - <short_description param="Klausurmodus geändert, bitte PC neustarten"/> - <long_description param="Der Klausurmodus wurde ein- oder ausgeschaltet, bitte starten Sie den PC neu"/> + <short_description param="Prüfungsmodus geändert, bitte PC neustarten"/> + <long_description param="Der Prüfungsmodus wurde ein- oder ausgeschaltet, bitte starten Sie den PC neu"/> <uuid param="exam-mode-warning"/> <virtualmachine param="exam-mode-warning"/> <os param="debian8"/> @@ -142,7 +150,7 @@ BLA; } /** Caching wrapper around _getLecturesForLocations() */ -function getListForLocations($locationIds, $raw) +function getListForLocations(array $locationIds, bool $raw) { /* if in any of the locations there is an exam active, consider the client to be in "exam-mode" and only offer him exams (no lectures) */ @@ -179,7 +187,12 @@ function getListForLocations($locationIds, $raw) if ($examMode) { $url .= '&exams'; } + $t = microtime(true); $value = Download::asString($url, 60, $code); + $t = microtime(true) - $t; + if ($t > 5) { + error_log("DMSD-cache: Download of lecture list took $t ($code)"); + } if ($value === false || $code < 200 || $code > 299) return false; cache_put($rawKey, $value); @@ -191,30 +204,37 @@ function getListForLocations($locationIds, $raw) return $list; } -function getLectureUuidsForLocations($locationIds) +function getLectureUuidsForLocations(array $locationIds) { return getListForLocations($locationIds, false); } -function outputLectureXmlForLocation($locationIds) +function outputLectureXmlForLocation(array $locationIds) { return getListForLocations($locationIds, true); } -function _getVmData($lecture_uuid, $subResource = false) +function _getVmData(string $lecture_uuid, string $subResource = null) { $url = VMX_URL . '/' . $lecture_uuid; - if ($subResource !== false) { + if ($subResource !== null) { $url .= '/' . $subResource; } + $t = microtime(true); $response = Download::asString($url, 60, $code); - if ($code < 200 || $code > 299) + $t = microtime(true) - $t; + if ($t > 5) { + error_log("DMSD-cache: Download of $subResource took $t ($code)"); + } + if ($code < 200 || $code > 299) { + error_log("DMSD-cache: Return code $code, payload len " . strlen($response)); return (int)$code; + } return $response; } /** Caching wrapper around _getVmData() **/ -function outputResource($lecture_uuid, $resource) +function outputResource(string $lecture_uuid, string $resource): void { if ($resource === 'metadata') { // HACK: config.tgz is compressed, don't use gzip output handler @@ -235,7 +255,7 @@ function outputResource($lecture_uuid, $resource) } else { $value = _getVmData($lecture_uuid, $resource); if ($value === false) - return false; + return; if (is_int($value)) { http_response_code($value); exit; @@ -243,16 +263,16 @@ function outputResource($lecture_uuid, $resource) cache_put($key, $value); die($value); } - return false; } +#[NoReturn] function fatalDozmodUnreachable() { Header('HTTP/1.1 504 Gateway Timeout'); die('DMSD currently not available'); } -function readLectureParam($locationIds) +function readLectureParam(array $locationIds): string { $lecture = Request::get('lecture', false, 'string'); if ($lecture === false) { @@ -272,12 +292,26 @@ function readLectureParam($locationIds) } +// in this context the lecture param is an image id (container), +// just read and check if valid. +// TODO do we need to check if this is allowed? +function readImageParam(): string +{ + $image = Request::get('lecture', false, 'string'); + + if ($image === false) { + Header('HTTP/1.1 400 Bad Request'); + die('Missing IMAGE UUID'); + } + return $image; +} + // -----------------------------------------------------------------------------// /* request data, don't trust */ $resource = Request::get('resource', false, 'string'); if ($resource === false) { - Util::traceError("you have to specify the 'resource' parameter"); + ErrorHandler::traceError("you have to specify the 'resource' parameter"); } if (!in_array($resource, $availableRessources)) { @@ -298,12 +332,11 @@ $location_ids = Location::getLocationRootChain($location_ids); if ($resource === 'list') { outputLectureXmlForLocation($location_ids); // Won't return on success... - fatalDozmodUnreachable(); +} elseif ($resource === 'imagemeta') { + $image = readImageParam(); + outputResource($image, $resource); } else { $lecture = readLectureParam($location_ids); outputResource($lecture, $resource); - fatalDozmodUnreachable(); } - -Header('HTTP/1.1 400 Bad Request'); -die("I don't know how to give you that resource"); +fatalDozmodUnreachable(); |