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

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-instalacionwebconsole3
Last change on this file since dee9fac was 232d1da, checked in by ramon <ramongomez@…>, 8 years ago

#708 #730: Activar calendario de eventos de MySQL; creación correcta de eventos MySQL para liberar reservas sin acción asociada.branches/version1.1/admin/Database

git-svn-id: https://opengnsys.es/svn/branches/version1.1@5319 a21b9725-9963-47de-94b9-378ad31fedc9

  • Property mode set to 100644
File size: 12.7 KB
Line 
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
14// REST routes.
15
16/**
17 * @brief    Reserve a client with an installed image and the older reservation time, then send a boot/reboot operation depending on its status.
18 * @warning  If "lab" parameter is specified, then choose a client from this lab.
19 * @note     Route: /ous/:ouid/images/:imageid/reserve, Method: POST
20 * @param    integer ouid      OU identificator
21 * @param    integer imageid   image identificator
22 * @note     Input JSON message: {"labid":int_labid,"maxtime":int_hours}
23 */
24$app->post('/ous/:ouid/images/:imageid/reserve(/)', 'validateApiKey',
25    function($ouid, $imageid) use ($app) {
26        global $cmd;
27        global $AMBITO_ORDENADORES;
28        global $EJECUCION_COMANDO;
29        global $ACCION_INICIADA;
30        global $ACCION_FINALIZADA;
31        global $ACCION_SINRESULTADO;
32        global $ACCION_FALLIDA;
33        global $userid;
34        $response = Array();
35        $ogagent = Array();
36
37        // Checking parameters.
38        try {
39                if (!checkIds($ouid, $imageid)) {
40                        throw new Exception("Ids. must be positive integers");
41                }
42                // Reading POST parameters in JSON format.
43                $input = json_decode($app->request()->getBody());
44                // Default: no lab. filter.
45                if (isset($input->labid)) {
46                        $labid = $input->labid != "0" ? $input->labid : '%';
47                } else {
48                        $labid = '%';
49                }
50                $maxtime = isset($input->maxtime) ? $input->maxtime : 24;       // Default: 24 h.
51                $opts = Array('options' => Array('min_range' => 1));    // Check for int>0
52                if (!filter_var($labid, FILTER_VALIDATE_INT, $opts) and $labid !== '%') {
53                        throw new Exception("Lab id. must be positive integer");
54                }
55                if (!filter_var($maxtime, FILTER_VALIDATE_INT, $opts)) {
56                        throw new Exception("Time must be positive integer (in hours)");
57                }
58        } catch (Exception $e) {
59                // Communication error.
60                $response["message"] = $e->getMessage();
61                jsonResponse(400, $response);
62                $app->stop();
63        }
64        // Choose older not-reserved client with image installed and get ogAdmServer data.
65        $cmd->texto = <<<EOD
66SELECT adm.idadministradorcentro, entornos.ipserveradm, entornos.portserveradm,
67       ordenadores.idordenador, ordenadores.nombreordenador, ordenadores.ip,
68       ordenadores.mac, ordenadores.agentkey, ordenadores_particiones.numdisk,
69       ordenadores_particiones.numpar, aulas.idaula, aulas.idcentro
70  FROM entornos, ordenadores
71  JOIN aulas USING(idaula)
72 RIGHT JOIN administradores_centros AS adm USING(idcentro)
73 RIGHT JOIN usuarios USING(idusuario)
74 RIGHT JOIN ordenadores_particiones USING(idordenador)
75 RIGHT JOIN imagenes USING(idimagen)
76  LEFT JOIN remotepc ON remotepc.id=ordenadores.idordenador
77 WHERE adm.idadministradorcentro = '$userid'
78   AND aulas.idcentro = '$ouid' AND aulas.idaula LIKE '$labid' AND aulas.inremotepc = 1
79   AND imagenes.idimagen = '$imageid' AND imagenes.inremotepc = 1
80   AND (remotepc.reserved < NOW() OR ISNULL(reserved))
81 ORDER BY remotepc.reserved ASC LIMIT 1;
82EOD;
83        $rs=new Recordset;
84        $rs->Comando=&$cmd;
85        if (!$rs->Abrir()) return(false);       // Error opening recordset.
86        // Check if user is admin and client exists.
87        $rs->Primero();
88        if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) {
89                // Read query data.
90                $serverip = $rs->campos["ipserveradm"];
91                $serverport = $rs->campos["portserveradm"];
92                $clntid = $rs->campos["idordenador"];
93                $clntname = $rs->campos["nombreordenador"];
94                $clntip = $rs->campos["ip"];
95                $clntmac = $rs->campos["mac"];
96                $agentkey = $rs->campos["agentkey"];
97                $disk = $rs->campos["numdisk"];
98                $part = $rs->campos["numpar"];
99                $labid = $rs->campos["idaula"];
100                $ouid = $rs->campos["idcentro"];
101                // Check client's status.
102                $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/status";
103                $result = multiRequest($ogagent);
104                if (empty($result[$clntip]['data'])) {
105                        // Client is off, send a boot command to ogAdmServer.
106                        // TODO: if client is busy?????
107                        $reqframe = "nfn=Arrancar\r".
108                                    "ido=$clntid\r".
109                                    "iph=$clntip\r".
110                                    "mac=$clntmac\r".
111                                    "mar=1\r";
112                        sendCommand($serverip, $serverport, $reqframe, $values);
113                } else {
114                        // Client is on, send a reboot command to its OGAgent.
115                        $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/reboot";
116                        $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey);
117                        $result = multiRequest($ogagent);
118                        // ... (check response)
119                        //if ($result[$clntip]['code'] != 200) {
120                        // ...
121                }
122                // DB Transaction: mark choosed client as reserved and
123                // create an init session command into client's actions queue.
124                $cmd->texto = "START TRANSACTION;";
125                $cmd->Ejecutar();
126                $timestamp = time();
127                $cmd->texto = <<<EOD
128INSERT INTO remotepc
129   SET id='$clntid', reserved=NOW() + INTERVAL $maxtime HOUR, urllogin=NULL, urllogout=NULL
130    ON DUPLICATE KEY UPDATE
131       id=VALUES(id), reserved=VALUES(reserved),
132       urllogin=VALUES(urllogin), urllogout=VALUES(urllogout);
133EOD;
134                $t1 = $cmd->Ejecutar();
135                $cmd->texto = <<<EOD
136INSERT INTO acciones
137   SET tipoaccion=$EJECUCION_COMANDO,
138       idtipoaccion=9,
139       idcomando=9,
140       parametros='nfn=IniciarSesion\rdsk=$disk\rpar=$part',
141       descriaccion='RemotePC Session',
142       idordenador=$clntid,
143       ip='$clntip',
144       sesion=$timestamp,
145       fechahorareg=NOW(),
146       estado=$ACCION_INICIADA,
147       resultado=$ACCION_SINRESULTADO,
148       ambito=$AMBITO_ORDENADORES,
149       idambito=$clntid,
150       restrambito='$clntip',
151       idcentro=$ouid;
152EOD;
153                $t2 = $cmd->Ejecutar();
154                // Create event to remove reservation on timeout (15 min.).
155                $timeout = "15 MINUTE";
156                $cmd->texto = <<<EOD
157CREATE EVENT e_timeout_$clntid
158       ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL $timeout DO
159       BEGIN
160            SET @clntid = NULL;
161            UPDATE acciones
162               SET estado = $ACCION_FINALIZADA, resultado = $ACCION_FALLIDA,
163                   descrinotificacion = 'Timeout'
164             WHERE descriaccion = 'RemotePC Session' AND estado = $ACCION_INICIADA
165               AND idordenador = (SELECT @clntid := '$clntid');
166            IF @clntid IS NOT NULL THEN
167               UPDATE remotepc
168                  SET reserved=NOW() - INTERVAL 1 SECOND, urllogin=NULL, urllogout=NULL
169                WHERE id = @clntid;
170               DELETE FROM acciones
171                WHERE idordenador = @clntid
172                  AND descriaccion = 'RemotePC Session'
173                  AND descrinotificacion = 'Timeout';
174            END IF;
175       END
176EOD;
177                $t3 = $cmd->Ejecutar();
178                if ($t1 and $t2 and $t3) {
179                        // Commit transaction on success.
180                        $cmd->texto = "COMMIT;";
181                        $cmd->Ejecutar();
182                        // Send init session command if client is booted on ogLive.
183                        $reqframe = "nfn=IniciarSesion\r".
184                                    "ido=$clntid\r".
185                                    "iph=$clntip\r".
186                                    "dsk=$disk\r".
187                                    "par=$part\r";
188                        sendCommand($serverip, $serverport, $reqframe, $values);
189                        // Compose JSON response.
190                        $response['id'] = $clntid;
191                        $response['name'] = $clntname;
192                        $response['ip'] = $clntip;
193                        $response['mac'] = $clntmac;
194                        $response['lab']['id'] = $labid;
195                        $response['ou']['id'] = $ouid;
196                        jsonResponse(200, $response);
197                } else {
198                        // Roll-back transaction on DB error.
199                        $cmd->texto = "ROLLBACK;";
200                        $cmd->Ejecutar();
201                        // Error message.
202                        $response["message"] = "Database error";
203                        jsonResponse(400, $response);
204                        $app->stop();
205                }
206        }
207        $rs->Cerrar();
208    }
209);
210
211
212/**
213 * @brief    Store UDS server URLs to resend some events recieved from OGAgent.
214 * @note     Route: /ous/:ouid/labs/:labid/clients/:clntid/events, Method: POST
215 * @param    string urlLogin   URL to redirect login notification.
216 * @param    string urlLogout  URL to redirect logout notification.
217 * @warning  Events parameters will be stored in a new "remotepc" table.
218 */
219$app->post('/ous/:ouid/labs/:labid/clients/:clntid/events', 'validateApiKey',
220    function($ouid, $labid, $clntid) use ($app) {
221        global $cmd;
222        global $userid;
223        $response = Array();
224
225        // Checking parameters.
226        try {
227                if (!checkIds($ouid, $labid, $clntid)) {
228                        throw new Exception("Ids. must be positive integers");
229                }
230                // Reading JSON parameters.
231                $input = json_decode($app->request()->getBody());
232                $urlLogin = htmlspecialchars($input->urlLogin);
233                $urlLogout = htmlspecialchars($input->urlLogout);
234                if (!filter_var($urlLogin, FILTER_VALIDATE_URL)) {
235                        throw new Exception("Must be a valid URL for login notification");
236                }
237                if (!filter_var($urlLogout, FILTER_VALIDATE_URL)) {
238                        throw new Exception("Must be a valid URL for logout notification");
239                }
240        } catch (Exception $e) {
241                // Error message.
242                $response["message"] = $e->getMessage();
243                jsonResponse(400, $response);
244                $app->stop();
245        }
246
247        // Select client data for UDS compatibility.
248        $cmd->texto = <<<EOD
249SELECT adm.idadministradorcentro, ordenadores.idordenador, remotepc.*
250  FROM remotepc
251 RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador
252  JOIN aulas USING(idaula)
253 RIGHT JOIN administradores_centros AS adm USING(idcentro)
254 RIGHT JOIN usuarios USING(idusuario)
255 WHERE adm.idadministradorcentro = '$userid'
256   AND idcentro = '$ouid' AND aulas.idaula ='$labid'
257   AND ordenadores.idordenador = '$clntid';
258EOD;
259        $rs=new Recordset;
260        $rs->Comando=&$cmd;
261        if (!$rs->Abrir()) return(false);       // Error opening recordset.
262        // Check if user is admin and client exists.
263        $rs->Primero();
264        if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) {
265                // Check if client is reserved.
266                if (! is_null($rs->campos["reserved"])) {
267                        // Updating DB if client is reserved.
268                        $cmd->CreaParametro("@urllogin", $urlLogin, 0);
269                        $cmd->CreaParametro("@urllogout", $urlLogout, 0);
270                        $cmd->texto = <<<EOD
271UPDATE remotepc
272   SET urllogin=@urllogin, urllogout=@urllogout
273 WHERE id='$clntid';
274EOD;
275                        if ($cmd->Ejecutar()) {
276                                // Confirm operation.
277                                jsonResponse(200, "");
278                        } else {
279                                // Error message.
280                                $response["message"] = "Database error";
281                                jsonResponse(400, $response);
282                                $app->stop();
283                        }
284                } else {
285                        // Error message.
286                        $response["message"] = "Client is not reserved";
287                        jsonResponse(400, $response);
288                        $app->stop();
289                }
290        }
291        $rs->Cerrar();
292    }
293);
294
295
296$app->post('/ous/:ouid/labs/:labid/clients/:clntid/session', 'validateApiKey',
297    function($ouid, $imageid) use ($app) {
298    }
299);
300
301
302$app->delete('/ous/:ouid/labs/:labid/clients/:clntid/unreserve', 'validateApiKey',
303    function($ouid, $labid, $clntid) {
304        global $cmd;
305        global $userid;
306        global $ACCION_INICIADA;
307        $response = Array();
308        $ogagent = Array();
309
310        // Checking parameters.
311        try {
312                if (!checkIds($ouid, $labid, $clntid)) {
313                        throw new Exception("Ids. must be positive integers");
314                }
315        } catch (Exception $e) {
316                // Error message.
317                $response["message"] = $e->getMessage();
318                jsonResponse(400, $response);
319                $app->stop();
320        }
321
322        // Select client data for UDS compatibility.
323        $cmd->texto = <<<EOD
324SELECT adm.idadministradorcentro, ordenadores.idordenador, ordenadores.ip, ordenadores.agentkey, remotepc.reserved
325  FROM remotepc
326 RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador
327  JOIN aulas USING(idaula)
328 RIGHT JOIN administradores_centros AS adm USING(idcentro)
329 RIGHT JOIN usuarios USING(idusuario)
330 WHERE adm.idadministradorcentro = '$userid'
331   AND idcentro = '$ouid' AND aulas.idaula ='$labid'
332   AND ordenadores.idordenador = '$clntid';
333EOD;
334        $rs=new Recordset;
335        $rs->Comando=&$cmd;
336        if (!$rs->Abrir()) return(false);       // Error opening recordset.
337        // Check if user is admin and client exists.
338        $rs->Primero();
339        if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) {
340                // Check if client is reserved.
341                if (! is_null($rs->campos["reserved"])) {
342                        // Read query data.
343                        $clntip = $rs->campos["ip"];
344                        $agentkey = $rs->campos["agentkey"];
345                        // DB Transaction: set reservation time to the past and
346                        // remove pending boot commands from client's actions queue.
347                        $cmd->texto = "START TRANSACTION;";
348                        $cmd->Ejecutar();
349                        $cmd->texto = <<<EOD
350UPDATE remotepc
351   SET reserved=NOW() - INTERVAL 1 SECOND, urllogin=NULL, urllogout=NULL
352 WHERE id='$clntid';
353EOD;
354                        $cmd->Ejecutar();
355                        $cmd->texto = <<<EOD
356DELETE FROM acciones
357 WHERE idordenador = '$clntid'
358   AND descriaccion = 'RemotePC Session';
359EOD;
360                        $cmd->Ejecutar();
361                        $cmd->texto = "COMMIT;";
362                        $cmd->Ejecutar();
363                        // Send a poweroff command to client's OGAgent.
364                        $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/poweroff";
365                        $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey);
366                        $result = multiRequest($ogagent);
367                        // ... (check response)
368                        //if ($result[$clntip]['code'] != 200) {
369                        // ...
370                        // Confirm operation.
371                        jsonResponse(200, "");
372                } else {
373                        // Error message.
374                        $response["message"] = "Client is not reserved";
375                        jsonResponse(400, $response);
376                }
377        }
378        $rs->Cerrar();
379    }
380);
381
382?>
Note: See TracBrowser for help on using the repository browser.