[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 | |
---|
| 13 | |
---|
| 14 | // REST routes. |
---|
| 15 | |
---|
| 16 | /** |
---|
[9ed6a67] | 17 | * @brief Reserve a random client with an installed image and send a boot/reboot operation depending on its status. |
---|
| 18 | * @warning If "lab" parameter is specified, then choose a client from this lab. |
---|
[e0b6a5e] | 19 | * @note Route: /ous/:ouid/labs/:labid/clients/:clntid/events, Method: POST |
---|
[9a39c75] | 20 | * @param integer ouid OU identificator |
---|
| 21 | * @param integer imageid image identificator |
---|
[e0b6a5e] | 22 | * @param integer labid lab. identificator (optional) |
---|
| 23 | */ |
---|
[9a39c75] | 24 | $app->post('/ous/:ouid/images/:imageid/reserve', 'validateApiKey', |
---|
[e0b6a5e] | 25 | function($ouid, $imageid) use ($app) { |
---|
| 26 | global $cmd; |
---|
| 27 | global $AMBITO_ORDENADORES; |
---|
| 28 | global $EJECUCION_COMANDO; |
---|
| 29 | global $ACCION_INICIADA; |
---|
| 30 | global $ACCION_SINRESULTADO; |
---|
| 31 | global $userid; |
---|
[6f17d76] | 32 | $response = Array(); |
---|
| 33 | $ogagent = Array(); |
---|
[e0b6a5e] | 34 | |
---|
| 35 | // Checking parameters. |
---|
| 36 | $ouid = htmlspecialchars($ouid); |
---|
| 37 | $imageid = htmlspecialchars($imageid); |
---|
| 38 | $labid = str_replace("%", "\%", htmlspecialchars($app->request()->params('lab'))); |
---|
| 39 | if (empty($labid)) $labid = '%'; // Clients in any lab. |
---|
| 40 | // Randomly choose a client with image installed and get ogAdmServer data. |
---|
| 41 | $cmd->texto = <<<EOD |
---|
[e7d47882] | 42 | SELECT adm.idadministradorcentro, entornos.ipserveradm, entornos.portserveradm, |
---|
[e0b6a5e] | 43 | ordenadores.idordenador, ordenadores.ip, ordenadores.mac, ordenadores.agentkey, |
---|
| 44 | ordenadores_particiones.numdisk, ordenadores_particiones.numpar, |
---|
| 45 | aulas.idaula, aulas.idcentro, remotepc.reserved |
---|
| 46 | FROM entornos, ordenadores |
---|
| 47 | JOIN aulas USING(idaula) |
---|
[e7d47882] | 48 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
[e0b6a5e] | 49 | RIGHT JOIN usuarios USING(idusuario) |
---|
| 50 | RIGHT JOIN ordenadores_particiones USING(idordenador) |
---|
| 51 | RIGHT JOIN imagenes USING(idimagen) |
---|
[6f17d76] | 52 | LEFT JOIN remotepc ON remotepc.id=ordenadores.idordenador |
---|
[e7d47882] | 53 | WHERE adm.idadministradorcentro = '$userid' |
---|
[9a39c75] | 54 | AND aulas.idcentro = '$ouid' AND aulas.idaula LIKE '$labid' AND aulas.inremotepc = 1 |
---|
| 55 | AND imagenes.idimagen = '$imageid' AND imagenes.inremotepc = 1 |
---|
[e0b6a5e] | 56 | ORDER BY RAND() LIMIT 1; |
---|
| 57 | EOD; |
---|
| 58 | $rs=new Recordset; |
---|
| 59 | $rs->Comando=&$cmd; |
---|
| 60 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
[e7d47882] | 61 | // Check if user is admin and client exists. |
---|
[e0b6a5e] | 62 | $rs->Primero(); |
---|
[e7d47882] | 63 | if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) { |
---|
[9a39c75] | 64 | // Check if client is not reserved. |
---|
[6f17d76] | 65 | if ($rs->campos["reserved"] !== 1) { |
---|
[9a39c75] | 66 | // Read query data. |
---|
| 67 | $serverip = $rs->campos["ipserveradm"]; |
---|
| 68 | $serverport = $rs->campos["portserveradm"]; |
---|
[6f17d76] | 69 | $clntid = $rs->campos["idordenador"]; |
---|
| 70 | $clntip = $rs->campos["ip"]; |
---|
| 71 | $clntmac = $rs->campos["mac"]; |
---|
[9a39c75] | 72 | $agentkey = $rs->campos["agentkey"]; |
---|
| 73 | $disk = $rs->campos["numdisk"]; |
---|
| 74 | $part = $rs->campos["numpar"]; |
---|
| 75 | $labid = $rs->campos["idaula"]; |
---|
| 76 | $ouid = $rs->campos["idcentro"]; |
---|
| 77 | // Check client's status. |
---|
[6f17d76] | 78 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/status"; |
---|
| 79 | $result = multiRequest($ogagent); |
---|
[357352b] | 80 | if (empty($result[$clntip]['data'])) { |
---|
[6f17d76] | 81 | // Client is off, send a boot command to ogAdmServer. |
---|
[9a39c75] | 82 | $reqframe = "nfn=Arrancar\r". |
---|
[6f17d76] | 83 | "ido=$clntid\r". |
---|
| 84 | "iph=$clntip\r". |
---|
| 85 | "mac=$clntmac\r". |
---|
[9a39c75] | 86 | "mar=1\r"; |
---|
| 87 | sendCommand($serverip, $serverport, $reqframe, $values); |
---|
| 88 | } else { |
---|
[6f17d76] | 89 | // Client is on, send a reboot command to its OGAgent. |
---|
| 90 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/reboot"; |
---|
| 91 | $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey); |
---|
| 92 | $result = multiRequest($ogagent); |
---|
[9a39c75] | 93 | // ... (check response) |
---|
[357352b] | 94 | //if ($result[$clntip]['code'] != 200) { |
---|
[9a39c75] | 95 | // ... |
---|
| 96 | } |
---|
[6f17d76] | 97 | // DB Transaction: mark choosed client as reserved and |
---|
[9ed6a67] | 98 | // create an init session command into client's actions queue. |
---|
[6f17d76] | 99 | $cmd->texto = "START TRANSACTION;"; |
---|
| 100 | $cmd->Ejecutar(); |
---|
| 101 | $timestamp = time(); |
---|
[9a39c75] | 102 | $cmd->texto = <<<EOD |
---|
[e0b6a5e] | 103 | INSERT INTO remotepc |
---|
[9a39c75] | 104 | SET id='$clntid', reserved=1, urllogin=NULL, urllogout=NULL |
---|
[6f17d76] | 105 | ON DUPLICATE KEY UPDATE |
---|
[e0b6a5e] | 106 | id=VALUES(id), reserved=VALUES(reserved), |
---|
[6f17d76] | 107 | urllogin=VALUES(urllogin), urllogout=VALUES(urllogout); |
---|
| 108 | EOD; |
---|
| 109 | $t1 = $cmd->Ejecutar(); |
---|
| 110 | $cmd->texto = <<<EOD |
---|
[e0b6a5e] | 111 | INSERT INTO acciones |
---|
| 112 | SET tipoaccion=$EJECUCION_COMANDO, |
---|
| 113 | idtipoaccion=9, |
---|
| 114 | idcomando=9, |
---|
[6f17d76] | 115 | parametros='nfn=IniciarSesion\rdsk=$disk\rpar=$part', |
---|
[e0b6a5e] | 116 | descriaccion='RemotePC Session', |
---|
[6f17d76] | 117 | idordenador=$clntid, |
---|
| 118 | ip='$clntip', |
---|
| 119 | sesion=$timestamp, |
---|
[e0b6a5e] | 120 | fechahorareg=NOW(), |
---|
| 121 | estado=$ACCION_INICIADA, |
---|
| 122 | resultado=$ACCION_SINRESULTADO, |
---|
| 123 | ambito=$AMBITO_ORDENADORES, |
---|
[6f17d76] | 124 | idambito=$clntid, |
---|
| 125 | restrambito='$clntip', |
---|
[e0b6a5e] | 126 | idcentro=$ouid; |
---|
[9a39c75] | 127 | EOD; |
---|
[6f17d76] | 128 | $t2 = $cmd->Ejecutar(); |
---|
| 129 | if ($t1 and $t2) { |
---|
| 130 | // Commit transaction on success. |
---|
| 131 | $cmd->texto = "COMMIT;"; |
---|
| 132 | $cmd->Ejecutar(); |
---|
| 133 | // Send init session command if client is booted on ogLive. |
---|
| 134 | $reqframe = "nfn=IniciarSesion\r". |
---|
| 135 | "ido=$clntid\r". |
---|
| 136 | "iph=$clntip\r". |
---|
| 137 | "dsk=$disk\r". |
---|
| 138 | "par=$part\r"; |
---|
| 139 | sendCommand($serverip, $serverport, $reqframe, $values); |
---|
| 140 | // Compose JSON response. |
---|
| 141 | $response['id'] = $clntid; |
---|
| 142 | $response['ip'] = $clntip; |
---|
| 143 | $response['mac'] = $clntmac; |
---|
| 144 | $response['lab']['id'] = $labid; |
---|
| 145 | $response['ou']['id'] = $ouid; |
---|
| 146 | jsonResponse(200, $response); |
---|
| 147 | } else{ |
---|
| 148 | // Roll-back transaction on DB error. |
---|
| 149 | $cmd->texto = "ROLLBACK;"; |
---|
| 150 | $cmd->Ejecutar(); |
---|
| 151 | // Error message. |
---|
| 152 | $response["message"] = "Error updating database"; |
---|
| 153 | jsonResponse(400, $response); |
---|
| 154 | $app->stop(); |
---|
| 155 | } |
---|
[9a39c75] | 156 | } else { |
---|
| 157 | // Error message. |
---|
| 158 | $response["message"] = "Client is already reserved"; |
---|
| 159 | jsonResponse(400, $response); |
---|
| 160 | $app->stop(); |
---|
| 161 | } |
---|
[9ed6a67] | 162 | } |
---|
[e0b6a5e] | 163 | $rs->Cerrar(); |
---|
| 164 | } |
---|
| 165 | ); |
---|
| 166 | |
---|
| 167 | |
---|
| 168 | /** |
---|
| 169 | * @brief Store UDS server URLs to resend some events recieved from OGAgent. |
---|
| 170 | * @note Route: /ous/:ouid/labs/:labid/clients/:clntid/events, Method: POST |
---|
| 171 | * @param string urlLogin URL to redirect login notification. |
---|
| 172 | * @param string urlLogout URL to redirect logout notification. |
---|
| 173 | * @warning Events parameters will be stored in a new "remotepc" table. |
---|
| 174 | */ |
---|
| 175 | $app->post('/ous/:ouid/labs/:labid/clients/:clntid/events', 'validateApiKey', |
---|
| 176 | function($ouid, $labid, $clntid) use ($app) { |
---|
| 177 | global $cmd; |
---|
| 178 | global $userid; |
---|
[6f17d76] | 179 | $response = Array(); |
---|
[e0b6a5e] | 180 | |
---|
| 181 | // Reading JSON parameters. |
---|
| 182 | try { |
---|
| 183 | $input = json_decode($app->request()->getBody()); |
---|
| 184 | $urlLogin = htmlspecialchars($input->urlLogin); |
---|
| 185 | $urlLogout = htmlspecialchars($input->urlLogout); |
---|
| 186 | } catch (Exception $e) { |
---|
| 187 | // Error message. |
---|
| 188 | $response["message"] = $e->getMessage(); |
---|
| 189 | jsonResponse(400, $response); |
---|
| 190 | $app->stop(); |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | // Checking parameters. |
---|
| 194 | $ouid = htmlspecialchars($ouid); |
---|
| 195 | $labid = htmlspecialchars($labid); |
---|
| 196 | $clntid = htmlspecialchars($clntid); |
---|
| 197 | // Select client data for UDS compatibility. |
---|
| 198 | $cmd->texto = <<<EOD |
---|
[e7d47882] | 199 | SELECT adm.idadministradorcentro, ordenadores.idordenador, remotepc.* |
---|
[e0b6a5e] | 200 | FROM remotepc |
---|
| 201 | RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador |
---|
| 202 | JOIN aulas USING(idaula) |
---|
[e7d47882] | 203 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
[e0b6a5e] | 204 | RIGHT JOIN usuarios USING(idusuario) |
---|
[e7d47882] | 205 | WHERE adm.idadministradorcentro = '$userid' |
---|
[e0b6a5e] | 206 | AND idcentro = '$ouid' AND aulas.idaula ='$labid' |
---|
| 207 | AND ordenadores.idordenador = '$clntid'; |
---|
| 208 | EOD; |
---|
| 209 | $rs=new Recordset; |
---|
| 210 | $rs->Comando=&$cmd; |
---|
| 211 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
[e7d47882] | 212 | // Check if user is admin and client exists. |
---|
[e0b6a5e] | 213 | $rs->Primero(); |
---|
[e7d47882] | 214 | if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) { |
---|
[e0b6a5e] | 215 | // Check if client is reserved. |
---|
[a26527d] | 216 | if ($rs->campos["reserved"] == 1) { |
---|
[9a39c75] | 217 | // Updating DB if client is reserved. |
---|
[e0b6a5e] | 218 | $cmd->texto = <<<EOD |
---|
| 219 | INSERT INTO remotepc |
---|
[9a39c75] | 220 | SET id='$clntid', reserved=1, urllogin='$urlLogin', urllogout='$urlLogout' |
---|
[a26527d] | 221 | ON DUPLICATE KEY UPDATE |
---|
[e0b6a5e] | 222 | id=VALUES(id), reserved=VALUES(reserved), |
---|
[a26527d] | 223 | urllogin=VALUES(urllogin), urllogout=VALUES(urllogout); |
---|
[9a39c75] | 224 | EOD; |
---|
[e0b6a5e] | 225 | $cmd->Ejecutar(); |
---|
[9a39c75] | 226 | // Confirm operation. |
---|
[e0b6a5e] | 227 | jsonResponse(200, ""); |
---|
| 228 | } else { |
---|
| 229 | // Error message. |
---|
[9a39c75] | 230 | $response["message"] = "Client is not reserved"; |
---|
[e0b6a5e] | 231 | jsonResponse(400, $response); |
---|
| 232 | $app->stop(); |
---|
| 233 | } |
---|
| 234 | } |
---|
| 235 | $rs->Cerrar(); |
---|
| 236 | } |
---|
| 237 | ); |
---|
| 238 | |
---|
| 239 | |
---|
| 240 | $app->post('/ous/:ouid/labs/:labid/clients/:clntid/session', 'validateApiKey', |
---|
| 241 | function($ouid, $imageid) use ($app) { |
---|
| 242 | } |
---|
| 243 | ); |
---|
| 244 | |
---|
| 245 | |
---|
[9a39c75] | 246 | $app->delete('/ous/:ouid/labs/:labid/clients/:clntid/unreserve', 'validateApiKey', |
---|
[9ed6a67] | 247 | function($ouid, $labid, $clntid) { |
---|
[e0b6a5e] | 248 | global $cmd; |
---|
| 249 | global $userid; |
---|
[9ed6a67] | 250 | $response = Array(); |
---|
| 251 | $ogagent = Array(); |
---|
[e0b6a5e] | 252 | |
---|
[9ed6a67] | 253 | // Checking parameters. |
---|
| 254 | $ouid = htmlspecialchars($ouid); |
---|
| 255 | $labid = htmlspecialchars($labid); |
---|
| 256 | $clntid = htmlspecialchars($clntid); |
---|
| 257 | // Select client data for UDS compatibility. |
---|
| 258 | $cmd->texto = <<<EOD |
---|
[e7d47882] | 259 | SELECT adm.idadministradorcentro, ordenadores.idordenador, ordenadores.ip, ordenadores.agentkey, remotepc.reserved |
---|
[9ed6a67] | 260 | FROM remotepc |
---|
| 261 | RIGHT JOIN ordenadores ON remotepc.id=ordenadores.idordenador |
---|
| 262 | JOIN aulas USING(idaula) |
---|
[e7d47882] | 263 | RIGHT JOIN administradores_centros AS adm USING(idcentro) |
---|
[9ed6a67] | 264 | RIGHT JOIN usuarios USING(idusuario) |
---|
[e7d47882] | 265 | WHERE adm.idadministradorcentro = '$userid' |
---|
[9ed6a67] | 266 | AND idcentro = '$ouid' AND aulas.idaula ='$labid' |
---|
| 267 | AND ordenadores.idordenador = '$clntid'; |
---|
| 268 | EOD; |
---|
| 269 | $rs=new Recordset; |
---|
| 270 | $rs->Comando=&$cmd; |
---|
| 271 | if (!$rs->Abrir()) return(false); // Error opening recordset. |
---|
[e7d47882] | 272 | // Check if user is admin and client exists. |
---|
[9ed6a67] | 273 | $rs->Primero(); |
---|
[e7d47882] | 274 | if (checkAdmin($rs->campos["idadministradorcentro"]) and checkParameter($rs->campos["idordenador"])) { |
---|
[9ed6a67] | 275 | // Check if client is reserved. |
---|
| 276 | if ($rs->campos["reserved"] == 1) { |
---|
| 277 | // Read query data. |
---|
[40db2a3] | 278 | $clntip = $rs->campos["ip"]; |
---|
[9ed6a67] | 279 | $agentkey = $rs->campos["agentkey"]; |
---|
| 280 | // DB Transaction: clear client reservation data and |
---|
| 281 | // remove pending boot commands from client's actions queue. |
---|
| 282 | $cmd->texto = "START TRANSACTION;"; |
---|
| 283 | $cmd->Ejecutar(); |
---|
| 284 | $cmd->texto = <<<EOD |
---|
| 285 | UPDATE remotepc |
---|
| 286 | SET reserved=0, urllogin=NULL, urllogout=NULL |
---|
| 287 | WHERE id='$clntid'; |
---|
| 288 | EOD; |
---|
| 289 | $cmd->Ejecutar(); |
---|
| 290 | $cmd->texto = <<<EOD |
---|
| 291 | DELETE FROM acciones |
---|
| 292 | WHERE idordenador = '$clntid' |
---|
| 293 | AND descriaccion = 'RemotePC Session' |
---|
| 294 | AND fechahorafin = '0000-00-00 00:00:00'; |
---|
| 295 | EOD; |
---|
| 296 | $cmd->Ejecutar(); |
---|
| 297 | $cmd->texto = "COMMIT;"; |
---|
| 298 | $cmd->Ejecutar(); |
---|
| 299 | // Send a poweroff command to client's OGAgent. |
---|
| 300 | $ogagent[$clntip]['url'] = "https://$clntip:8000/opengnsys/poweroff"; |
---|
| 301 | $ogagent[$clntip]['header'] = Array("Authorization: ".$agentkey); |
---|
| 302 | $result = multiRequest($ogagent); |
---|
| 303 | // ... (check response) |
---|
[357352b] | 304 | //if ($result[$clntip]['code'] != 200) { |
---|
[9ed6a67] | 305 | // ... |
---|
| 306 | // Confirm operation. |
---|
| 307 | jsonResponse(200, ""); |
---|
| 308 | } else { |
---|
| 309 | // Error message. |
---|
| 310 | $response["message"] = "Client is not reserved"; |
---|
| 311 | jsonResponse(400, $response); |
---|
| 312 | } |
---|
| 313 | } |
---|
| 314 | $rs->Cerrar(); |
---|
[e0b6a5e] | 315 | } |
---|
| 316 | ); |
---|
| 317 | |
---|
| 318 | ?> |
---|