1 | <?php |
---|
2 | /** |
---|
3 | * @file remotepc.php |
---|
4 | * @brief OpenGnsys Server REST API consumed by UDS Server for Remote PC implementation. |
---|
5 | * @warning All input and output messages are formatted in JSON. |
---|
6 | * @note Some ideas are based on article "How to create REST API for Android app using PHP, Slim and MySQL" by Ravi Tamada, thanx. |
---|
7 | * @license GNU GPLv3+ |
---|
8 | * @author Ramón M. Gómez, ETSII Univ. Sevilla |
---|
9 | * @version 1.1.0 - First version |
---|
10 | * @date 2017-02-01 |
---|
11 | */ |
---|
12 | |
---|
13 | // OGAgent sessions log file. |
---|
14 | define('REMOTEPC_LOGFILE', '/opt/opengnsys/log/remotepc.log'); |
---|
15 | |
---|
16 | // Function to write a line into log file. |
---|
17 | function writeRemotepcLog($message = "") { |
---|
18 | file_put_contents(REMOTEPC_LOGFILE, date(DATE_ISO8601).": $message\n", FILE_APPEND); |
---|
19 | } |
---|
20 | |
---|
21 | |
---|
22 | // REST routes. |
---|
23 | |
---|
24 | /** |
---|
25 | * @brief Reserve a client with an installed image and the older reservation time, then send a boot/reboot operation depending on its status. |
---|
26 | * @warning If "lab" parameter is specified, then choose a client from this lab. |
---|
27 | * @note Route: /ous/:ouid/images/:imageid/reserve, Method: POST |
---|
28 | * @param integer ouid OU identificator |
---|
29 | * @param integer imageid image identificator |
---|
30 | * @note Input JSON message: {"labid":int_labid,"maxtime":int_hours} |
---|
31 | */ |
---|
32 | $app->post('/ous/:ouid/images/:imageid/reserve(/)', 'validateApiKey', |
---|
33 | function($ouid, $imageid) use ($app) { |
---|
34 | global $cmd; |
---|
35 | global $AMBITO_ORDENADORES; |
---|
36 | global $EJECUCION_COMANDO; |
---|
37 | global $ACCION_INICIADA; |
---|
38 | global $ACCION_FINALIZADA; |
---|
39 | global $ACCION_SINRESULTADO; |
---|
40 | global $ACCION_FALLIDA; |
---|
41 | global $userid; |
---|
42 | $response = Array(); |
---|
43 | $ogagent = Array(); |
---|
44 | $repo = Array(); |
---|
45 | |
---|
46 | if ($app->settings['debug']) |
---|
47 | writeRemotepcLog($app->request()->getResourceUri(). ": Init."); |
---|
48 | // Checking parameters. |
---|
49 | try { |
---|
50 | if (empty(preg_match('/^python-requests\//', $_SERVER['HTTP_USER_AGENT']))) { |
---|
51 | throw new Exception("Bad agent: sender=".$_SERVER['REMOTE_ADDR'].", agent=".$_SERVER['HTTP_USER_AGENT']); |
---|
52 | } |
---|
53 | if (!checkIds($ouid, $imageid)) { |
---|
54 | throw new Exception("Ids. must be positive integers"); |
---|
55 | } |
---|
56 | // Reading POST parameters in JSON format. |
---|
57 | $input = json_decode($app->request()->getBody()); |
---|
58 | // Default: no lab. filter. |
---|
59 | if (isset($input->labid)) { |
---|
60 | $labid = $input->labid != "0" ? $input->labid : '%'; |
---|
61 | } else { |
---|
62 | $labid = '%'; |
---|
63 | } |
---|
64 | $maxtime = isset($input->maxtime) ? $input->maxtime : 24; // Default: 24 h. |
---|
65 | $opts = Array('options' => Array('min_range' => 1)); // Check for int>0 |
---|
66 | if (filter_var($labid, FILTER_VALIDATE_INT, $opts) === false and $labid !== '%') { |
---|
67 | throw new Exception("Lab id. must be positive integer"); |
---|
68 | } |
---|
69 | if (filter_var($maxtime, FILTER_VALIDATE_INT, $opts) === false) { |
---|
70 | throw new Exception("Time must be positive integer (in hours)"); |
---|
71 | } |
---|
72 | } catch (Exception $e) { |
---|
73 | // Communication error. |
---|
74 | $response["message"] = $e->getMessage(); |
---|
75 | if ($app->settings['debug']) |
---|
76 | writeRemotepcLog($app->request()->getResourceUri(). ": ERROR: ".$response["message"]."."); |
---|
77 | jsonResponse(400, $response); |
---|
78 | $app->stop(); |
---|
79 | } |
---|
80 | |
---|
81 | if ($app->settings['debug']) |
---|
82 | writeRemotepcLog($app->request()->getResourceUri(). ": Parameters: labid=$labid, maxtime=$maxtime"); |
---|
83 | // Choose older not-reserved client with image installed and get ogAdmServer data. |
---|
84 | $cmd->texto = <<<EOD |
---|
85 | SELECT adm.idusuario, ordenadores.idordenador, ordenadores.nombreordenador, ordenadores.ip, |
---|
86 | ordenadores.mac, ordenadores.agentkey, par.numdisk, par.numpar, |
---|
87 | aulas.idaula, aulas.idcentro, repo.ip AS repoip, repo.apikey AS repokey |
---|
88 | FROM ordenadores |
---|
89 | JOIN aulas USING(idaula) |
---|
90 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
91 | RIGHT JOIN usuarios USING(idusuario) |
---|
92 | RIGHT JOIN ordenadores_particiones AS par USING(idordenador) |
---|
93 | RIGHT JOIN imagenes USING(idimagen) |
---|
94 | RIGHT JOIN repositorios AS repo ON repo.idrepositorio = ordenadores.idrepositorio |
---|
95 | LEFT JOIN remotepc ON remotepc.id=ordenadores.idordenador |
---|
96 | WHERE adm.idusuario = '$userid' |
---|
97 | AND aulas.idcentro = '$ouid' AND aulas.idaula LIKE '$labid' AND aulas.inremotepc = 1 |
---|
98 | AND ordenadores.maintenance = 0 |
---|
99 | AND imagenes.idimagen = '$imageid' AND imagenes.inremotepc = 1 |
---|
100 | AND (remotepc.reserved < NOW() OR ISNULL(reserved)) |
---|
101 | ORDER BY RAND() LIMIT 1; |
---|
102 | EOD; |
---|
103 | $rs=new Recordset; |
---|
104 | $rs->Comando=&$cmd; |
---|
105 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
106 | // Check if user is admin and client exists. |
---|
107 | $rs->Primero(); |
---|
108 | if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idordenador"])) { |
---|
109 | // Read query data. |
---|
110 | $clntid = $rs->campos["idordenador"]; |
---|
111 | $clntname = $rs->campos["nombreordenador"]; |
---|
112 | $clntip = $rs->campos["ip"]; |
---|
113 | $clntmac = $rs->campos["mac"]; |
---|
114 | $agentkey = $rs->campos["agentkey"]; |
---|
115 | $disk = $rs->campos["numdisk"]; |
---|
116 | $part = $rs->campos["numpar"]; |
---|
117 | $labid = $rs->campos["idaula"]; |
---|
118 | $ouid = $rs->campos["idcentro"]; |
---|
119 | $repoip = $rs->campos["repoip"]; |
---|
120 | $repokey = $rs->campos["repokey"]; |
---|
121 | // Check client's status. |
---|
122 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/status"; |
---|
123 | if ($app->settings['debug']) |
---|
124 | writeRemotepcLog($app->request()->getResourceUri(). ": OGAgent status, url=".$ogagent[$clntip]['url']."."); |
---|
125 | $result = multiRequest($ogagent); |
---|
126 | if (empty($result[$clntip]['data'])) { |
---|
127 | // Client is off, send WOL command to ogAdmServer. |
---|
128 | // TODO: if client is busy????? |
---|
129 | if ($app->settings['debug']) |
---|
130 | writeRemotepcLog($app->request()->getResourceUri(). ": Send boot command through ogAdmServer: iph=$clntip,mac=$clntmac."); |
---|
131 | wol(1, [$clntmac], [$clntip]); |
---|
132 | // Send WOL command to client repository. |
---|
133 | $repo[$repoip]['url'] = "https://$repoip/opengnsys/rest/repository/poweron"; |
---|
134 | $repo[$repoip]['header'] = Array("Authorization: ".$repokey); |
---|
135 | $repo[$repoip]['post'] = '{"macs": ["'.$clntmac.'"], "ips": ["'.$clntip.'"]}'; |
---|
136 | if ($app->settings['debug']) |
---|
137 | writeRemotepcLog($app->request()->getResourceUri(). ": Send Boot command through repo: repo=$repoip, ip=$clntip,mac=$clntmac."); |
---|
138 | $result = multiRequest($repo); |
---|
139 | // ... (check response) |
---|
140 | //if ($result[$repoip]['code'] != 200) { |
---|
141 | // ... |
---|
142 | } else { |
---|
143 | // Client is on, send a rieboot command to its OGAgent. |
---|
144 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/reboot"; |
---|
145 | $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey); |
---|
146 | if ($app->settings['debug']) |
---|
147 | writeRemotepcLog($app->request()->getResourceUri(). ": OGAgent reboot, url=".$ogagent[$clntip]['url']."."); |
---|
148 | $result = multiRequest($ogagent); |
---|
149 | // ... (check response) |
---|
150 | //if ($result[$clntip]['code'] != 200) { |
---|
151 | // ... |
---|
152 | } |
---|
153 | // DB Transaction: mark choosed client as reserved and |
---|
154 | // create an init session command into client's actions queue. |
---|
155 | $cmd->texto = "START TRANSACTION;"; |
---|
156 | $cmd->Ejecutar(); |
---|
157 | $timestamp = time(); |
---|
158 | $cmd->texto = <<<EOD |
---|
159 | INSERT INTO remotepc |
---|
160 | SET id='$clntid', reserved=NOW() + INTERVAL $maxtime HOUR, urllogin=NULL, urllogout=NULL |
---|
161 | ON DUPLICATE KEY UPDATE |
---|
162 | id=VALUES(id), reserved=VALUES(reserved), |
---|
163 | urllogin=VALUES(urllogin), urllogout=VALUES(urllogout); |
---|
164 | EOD; |
---|
165 | $t1 = $cmd->Ejecutar(); |
---|
166 | $cmd->texto = <<<EOD |
---|
167 | INSERT INTO acciones |
---|
168 | SET tipoaccion=$EJECUCION_COMANDO, |
---|
169 | idtipoaccion=9, |
---|
170 | idcomando=9, |
---|
171 | parametros='nfn=IniciarSesion\rdsk=$disk\rpar=$part', |
---|
172 | descriaccion='RemotePC Session', |
---|
173 | idordenador=$clntid, |
---|
174 | ip='$clntip', |
---|
175 | sesion=$timestamp, |
---|
176 | fechahorareg=NOW(), |
---|
177 | estado=$ACCION_INICIADA, |
---|
178 | resultado=$ACCION_SINRESULTADO, |
---|
179 | ambito=$AMBITO_ORDENADORES, |
---|
180 | idambito=$clntid, |
---|
181 | restrambito='$clntip', |
---|
182 | idcentro=$ouid; |
---|
183 | EOD; |
---|
184 | $t2 = $cmd->Ejecutar(); |
---|
185 | // Create event to remove reservation on timeout (15 min.). |
---|
186 | $timeout = "15 MINUTE"; |
---|
187 | $cmd->texto = <<<EOD |
---|
188 | CREATE EVENT e_timeout_$clntid |
---|
189 | ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL $timeout DO |
---|
190 | BEGIN |
---|
191 | SET @action_id = NULL; |
---|
192 | UPDATE acciones |
---|
193 | SET estado = $ACCION_FINALIZADA, resultado = $ACCION_FALLIDA, |
---|
194 | descrinotificacion = 'Timeout' |
---|
195 | WHERE descriaccion = 'RemotePC Session' AND estado = $ACCION_INICIADA |
---|
196 | AND idordenador = '$clntid' |
---|
197 | AND (SELECT @action_id := idaccion); |
---|
198 | IF @action_id IS NOT NULL THEN |
---|
199 | UPDATE remotepc |
---|
200 | SET reserved=NOW() - INTERVAL 1 SECOND, urllogin=NULL, urllogout=NULL |
---|
201 | WHERE id = '$clntid'; |
---|
202 | DELETE FROM acciones |
---|
203 | WHERE idaccion = @action_id; |
---|
204 | END IF; |
---|
205 | END |
---|
206 | EOD; |
---|
207 | // #839 Fixes problem of expulsion of the user from the session at 15min |
---|
208 | $t3=1; //$t3 = $cmd->Ejecutar(); |
---|
209 | if ($t1 and $t2 and $t3) { |
---|
210 | // Commit transaction on success. |
---|
211 | $cmd->texto = "COMMIT;"; |
---|
212 | $cmd->Ejecutar(); |
---|
213 | if ($app->settings['debug']) |
---|
214 | writeRemotepcLog($app->request()->getResourceUri(). ": DB tables and events updated, clntid=$clntid."); |
---|
215 | // Send init session command if client is booted on ogLive. |
---|
216 | if ($app->settings['debug']) |
---|
217 | writeRemotepcLog($app->request()->getResourceUri(). ": Send Init Session command to ogAdmClient, ido=$clntid,iph=$clntip,dsk=$disk,par=$part."); |
---|
218 | session($clntip, "$disk\r$part"); |
---|
219 | // Compose JSON response. |
---|
220 | $response['id'] = (int)$clntid; |
---|
221 | $response['name'] = $clntname; |
---|
222 | $response['ip'] = $clntip; |
---|
223 | $response['mac'] = $clntmac; |
---|
224 | $response['lab']['id'] = $labid; |
---|
225 | $response['ou']['id'] = (int)$ouid; |
---|
226 | if ($app->settings['debug']) |
---|
227 | writeRemotepcLog($app->request()->getResourceUri(). ": Response, ".var_export($response,true)."."); |
---|
228 | jsonResponse(200, $response); |
---|
229 | } else { |
---|
230 | // Roll-back transaction on DB error. |
---|
231 | $cmd->texto = "ROLLBACK;"; |
---|
232 | $cmd->Ejecutar(); |
---|
233 | // Error message. |
---|
234 | $response["message"] = "Database error: $t1, $t2, $t3"; |
---|
235 | if ($app->settings['debug']) |
---|
236 | writeRemotepcLog($app->request()->getResourceUri(). ": ERROR: ".$response["message"]."."); |
---|
237 | jsonResponse(400, $response); |
---|
238 | } |
---|
239 | } else { |
---|
240 | if ($app->settings['debug']) |
---|
241 | writeRemotepcLog($app->request()->getResourceUri(). ": UNASSIGNED"); |
---|
242 | } |
---|
243 | $rs->Cerrar(); |
---|
244 | $app->stop(); |
---|
245 | } |
---|
246 | ); |
---|
247 | |
---|
248 | |
---|
249 | /** |
---|
250 | * @brief Store UDS server URLs to resend some events recieved from OGAgent. |
---|
251 | * @note Route: /ous/:ouid/labs/:labid/clients/:clntid/events, Method: POST |
---|
252 | * @param string urlLogin URL to redirect login notification. |
---|
253 | * @param string urlLogout URL to redirect logout notification. |
---|
254 | * @warning Events parameters will be stored in a new "remotepc" table. |
---|
255 | */ |
---|
256 | $app->post('/ous/:ouid/labs/:labid/clients/:clntid/events', 'validateApiKey', |
---|
257 | function($ouid, $labid, $clntid) use ($app) { |
---|
258 | global $cmd; |
---|
259 | global $userid; |
---|
260 | $response = Array(); |
---|
261 | |
---|
262 | if ($app->settings['debug']) |
---|
263 | writeRemotepcLog($app->request()->getResourceUri(). ": Init."); |
---|
264 | // Checking parameters. |
---|
265 | try { |
---|
266 | if (empty(preg_match('/^python-requests\//', $_SERVER['HTTP_USER_AGENT']))) { |
---|
267 | throw new Exception("Bad agent: sender=".$_SERVER['REMOTE_ADDR'].", agent=".$_SERVER['HTTP_USER_AGENT']); |
---|
268 | } |
---|
269 | if (!checkIds($ouid, $labid, $clntid)) { |
---|
270 | throw new Exception("Ids. must be positive integers"); |
---|
271 | } |
---|
272 | // Reading JSON parameters. |
---|
273 | $input = json_decode($app->request()->getBody()); |
---|
274 | $urlLogin = htmlspecialchars($input->urlLogin); |
---|
275 | $urlLogout = htmlspecialchars($input->urlLogout); |
---|
276 | if (filter_var($urlLogin, FILTER_VALIDATE_URL) === false) { |
---|
277 | throw new Exception("Must be a valid URL for login notification"); |
---|
278 | } |
---|
279 | if (filter_var($urlLogout, FILTER_VALIDATE_URL) === false) { |
---|
280 | throw new Exception("Must be a valid URL for logout notification"); |
---|
281 | } |
---|
282 | } catch (Exception $e) { |
---|
283 | // Error message. |
---|
284 | $response["message"] = $e->getMessage(); |
---|
285 | if ($app->settings['debug']) |
---|
286 | writeRemotepcLog($app->request()->getResourceUri(). ": ERROR: ".$response["message"]."."); |
---|
287 | jsonResponse(400, $response); |
---|
288 | $app->stop(); |
---|
289 | } |
---|
290 | |
---|
291 | if ($app->settings['debug']) |
---|
292 | writeRemotepcLog($app->request()->getResourceUri(). ": Parameters: urlLogin=$urlLogin, urlLogout=$urlLogout"); |
---|
293 | // Select client data for UDS compatibility. |
---|
294 | $cmd->texto = <<<EOD |
---|
295 | SELECT adm.idusuario, ordenadores.idordenador, remotepc.* |
---|
296 | FROM remotepc |
---|
297 | RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador |
---|
298 | JOIN aulas USING(idaula) |
---|
299 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
300 | RIGHT JOIN usuarios USING(idusuario) |
---|
301 | WHERE adm.idusuario = '$userid' |
---|
302 | AND idcentro = '$ouid' AND aulas.idaula ='$labid' |
---|
303 | AND ordenadores.idordenador = '$clntid'; |
---|
304 | EOD; |
---|
305 | $rs=new Recordset; |
---|
306 | $rs->Comando=&$cmd; |
---|
307 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
308 | // Check if user is admin and client exists. |
---|
309 | $rs->Primero(); |
---|
310 | if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idordenador"])) { |
---|
311 | // Check if client is reserved. |
---|
312 | if (! is_null($rs->campos["reserved"])) { |
---|
313 | // Updating DB if client is reserved. |
---|
314 | $cmd->CreaParametro("@urllogin", $urlLogin, 0); |
---|
315 | $cmd->CreaParametro("@urllogout", $urlLogout, 0); |
---|
316 | $cmd->texto = <<<EOD |
---|
317 | UPDATE remotepc |
---|
318 | SET urllogin=@urllogin, urllogout=@urllogout |
---|
319 | WHERE id='$clntid'; |
---|
320 | EOD; |
---|
321 | if ($cmd->Ejecutar()) { |
---|
322 | // Confirm operation. |
---|
323 | $response = ""; |
---|
324 | jsonResponse(200, $response); |
---|
325 | } else { |
---|
326 | // Error message. |
---|
327 | $response["message"] = "Database error"; |
---|
328 | jsonResponse(400, $response); |
---|
329 | } |
---|
330 | } else { |
---|
331 | // Error message. |
---|
332 | $response["message"] = "Client is not reserved"; |
---|
333 | jsonResponse(400, $response); |
---|
334 | } |
---|
335 | } |
---|
336 | $rs->Cerrar(); |
---|
337 | $app->stop(); |
---|
338 | } |
---|
339 | ); |
---|
340 | |
---|
341 | |
---|
342 | /* |
---|
343 | * @brief Store session time (in sec). |
---|
344 | * @note Route: /ous/:ouid/labs/:labid/clients/:clntid/session, Method: POST |
---|
345 | * @param int deadLine maximum session time, in seconds (0 for unlimited) |
---|
346 | * @warning Parameters will be stored in a new "remotepc" table. |
---|
347 | */ |
---|
348 | $app->post('/ous/:ouid/labs/:labid/clients/:clntid/session', 'validateApiKey', |
---|
349 | function($ouid, $labid, $clntid) use ($app) { |
---|
350 | global $cmd; |
---|
351 | global $userid; |
---|
352 | $response = Array(); |
---|
353 | |
---|
354 | if ($app->settings['debug']) |
---|
355 | writeRemotepcLog($app->request()->getResourceUri(). ": Init."); |
---|
356 | // Checking parameters. |
---|
357 | try { |
---|
358 | if (empty(preg_match('/^python-requests\//', $_SERVER['HTTP_USER_AGENT']))) { |
---|
359 | throw new Exception("Bad agent: sender=".$_SERVER['REMOTE_ADDR'].", agent=".$_SERVER['HTTP_USER_AGENT']); |
---|
360 | } |
---|
361 | if (!checkIds($ouid, $labid, $clntid)) { |
---|
362 | throw new Exception("Ids. must be positive integers"); |
---|
363 | } |
---|
364 | // Reading JSON parameters. |
---|
365 | $input = json_decode($app->request()->getBody()); |
---|
366 | $deadLine = $input->deadLine; |
---|
367 | if (filter_var($deadLine, FILTER_VALIDATE_INT) === false) { |
---|
368 | throw new Exception("Deadline must be integer"); |
---|
369 | } |
---|
370 | if ($deadLine < 0) { |
---|
371 | throw new Exception("Resource unavailable"); |
---|
372 | } |
---|
373 | } catch (Exception $e) { |
---|
374 | // Error message. |
---|
375 | $response["message"] = $e->getMessage(); |
---|
376 | if ($app->settings['debug']) |
---|
377 | writeRemotepcLog($app->request()->getResourceUri(). ": ERROR: ".$response["message"]."."); |
---|
378 | jsonResponse(400, $response); |
---|
379 | $app->stop(); |
---|
380 | } |
---|
381 | |
---|
382 | if ($app->settings['debug']) |
---|
383 | writeRemotepcLog($app->request()->getResourceUri(). ": Parameters: deadLine=$deadLine"); |
---|
384 | // Get client's data. |
---|
385 | $cmd->texto = <<<EOD |
---|
386 | SELECT adm.idusuario, ordenadores.idordenador, remotepc.* |
---|
387 | FROM remotepc |
---|
388 | RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador |
---|
389 | JOIN aulas USING(idaula) |
---|
390 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
391 | WHERE adm.idusuario = '$userid' |
---|
392 | AND aulas.idcentro = '$ouid' AND aulas.idaula = '$labid' |
---|
393 | AND ordenadores.idordenador = '$clntid'; |
---|
394 | EOD; |
---|
395 | $rs=new Recordset; |
---|
396 | $rs->Comando=&$cmd; |
---|
397 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
398 | // Check if user is admin and client exists. |
---|
399 | $rs->Primero(); |
---|
400 | if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idordenador"])) { |
---|
401 | // Check if client is reserved. |
---|
402 | if (! is_null($rs->campos["urllogin"])) { |
---|
403 | // Read query data. |
---|
404 | $clntid = $rs->campos["idordenador"]; |
---|
405 | # Removing previous commands from OGAgent operations queue. |
---|
406 | if ($app->settings['debug']) |
---|
407 | writeRemotepcLog($app->request()->getResourceUri(). ": Updating database."); |
---|
408 | $cmd->texto = <<<EOD |
---|
409 | DELETE FROM ogagent_queue |
---|
410 | WHERE clientid = '$clntid' AND operation IN ('popup-10', 'popup-5', 'poweroff'); |
---|
411 | EOD; |
---|
412 | $cmd->Ejecutar(); |
---|
413 | # Add new commands to OGAgent operations queue. |
---|
414 | $cmd->texto = "INSERT INTO ogagent_queue (clientid, exectime, operation) VALUES"; |
---|
415 | if ($deadLine > 600) { |
---|
416 | # Add reminder 10 min. before deadline. |
---|
417 | $cmd->texto .= " ($clntid, NOW() + INTERVAL $deadLine SECOND - INTERVAL 10 MINUTE, 'popup-10'),"; |
---|
418 | } |
---|
419 | if ($deadLine > 300) { |
---|
420 | # Add reminder 5 min. before deadline. |
---|
421 | $cmd->texto .= " ($clntid, NOW() + INTERVAL $deadLine SECOND - INTERVAL 5 MINUTE, 'popup-5'),"; |
---|
422 | } |
---|
423 | # Add power off command at deadline time. |
---|
424 | $cmd->texto .= " ($clntid, NOW() + INTERVAL $deadLine SECOND, 'poweroff');"; |
---|
425 | if ($deadLine == 0 or $cmd->Ejecutar()) { |
---|
426 | // Confirm operation. |
---|
427 | $cmd->texto = ""; |
---|
428 | $response = ""; |
---|
429 | jsonResponse(200, $response); |
---|
430 | } else { |
---|
431 | // Error message. |
---|
432 | $response["message"] = "Database error"; |
---|
433 | jsonResponse(400, $response); |
---|
434 | } |
---|
435 | } else { |
---|
436 | // Error message. |
---|
437 | $response["message"] = "Client is not reserved"; |
---|
438 | jsonResponse(400, $response); |
---|
439 | } |
---|
440 | } else { |
---|
441 | // Error message. |
---|
442 | $response["message"] = "Client does not exist"; |
---|
443 | jsonResponse(404, $response); |
---|
444 | } |
---|
445 | $rs->Cerrar(); |
---|
446 | } |
---|
447 | ); |
---|
448 | |
---|
449 | |
---|
450 | /** |
---|
451 | * @brief Store UDS server URLs to resend some events recieved from OGAgent. |
---|
452 | * @brief Unreserve a client and send a poweroff operation. |
---|
453 | * @note Route: /ous/:ouid/labs/:labid/clients/:clntid/unreserve, Method: DELETE |
---|
454 | */ |
---|
455 | $app->delete('/ous/:ouid/labs/:labid/clients/:clntid/unreserve', 'validateApiKey', |
---|
456 | function($ouid, $labid, $clntid) use ($app) { |
---|
457 | global $cmd; |
---|
458 | global $userid; |
---|
459 | global $ACCION_INICIADA; |
---|
460 | $response = Array(); |
---|
461 | $ogagent = Array(); |
---|
462 | |
---|
463 | if ($app->settings['debug']) |
---|
464 | writeRemotepcLog($app->request()->getResourceUri(). ": Init."); |
---|
465 | // Checking parameters. |
---|
466 | try { |
---|
467 | if (empty(preg_match('/^python-requests\//', $_SERVER['HTTP_USER_AGENT']))) { |
---|
468 | throw new Exception("Bad agent: sender=".$_SERVER['REMOTE_ADDR'].", agent=".$_SERVER['HTTP_USER_AGENT']); |
---|
469 | } |
---|
470 | if (!checkIds($ouid, $labid, $clntid)) { |
---|
471 | throw new Exception("Ids. must be positive integers"); |
---|
472 | } |
---|
473 | } catch (Exception $e) { |
---|
474 | // Error message. |
---|
475 | $response["message"] = $e->getMessage(); |
---|
476 | if ($app->settings['debug']) |
---|
477 | writeRemotepcLog($app->request()->getResourceUri(). ": ERROR: ".$response["message"]."."); |
---|
478 | jsonResponse(400, $response); |
---|
479 | $app->stop(); |
---|
480 | } |
---|
481 | |
---|
482 | // Select client data for UDS compatibility. |
---|
483 | $cmd->texto = <<<EOD |
---|
484 | SELECT adm.idusuario, ordenadores.idordenador, ordenadores.ip, ordenadores.agentkey, remotepc.reserved |
---|
485 | FROM remotepc |
---|
486 | RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador |
---|
487 | JOIN aulas USING(idaula) |
---|
488 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
489 | RIGHT JOIN usuarios USING(idusuario) |
---|
490 | WHERE adm.idusuario = '$userid' |
---|
491 | AND idcentro = '$ouid' AND aulas.idaula ='$labid' |
---|
492 | AND ordenadores.idordenador = '$clntid'; |
---|
493 | EOD; |
---|
494 | $rs=new Recordset; |
---|
495 | $rs->Comando=&$cmd; |
---|
496 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
497 | // Check if user is admin and client exists. |
---|
498 | $rs->Primero(); |
---|
499 | if (checkAdmin($rs->campos["idusuario"]) and checkParameter($rs->campos["idordenador"])) { |
---|
500 | // Check if client is reserved. |
---|
501 | if (! is_null($rs->campos["reserved"])) { |
---|
502 | // Read query data. |
---|
503 | $clntip = $rs->campos["ip"]; |
---|
504 | $agentkey = $rs->campos["agentkey"]; |
---|
505 | // DB Transaction: set reservation time to the past, remove pending |
---|
506 | // boot commands from client's and agent's queues, and drop its event. |
---|
507 | if ($app->settings['debug']) |
---|
508 | writeRemotepcLog($app->request()->getResourceUri(). ": Updating database."); |
---|
509 | $cmd->texto = "START TRANSACTION;"; |
---|
510 | $cmd->Ejecutar(); |
---|
511 | $cmd->texto = <<<EOD |
---|
512 | UPDATE remotepc |
---|
513 | SET reserved=NOW() - INTERVAL 1 SECOND, urllogin=NULL, urllogout=NULL |
---|
514 | WHERE id='$clntid'; |
---|
515 | EOD; |
---|
516 | $cmd->Ejecutar(); |
---|
517 | $cmd->texto = <<<EOD |
---|
518 | DELETE FROM acciones |
---|
519 | WHERE idordenador = '$clntid' |
---|
520 | AND descriaccion = 'RemotePC Session'; |
---|
521 | EOD; |
---|
522 | $cmd->Ejecutar(); |
---|
523 | $cmd->texto = <<<EOD |
---|
524 | DELETE FROM ogagent_queue |
---|
525 | WHERE clientid = '$clntid' AND operation IN ('popup-10', 'popup-5', 'poweroff'); |
---|
526 | EOD; |
---|
527 | $cmd->Ejecutar(); |
---|
528 | $cmd->texto = "DROP EVENT IF EXISTS e_timeout_$clntid;"; |
---|
529 | $cmd->Ejecutar(); |
---|
530 | $cmd->texto = "COMMIT;"; |
---|
531 | $cmd->Ejecutar(); |
---|
532 | // Send a poweroff command to client's OGAgent. |
---|
533 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/poweroff"; |
---|
534 | $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey); |
---|
535 | if ($app->settings['debug']) |
---|
536 | writeRemotepcLog($app->request()->getResourceUri(). ": OGAgent poweroff, url=".$ogagent[$clntip]['url']."."); |
---|
537 | $result = multiRequest($ogagent); |
---|
538 | // ... (check response) |
---|
539 | //if ($result[$clntip]['code'] != 200) { |
---|
540 | // ... |
---|
541 | // Confirm operation. |
---|
542 | $response = ""; |
---|
543 | jsonResponse(200, $response); |
---|
544 | } else { |
---|
545 | // Error message. |
---|
546 | $response["message"] = "Client is not reserved"; |
---|
547 | jsonResponse(400, $response); |
---|
548 | } |
---|
549 | } else { |
---|
550 | // Error message. |
---|
551 | $response["message"] = "Client does not exist"; |
---|
552 | jsonResponse(404, $response); |
---|
553 | } |
---|
554 | $rs->Cerrar(); |
---|
555 | } |
---|
556 | ); |
---|
557 | |
---|
558 | |
---|