ogserver/src/ogAdmServer.c

619 lines
21 KiB
C

// *******************************************************************************************************
// 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 "wol.h"
#include <syslog.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <jansson.h>
#include <time.h>
// ________________________________________________________________________________________________________
// 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: 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 - 1] = dbi_conn_sequence_last(dbi->conn, NULL);
} else {
tbidsoftware[i - 1] = dbi_result_get_uint(result, "idsoftware");
}
dbi_result_free(result);
}
lon--;
// 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 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;
}