diff options
author | Roberto Hueso Gómez <rhueso@soleta.eu> | 2020-07-22 10:07:05 +0200 |
---|---|---|
committer | OpenGnSys Support Team <soporte-og@soleta.eu> | 2020-07-29 20:17:34 +0200 |
commit | 532b0819c48af5fd26592726280374b5abfeacaf (patch) | |
tree | 3aa599bafb6a015b12cea15c13b824bc40dd6e35 /src | |
parent | a8e5b844c5ea1c0e2c8339870739298ecaedcf69 (diff) |
#980 Fix POST /modes to use 'setclientmode' script
Now POST /modes does not only write to the database, it also uses the
external bash script 'setclientmode' to generate configured PXE
templates for each machine.
NOTE: This fix requires that room and computer names are unique in the
OpenGnsys DB. This behaviour is inherited from the previous
'setclientmode' script but, eventually, it should be replaced for an
actual scope selector.
Diffstat (limited to 'src')
-rw-r--r-- | src/rest.c | 175 |
1 files changed, 140 insertions, 35 deletions
@@ -23,6 +23,7 @@ #include <jansson.h> #include <dirent.h> #include <time.h> +#include <stdlib.h> struct ev_loop *og_loop; @@ -906,23 +907,118 @@ static int og_cmd_get_modes(json_t *element, struct og_msg_params *params, return 0; } +static int og_change_db_mode(struct og_dbi *dbi, const char *mac, + const char * mode) +{ + const char *msglog; + dbi_result result; + + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET arranque='%s' " + "WHERE mac='%s'", + mode, mac); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + dbi_result_free(result); + return 0; +} + +static int og_set_client_mode(struct og_dbi *dbi, const char *mac, + const char *mode, const char *template_name, + const char *scope_name) +{ + char filename[PATH_MAX + 1] = "/tmp/mode_params_XXXXXX"; + char cmd_params[PATH_MAX + 1] = {}; + char params[PATH_MAX + 1] = "\0"; + const char *msglog; + dbi_result result; + unsigned int i; + char cmd[200]; + int numbytes; + int err = 0; + int fd; + + result = dbi_conn_queryf(dbi->conn, + "SELECT ' LANG=%s', ' ip=', CONCAT_WS(':', ordenadores.ip, (SELECT (@serverip:=ipserveradm) FROM entornos LIMIT 1), aulas.router, aulas.netmask, ordenadores.nombreordenador, ordenadores.netiface, 'none'), ' group=', REPLACE(TRIM(aulas.nombreaula), ' ', '_'), ' ogrepo=', (@repoip:=IFNULL(repositorios.ip, '')), ' oglive=', @serverip, ' oglog=', @serverip, ' ogshare=', @serverip, ' oglivedir=', ordenadores.oglivedir, ' ogprof=', IF(ordenadores.idordenador=aulas.idordprofesor, 'true', 'false'), IF(perfileshard.descripcion<>'', CONCAT(' hardprofile=', REPLACE(TRIM(perfileshard.descripcion), ' ', '_')), ''), IF(aulas.ntp<>'', CONCAT(' ogntp=', aulas.ntp), ''), IF(aulas.dns<>'', CONCAT(' ogdns=', aulas.dns), ''), IF(aulas.proxy<>'', CONCAT(' ogproxy=', aulas.proxy), ''), IF(entidades.ogunit=1 AND NOT centros.directorio='', CONCAT(' ogunit=', centros.directorio), ''), CASE WHEN menus.resolucion IS NULL THEN '' WHEN menus.resolucion <= '999' THEN CONCAT(' vga=', menus.resolucion) WHEN menus.resolucion LIKE '%:%' THEN CONCAT(' video=', menus.resolucion) ELSE menus.resolucion END FROM ordenadores JOIN aulas USING(idaula) JOIN centros USING(idcentro) JOIN entidades USING(identidad) LEFT JOIN repositorios USING(idrepositorio) LEFT JOIN perfileshard USING(idperfilhard) LEFT JOIN menus USING(idmenu) WHERE ordenadores.mac='%s'", getenv("LANG"), mac); + + if (dbi_result_get_numrows(result) != 1) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __FILE__, __LINE__, msglog); + dbi_result_free(result); + return -1; + } + dbi_result_next_row(result); + + for (i = 1; i <= dbi_result_get_numfields(result); ++i) + strcat(params, dbi_result_get_string_idx(result, i)); + + dbi_result_free(result); + + snprintf(cmd_params, sizeof(cmd_params), + "MODE_FILE='%s'\nMAC='%s'\nDATA='%s'\n" + "MODE='PERM'\nTEMPLATE_NAME='%s'", + mode, mac, params, template_name); + + fd = mkstemp(filename); + if (fd < 0) { + syslog(LOG_ERR, "cannot generate temp file (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + numbytes = write(fd, cmd_params, strlen(cmd_params) + 1); + close(fd); + + if (numbytes < 0) { + syslog(LOG_ERR, "cannot write file\n"); + unlink(filename); + return -1; + } + + snprintf(cmd, sizeof(cmd), "/opt/opengnsys/bin/setclientmode %s", + filename); + + err = system(cmd); + unlink(filename); + if (err != 0) { + syslog(LOG_ERR, "failed script execution (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + if (og_change_db_mode(dbi, mac, mode) < 0) { + syslog(LOG_ERR, "failed to change db mode (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + return 0; +} + static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) { - struct og_scope scope = {}; - const char *mode_str; + const char *mode_str, *mac, *scope_name; + char template_file[PATH_MAX + 1] = {}; + char template_name[PATH_MAX + 1] = {}; + char first_line[PATH_MAX + 1] = {}; struct og_dbi *dbi; - const char *msglog; uint64_t flags = 0; dbi_result result; const char *key; json_t *value; int err = 0; + FILE *f; json_object_foreach(element, key, value) { - if (!strcmp(key, "scope")) { - err = og_json_parse_scope(value, &scope, - OG_PARAM_SCOPE_ID | - OG_PARAM_SCOPE_TYPE); + if (!strcmp(key, "scope_name")) { + err = og_json_parse_string(value, &scope_name); flags |= OG_REST_PARAM_SCOPE; } else if (!strcmp(key, "mode")) { err = og_json_parse_string(value, &mode_str); @@ -939,45 +1035,54 @@ static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) OG_REST_PARAM_MODE)) return -1; - dbi = og_dbi_open(&dbi_config); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + snprintf(template_file, sizeof(template_file), "%s/%s", + OG_TFTP_TMPL_PATH, mode_str); + f = fopen(template_file, "r"); + if (!f) { + syslog(LOG_ERR, "cannot open file (%s:%d)\n", __func__, __LINE__); return -1; } - if (!strcmp(scope.type, "computer")) { - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET arranque='%s' " - "WHERE idordenador=%u", - mode_str, scope.id); - } else if (!strcmp(scope.type, "room")) { - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET arranque='%s' " - "WHERE idaula=%u", - mode_str, scope.id); - } else if (!strcmp(scope.type, "center")) { - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET arranque='%s' " - "INNER JOIN aulas ON " - "ordenadores.idaula=aulas.idcentro " - "WHERE aulas.idcentro=%u", - mode_str, scope.id); - } else { - syslog(LOG_ERR, "unknown scope type (%s:%d)\n", + if (!fgets(first_line, sizeof(first_line), f)) { + fclose(f); + syslog(LOG_ERR, "cannot read file (%s:%d)\n", __func__, __LINE__); - og_dbi_close(dbi); return -1; } - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - og_dbi_close(dbi); + fclose(f); + + if (sscanf(first_line, "##NO-TOCAR-ESTA-LINEA %s", template_name) != 1) { + syslog(LOG_ERR, "malformed template: %s", first_line); return -1; } + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT mac FROM ordenadores " + "JOIN aulas USING (idaula) " + "WHERE aulas.nombreaula='%s' OR " + "nombreordenador='%s'", + scope_name, scope_name); + + while (dbi_result_next_row(result)) { + mac = dbi_result_get_string(result, "mac"); + err = og_set_client_mode(dbi, mac, mode_str, + template_name, scope_name); + if (err != 0) { + dbi_result_free(result); + og_dbi_close(dbi); + return -1; + } + } + dbi_result_free(result); og_dbi_close(dbi); |