diff options
Diffstat (limited to 'src/ogAdmServer.c')
-rw-r--r-- | src/ogAdmServer.c | 1301 |
1 files changed, 1301 insertions, 0 deletions
diff --git a/src/ogAdmServer.c b/src/ogAdmServer.c new file mode 100644 index 0000000..436c3b1 --- /dev/null +++ b/src/ogAdmServer.c @@ -0,0 +1,1301 @@ +// ******************************************************************************************************* +// Servicio: ogAdmServer +// Autor: José Manuel Alonso (E.T.S.I.I.) Universidad de Sevilla +// Fecha Creación: Marzo-2010 +// Fecha Última modificación: Marzo-2010 +// Nombre del fichero: ogAdmServer.cpp +// Descripción :Este fichero implementa el servicio de administración general del sistema +// ******************************************************************************************************* +#include "ogAdmServer.h" +#include "dbi.h" +#include "utils.h" +#include "list.h" +#include "rest.h" +#include "client.h" +#include "json.h" +#include "schedule.h" +#include <syslog.h> +#include <sys/ioctl.h> +#include <ifaddrs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <jansson.h> +#include <time.h> + +char usuario[LONPRM]; // Usuario de acceso a la base de datos +char pasguor[LONPRM]; // Password del usuario +char datasource[LONPRM]; // Dirección IP del gestor de base de datos +char catalog[LONPRM]; // Nombre de la base de datos +char interface[LONPRM]; // Interface name +char auth_token[LONPRM]; // API token + +struct og_dbi_config dbi_config = { + .user = usuario, + .passwd = pasguor, + .host = datasource, + .database = catalog, +}; + +//________________________________________________________________________________________________________ +// Función: tomaConfiguracion +// +// Descripción: +// Lee el fichero de configuración del servicio +// Parámetros: +// filecfg : Ruta completa al fichero de configuración +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +//________________________________________________________________________________________________________ +bool tomaConfiguracion(const char *filecfg) +{ + char buf[1024], *line; + char *key, *value; + FILE *fcfg; + + if (filecfg == NULL || strlen(filecfg) == 0) { + syslog(LOG_ERR, "No configuration file has been specified\n"); + return false; + } + + fcfg = fopen(filecfg, "rt"); + if (fcfg == NULL) { + syslog(LOG_ERR, "Cannot open configuration file `%s'\n", + filecfg); + return false; + } + + servidoradm[0] = '\0'; //inicializar variables globales + + line = fgets(buf, sizeof(buf), fcfg); + while (line != NULL) { + const char *delim = "="; + + line[strlen(line) - 1] = '\0'; + + key = strtok(line, delim); + value = strtok(NULL, delim); + + if (!strcmp(str_toupper(key), "SERVIDORADM")) + snprintf(servidoradm, sizeof(servidoradm), "%s", value); + else if (!strcmp(str_toupper(key), "PUERTO")) + snprintf(puerto, sizeof(puerto), "%s", value); + else if (!strcmp(str_toupper(key), "USUARIO")) + snprintf(usuario, sizeof(usuario), "%s", value); + else if (!strcmp(str_toupper(key), "PASSWORD")) + snprintf(pasguor, sizeof(pasguor), "%s", value); + else if (!strcmp(str_toupper(key), "DATASOURCE")) + snprintf(datasource, sizeof(datasource), "%s", value); + else if (!strcmp(str_toupper(key), "CATALOG")) + snprintf(catalog, sizeof(catalog), "%s", value); + else if (!strcmp(str_toupper(key), "INTERFACE")) + snprintf(interface, sizeof(interface), "%s", value); + else if (!strcmp(str_toupper(key), "APITOKEN")) + snprintf(auth_token, sizeof(auth_token), "%s", value); + + line = fgets(buf, sizeof(buf), fcfg); + } + + fclose(fcfg); + + if (!servidoradm[0]) { + syslog(LOG_ERR, "Missing SERVIDORADM in configuration file\n"); + return false; + } + if (!puerto[0]) { + syslog(LOG_ERR, "Missing PUERTO in configuration file\n"); + return false; + } + if (!usuario[0]) { + syslog(LOG_ERR, "Missing USUARIO in configuration file\n"); + return false; + } + if (!pasguor[0]) { + syslog(LOG_ERR, "Missing PASSWORD in configuration file\n"); + return false; + } + if (!datasource[0]) { + syslog(LOG_ERR, "Missing DATASOURCE in configuration file\n"); + return false; + } + if (!catalog[0]) { + syslog(LOG_ERR, "Missing CATALOG in configuration file\n"); + return false; + } + if (!interface[0]) + syslog(LOG_ERR, "Missing INTERFACE in configuration file\n"); + + return true; +} + +#define OG_CMD_MAXLEN 64 + +// ________________________________________________________________________________________________________ +// Función: clienteDisponible +// +// Descripción: +// Comprueba la disponibilidad del cliente para recibir comandos interactivos +// Parametros: +// - ip : La ip del cliente a buscar +// - idx: (Salida) Indice que ocupa el cliente, de estar ya registrado +// Devuelve: +// true: Si el cliente está disponible +// false: En caso contrario +// ________________________________________________________________________________________________________ +bool clienteDisponible(char *ip, int* idx) +{ + int estado; + + if (clienteExistente(ip, idx)) { + estado = strcmp(tbsockets[*idx].estado, CLIENTE_OCUPADO); // Cliente ocupado + if (estado == 0) + return false; + + estado = strcmp(tbsockets[*idx].estado, CLIENTE_APAGADO); // Cliente apagado + if (estado == 0) + return false; + + estado = strcmp(tbsockets[*idx].estado, CLIENTE_INICIANDO); // Cliente en proceso de inclusión + if (estado == 0) + return false; + + return true; // En caso contrario el cliente está disponible + } + return false; // Cliente no está registrado en el sistema +} +// ________________________________________________________________________________________________________ +// Función: clienteExistente +// +// Descripción: +// Comprueba si el cliente está registrado en la tabla de socket del sistema +// Parametros: +// - ip : La ip del cliente a buscar +// - idx:(Salida) Indice que ocupa el cliente, de estar ya registrado +// Devuelve: +// true: Si el cliente está registrado +// false: En caso contrario +// ________________________________________________________________________________________________________ +bool clienteExistente(char *ip, int* idx) +{ + int i; + for (i = 0; i < MAXIMOS_CLIENTES; i++) { + if (contieneIP(ip, tbsockets[i].ip)) { // Si existe la IP en la cadena + *idx = i; + return true; + } + } + return false; +} +// ________________________________________________________________________________________________________ +// 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[7], *ptrDual[2], tbPar[LONSTD]; + char *ser, *disk, *par, *cpt, *sfi, *soi, *tam, *uso; // Parametros de configuración. + dbi_result result, result_update; + const char *msglog; + + 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 (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 = 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. + + 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,numpar,codpar,tamano,uso,idsistemafichero,idnombreso,idimagen)" + " VALUES(%d,%s,%s,0x%s,%s,%s,%d,%d,0)", + ido, disk, 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_uint(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 +// +// Descripción: +// Esta función comprueba si existe un dato en una tabla y si no es así lo incluye. devuelve en +// cualquier caso el identificador del registro existenet o del insertado +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - dato: Dato +// - tabla: Nombre de la tabla +// - nomdato: Nombre del dato en la tabla +// - nomidentificador: Nombre del identificador en la tabla +// Devuelve: +// El identificador del registro existente o el del insertado +// +// Especificaciones: +// En caso de producirse algún error se devuelve el valor 0 +// ________________________________________________________________________________________________________ + +int checkDato(struct og_dbi *dbi, char *dato, const char *tabla, + const char *nomdato, const char *nomidentificador) +{ + const char *msglog; + int identificador; + dbi_result result; + + if (strlen(dato) == 0) + return (0); // EL dato no tiene valor + result = dbi_conn_queryf(dbi->conn, + "SELECT %s FROM %s WHERE %s ='%s'", nomidentificador, + tabla, nomdato, dato); + + // Ejecuta consulta + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return (0); + } + if (!dbi_result_next_row(result)) { // Software NO existente + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO %s (%s) VALUES('%s')", tabla, nomdato, dato); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return (0); + } + // Recupera el identificador del software + identificador = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + identificador = dbi_result_get_uint(result, nomidentificador); + } + dbi_result_free(result); + + return (identificador); +} + +// ________________________________________________________________________________________________________ +// Función: Levanta +// +// Descripción: +// Enciende ordenadores a través de la red cuyas macs se pasan como parámetro +// Parámetros: +// - iph: Cadena de direcciones ip separadas por ";" +// - mac: Cadena de direcciones mac separadas por ";" +// - mar: Método de arranque (1=Broadcast, 2=Unicast) +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ + +bool Levanta(char *ptrIP[], char *ptrMacs[], int lon, char *mar) +{ + unsigned int on = 1; + struct sockaddr_in local; + int i, res; + int s; + + /* Creación de socket para envío de magig packet */ + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s < 0) { + syslog(LOG_ERR, "cannot create socket for magic packet\n"); + return false; + } + res = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (unsigned int *) &on, + sizeof(on)); + if (res < 0) { + syslog(LOG_ERR, "cannot set broadcast socket\n"); + return false; + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(PUERTO_WAKEUP); + local.sin_addr.s_addr = htonl(INADDR_ANY); + + for (i = 0; i < lon; i++) { + if (!WakeUp(s, ptrIP[i], ptrMacs[i], mar)) { + syslog(LOG_ERR, "problem sending magic packet\n"); + close(s); + return false; + } + } + close(s); + return true; +} + +#define OG_WOL_SEQUENCE 6 +#define OG_WOL_MACADDR_LEN 6 +#define OG_WOL_REPEAT 16 + +struct wol_msg { + char secuencia_FF[OG_WOL_SEQUENCE]; + char macbin[OG_WOL_REPEAT][OG_WOL_MACADDR_LEN]; +}; + +static bool wake_up_broadcast(int sd, struct sockaddr_in *client, + const struct wol_msg *msg) +{ + struct sockaddr_in *broadcast_addr; + struct ifaddrs *ifaddr, *ifa; + int ret; + + if (getifaddrs(&ifaddr) < 0) { + syslog(LOG_ERR, "cannot get list of addresses\n"); + return false; + } + + client->sin_addr.s_addr = htonl(INADDR_BROADCAST); + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL || + ifa->ifa_addr->sa_family != AF_INET || + strcmp(ifa->ifa_name, interface) != 0) + continue; + + broadcast_addr = + (struct sockaddr_in *)ifa->ifa_ifu.ifu_broadaddr; + client->sin_addr.s_addr = broadcast_addr->sin_addr.s_addr; + break; + } + freeifaddrs(ifaddr); + + ret = sendto(sd, msg, sizeof(*msg), 0, + (struct sockaddr *)client, sizeof(*client)); + if (ret < 0) { + syslog(LOG_ERR, "failed to send broadcast wol\n"); + return false; + } + + return true; +} + +static bool wake_up_unicast(int sd, struct sockaddr_in *client, + const struct wol_msg *msg, + const struct in_addr *addr) +{ + int ret; + + client->sin_addr.s_addr = addr->s_addr; + + ret = sendto(sd, msg, sizeof(*msg), 0, + (struct sockaddr *)client, sizeof(*client)); + if (ret < 0) { + syslog(LOG_ERR, "failed to send unicast wol\n"); + return false; + } + + return true; +} + +enum wol_delivery_type { + OG_WOL_BROADCAST = 1, + OG_WOL_UNICAST = 2 +}; + +//_____________________________________________________________________________________________________________ +// Función: WakeUp +// +// Descripción: +// Enciende el ordenador cuya MAC se pasa como parámetro +// Parámetros: +// - s : Socket para enviar trama magic packet +// - iph : Cadena con la dirección ip +// - mac : Cadena con la dirección mac en formato XXXXXXXXXXXX +// - mar: Método de arranque (1=Broadcast, 2=Unicast) +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +//_____________________________________________________________________________________________________________ +// +bool WakeUp(int s, char* iph, char *mac, char *mar) +{ + unsigned int macaddr[OG_WOL_MACADDR_LEN]; + char HDaddress_bin[OG_WOL_MACADDR_LEN]; + struct sockaddr_in WakeUpCliente; + struct wol_msg Trama_WakeUp; + struct in_addr addr; + bool ret; + int i; + + for (i = 0; i < 6; i++) // Primera secuencia de la trama Wake Up (0xFFFFFFFFFFFF) + Trama_WakeUp.secuencia_FF[i] = 0xFF; + + sscanf(mac, "%02x%02x%02x%02x%02x%02x", + &macaddr[0], &macaddr[1], &macaddr[2], + &macaddr[3], &macaddr[4], &macaddr[5]); + + for (i = 0; i < 6; i++) + HDaddress_bin[i] = (uint8_t)macaddr[i]; + + for (i = 0; i < 16; i++) // Segunda secuencia de la trama Wake Up , repetir 16 veces su la MAC + memcpy(&Trama_WakeUp.macbin[i][0], &HDaddress_bin, 6); + + /* Creación de socket del cliente que recibe la trama magic packet */ + WakeUpCliente.sin_family = AF_INET; + WakeUpCliente.sin_port = htons((short) PUERTO_WAKEUP); + + switch (atoi(mar)) { + case OG_WOL_BROADCAST: + ret = wake_up_broadcast(s, &WakeUpCliente, &Trama_WakeUp); + break; + case OG_WOL_UNICAST: + if (inet_aton(iph, &addr) < 0) { + syslog(LOG_ERR, "bad IP address for unicast wol\n"); + ret = false; + break; + } + ret = wake_up_unicast(s, &WakeUpCliente, &Trama_WakeUp, &addr); + break; + default: + syslog(LOG_ERR, "unknown wol type\n"); + ret = false; + break; + } + return ret; +} + +// ________________________________________________________________________________________________________ +// Función: actualizaCreacionImagen +// +// Descripción: +// Esta función actualiza la base de datos con el resultado de la creación de una imagen +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idi: Identificador de la imagen +// - dsk: Disco de donde se creó +// - par: Partición de donde se creó +// - cpt: Código de partición +// - ipr: Ip del repositorio +// - ido: Identificador del ordenador modelo +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool actualizaCreacionImagen(struct og_dbi *dbi, char *idi, char *dsk, + char *par, char *cpt, char *ipr, char *ido) +{ + const char *msglog; + dbi_result result; + int idr,ifs; + + /* Toma identificador del repositorio correspondiente al ordenador modelo */ + result = dbi_conn_queryf(dbi->conn, + "SELECT repositorios.idrepositorio" + " FROM repositorios" + " LEFT JOIN ordenadores USING (idrepositorio)" + " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", ipr, 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; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, + "repository does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + idr = dbi_result_get_uint(result, "idrepositorio"); + dbi_result_free(result); + + /* Toma identificador del perfilsoftware */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft" + " FROM ordenadores_particiones" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", ido, dsk, 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)) { + syslog(LOG_ERR, + "software profile does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + ifs = dbi_result_get_uint(result, "idperfilsoft"); + dbi_result_free(result); + + /* Actualizar los datos de la imagen */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE imagenes" + " SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s," + " idperfilsoft=%d, idrepositorio=%d," + " fechacreacion=NOW(), revision=revision+1" + " WHERE idimagen=%s", ido, dsk, par, cpt, ifs, idr, idi); + + 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); + + /* Actualizar los datos en el cliente */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones" + " SET idimagen=%s, revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," + " fechadespliegue=NOW()" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", + idi, idi, ido, dsk, 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; + } + dbi_result_free(result); + + return true; +} + +// ________________________________________________________________________________________________________ +// Función: actualizaRestauracionImagen +// +// Descripción: +// Esta función actualiza la base de datos con el resultado de la restauración de una imagen +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idi: Identificador de la imagen +// - dsk: Disco de donde se restauró +// - par: Partición de donde se restauró +// - ido: Identificador del cliente donde se restauró +// - ifs: Identificador del perfil software contenido en la imagen +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// ________________________________________________________________________________________________________ +bool actualizaRestauracionImagen(struct og_dbi *dbi, char *idi, + char *dsk, char *par, char *ido, char *ifs) +{ + const char *msglog; + dbi_result result; + + /* Actualizar los datos de la imagen */ + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones" + " SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW()," + " revision=(SELECT revision FROM imagenes WHERE idimagen=%s)," + " idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)" + " WHERE idordenador=%s AND numdisk=%s AND numpar=%s", idi, ifs, idi, ifs, ido, dsk, 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; + } + dbi_result_free(result); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: actualizaHardware +// +// Descripción: +// Actualiza la base de datos con la configuracion hardware del cliente +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - hrd: cadena con el inventario hardware +// - ido: Identificador del ordenador +// - npc: Nombre del ordenador +// - idc: Identificador del centro o Unidad organizativa +// ________________________________________________________________________________________________________ +// +bool actualizaHardware(struct og_dbi *dbi, char *hrd, char *ido, char *npc, + char *idc) +{ + const char *msglog; + int idtipohardware, idperfilhard; + int lon, i, j, aux; + bool retval; + char *whard; + int tbidhardware[MAXHARDWARE]; + char *tbHardware[MAXHARDWARE],*dualHardware[2], strInt[LONINT], *idhardwares; + dbi_result result; + + /* Toma Centro (Unidad Organizativa) */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilhard FROM ordenadores WHERE idordenador=%s", + 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; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "client does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return false; + } + idperfilhard = dbi_result_get_uint(result, "idperfilhard"); + dbi_result_free(result); + + whard=escaparCadena(hrd); // Codificar comillas simples + if(!whard) + return false; + /* Recorre componentes hardware*/ + lon = splitCadena(tbHardware, whard, '\n'); + if (lon > MAXHARDWARE) + lon = MAXHARDWARE; // Limita el número de componentes hardware + /* + for (i=0;i<lon;i++){ + sprintf(msglog,"Linea de inventario: %s",tbHardware[i]); + RegistraLog(msglog,false); + } + */ + for (i = 0; i < lon; i++) { + splitCadena(dualHardware, rTrim(tbHardware[i]), '='); + //sprintf(msglog,"nemonico: %s",dualHardware[0]); + //RegistraLog(msglog,false); + //sprintf(msglog,"valor: %s",dualHardware[1]); + //RegistraLog(msglog,false); + result = dbi_conn_queryf(dbi->conn, + "SELECT idtipohardware,descripcion FROM tipohardwares WHERE nemonico='%s'", + dualHardware[0]); + 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)) { // Tipo de Hardware NO existente + dbi_result_free(result); + return false; + } else { // Tipo de Hardware Existe + idtipohardware = dbi_result_get_uint(result, "idtipohardware"); + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "SELECT idhardware FROM hardwares WHERE idtipohardware=%d AND descripcion='%s'", + idtipohardware, dualHardware[1]); + + 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)) { // Hardware NO existente + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT hardwares (idtipohardware,descripcion,idcentro,grupoid) " + " VALUES(%d,'%s',%s,0)", idtipohardware, + dualHardware[1], idc); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + // Recupera el identificador del hardware + tbidhardware[i] = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + tbidhardware[i] = dbi_result_get_uint(result, "idhardware"); + } + dbi_result_free(result); + } + } + // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones + + for (i = 0; i < lon - 1; i++) { + for (j = i + 1; j < lon; j++) { + if (tbidhardware[i] > tbidhardware[j]) { + aux = tbidhardware[i]; + tbidhardware[i] = tbidhardware[j]; + tbidhardware[j] = aux; + } + } + } + /* Crea cadena de identificadores de componentes hardware separados por coma */ + sprintf(strInt, "%d", tbidhardware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud + aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles + idhardwares = calloc(1, sizeof(aux) * lon + lon); + if (idhardwares == NULL) { + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + return false; + } + aux = sprintf(idhardwares, "%d", tbidhardware[0]); + for (i = 1; i < lon; i++) + aux += sprintf(idhardwares + aux, ",%d", tbidhardware[i]); + + if (!cuestionPerfilHardware(dbi, idc, ido, idperfilhard, idhardwares, + npc, tbidhardware, lon)) { + syslog(LOG_ERR, "Problem updating client hardware\n"); + retval=false; + } else { + retval=true; + } + free(whard); + free(idhardwares); + + return (retval); +} +// ________________________________________________________________________________________________________ +// Función: cuestionPerfilHardware +// +// Descripción: +// Comprueba existencia de perfil hardware y actualización de éste para el ordenador +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idc: Identificador de la Unidad organizativa donde se encuentra el cliente +// - ido: Identificador del ordenador +// - tbidhardware: Identificador del tipo de hardware +// - con: Número de componentes detectados para configurar un el perfil hardware +// - npc: Nombre del cliente +// ________________________________________________________________________________________________________ +bool cuestionPerfilHardware(struct og_dbi *dbi, char *idc, char *ido, + int idperfilhardware, char *idhardwares, char *npc, int *tbidhardware, + int lon) +{ + const char *msglog; + dbi_result result; + int i; + int nwidperfilhard; + + // Busca perfil hard del ordenador que contenga todos los componentes hardware encontrados + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilhard FROM" + " (SELECT perfileshard_hardwares.idperfilhard as idperfilhard," + " group_concat(cast(perfileshard_hardwares.idhardware AS char( 11) )" + " ORDER BY perfileshard_hardwares.idhardware SEPARATOR ',' ) AS idhardwares" + " FROM perfileshard_hardwares" + " GROUP BY perfileshard_hardwares.idperfilhard) AS temp" + " WHERE idhardwares LIKE '%s'", idhardwares); + + 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)) { + // No existe un perfil hardware con esos componentes de componentes hardware, lo crea + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT perfileshard (descripcion,idcentro,grupoid)" + " VALUES('Perfil hardware (%s) ',%s,0)", npc, idc); + 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); + + // Recupera el identificador del nuevo perfil hardware + nwidperfilhard = dbi_conn_sequence_last(dbi->conn, NULL); + + // Crea la relación entre perfiles y componenetes hardware + for (i = 0; i < lon; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT perfileshard_hardwares (idperfilhard,idhardware)" + " VALUES(%d,%d)", nwidperfilhard, tbidhardware[i]); + 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); + } + } else { // Existe un perfil con todos esos componentes + nwidperfilhard = dbi_result_get_uint(result, "idperfilhard"); + dbi_result_free(result); + } + if (idperfilhardware != nwidperfilhard) { // No coinciden los perfiles + // Actualiza el identificador del perfil hardware del ordenador + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET idperfilhard=%d" + " WHERE idordenador=%s", nwidperfilhard, 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); + } + /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard_hardwares WHERE idperfilhard IN " + " (SELECT idperfilhard FROM perfileshard WHERE idperfilhard NOT IN" + " (SELECT DISTINCT idperfilhard from ordenadores))"); + 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); + + /* Eliminar Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard WHERE idperfilhard NOT IN" + " (SELECT DISTINCT idperfilhard FROM ordenadores)"); + 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); + + /* Eliminar Relación de hardwares con Perfiles hardware que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfileshard_hardwares WHERE idperfilhard NOT IN" + " (SELECT idperfilhard FROM perfileshard)"); + 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); + + return true; +} +// ________________________________________________________________________________________________________ +// Función: actualizaSoftware +// +// Descripción: +// Actualiza la base de datos con la configuración software del cliente +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - sft: cadena con el inventario software +// - par: Número de la partición +// - ido: Identificador del ordenador del cliente en la tabla +// - npc: Nombre del ordenador +// - idc: Identificador del centro o Unidad organizativa +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// +// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla +// ________________________________________________________________________________________________________ +bool actualizaSoftware(struct og_dbi *dbi, char *sft, char *par,char *ido, + char *npc, char *idc) +{ + int i, j, lon, aux, idperfilsoft, idnombreso; + bool retval; + char *wsft; + int tbidsoftware[MAXSOFTWARE]; + char *tbSoftware[MAXSOFTWARE], strInt[LONINT], *idsoftwares; + const char *msglog; + dbi_result result; + + /* Toma Centro (Unidad Organizativa) y perfil software */ + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft,numpar" + " FROM ordenadores_particiones" + " WHERE idordenador=%s", 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; + } + idperfilsoft = 0; // Por defecto se supone que el ordenador no tiene aún detectado el perfil software + while (dbi_result_next_row(result)) { + aux = dbi_result_get_uint(result, "numpar"); + if (aux == atoi(par)) { // Se encuentra la partición + idperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); + break; + } + } + dbi_result_free(result); + wsft=escaparCadena(sft); // Codificar comillas simples + if(!wsft) + return false; + + /* Recorre componentes software*/ + lon = splitCadena(tbSoftware, wsft, '\n'); + + if (lon == 0) + return true; // No hay lineas que procesar + if (lon > MAXSOFTWARE) + lon = MAXSOFTWARE; // Limita el número de componentes software + + idnombreso = 0; + for (i = 0; i < lon; i++) { + // Primera línea es el sistema operativo: se obtiene identificador + if (i == 0) { + idnombreso = checkDato(dbi, rTrim(tbSoftware[i]), "nombresos", "nombreso", "idnombreso"); + continue; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT idsoftware FROM softwares WHERE descripcion ='%s'", + rTrim(tbSoftware[i])); + 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)) { + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO softwares (idtiposoftware,descripcion,idcentro,grupoid)" + " VALUES(2,'%s',%s,0)", tbSoftware[i], idc); + if (!result) { // Error al insertar + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + return false; + } + + // Recupera el identificador del software + tbidsoftware[i] = dbi_conn_sequence_last(dbi->conn, NULL); + } else { + tbidsoftware[i] = dbi_result_get_uint(result, "idsoftware"); + } + dbi_result_free(result); + } + + // Ordena tabla de identificadores para cosultar si existe un pefil con esas especificaciones + + for (i = 0; i < lon - 1; i++) { + for (j = i + 1; j < lon; j++) { + if (tbidsoftware[i] > tbidsoftware[j]) { + aux = tbidsoftware[i]; + tbidsoftware[i] = tbidsoftware[j]; + tbidsoftware[j] = aux; + } + } + } + /* Crea cadena de identificadores de componentes software separados por coma */ + sprintf(strInt, "%d", tbidsoftware[lon - 1]); // Pasa a cadena el último identificador que es de mayor longitud + aux = strlen(strInt); // Calcula longitud de cadena para reservar espacio a todos los perfiles + idsoftwares = calloc(1, (sizeof(aux)+1) * lon + lon); + if (idsoftwares == NULL) { + syslog(LOG_ERR, "%s:%d OOM\n", __FILE__, __LINE__); + return false; + } + aux = sprintf(idsoftwares, "%d", tbidsoftware[0]); + for (i = 1; i < lon; i++) + aux += sprintf(idsoftwares + aux, ",%d", tbidsoftware[i]); + + // Comprueba existencia de perfil software y actualización de éste para el ordenador + if (!cuestionPerfilSoftware(dbi, idc, ido, idperfilsoft, idnombreso, idsoftwares, + npc, par, tbidsoftware, lon)) { + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + retval=false; + } else { + retval=true; + } + free(wsft); + free(idsoftwares); + + return retval; +} +// ________________________________________________________________________________________________________ +// Función: CuestionPerfilSoftware +// +// Parámetros: +// - db: Objeto base de datos (ya operativo) +// - tbl: Objeto tabla +// - idcentro: Identificador del centro en la tabla +// - ido: Identificador del ordenador del cliente en la tabla +// - idnombreso: Identificador del sistema operativo +// - idsoftwares: Cadena con los identificadores de componentes software separados por comas +// - npc: Nombre del ordenador del cliente +// - particion: Número de la partición +// - tbidsoftware: Array con los identificadores de componentes software +// - lon: Número de componentes +// Devuelve: +// true: Si el proceso es correcto +// false: En caso de ocurrir algún error +// +// Versión 1.1.0: Se incluye el sistema operativo. Autora: Irina Gómez - ETSII Universidad Sevilla +//_________________________________________________________________________________________________________ +bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido, + int idperfilsoftware, int idnombreso, + char *idsoftwares, char *npc, char *par, + int *tbidsoftware, int lon) +{ + int i, nwidperfilsoft; + const char *msglog; + dbi_result result; + + // Busca perfil soft del ordenador que contenga todos los componentes software encontrados + result = dbi_conn_queryf(dbi->conn, + "SELECT idperfilsoft FROM" + " (SELECT perfilessoft_softwares.idperfilsoft as idperfilsoft," + " group_concat(cast(perfilessoft_softwares.idsoftware AS char( 11) )" + " ORDER BY perfilessoft_softwares.idsoftware SEPARATOR ',' ) AS idsoftwares" + " FROM perfilessoft_softwares" + " GROUP BY perfilessoft_softwares.idperfilsoft) AS temp" + " WHERE idsoftwares LIKE '%s'", idsoftwares); + + 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)) { // No existe un perfil software con esos componentes de componentes software, lo crea + dbi_result_free(result); + result = dbi_conn_queryf(dbi->conn, + "INSERT perfilessoft (descripcion, idcentro, grupoid, idnombreso)" + " VALUES('Perfil Software (%s, Part:%s) ',%s,0,%i)", npc, par, idc,idnombreso); + 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); + // Recupera el identificador del nuevo perfil software + nwidperfilsoft = dbi_conn_sequence_last(dbi->conn, NULL); + + // Crea la relación entre perfiles y componenetes software + for (i = 0; i < lon; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT perfilessoft_softwares (idperfilsoft,idsoftware)" + " VALUES(%d,%d)", nwidperfilsoft, tbidsoftware[i]); + 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); + } + } else { // Existe un perfil con todos esos componentes + nwidperfilsoft = dbi_result_get_uint(result, "idperfilsoft"); + dbi_result_free(result); + } + + if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles + // Actualiza el identificador del perfil software del ordenador + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0" + " WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par); + if (!result) { // Error al insertar + 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); + } + + /* DEPURACIÓN DE PERFILES SOFTWARE */ + + /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft_softwares WHERE idperfilsoft IN "\ + " (SELECT idperfilsoft FROM perfilessoft WHERE idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from ordenadores_particiones) AND idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from imagenes))"); + 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), + /* Eliminar Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft WHERE idperfilsoft NOT IN" + " (SELECT DISTINCT idperfilsoft from ordenadores_particiones)"\ + " AND idperfilsoft NOT IN"\ + " (SELECT DISTINCT idperfilsoft from imagenes)"); + 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), + + /* Eliminar Relación de softwares con Perfiles software que quedan húerfanos */ + result = dbi_conn_queryf(dbi->conn, + "DELETE FROM perfilessoft_softwares WHERE idperfilsoft NOT IN" + " (SELECT idperfilsoft from perfilessoft)"); + 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); + + return true; +} |