From 5d97a721d0d475ea86e9d503a2e413e22f53492b Mon Sep 17 00:00:00 2001 From: OpenGnSys Support Team Date: Thu, 19 Sep 2024 10:30:46 +0200 Subject: ogAdmServer: replace old actualizaConfiguracion Reimplement the legacy funcion actualizaConfiguracion with og_update_client_config in src/client.c if disk does not exist, add it, otherwise update disk contents. if partition size, code, filesystem or os is different, reset image id, otherwise update partition usage only. delete partitions that are gone at the end. --- src/client.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/dbi.c | 61 +++++++++++ src/dbi.h | 1 + src/ogAdmServer.c | 193 ---------------------------------- 4 files changed, 347 insertions(+), 210 deletions(-) (limited to 'src') diff --git a/src/client.c b/src/client.c index 96b522f..50d3373 100644 --- a/src/client.c +++ b/src/client.c @@ -30,6 +30,40 @@ #define OG_CLIENT_SESSION_OS_WINDOWS "Windows" #define OG_CLIENT_SESSION_TIMEDATE_LEN 20 +static struct { + const char *name; + uint32_t id; +} og_fs[] = { + { "EMPTY", 1 }, + { "CACHE", 2 }, + { "BTRFS", 3 }, + { "EXT3", 5 }, + { "EXT4", 6 }, + { "FAT32", 9 }, + { "HFS", 10 }, + { "HFSPLUS", 11 }, + { "NTFS", 13 }, + { "EXFAT", 18 }, + { "LINUX-SWAP", 19 }, + { "SWAP", 22 }, + { NULL, 0 }, +}; + +static uint32_t get_filesystem_id(const char *fs_name) +{ + uint32_t i; + + if (strlen(fs_name) == 0) + return 0; + + for (i = 0; og_fs[i].name != NULL; i++) { + if (!strcmp(og_fs[i].name, fs_name)) + return og_fs[i].id; + } + + return 0; +} + static void og_status_session_log(const struct og_client *cli, const char *type, const char* user, const char *os) @@ -502,17 +536,262 @@ static int og_resp_update_cache(json_t *data, struct og_client *cli) return 0; } +struct og_disk { + uint64_t size; +}; + +struct og_part { + uint32_t filesystem; + uint32_t os; + uint32_t code; + uint64_t size; + uint64_t used_size; +}; + +static bool og_update_client_disk_info(struct og_dbi *dbi, + const struct og_client *cli, + int computer_id, + const struct og_partition *disks, + uint32_t num_disks, + const struct og_partition *partitions, + uint32_t num_partitions, + const char *serial_number) +{ + struct og_disk cur_disk = {}, reported_disk = {}; + struct og_part cur_part = {}, reported_part = {}; + dbi_result result, result_update; + int disk_part_len = 0; + char disk_part[1024]; + const char *msglog; + int i; + + if (serial_number && strlen(serial_number) > 0) { + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET numserie='%s'" + " WHERE idordenador=%d AND numserie IS NULL", + serial_number, computer_id); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result); + } + + for (i = 0; i < num_disks; i++) { + disk_part_len += snprintf(&disk_part[disk_part_len], + sizeof(disk_part) - disk_part_len, + "(%s, 0),", disks[i].disk); + + result = dbi_conn_queryf(dbi->conn, + "SELECT tamano " + " FROM ordenadores_particiones" + " WHERE idordenador=%d AND numdisk=%s AND numpar=0", + computer_id, disks[i].disk); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + if (!dbi_result_next_row(result)) { + result_update = dbi_conn_queryf(dbi->conn, + "INSERT INTO ordenadores_particiones(" + "idordenador, numdisk, numpar, codpar, tamano, uso, " + "idsistemafichero, idnombreso, disk_type, idimagen)" + " VALUES(%d,%s,0,0x%s,%s,0,0,0,'%s',0)", + computer_id, + disks[i].disk, + disks[i].code, + disks[i].size, + disks[i].disk_type); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + dbi_result_free(result); + + syslog(LOG_INFO, "adding disk %u with size %s to client %s\n", + i, disks[i].size, inet_ntoa(cli->addr.sin_addr)); + + continue; + } + + reported_disk.size = strtoull(disks[i].size, NULL, 0); + cur_disk.size = dbi_result_get_longlong(result, "tamano"); + + dbi_result_free(result); + + result_update = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET tamano=%s," + " codpar=%s, disk_type='%s' " + " WHERE idordenador=%d AND numdisk=%s AND numpar=0", + disks[i].size, disks[i].code, disks[i].disk_type, computer_id, disks[i].disk); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + + if (cur_disk.size != reported_disk.size) + syslog(LOG_INFO, "disk %s in client %s has changed size, before %lu after %lu bytes\n", + disks[i].disk, inet_ntoa(cli->addr.sin_addr), cur_disk.size, reported_disk.size); + + continue; + } + + for (i = 0; i < num_partitions; i++) { + disk_part_len += snprintf(&disk_part[disk_part_len], + sizeof(disk_part) - disk_part_len, + "(%s, %s),", + partitions[i].disk, partitions[i].number); + + result = dbi_conn_queryf(dbi->conn, + "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso, codpar" + " FROM ordenadores_particiones" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + computer_id, partitions[i].disk, partitions[i].number); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + reported_part.size = strtoull(partitions[i].size, NULL, 0); + reported_part.used_size = strtoull(partitions[i].used_size, NULL, 0); + reported_part.code = strtoul(partitions[i].code, NULL, 16); + reported_part.filesystem = get_filesystem_id(partitions[i].filesystem); + + if (og_dbi_get_os_id(dbi, partitions[i].os, &reported_part.os) < 0) { + return false; + } + + if (!dbi_result_next_row(result)) { + result_update = dbi_conn_queryf(dbi->conn, + "INSERT INTO ordenadores_particiones(" + "idordenador, numdisk, numpar, codpar, tamano, uso, " + "idsistemafichero, idnombreso, idimagen)" + " VALUES(%d,%s,%s,0x%d,%s,%d,%d,%d,0)", + computer_id, + partitions[i].disk, + partitions[i].number, + reported_part.code, + partitions[i].size, + reported_part.used_size, + reported_part.filesystem, + reported_part.os); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + dbi_result_free(result); + + syslog(LOG_INFO, "new partition %s in disk %s client %s\n", + partitions[i].number, partitions[i].disk, inet_ntoa(cli->addr.sin_addr)); + + continue; + } + + cur_part.size = dbi_result_get_longlong(result, "tamano"); + cur_part.used_size = dbi_result_get_longlong(result, "uso"); + cur_part.code = dbi_result_get_int(result, "codpar"); + cur_part.filesystem = dbi_result_get_uint(result, "idsistemafichero"); + cur_part.os = dbi_result_get_uint(result, "idnombreso"); + dbi_result_free(result); + + if (cur_part.size != reported_part.size || + cur_part.code != reported_part.code || + cur_part.filesystem != reported_part.filesystem || + cur_part.os != reported_part.os) { + result_update = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET " + " codpar=0x%s," + " tamano=%s," + " uso=%d," + " idsistemafichero=%d," + " idnombreso=%d," + " idimagen=0," + " idperfilsoft=0," + " fechadespliegue=NULL" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + partitions[i].code, partitions[i].size, reported_part.used_size, + reported_part.filesystem, reported_part.os, computer_id, + partitions[i].disk, partitions[i].number); + + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + dbi_result_free(result_update); + + syslog(LOG_INFO, "Disk %s partition %s in client %s has changed\n", + partitions[i].disk, partitions[i].number, inet_ntoa(cli->addr.sin_addr)); + + continue; + } + + if (cur_part.used_size == reported_part.used_size) + continue; + + result_update = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET " + " uso=%d" + " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", + reported_part.used_size, computer_id, + partitions[i].disk, partitions[i].number); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + + syslog(LOG_INFO, "partition usage in disk %s partition %s client %s has changed\n", + partitions[i].disk, partitions[i].number, inet_ntoa(cli->addr.sin_addr)); + } + /* remove trailing comma */ + disk_part[disk_part_len - 1] = '\0'; + + result_update = dbi_conn_queryf(dbi->conn, + "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)", + computer_id, disk_part); + if (!result_update) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + dbi_result_free(result_update); + + return true; +} + static int og_resp_refresh(json_t *data, struct og_client *cli) { struct og_partition partitions[OG_PARTITION_MAX] = {}; struct og_partition disks[OG_DISK_MAX] = {}; + uint32_t num_disks = 0, num_partitions = 0; const char *serial_number = NULL; struct og_computer computer = {}; json_t *value, *cache = NULL; const char *status = NULL; LIST_HEAD(boot_entry_list); LIST_HEAD(cache_list); - char cfg[4096] = {}; struct og_dbi *dbi; uint32_t link = 0; const char *key; @@ -561,9 +840,6 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) return 0; } - if (serial_number && strlen(serial_number) > 0) - snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number); - for (i = 0; i < OG_DISK_MAX; i++) { if (!disks[i].disk || !disks[i].number || !disks[i].code || !disks[i].filesystem || @@ -571,12 +847,7 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) !disks[i].used_size) continue; - snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg), - "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\tdtype=%s\n", - disks[i].disk, disks[i].number, - disks[i].code, disks[i].filesystem, - disks[i].os, disks[i].size, - disks[i].used_size, disks[i].disk_type); + num_disks++; } for (i = 0; i < OG_PARTITION_MAX; i++) { @@ -586,12 +857,7 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) !partitions[i].used_size) continue; - snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg), - "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n", - partitions[i].disk, partitions[i].number, - partitions[i].code, partitions[i].filesystem, - partitions[i].os, partitions[i].size, - partitions[i].used_size); + num_partitions++; } dbi = og_dbi_open(&ogconfig.db); @@ -618,7 +884,9 @@ static int og_resp_refresh(json_t *data, struct og_client *cli) goto err_out; } - res = actualizaConfiguracion(dbi, cfg, computer.id); + res = og_update_client_disk_info(dbi, cli, computer.id, disks, num_disks, + partitions, num_partitions, + serial_number); og_dbi_close(dbi); if (!res) { diff --git a/src/dbi.c b/src/dbi.c index 78485a6..0b5bbbb 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -456,3 +456,64 @@ int og_dbi_get_repository_ip(const struct og_dbi *dbi, const uint32_t repo_id, return 0; } + +int og_dbi_get_os_id(const struct og_dbi *dbi, const char *os_name, uint32_t *os_id) +{ + const char *msglog; + dbi_result result; + + if (strlen(os_name) == 0) + return 0; + + result = dbi_conn_queryf(dbi->conn, + "SELECT idnombreso FROM nombresos " + "WHERE nombreso = '%s'", os_name); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query OS id (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + if (dbi_result_next_row(result)) { + *os_id = dbi_result_get_uint(result, "idnombreso"); + dbi_result_free(result); + return 0; + } + + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO nombresos (nombreso) " + "VALUES ('%s') ", os_name); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to insert OS id (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "SELECT idnombreso FROM nombresos " + "WHERE nombreso = '%s'", os_name); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query OS id (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + if (!dbi_result_next_row(result)) { + dbi_result_free(result); + syslog(LOG_ERR, "failed to query OS id (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + *os_id = dbi_result_get_uint(result, "idnombreso"); + dbi_result_free(result); + + return 0; +} diff --git a/src/dbi.h b/src/dbi.h index b2eca96..9e8dd6e 100644 --- a/src/dbi.h +++ b/src/dbi.h @@ -142,5 +142,6 @@ int og_dbi_get_repository_ip(const struct og_dbi *dbi, const uint32_t repo_id, const char *client_ip, char *repository_ip); int og_dbi_get_server_ip(const struct og_dbi *dbi, const char *client_ip, char *server_ip); +int og_dbi_get_os_id(const struct og_dbi *dbi, const char *os_name, uint32_t *os_id); #endif diff --git a/src/ogAdmServer.c b/src/ogAdmServer.c index 107342d..23f0b91 100644 --- a/src/ogAdmServer.c +++ b/src/ogAdmServer.c @@ -22,199 +22,6 @@ #include #include -// ________________________________________________________________________________________________________ -// Función: actualizaConfiguracion -// -// Descripción: -// Esta función actualiza la base de datos con la configuracion de particiones de un cliente -// Parámetros: -// - db: Objeto base de datos (ya operativo) -// - tbl: Objeto tabla -// - cfg: cadena con una Configuración -// - ido: Identificador del ordenador cliente -// Devuelve: -// true: Si el proceso es correcto -// false: En caso de ocurrir algún error -// Especificaciones: -// Los parametros de la configuración son: -// par= Número de partición -// cpt= Codigo o tipo de partición -// sfi= Sistema de ficheros que está implementado en la partición -// soi= Nombre del sistema de ficheros instalado en la partición -// tam= Tamaño de la partición -// ________________________________________________________________________________________________________ -bool actualizaConfiguracion(struct og_dbi *dbi, char *cfg, int ido) -{ - int lon, p, c,i, dato, swu, idsoi, idsfi,k; - char *ptrPar[MAXPAR], *ptrCfg[8], *ptrDual[2], tbPar[LONSTD]; - char *ser, *disk, *disk_type, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración. - dbi_result result, result_update; - const char *msglog; - - if (cfg && strlen(cfg) == 0) { - syslog(LOG_ERR, "Empty configuration string (%s:%d)\n", - __func__, __LINE__); - return false; - } - - lon = 0; - p = splitCadena(ptrPar, cfg, '\n'); - for (i = 0; i < p; i++) { - c = splitCadena(ptrCfg, ptrPar[i], '\t'); - - // Si la 1ª línea solo incluye el número de serie del equipo; actualizar BD. - if (i == 0 && c == 1) { - splitCadena(ptrDual, ptrCfg[0], '='); - ser = ptrDual[1]; - if (ser && strlen(ser) > 0) { - // Solo actualizar si número de serie no existía. - result = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores SET numserie='%s'" - " WHERE idordenador=%d AND numserie IS NULL", - ser, ido); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result); - } - continue; - } - - // Distribución de particionado. - disk = disk_type = par = cpt = sfi = soi = tam = uso = NULL; - - splitCadena(ptrDual, ptrCfg[0], '='); - disk = ptrDual[1]; // Número de disco - - splitCadena(ptrDual, ptrCfg[1], '='); - par = ptrDual[1]; // Número de partición - - k=splitCadena(ptrDual, ptrCfg[2], '='); - if(k==2){ - cpt = ptrDual[1]; // Código de partición - }else{ - cpt = (char*)"0"; - } - - k=splitCadena(ptrDual, ptrCfg[3], '='); - if(k==2){ - sfi = ptrDual[1]; // Sistema de ficheros - /* Comprueba existencia del s0xistema de ficheros instalado */ - idsfi = checkDato(dbi, sfi, "sistemasficheros", "descripcion","idsistemafichero"); - } - else - idsfi=0; - - k=splitCadena(ptrDual, ptrCfg[4], '='); - if(k==2){ // Sistema operativo detecdtado - soi = ptrDual[1]; // Nombre del S.O. instalado - /* Comprueba existencia del sistema operativo instalado */ - idsoi = checkDato(dbi, soi, "nombresos", "nombreso", "idnombreso"); - } - else - idsoi=0; - - splitCadena(ptrDual, ptrCfg[5], '='); - tam = ptrDual[1]; // Tamaño de la partición - - splitCadena(ptrDual, ptrCfg[6], '='); - uso = ptrDual[1]; // Porcentaje de uso del S.F. - - k = splitCadena(ptrDual, ptrCfg[7], '='); - if (k == 2) - disk_type = ptrDual[1]; - else - disk_type = NULL; - - lon += sprintf(tbPar + lon, "(%s, %s),", disk, par); - - result = dbi_conn_queryf(dbi->conn, - "SELECT numdisk, numpar, tamano, uso, idsistemafichero, idnombreso" - " FROM ordenadores_particiones" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - ido, disk, par); - if (!result) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - if (!dbi_result_next_row(result)) { - result_update = dbi_conn_queryf(dbi->conn, - "INSERT INTO ordenadores_particiones(idordenador,numdisk,disk_type,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)" - " VALUES(%d,%s,'%s',%s,0x%s,%s,%s,%d,%d,0)", - ido, disk, disk_type, par, cpt, tam, uso, idsfi, idsoi); - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result_update); - - } else { // Existe el registro - swu = true; // Se supone que algún dato ha cambiado - - dato = dbi_result_get_longlong(result, "tamano"); - if (atoi(tam) == dato) {// Parámetro tamaño igual al almacenado - dato = dbi_result_get_uint(result, "idsistemafichero"); - if (idsfi == dato) {// Parámetro sistema de fichero igual al almacenado - dato = dbi_result_get_uint(result, "idnombreso"); - if (idsoi == dato) {// Parámetro sistema de fichero distinto al almacenado - swu = false; // Todos los parámetros de la partición son iguales, no se actualiza - } - } - } - if (swu) { // Hay que actualizar los parámetros de la partición - result_update = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones SET " - " codpar=0x%s," - " tamano=%s," - " uso=%s," - " idsistemafichero=%d," - " idnombreso=%d," - " idimagen=0," - " idperfilsoft=0," - " fechadespliegue=NULL" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - cpt, tam, uso, idsfi, idsoi, ido, disk, par); - } else { // Actualizar porcentaje de uso. - result_update = dbi_conn_queryf(dbi->conn, - "UPDATE ordenadores_particiones SET " - " codpar=0x%s," - " uso=%s" - " WHERE idordenador=%d AND numdisk=%s AND numpar=%s", - cpt, uso, ido, disk, par); - } - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - - dbi_result_free(result_update); - } - dbi_result_free(result); - } - lon += sprintf(tbPar + lon, "(0,0)"); - // Eliminar particiones almacenadas que ya no existen - result_update = dbi_conn_queryf(dbi->conn, - "DELETE FROM ordenadores_particiones WHERE idordenador=%d AND (numdisk, numpar) NOT IN (%s)", - ido, tbPar); - if (!result_update) { - dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", - __func__, __LINE__, msglog); - return false; - } - dbi_result_free(result_update); - - return true; -} // ________________________________________________________________________________________________________ // Función: checkDato // -- cgit v1.2.3-18-g5258