/** * Get logs of job * * @param array $task_ids list of tasks id * @return array */ function getJoblogs($task_ids = array()) { global $DB; $debug_mode = $_SESSION['glpi_use_mode'] == Session::DEBUG_MODE; $runclass = new PluginFusioninventoryTaskjobstate(); $run_states = $runclass->getStateNames(); $query_where = array(); $query_where[] = "WHERE 1"; if (isset($_SESSION['glpiactiveentities_string'])) { $query_where[] = getEntitiesRestrictRequest("AND", 'task'); } if (is_array($task_ids) and count($task_ids) > 0) { $query_where[] = "AND task.`id` IN (" . implode(",", $task_ids) . ")"; } // quickly filter empty WHERE entry $query_where = array_filter($query_where); $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('job.targets', 'job.`targets`')); $fieldmap = array(); foreach ($query_fields as $index => $key) { $fieldmap[$key[0]] = $index; } $query_select = array(); foreach ($query_fields as $index => $key) { $query_select[] = $key[1] . " AS '" . $key[0] . "'"; } $query_joins = array(); $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", " ON job.`plugin_fusioninventory_tasks_id` = task.`id`", " AND task.`is_active` = 1")); $data_structure = array('query' => implode("\n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_taskjobs` as job", implode("\n", $query_joins), implode("\n", $query_where))), 'result' => null); $data_structure['result'] = $DB->query($data_structure['query']); //Results grouped by tasks > jobs > jobstates $logs = array(); //Target cache (used to speed up data formatting) $targets_cache = array(); $expanded = array(); if (isset($_SESSION['plugin_fusioninventory_tasks_expanded'])) { $expanded = $_SESSION['plugin_fusioninventory_tasks_expanded']; } while ($result = $data_structure['result']->fetch_row()) { $task_id = $result[$fieldmap['task.id']]; if (!array_key_exists($task_id, $logs)) { $logs[$task_id] = array('task_name' => $result[$fieldmap['task.name']], 'task_id' => $result[$fieldmap['task.id']], 'expanded' => false, 'jobs' => array()); } if (isset($expanded[$task_id])) { $logs[$task_id]['expanded'] = $expanded[$task_id]; } $job_id = $result[$fieldmap['job.id']]; $jobs_handle =& $logs[$task_id]['jobs']; if (!array_key_exists($job_id, $jobs_handle)) { $jobs_handle[$job_id] = array('name' => $result[$fieldmap['job.name']], 'id' => $result[$fieldmap['job.id']], 'method' => $result[$fieldmap['job.method']], 'targets' => array()); } $targets = importArrayFromDB($result[$fieldmap['job.targets']]); $targets_handle =& $jobs_handle[$job_id]['targets']; $agent_state_types = array('agents_prepared', 'agents_cancelled', 'agents_running', 'agents_success', 'agents_error', 'agents_notdone'); if ($result[$fieldmap['job.method']] == 'networkinventory') { $pfNetworkinventory = new PluginFusioninventoryNetworkinventory(); foreach ($targets as $keyt => $target) { $item_type = key($target); $items_id = current($target); if ($item_type == 'PluginFusioninventoryIPRange') { unset($targets[$keyt]); // In this case get devices of this iprange $deviceList = $pfNetworkinventory->getDevicesOfIPRange($items_id); $targets = array_merge($targets, $deviceList); } } } foreach ($targets as $target) { $item_type = key($target); $item_id = current($target); $target_id = $item_type . "_" . $item_id; if (isset($targets_cache[$target_id])) { $item = $targets_cache[$target_id]; } else { $item = new $item_type(); $item->getFromDB($item_id); $targets_cache[$target_id] = $item; } $targets_handle[$target_id] = array('id' => $item->fields['id'], 'name' => $item->fields['name'], 'type_name' => $item->getTypeName(), 'item_link' => $item->getLinkUrl(), 'counters' => array(), 'agents' => array()); // create agent states counter lists foreach ($agent_state_types as $type) { $targets_handle[$target_id]['counters'][$type] = array(); } } } // Query fields mapping used to easily select fields by name $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('agent.id', 'agent.`id`'), array('agent.name', 'agent.`name`'), array('run.id', 'run.`id`'), array('run.itemtype', 'run.`itemtype`'), array('run.items_id', 'run.`items_id`'), array('run.state', 'run.`state`'), array('log.last_date', 'log.`date`'), array('log.last_timestamp', 'UNIX_TIMESTAMP(log.`date`)'), array('log.last_id', 'log.`id`'), array('log.last_comment', 'log.`comment`')); $fieldmap = array(); foreach ($query_fields as $index => $key) { $fieldmap[$key[0]] = $index; } $query_select = array(); foreach ($query_fields as $index => $key) { $query_select[] = $key[1] . " AS '" . $key[0] . "'"; } $query_joins = array(); $query_joins['max_run'] = implode("\n", array("INNER JOIN (", " SELECT", " MAX(run.`id`) AS max_id,", " run.`plugin_fusioninventory_agents_id`,", " run.`plugin_fusioninventory_taskjobs_id`,", " run.`items_id`, run.`itemtype`,", " MAX(log.`id`) AS max_log_id", " FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", " LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", " ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", " GROUP BY", " run.`plugin_fusioninventory_agents_id`,", " run.`plugin_fusioninventory_taskjobs_id`,", " run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`")); $query_joins['run'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobstates` AS run", " ON max_run.`max_id` = run.`id`")); $query_joins['log'] = implode("\n", array("LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` as log", " ON log.`id` = max_run.`max_log_id`")); $query_joins['job'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobs` AS job", " ON job.`id` = run.`plugin_fusioninventory_taskjobs_id`")); $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", " ON job.`plugin_fusioninventory_tasks_id` = task.`id`")); $queries = array(); /* * Get latest jobstates for agents */ $queries['1_last_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null); /* * Get last finished jobstates (ie. `state` >= 3) */ $query_joins['max_run'] = implode("\n", array("INNER JOIN (", " SELECT", " MAX(run.`id`) AS max_id,", " run.`plugin_fusioninventory_agents_id`,", " run.`plugin_fusioninventory_taskjobs_id`,", " run.`items_id`, run.`itemtype`,", " MAX(log.`id`) AS max_log_id", " FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", " LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", " ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", " WHERE run.`state` IN ( " . implode(",", array(PluginFusioninventoryTaskjobstate::FINISHED, PluginFusioninventoryTaskjobstate::IN_ERROR)) . " )", " GROUP BY", " run.`plugin_fusioninventory_agents_id`,", " run.`plugin_fusioninventory_taskjobs_id`,", " run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`")); $queries['2_finished_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null); $query_chrono = array("start" => microtime(true), "end" => 0); ksort($queries); foreach ($queries as $query_name => $contents) { $queries[$query_name]['result'] = $DB->query($contents['query']); $query_chrono['end'] = microtime(true); // For debug only //if ($debug_mode) { // file_put_contents("/tmp/glpi_".$query_name.".sql",$contents['query']); //} } $agents = array(); $format_chrono = array("start" => microtime(true), "end" => 0); foreach ($queries as $query_name => $contents) { if (!is_null($contents['result'])) { while ($result = $contents['result']->fetch_row()) { // We need to check if the results are consistent with the view's structure gathered // by the first query $task_id = $result[$fieldmap['task.id']]; //if (!array_key_exists($task_id, $logs)) { if (!isset($logs[$task_id])) { continue; } $job_id = $result[$fieldmap['job.id']]; $jobs =& $logs[$task_id]['jobs']; if (!isset($jobs[$job_id])) { continue; } $target_id = $result[$fieldmap['run.itemtype']] . '_' . $result[$fieldmap['run.items_id']]; $targets =& $jobs[$job_id]['targets']; if (!isset($targets[$target_id])) { continue; } $counters =& $targets[$target_id]['counters']; $agent_id = $result[$fieldmap['agent.id']]; $agents[$agent_id] = $result[$fieldmap['agent.name']]; if (!isset($targets[$target_id]['agents'][$agent_id])) { $targets[$target_id]['agents'][$agent_id] = array(); } $agent_state = ''; // Update counters switch ($result[$fieldmap['run.state']]) { case PluginFusioninventoryTaskjobstate::CANCELLED: // We put this agent in the cancelled counter if it does not have any other job // states. if (!isset($counters['agents_prepared'][$agent_id]) and !isset($counters['agents_running'][$agent_id])) { $counters['agents_cancelled'][$agent_id] = 1; $agent_state = 'cancelled'; } break; case PluginFusioninventoryTaskjobstate::PREPARED: // We put this agent in the prepared counter if it has not yet completed any job. $counters['agents_prepared'][$agent_id] = 1; $agent_state = 'prepared'; break; case PluginFusioninventoryTaskjobstate::SERVER_HAS_SENT_DATA: case PluginFusioninventoryTaskjobstate::AGENT_HAS_SENT_DATA: // This agent is running so it must not be in any other counter foreach ($agent_state_types as $type) { if (isset($counters[$type][$agent_id])) { unset($counters[$type][$agent_id]); } } $counters['agents_running'][$agent_id] = 1; $agent_state = 'running'; break; case PluginFusioninventoryTaskjobstate::IN_ERROR: if (isset($counters['agents_success'][$agent_id])) { unset($counters['agents_success'][$agent_id]); } $counters['agents_error'][$agent_id] = 1; $agent_state = 'error'; if (isset($counters['agents_notdone'][$agent_id])) { unset($counters['agents_notdone'][$agent_id]); } break; case PluginFusioninventoryTaskjobstate::FINISHED: if (isset($counters['agents_error'][$agent_id])) { unset($counters['agents_error'][$agent_id]); } $counters['agents_success'][$agent_id] = 1; $agent_state = 'success'; if (isset($counters['agents_notdone'][$agent_id])) { unset($counters['agents_notdone'][$agent_id]); } break; } if (!isset($counters['agents_error'][$agent_id]) and !isset($counters['agents_success'][$agent_id])) { $counters['agents_notdone'][$agent_id] = 1; } if (isset($counters['agents_running'][$agent_id]) or isset($counters['agents_prepared'][$agent_id])) { unset($counters['agents_cancelled'][$agent_id]); } $targets[$target_id]['agents'][$agent_id][] = array('agent_id' => $agent_id, 'numstate' => $result[$fieldmap['run.state']], 'state' => $agent_state, 'jobstate_id' => $result[$fieldmap['run.id']], 'last_log_id' => $result[$fieldmap['log.last_id']], 'last_log_date' => $result[$fieldmap['log.last_date']], 'timestamp' => $result[$fieldmap['log.last_timestamp']], 'last_log' => $result[$fieldmap['log.last_comment']]); } } } $format_chrono['end'] = microtime(true); if ($debug_mode) { function tmp_display_log($log) { return "ID:" . $log['task_id'] . "(" . $log['task_name'] . ")"; } if (PluginFusioninventoryConfig::isExtradebugActive()) { Toolbox::logDebug(array("tasks" => implode(',', array_map('tmp_display_log', $logs)), "row count" => count($logs), "Joblogs Query" => self::FormatChrono($query_chrono), "Format logs results" => self::FormatChrono($format_chrono))); } } return array('tasks' => $logs, 'agents' => $agents); }