diff --git a/pandora_console/include/class/TreeService.class.php b/pandora_console/include/class/TreeService.class.php index cb5ae2011c..150eb5f7c3 100644 --- a/pandora_console/include/class/TreeService.class.php +++ b/pandora_console/include/class/TreeService.class.php @@ -1,31 +1,85 @@ 0) { $this->metaID = $id_server_meta; + $this->serverID = $id_server_meta; } parent::__construct( @@ -66,23 +121,45 @@ class TreeService extends Tree $this->L2inner = 'LEFT JOIN tservice_element tse ON tse.id_agent = ta.id_agente'; - $this->L2condition = 'AND tse.id_service='.$this->id; + $this->L2condition = sprintf( + ' AND tse.id_service=%d AND tse.id_server_meta=0 ', + $this->id + ); } + /** + * Setter (propagate counters). + * + * @param boolean $value Set. + * + * @return void + */ public function setPropagateCounters($value) { $this->propagateCounters = (bool) $value; } + /** + * Set display all groups. + * + * @param boolean $value Set. + * + * @return void + */ public function setDisplayAllGroups($value) { $this->displayAllGroups = (bool) $value; } + /** + * Generates tree data. + * + * @return void + */ protected function getData() { if (is_metaconsole() === true && $this->metaID > 0) { @@ -95,6 +172,7 @@ class TreeService extends Tree $this->metaID, ] ); + $this->connectedToNode = true; } if ($this->id == -1) { @@ -112,6 +190,11 @@ class TreeService extends Tree } + /** + * Generates first level data. + * + * @return void + */ protected function getFirstLevel() { global $config; @@ -160,6 +243,11 @@ class TreeService extends Tree } + /** + * Retrieve root services. + * + * @return array Of root services. + */ protected function getProcessedServices() { $is_favourite = $this->getServiceFavouriteFilter(); @@ -224,6 +312,13 @@ class TreeService extends Tree } + /** + * Retrieve first level fields. + * + * @deprecated 746. + * + * @return string With a first level fields. + */ protected function getFirstLevelFields() { $fields = []; @@ -232,194 +327,310 @@ class TreeService extends Tree } + /** + * Retrieves elements (second level) from selected rootID. + * + * @return void + */ protected function getSecondLevel() { - $data = []; - $data_agents = []; - $data_modules = []; - $data_services = []; + $service = new Service($this->id, true); - $sql = $this->getSecondLevelSql(); - $data_agents = db_process_sql($sql); + $output = []; + foreach ($service->children() as $item) { + $tmp = []; - if (empty($data_agents)) { - $data_agents = []; - } - - $this->processAgents($data_agents); - - foreach ($data_agents as $key => $agent) { - $data_agents[$key]['showEventsBtn'] = 1; - $data_agents[$key]['eventAgent'] = $agent['id']; - } - - $sql = $this->getSecondLevelModulesSql(); - $data_modules = db_process_sql($sql); - - if (empty($data_modules)) { - $data_modules = []; - } else { - foreach ($data_modules as $key => $module) { - switch ($module['estado']) { - case '0': - $module_status = 'ok'; - $module_title = 'NORMAL'; - break; - - case '1': - $module_status = 'critical'; - $module_title = 'CRITICAL'; - break; - - case '2': - $module_status = 'warning'; - $module_title = 'WARNING'; - break; - - case '3': - $module_status = 'down'; - $module_title = 'UNKNOWN'; - break; - - case '4': - $module_status = 'no_data'; - $module_title = 'NOT INITIALIZED'; - break; - - default: - $module_status = 'down'; - $module_title = 'UNKNOWN'; - break; - } - - $data_modules[$key]['statusImageHTML'] = ''.$module_title.' status.'; - $data_modules[$key]['showEventsBtn'] = 1; - $data_modules[$key]['eventModule'] = $module['id_agente_modulo']; + if ($this->metaID > 0) { + $tmp['metaID'] = $this->metaID; + } else if ($item->id_server_meta() !== 0) { + $tmp['metaID'] = $item->id_server_meta(); } - } - $sql = $this->getSecondLevelServicesSql(); - $data_services = db_process_sql($sql); + $tmp['serverID'] = $tmp['metaID']; - $data_services = array_reduce( - $data_services, - function ($carry, $item) { - if ($item['id_server_meta'] > 0 - && is_metaconsole() === true - ) { - // Impersonate node. - \enterprise_include_once('include/functions_metaconsole.php'); - $r = \enterprise_hook( - 'metaconsole_connect', - [ - null, - $item['id_server_meta'], - ] - ); - - if ($r === NOERR) { - $item = db_get_row_sql( - sprintf( - 'SELECT - ts.id, - ts.id_agent_module, - ts.name, - ts.name as `alias`, - %d as `rootID`, - "services" as `rootType`, - "services" as `type`, - ts.quiet, - %d as id_server_meta, - SUM(if((tse.id_agent<>0), 1, 0)) AS `total_agents`, - SUM(if((tse.id_agente_modulo<>0), 1, 0)) AS `total_modules`, - SUM(if((tse.id_service_child<>0), 1, 0)) AS `total_services` - FROM tservice ts - LEFT JOIN tservice_element tse - ON tse.id_service = ts.id - WHERE ts.id = %d - GROUP BY ts.id', - $item['id_server_meta'], - $item['rootID'], - $item['id'] - ) - ); - $item['obj'] = new Service($item['id']); + switch ($item->type()) { + case SERVICE_ELEMENT_AGENT: + if ($item->agent() === null) { + // Skip item. + continue 2; } - // Restore connection. - \enterprise_hook('metaconsole_restore_db'); - } else { - $item['obj'] = new Service($item['id']); - } + $tmp['id'] = $item->agent()->id_agente(); + $tmp['name'] = $item->agent()->nombre(); + $tmp['alias'] = $item->agent()->alias(); + $tmp['fired_count'] = $item->agent()->fired_count(); + $tmp['normal_count'] = $item->agent()->normal_count(); + $tmp['warning_count'] = $item->agent()->warning_count(); + $tmp['critical_count'] = $item->agent()->critical_count(); + $tmp['unknown_count'] = $item->agent()->unknown_count(); + $tmp['notinit_count'] = $item->agent()->notinit_count(); + $tmp['total_count'] = $item->agent()->total_count(); - $carry[] = $item; - return $carry; - }, - [] - ); + if ($item->agent()->quiet() > 0 + || $item->agent()->cps() > 0 + ) { + $tmp['quiet'] = 1; + } else { + $tmp['quiet'] = 0; + } - $service_stats = []; + $tmp['state_critical'] = $tmp['critical_count']; + $tmp['state_warning'] = $tmp['warning_count']; + $tmp['state_unknown'] = $tmp['unknown_count']; + $tmp['state_notinit'] = $tmp['notinit_count']; + $tmp['state_normal'] = $tmp['normal_count']; + $tmp['state_total'] = $tmp['total_count']; + $tmp['type'] = SERVICE_ELEMENT_AGENT; + $tmp['rootID'] = $this->rootID; + $tmp['rootType'] = $this->rootType; + $tmp['counters'] = [ + 'alerts' => $item->agent()->fired_count(), + 'ok' => $item->agent()->normal_count(), + 'warning' => $item->agent()->warning_count(), + 'critical' => $item->agent()->critical_count(), + 'unknown' => $item->agent()->unknown_count(), + 'not_init' => $item->agent()->notinit_count(), + 'total' => $item->agent()->total_count(), + ]; - foreach ($data_services as $service) { - $service_stats[$service['id']]['id'] = (int) $service['id']; - $service_stats[$service['id']]['name'] = $service['name']; - $service_stats[$service['id']]['alias'] = $service['name']; - if (($service['total_services'] + $service['total_agents'] + $service['total_modules']) > 0) { - $service_stats[$service['id']]['searchChildren'] = 1; - } else { - $services[$service['id']]['searchChildren'] = 0; - } + switch ($item->agent()->lastStatus()) { + case AGENT_STATUS_NORMAL: + $tmp['statusImageHTML'] = 'NORMAL status.'; + break; - $service_stats[$service['id']]['rootID'] = $service['rootID']; - if ($this->metaID > 0) { - $service_stats[$service['id']]['metaID'] = $this->metaID; - } else { - $service_stats[$service['id']]['metaID'] = $service['id_server_meta']; - } + case AGENT_STATUS_CRITICAL: + case AGENT_STATUS_ALERT_FIRED: + $tmp['statusImageHTML'] = 'CRITICAL status.'; + break; - $service_stats[$service['id']]['rootType'] = $service['rootType']; - $service_stats[$service['id']]['type'] = 'services'; - $service_stats[$service['id']]['children'] = []; - $service_stats[$service['id']]['serviceDetail'] = 'index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.(int) $service['id']; - $service_stats[$service['id']]['counters'] = [ - 'total_services' => $service['total_services'], - 'total_agents' => $service['total_agents'], - 'total_modules' => $service['total_modules'], - ]; + case AGENT_STATUS_WARNING: + $tmp['statusImageHTML'] = 'WARNING status.'; + break; - switch ($service['obj']->status()) { - case SERVICE_STATUS_NORMAL: - $service_stats[$service['id']]['statusImageHTML'] = 'NORMAL status.'; + case AGENT_STATUS_UNKNOWN: + default: + $tmp['statusImageHTML'] = 'UNKNOWN status.'; + break; + } + + $tmp['children'] = []; + $tmp['searchChildren'] = 1; + $tmp['showEventsBtn'] = 1; + $tmp['eventAgent'] = $item->agent()->id_agente(); break; - case SERVICE_STATUS_CRITICAL: - $service_stats[$service['id']]['statusImageHTML'] = 'CRITICAL status.'; + case SERVICE_ELEMENT_MODULE: + if ($item->module() === null) { + // Skip item. + continue 2; + } + + $tmp['id'] = $item->module()->id_agente_modulo(); + $tmp['name'] = $item->module()->nombre(); + $tmp['id_tipo_modulo'] = $item->module()->id_tipo_modulo(); + $tmp['id_modulo'] = $item->module()->id_modulo(); + $tmp['estado'] = $item->module()->lastStatus(); + $tmp['datos'] = $item->module()->lastValue(); + $tmp['parent'] = $item->module()->parent_module_id(); + $alerts = alerts_get_alerts_module_name( + $item->module()->id_agente_modulo() + ); + if ($alerts !== false) { + // Seems to be used as 'flag'. + $tmp['alerts'] = $alerts[0]['id']; + } + + $tmp['unit'] = $item->module()->unit(); + $tmp['type'] = SERVICE_ELEMENT_MODULE; + $tmp['id_module_type'] = $item->module()->id_tipo_modulo(); + $tmp['server_type'] = $tmp['id_module_type']; + $tmp['status'] = $item->module()->lastStatus(); + $tmp['value'] = modules_get_agentmodule_data_for_humans( + array_merge( + $item->module()->toArray(), + [ 'datos' => $item->module()->lastValue() ] + ) + ); + + $title = $item->module()->lastStatusTitle(); + + if (is_numeric($item->module()->lastValue())) { + $divisor = get_data_multiplier($item->module()->unit()); + $title .= ' : '.format_for_graph( + $item->module()->lastValue(), + 1, + '.', + ',', + $divisor + ); + } else { + $title .= ' : '.substr( + io_safe_output( + $item->module()->lastValue() + ), + 0, + 42 + ); + } + + $tmp['serverName'] = $item->module()->agent()->server_name(); + $tmp['serverID'] = $tmp['metaID']; + $tmp['statusText'] = $item->module()->lastStatusText(); + $tmp['showGraphs'] = 1; + $tmp['showEventsBtn'] = 1; + $tmp['eventAgent'] = $item->module()->id_agente(); + + $html = 'module()->lastStatusTitle().'" />'; + $tmp['statusImageHTML'] = $html; + $tmp = array_merge( + $tmp, + $this->getModuleGraphLinks( + $tmp + ) + ); break; - case SERVICE_STATUS_WARNING: - $service_stats[$service['id']]['statusImageHTML'] = 'WARNING status.'; + case SERVICE_ELEMENT_SERVICE: + if ($item->service() === null) { + // Skip item. + continue 2; + } + + $tmp['id'] = (int) $item->service()->id(); + $tmp['name'] = $item->service()->name(); + $tmp['alias'] = $item->service()->name(); + + if ($this->connectedToNode === false + && is_metaconsole() === true + && $tmp['metaID'] > 0 + ) { + // Impersonate node. + \enterprise_include_once('include/functions_metaconsole.php'); + \enterprise_hook( + 'metaconsole_connect', + [ + null, + $tmp['metaID'], + ] + ); + } + + $grandchildren = $item->service()->children(); + + if ($this->connectedToNode === false + && is_metaconsole() === true + && $tmp['metaID'] > 0 + ) { + // Restore connection. + \enterprise_hook('metaconsole_restore_db'); + } + + $counters = [ + 'total_modules' => 0, + 'total_agents' => 0, + 'total_services' => 0, + 'total_dynamic' => 0, + 'total' => 0, + ]; + + if (is_array($grandchildren) === true) { + $counters = array_reduce( + $grandchildren, + function ($carry, $item) { + if ($item->type() === SERVICE_ELEMENT_MODULE) { + $carry['total_modules']++; + } else if ($item->type() === SERVICE_ELEMENT_AGENT) { + $carry['total_agents']++; + } else if ($item->type() === SERVICE_ELEMENT_SERVICE) { + $carry['total_services']++; + } else if ($item->type() === SERVICE_ELEMENT_DYNAMIC) { + $carry['total_dynamic']++; + } + + $carry['total']++; + + return $carry; + }, + $counters + ); + } + + if ($counters['total'] > 0) { + $tmp['searchChildren'] = 1; + } + + $tmp['type'] = 'services'; + $tmp['rootType'] = 'services'; + $tmp['children'] = []; + $tmp['serviceDetail'] = ui_get_full_url( + 'index.php?sec=network&sec2=enterprise/operation/services/services&tab=service_map&id_service='.$item->service()->id() + ); + $tmp['counters'] = $counters; + $tmp['rootID'] = $this->rootID; + switch ($item->service()->lastStatus()) { + case SERVICE_STATUS_NORMAL: + $tmp['statusImageHTML'] = 'NORMAL status.'; + break; + + case SERVICE_STATUS_CRITICAL: + $tmp['statusImageHTML'] = 'CRITICAL status.'; + break; + + case SERVICE_STATUS_WARNING: + $tmp['statusImageHTML'] = 'WARNING status.'; + break; + + case SERVICE_STATUS_UNKNOWN: + default: + $tmp['statusImageHTML'] = 'UNKNOWN status.'; + break; + } break; - case SERVICE_STATUS_UNKNOWN: + case SERVICE_ELEMENT_DYNAMIC: + // TODO. + continue 2; + default: - $service_stats[$service['id']]['statusImageHTML'] = 'UNKNOWN status.'; - break; + // Unknown type. + continue 2; } + + $output[] = $tmp; } - $data_services = array_values($service_stats); - - $data = array_merge($data_services, $data_agents, $data_modules); - - if (empty($data)) { - $this->tree = []; - return; - } - - $this->tree = $data; + $this->tree = $output; } + /** + * SQL query to retrieve second level items. + * + * @return string SQL. + */ protected function getSecondLevelServicesSql() { $group_acl = $this->getGroupAclCondition(); @@ -453,28 +664,16 @@ class TreeService extends Tree } - protected function getSecondLevelModulesSql() - { - $sql = "SELECT tse.id_agente_modulo, nombre AS `name`, nombre AS `alias`, tse.id_service AS `rootID`, 'services' AS `rootType`, 'modules' AS `type`, estado - FROM tservice_element tse - INNER JOIN tagente_modulo tam ON tse.id_agente_modulo=tam.id_agente_modulo - INNER JOIN tagente_estado tae ON tam.id_agente_modulo=tae.id_agente_estado - WHERE tse.id_service=$this->id AND tse.id_agente_modulo<>0 - "; - - return $sql; - } - - - protected function getAgentStatusFilter($status=self::TV_DEFAULT_AGENT_STATUS) - { - return ''; - } - - + /** + * Retrieve SQL filter for current filte.r + * + * @return string SQL filter. + */ protected function getServiceFavouriteFilter() { - if (isset($this->filter['is_favourite']) && !empty($this->filter['is_favourite'])) { + if (isset($this->filter['is_favourite']) === true + && empty($this->filter['is_favourite']) === false + ) { return ' AND is_favourite = 1'; } @@ -482,4 +681,70 @@ class TreeService extends Tree } + /** + * Overwrites partial functionality of general Tree.class. + * + * @param array $module Data of given module. + * + * @return array Complementary information. + */ + protected function getModuleGraphLinks(array $module) + { + $graphType = return_graphtype($module['id_module_type']); + $url = ui_get_full_url( + 'operation/agentes/stat_win.php', + false, + false, + false + ); + $winHandle = dechex(crc32($module['id'].$module['name'])); + + $graph_params = [ + 'type' => $graphType, + 'period' => SECONDS_1DAY, + 'id' => $module['id'], + 'refresh' => SECONDS_10MINUTES, + ]; + + if (is_metaconsole() === true) { + // Set the server id. + $graph_params['server'] = $module['serverID']; + } + + $graph_params_str = http_build_query($graph_params); + $moduleGraphURL = $url.'?'.$graph_params_str; + + return [ + 'moduleGraph' => [ + 'url' => $moduleGraphURL, + 'handle' => $winHandle, + ], + 'snapshot' => ui_get_snapshot_link( + [ + 'id_module' => $module['id'], + 'interval' => $module['current_interval'], + 'module_name' => $module['name'], + 'id_node' => (($module['serverID'] > 0) ? $module['serverID'] : 0), + ], + true + ), + ]; + + } + + + /** + * Needs to be defined to maintain Tree view functionality. + * + * @param integer $status Status. + * + * @return string Fixed string. + */ + protected function getAgentStatusFilter( + $status=self::TV_DEFAULT_AGENT_STATUS + ) { + return ''; + } + + } diff --git a/pandora_console/include/lib/Module.php b/pandora_console/include/lib/Module.php index 3076455d81..48240ca288 100644 --- a/pandora_console/include/lib/Module.php +++ b/pandora_console/include/lib/Module.php @@ -393,6 +393,99 @@ class Module extends Entity } + /** + * Retrieves last status in text format. + * + * @return string Status in text format. + */ + public function lastStatusText() + { + switch ($this->lastStatus()) { + case AGENT_MODULE_STATUS_CRITICAL_ALERT: + case AGENT_MODULE_STATUS_CRITICAL_BAD: + return 'critical'; + + case AGENT_MODULE_STATUS_WARNING_ALERT: + case AGENT_MODULE_STATUS_WARNING: + return 'warning'; + + case AGENT_MODULE_STATUS_UNKNOWN: + return 'unknown'; + + case AGENT_MODULE_STATUS_NO_DATA: + case AGENT_MODULE_STATUS_NOT_INIT: + return 'not_init'; + + case AGENT_MODULE_STATUS_NORMAL_ALERT: + case AGENT_MODULE_STATUS_NORMAL: + default: + return 'ok'; + } + } + + + /** + * Return path to image representing last status. + * + * @return string Relative URL to image. + */ + public function lastStatusImage() + { + switch ($this->lastStatus()) { + case AGENT_MODULE_STATUS_CRITICAL_ALERT: + case AGENT_MODULE_STATUS_CRITICAL_BAD: + return STATUS_MODULE_CRITICAL_BALL; + + case AGENT_MODULE_STATUS_WARNING_ALERT: + case AGENT_MODULE_STATUS_WARNING: + return STATUS_MODULE_WARNING_BALL; + + case AGENT_MODULE_STATUS_UNKNOWN: + return STATUS_MODULE_UNKNOWN_BALL; + + case AGENT_MODULE_STATUS_NO_DATA: + case AGENT_MODULE_STATUS_NOT_INIT: + return STATUS_MODULE_NO_DATA_BALL; + + case AGENT_MODULE_STATUS_NORMAL_ALERT: + case AGENT_MODULE_STATUS_NORMAL: + default: + return STATUS_MODULE_OK_BALL; + } + } + + + /** + * Return translated string representing last status of the module. + * + * @return string Title. + */ + public function lastStatusTitle() + { + switch ($this->lastStatus()) { + case AGENT_MODULE_STATUS_CRITICAL_ALERT: + case AGENT_MODULE_STATUS_CRITICAL_BAD: + return __('CRITICAL'); + + case AGENT_MODULE_STATUS_WARNING_ALERT: + case AGENT_MODULE_STATUS_WARNING: + return __('WARNING'); + + case AGENT_MODULE_STATUS_UNKNOWN: + return __('UNKNOWN'); + + case AGENT_MODULE_STATUS_NO_DATA: + case AGENT_MODULE_STATUS_NOT_INIT: + return __('NO DATA'); + + case AGENT_MODULE_STATUS_NORMAL_ALERT: + case AGENT_MODULE_STATUS_NORMAL: + default: + return __('NORMAL'); + } + } + + /** * Sets or retrieves value of id_tipo_modulo (complex). * diff --git a/pandora_server/lib/PandoraFMS/PredictionServer.pm b/pandora_server/lib/PandoraFMS/PredictionServer.pm index 361eb338e2..6f77845456 100644 --- a/pandora_server/lib/PandoraFMS/PredictionServer.pm +++ b/pandora_server/lib/PandoraFMS/PredictionServer.pm @@ -105,7 +105,7 @@ sub data_producer ($) { AND tagente_modulo.id_modulo = 5 AND (tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()) - ORDER BY last_execution_try ASC ', (is_metaconsole($pa_config) ? '' : safe_input($pa_config->{'servername'}))); + ORDER BY last_execution_try ASC ', safe_input($pa_config->{'servername'})); } else { @rows = get_db_rows ($dbh, 'SELECT DISTINCT(tagente_modulo.id_agente_modulo), @@ -123,7 +123,7 @@ sub data_producer ($) { AND tagente_modulo.id_modulo = 5 AND (tagente_modulo.flag = 1 OR (tagente_estado.last_execution_try + tagente_estado.current_interval) < UNIX_TIMESTAMP()) - ORDER BY last_execution_try ASC', (is_metaconsole($pa_config) ? '' : safe_input($pa_config->{'servername'})), PREDICTIONSERVER); + ORDER BY last_execution_try ASC', safe_input($pa_config->{'servername'}), PREDICTIONSERVER); } foreach my $row (@rows) {