source: admin/WebConsole/rest/remotepc.php @ dba299f

918-git-images-111dconfigfileconfigure-oglivegit-imageslgromero-new-oglivemainmaint-cronmount-efivarfsmultivmmultivm-ogboot-installerogClonningEngineogboot-installer-jenkinsoglive-ipv6test-python-scriptsticket-301ticket-50ticket-50-oldticket-577ticket-585ticket-611ticket-612ticket-693ticket-700ubu24tplunification2use-local-agent-oglivevarios-instalacion
Last change on this file since dba299f was 90da353, checked in by Ramón M. Gómez <ramongomez@…>, 6 years ago

#839: Drop database event when remote access reservation is finished.

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