%PDF- %PDF-
| Direktori : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/ |
| Current File : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/taskview.class.php |
<?php
/**
* ---------------------------------------------------------------------
* GLPI Inventory Plugin
* Copyright (C) 2021 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on FusionInventory for GLPI
* Copyright (C) 2010-2021 by the FusionInventory Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI Inventory Plugin.
*
* GLPI Inventory Plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPI Inventory Plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with GLPI Inventory Plugin. If not, see <https://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* Manage the display part of tasks.
*/
class PluginGlpiinventoryTaskView extends PluginGlpiinventoryCommonView
{
/**
* __contruct function where initialize base URLs
*/
public function __construct()
{
parent::__construct();
$this->base_urls = array_merge($this->base_urls, [
'fi.job.logs' => $this->getBaseUrlFor('fi.ajax') . "/taskjob_logs.php",
]);
}
/**
* Show job logs
*/
public function showJobLogs()
{
$task_id = $this->fields['id'] ?? null;
echo "<div class='card fusinv_panel'>";
echo "<div class='row'>";
// add a list limit for include old jobs
$include_oldjobs_id = $this->showDropdownFromArray(
__("Include old jobs", 'glpiinventory'),
null,
[
1 => __('Last'),
2 => 2,
5 => 5,
10 => 10,
25 => 25,
50 => 50,
100 => 100,
250 => 250,
-1 => __('All')
],
['value' => $_SESSION['glpi_plugin_glpiinventory']['includeoldjobs']]
);
// add an auto-refresh control
$refresh_randid = $this->showDropdownFromArray(
__("refresh interval", "glpiinventory"),
null,
[
"off" => __('Off', 'glpiinventory'),
"1" => '1 ' . _n('second', 'seconds', 1),
"5" => '5 ' . _n('second', 'seconds', 5),
"10" => '10 ' . _n('second', 'seconds', 10),
"60" => '1 ' . _n('minute', 'minutes', 1),
"120" => '2 ' . _n('minute', 'minutes', 2),
"300" => '5 ' . _n('minute', 'minutes', 5),
"600" => '10 ' . _n('minute', 'minutes', 10),
],
['value' => $_SESSION['glpi_plugin_glpiinventory']['refresh']]
);
// display export button
echo "<div class='col mt-auto'>";
echo '<a class="openExportDialog pointer btn btn-icon btn-sm btn-secondary me-1 pe-2">';
echo '<i class="ti ti-save"></i>';
echo'<span class="d-none d-xxl-block">' . __('Export task result', 'glpinventory') . '</span>';
echo '</a>';
// Add a manual refresh button
echo "<div class='refresh_button submit'>";
echo "<span></span>";
echo "</div>"; // .refresh_button
echo "</div>";
echo "</div>"; // .fusinv_form
echo "</div>"; // .fusinv_panel
// Display Export modal
echo "<div class='fusinv_panel' id='fiTaskExport_modalWindow'>";
echo "<form method='POST' class='task_export_form center'
action='" . self::getFormURLWithID($task_id) . "'>";
// states checkboxes
echo "<label for='include_old_jobs'>" . __("Task execution states", 'glpiinventory') .
"</label>";
echo "<div class='state_checkboxes'>";
// set options checked by default
$agent_state_types = [
'agents_prepared' => false,
'agents_running' => true,
'agents_cancelled' => false,
'agents_success' => true,
'agents_error' => true,
'agents_postponed' => false,
];
foreach ($agent_state_types as $agent_state_type => $agent_state_checked) {
$agent_state_type = str_replace("agents_", "", $agent_state_type);
$locale = __(ucfirst($agent_state_type), 'glpiinventory');
$checked = "";
if ($agent_state_checked) {
$checked = "checked='checked'";
}
echo "<div class='agent_state_type_checkbox'>";
echo "<input type='checkbox' $checked name='agent_state_types[]' " .
"value='$agent_state_type' id='agent_state_types_$agent_state_type' />";
echo "<label for='agent_state_types_$agent_state_type'> $locale</label>";
echo "</div>";
}
echo "</div>"; // .state_checkboxes
echo "<div class='clear_states'></div>";
echo Html::hidden('task_id', ['value' => $task_id]);
echo Html::submit(_sx('button', 'Export'), ['name' => 'export_jobs', 'class' => 'btn btn-icon btn-sm btn-secondary me-1 pe-2']);
Html::closeForm();
echo "</div>"; // #fiTaskExport_modalWindow
// Template structure for tasks' blocks
echo "<script id='template_task' type='x-tmpl-mustache'>
<div id='{{task_id}}' class='task_block {{expanded}}'>";
if (!$task_id != null) {
echo"<h3>" . _n('Task', 'Tasks', 1, 'glpiinventory') . "
<span class='task_name'>{{task_name}}</span></h3>
<a href='" . PluginGlpiinventoryTask::getFormURL() . "?id={{task_id}}' class='task_block_link'>
<i class='fa fa-link pointer'></i>
</a>";
}
echo "<div class='jobs_block'></div>
</div>
</script>";
// Template structure for jobs' blocks
echo "<script id='template_job' type='x-tmpl-mustache'>
<div id='{{job_id}}' class='card job_block'>
<h3 class='job_name'>{{job_name}}</h3>
<div class='card targets_block'></div>
</div>
</script>";
// Template structure for targets' blocks
echo "<script id='template_target' type='x-tmpl-mustache'>
<div id='{{target_id}}' class='card target_block'>
<div class='target_details'>
<div class='target_infos'>
<h4 class='target_name'>
<a target='_blank' href={{target_link}}>{{target_name}}</a>
</h4>
<div class='target_stats'>
</div>
</div>
<div class='progressbar'></div>
</div>
<div class='show_more'></div>
<div class='agents_block'></div>
<div class='show_more'></div>
</script>";
// Template structure for targets' statistics
echo "<script id='template_target_stats' type='x-tmp-mustache'>
<div class='{{stats_type}} stats_block'></div>
</script>";
// Template for counters' blocks
echo "<script id='template_counter_block' type='x-tmpl-mustache'>
<div class='counter_block {{counter_type}} {{#counter_empty}}empty{{/counter_empty}}'>
<a class='toggle_details_type'
data-counter_type='{{counter_type}}'
data-chart_id='{{chart_id}}'
title='" . __("Show/Hide details", "glpiinventory") . "'>
<div class='fold'></div>
<span class='counter_name'>{{counter_type_name}}</span>
<span class='counter_value'>{{counter_value}}</span>
</a>
</div>
</script>";
// List of counter names
echo Html::scriptBlock("$(document).ready(function() {
taskjobs.statuses_order = {
last_executions: [
'agents_prepared',
'agents_running',
'agents_cancelled',
],
last_finish_states: [
'agents_notdone',
'agents_success',
'agents_error'
]
};
taskjobs.statuses_names = {
'agents_notdone': '" . __('Not done yet', 'glpiinventory') . "',
'agents_error': '" . __('In error', 'glpiinventory') . "',
'agents_success': '" . __('Successful', 'glpiinventory') . "',
'agents_running': '" . __('Running', 'glpiinventory') . "',
'agents_prepared': '" . __('Prepared', 'glpiinventory') . "',
'agents_postponed': '" . __('Postponed', 'glpiinventory') . "',
'agents_cancelled': '" . __('Cancelled', 'glpiinventory') . "',
};
taskjobs.logstatuses_names = " .
json_encode(PluginGlpiinventoryTaskjoblog::dropdownStateValues()) . ";
});");
// Template for agents' blocks
echo "<script id='template_agent' type='x-tmpl-mustache'>
<div class='agent_block' id='{{agent_id}}'>
<div class='status {{status.last_exec}}'></span>
<div class='status {{status.last_finish}}'></span>
</div>
</script>";
// Display empty block for each jobs display
// which will be rendered later by mustache.js
echo "<div class='tasks_block'></div>";
$agent = new Agent();
$Computer = new Computer();
echo Html::scriptBlock("$(document).ready(function() {
taskjobs.task_id = '" . $task_id . "';
taskjobs.ajax_url = '" . $this->getBaseUrlFor('fi.job.logs') . "';
taskjobs.agents_url = '" . $agent->getFormUrl() . "';
taskjobs.includeoldjobs = '" . $_SESSION['glpi_plugin_glpiinventory']['includeoldjobs'] . "';
taskjobs.refresh = '" . $_SESSION['glpi_plugin_glpiinventory']['refresh'] . "';
taskjobs.computers_url = '" . $Computer->getFormUrl() . "';
taskjobs.init_templates();
taskjobs.init_refresh_form(
'" . $this->getBaseUrlFor('fi.job.logs') . "',
'" . $task_id . "',
'dropdown_" . $refresh_randid . "'
);
taskjobs.init_include_old_jobs_buttons(
'" . $this->getBaseUrlFor('fi.job.logs') . "',
'" . $task_id . "',
'dropdown_" . $include_oldjobs_id . "'
);
taskjobs.update_logs_timeout(
'" . $this->getBaseUrlFor('fi.job.logs') . "',
'" . $task_id . "',
'dropdown_" . $refresh_randid . "'
);
});");
}
/**
* Display form for task configuration
*
* @param integer $id ID of the task
* @param $options array
* @return boolean TRUE if form is ok
*
**/
public function showForm($id, $options = [])
{
$pfTaskjob = new PluginGlpiinventoryTaskjob();
$taskjobs = [];
$new_item = false;
if ($id > 0) {
$this->getFromDB($id);
$taskjobs = $pfTaskjob->find(['plugin_glpiinventory_tasks_id' => $id], ['id']);
} else {
$this->getEmpty();
$new_item = true;
}
$options['colspan'] = 2;
$this->initForm($id, $options);
$this->showFormHeader($options);
echo "<tr class='tab_bg_1'>";
echo "<td colspan='4'>";
echo "<div class='row'>";
$this->showTextField(__('Name'), "name");
$this->showTextArea(__('Comments'), "comment");
$this->showCheckboxField(
__('Permit to re-prepare task after run', 'glpiinventory'),
"reprepare_if_successful"
);
if ($this->fields['is_deploy_on_demand']) {
echo "<div class='mb-2 row col-12 col-sm-6'>";
echo __("This is an on demand deployment task", "glpiinventory");
echo "</div>";
}
if (!$new_item) {
$this->showCheckboxField(__('Active'), "is_active");
$datetime_field_options = [
'timestep' => 1,
'maybeempty' => true,
];
$this->showDateTimeField(
__('Schedule start', 'glpiinventory'),
"datetime_start",
$datetime_field_options
);
$this->showDateTimeField(
__('Schedule end', 'glpiinventory'),
"datetime_end",
$datetime_field_options
);
$this->showDropdownForItemtype(
__('Preparation timeslot', 'glpiinventory'),
"PluginGlpiinventoryTimeslot",
['name' => 'plugin_glpiinventory_timeslots_prep_id',
'value' => $this->fields['plugin_glpiinventory_timeslots_prep_id']
]
);
$this->showDropdownForItemtype(
__('Execution timeslot', 'glpiinventory'),
"PluginGlpiinventoryTimeslot",
['name' => 'plugin_glpiinventory_timeslots_exec_id',
'value' => $this->fields['plugin_glpiinventory_timeslots_exec_id']]
);
$this->showIntegerField(
__('Agent wakeup interval (in minutes)', 'glpiinventory'),
"wakeup_agent_time",
['value' => $this->fields['wakeup_agent_time'],
'toadd' => ['0' => __('Never')],
'min' => 1,
'step' => 1
]
);
$this->showIntegerField(
__('Number of agents to wake up', 'glpiinventory'),
"wakeup_agent_counter",
['value' => $this->fields['wakeup_agent_counter'],
'toadd' => ['0' => __('None')],
'min' => 0,
'step' => 1
]
);
}
echo "</div>";
echo "</td>";
echo "</tr>";
$this->showFormButtons($options);
return true;
}
public function showFormButtons($options = [])
{
$ID = 0;
if (isset($this->fields['id'])) {
$ID = $this->fields['id'];
}
echo "<tr>";
echo "<td colspan='2'>";
if ($this->isNewID($ID)) {
echo Html::submit(_x('button', 'Add'), [
'name' => 'add',
'class' => 'btn btn-primary'
]);
} else {
echo Html::hidden('id', ['value' => $ID]);
echo Html::submit("<i class='fas fa-save me-1'></i>" . _x('button', 'Save'), [
'name' => 'update',
'class' => 'btn btn-primary'
]);
}
echo "</td>";
if ($this->fields['is_active']) {
echo "<td>";
echo Html::submit("<i class='fas fa-bolt me-1'></i>" . __('Force start', 'glpiinventory'), [
'name' => 'forcestart',
'class' => 'btn btn-warning',
]);
echo "</td>";
}
echo "<td>";
if (!$this->isNewID($ID) && $this->can($ID, PURGE)) {
echo Html::submit("<i class='fas fa-trash me-1'></i>" . _x('button', 'Delete permanently'), [
'name' => 'purge',
'confirm' => __('Confirm the final deletion?'),
'class ' => 'btn btn-danger',
]);
}
echo "</td>";
echo "</tr>";
// Close for Form
echo "</table></div>";
Html::closeForm();
}
/**
* Manage the different actions in when submit form (add, update,purge...)
*
* @param array $postvars
*/
public function submitForm($postvars)
{
if (isset($postvars['forcestart'])) {
Session::checkRight('plugin_glpiinventory_task', UPDATE);
$this->getFromDB($postvars['id']);
$this->forceRunning();
Html::back();
} elseif (isset($postvars["add"])) {
Session::checkRight('plugin_glpiinventory_task', CREATE);
$items_id = $this->add($postvars);
Html::redirect(str_replace("add=1", "", $_SERVER['HTTP_REFERER']) . "?id=" . $items_id);
} elseif (isset($postvars["purge"])) {
Session::checkRight('plugin_glpiinventory_task', PURGE);
$pfTaskJob = new PluginGlpiinventoryTaskjob();
$taskjobs = $pfTaskJob->find(['plugin_glpiinventory_tasks_id' => $postvars['id']]);
foreach ($taskjobs as $taskjob) {
$pfTaskJob->delete($taskjob);
}
$this->delete($postvars);
Html::redirect(Toolbox::getItemTypeSearchURL(get_class($this)));
} elseif (isset($_POST["update"])) {
Session::checkRight('plugin_glpiinventory_task', UPDATE);
$this->getFromDB($postvars['id']);
//Ensure empty value are set to NULL for datetime fields
if (isset($postvars['datetime_start']) && $postvars['datetime_start'] === '') {
$postvars['datetime_start'] = 'NULL';
}
if (isset($postvars['datetime_end']) && $postvars['datetime_end'] === '') {
$postvars['datetime_end'] = 'NULL';
}
$this->update($postvars);
Html::back();
} elseif (isset($postvars['export_jobs'])) {
Session::checkRight('plugin_glpiinventory_task', READ);
$this->csvExport($postvars);
}
}
/**
* Define reprepare_if_successful field when get empty item
*
* @return bool
*/
public function getEmpty()
{
parent::getEmpty();
$pfConfig = new PluginGlpiinventoryConfig();
$this->fields['reprepare_if_successful'] = $pfConfig->getValue('reprepare_job');
return true;
}
public function rawSearchOptions()
{
$tab = [];
$tab[] = [
'id' => 'common',
'name' => __('Characteristics')
];
$tab[] = [
'id' => '1',
'table' => $this->getTable(),
'field' => 'name',
'name' => __('Name'),
'datatype' => 'itemlink'
];
return $tab;
}
/**
* Export a list of jobs in CSV format, and download file
*
* @param array $params these possible entries:
* - agent_state_types: array of agent states to filter output
* (prepared, cancelled, running, success, error)
* - debug_csv, possible values:
* - 0 : no debug (really export to csv,
* - 1 : display params AND html table,
* - 2: like 1 + display also json of jobs logs
*
* @return void
*/
public function csvExport($params = [])
{
global $CFG_GLPI;
$default_params = [
'agent_state_types' => [],
'debug_csv' => 0
];
$params = array_merge($default_params, $params);
$includeoldjobs = $_SESSION['glpi_plugin_glpiinventory']['includeoldjobs'];
$agent_state_types = ['prepared', 'cancelled', 'running', 'success', 'error' ];
if (isset($params['agent_state_types'])) {
$agent_state_types = $params['agent_state_types'];
}
if (!$params['debug_csv']) {
header("Expires: Mon, 26 Nov 1962 00:00:00 GMT");
header('Pragma: private'); /// IE BUG + SSL
header('Cache-control: private, must-revalidate'); /// IE BUG + SSL
header("Content-disposition: attachment; filename=export.csv");
header("Content-type: text/csv");
} else {
Html::printCleanArray($params);
Html::printCleanArray($agent_state_types);
}
$params['display'] = false;
$pfTask = new PluginGlpiinventoryTask();
$data = json_decode($pfTask->ajaxGetJobLogs($params), true);
//clean line with state_types with unwanted states
foreach ($data['tasks'] as $task_id => &$task) {
foreach ($task['jobs'] as $job_id => &$job) {
foreach ($job['targets'] as $target_id => &$target) {
foreach ($target['agents'] as $agent_id => &$agent) {
foreach ($agent as $exec_id => $exec) {
if (!in_array($exec['state'], $agent_state_types)) {
unset($agent[$exec_id]);
if (count($agent) === 0) {
unset($target['agents'][$agent_id]);
}
}
}
}
}
}
}
// clean old temporary variables
unset($task, $job, $target, $agent);
if (!$params['debug_csv']) {
define('SEP', $CFG_GLPI['csv_delimiter']);
define('NL', "\r\n");
} else {
define('SEP', '</td><td>');
define('NL', '</tr><tr><td>');
echo "<table border=1><tr><td>";
}
// cols titles
echo "Task_name" . SEP;
echo "Job_name" . SEP;
echo "Method" . SEP;
echo "Target" . SEP;
echo "Agent" . SEP;
echo "Computer name" . SEP;
echo "Date" . SEP;
echo "Status" . SEP;
echo "Last Message" . NL;
$agent_obj = new Agent();
$computer = new Computer();
// prepare an anonymous (and temporory) function
// for test if an element is the last of an array
$last = function (&$array, $key) {
end($array);
return $key === key($array);
};
// display lines
$csv_array = [];
$tab = 0;
foreach ($data['tasks'] as $task_id => $task) {
echo $task['task_name'] . SEP;
if (count($task['jobs']) == 0) {
echo NL;
} else {
foreach ($task['jobs'] as $job_id => $job) {
echo $job['name'] . SEP;
echo $job['method'] . SEP;
if (count($job['targets']) == 0) {
echo NL;
} else {
foreach ($job['targets'] as $target_id => $target) {
echo $target['name'] . SEP;
if (count($target['agents']) == 0) {
echo NL;
} else {
foreach ($target['agents'] as $agent_id => $agent) {
$agent_obj->getFromDB($agent_id);
echo $agent_obj->getName() . SEP;
$computer->getFromDB($agent_obj->fields['items_id']);
echo $computer->getname() . SEP;
$log_cpt = 0;
if (count($agent) == 0) {
echo NL;
} else {
foreach ($agent as $exec_id => $exec) {
echo $exec['last_log_date'] . SEP;
echo $exec['state'] . SEP;
echo $exec['last_log'] . NL;
$log_cpt++;
if ($includeoldjobs != -1 and $log_cpt >= $includeoldjobs) {
break;
}
if (!$last($agent, $exec_id)) {
echo SEP . SEP . SEP . SEP . SEP . SEP;
}
}
}
if (!$last($target['agents'], $agent_id)) {
echo SEP . SEP . SEP . SEP;
}
}
}
if (!$last($job['targets'], $target_id)) {
echo SEP . SEP . SEP;
}
}
}
if (!$last($task['jobs'], $job_id)) {
echo SEP;
}
}
}
}
if ($params['debug_csv'] === 2) {
echo "</td></tr></table>";
//echo original datas
echo "<pre>" . json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "</pre>";
}
// force exit to prevent further display
exit;
}
/**
* Force running the current task
**/
public function forceRunning()
{
$methods = [];
foreach (PluginGlpiinventoryStaticmisc::getmethods() as $method) {
$methods[] = $method['method'];
}
$this->prepareTaskjobs($methods, $this->getID());
}
/**
* Prepare task jobs
*
* @param array $methods
* @param false|integer $tasks_id the concerned task
* @return true
*/
public function prepareTaskjobs($methods = [], $tasks_id = false)
{
/** @var DBmysql $DB */
global $DB;
$now = new DateTime();
PluginGlpiinventoryToolbox::logIfExtradebug(
"pluginGlpiinventory-jobs",
"Preparing tasks jobs, task id: " . $tasks_id
);
//Get all active timeslots
$timeslot = new PluginGlpiinventoryTimeslot();
$timeslots = $timeslot->getCurrentActiveTimeslots();
if (empty($timeslots)) {
$it_timeslot = ['plugin_glpiinventory_timeslots_prep_id' => 0];
} else {
$it_timeslot = [
'OR' => [
[
'plugin_glpiinventory_timeslots_prep_id' => 0,
],
[
'plugin_glpiinventory_timeslots_prep_id' => $timeslots,
]
]
];
}
// limit preparation to a specific tasks_id
$it_task_id = [];
if ($tasks_id) {
$it_task_id = ['task.id' => $tasks_id];
}
$iterator = $DB->request([
'SELECT' => [
'task.id',
'task.name',
'task.reprepare_if_successful',
'job.id AS jobid',
'job.name AS jobname',
'job.method',
'job.targets',
'job.actors',
'job.restrict_to_task_entity'
],
'FROM' => 'glpi_plugin_glpiinventory_taskjobs AS job',
'LEFT JOIN' => [
'glpi_plugin_glpiinventory_tasks AS task' => [
'FKEY' => [
'task' => 'id',
'job' => 'plugin_glpiinventory_tasks_id'
]
]
],
'WHERE' => array_merge([
'task.is_active' => 1,
[
'OR' => [
[
[
'NOT' => [
'task.datetime_start' => null,
]
],
'task.datetime_end' => null,
'task.datetime_start' => ['<', $now->format("Y-m-d H:i:s")],
],
[
['NOT' => ['task.datetime_start' => null]],
['NOT' => ['task.datetime_end' => null]],
new QueryExpression(
$DB->quoteValue($now->format("Y-m-d H:i:s")) . ' BETWEEN ' .
$DB->quoteName('task.datetime_start') . ' AND ' .
$DB->quoteName('task.datetime_end')
),
],
[
'task.datetime_start' => null,
'task.datetime_end' => null
]
]
],
'job.method' => $methods,
], $it_timeslot, $it_task_id),
'ORDER' => [
'job.id'
]
]);
$results = PluginGlpiinventoryToolbox::fetchAssocByTableIterator($iterator);
// Fetch a list of actors to be prepared. We may have the same actors for each job so this
// part can speed up the process.
//$actors = [];
// Set basic elements of jobstates
$run_base = [
'state' => PluginGlpiinventoryTaskjobstate::PREPARED,
];
$log_base = [
'date' => $_SESSION['glpi_currenttime'],
'state' => PluginGlpiinventoryTaskjoblog::TASK_PREPARED,
'comment' => ''
];
$jobstate = new PluginGlpiinventoryTaskjobstate();
$joblog = new PluginGlpiinventoryTaskjoblog();
foreach ($results as $result) {
$actors = importArrayFromDB($result['job']['actors']);
// Get agents linked to the actors
$agent_ids = [];
foreach ($this->getAgentsFromActors($actors) as $agent_id) {
$agent_ids[$agent_id] = true;
}
//Continue with next job if there are no agents found from actors.
//TODO: This may be good to report this kind of information. We just need to do a list of
//agent's ids generated by actors like array('actors_type-id' => array( 'agent_0',...).
//Then the following could be put in the targets foreach loop before looping through
//agents.
if (count($agent_ids) == 0) {
continue;
}
$saved_agent_ids = $agent_ids;
$targets = importArrayFromDB($result['job']['targets']);
if ($result['job']['method'] == 'networkinventory') {
$newtargets = [];
$pfNetworkinventory = new PluginGlpiinventoryNetworkinventory();
foreach ($targets as $keyt => $target) {
$item_type = key($target);
$items_id = current($target);
if ($item_type == 'PluginGlpiinventoryIPRange') {
unset($targets[$keyt]);
// In this case get devices of this iprange
$deviceList = $pfNetworkinventory->getDevicesOfIPRange($items_id, $result['job']['restrict_to_task_entity']);
$newtargets = array_merge($newtargets, $deviceList);
}
}
$targets = array_merge($targets, $newtargets);
}
$limit = 0;
foreach ($targets as $target) {
$agent_ids = $saved_agent_ids;
$item_type = key($target);
$item_id = current($target);
$job_id = $result['job']['id'];
// Filter out agents that are already running the targets.
$jobstates_running = $jobstate->find(
['itemtype' => $item_type,
'items_id' => $item_id,
'plugin_glpiinventory_taskjobs_id' => $job_id,
'NOT' => ['state' => [
PluginGlpiinventoryTaskjobstate::FINISHED,
PluginGlpiinventoryTaskjobstate::IN_ERROR,
PluginGlpiinventoryTaskjobstate::POSTPONED,
PluginGlpiinventoryTaskjobstate::CANCELLED]],
'agents_id' => array_keys($agent_ids)]
);
foreach ($jobstates_running as $jobstate_running) {
$jobstate_agent_id = $jobstate_running['agents_id'];
if (isset($agent_ids[$jobstate_agent_id])) {
$agent_ids[$jobstate_agent_id] = false;
}
}
// If task have not reprepare_if_successful, do not reprerare
// successful taskjobstate
if (!$result['task']['reprepare_if_successful']) {
$jobstates_running = $jobstate->find(
['itemtype' => $item_type,
'items_id' => $item_id,
'plugin_glpiinventory_taskjobs_id' => $job_id,
'state' => PluginGlpiinventoryTaskjobstate::FINISHED,
'agents_id' => array_keys($agent_ids)]
);
foreach ($jobstates_running as $jobstate_running) {
$jobstate_agent_id = $jobstate_running['agents_id'];
if (isset($agent_ids[$jobstate_agent_id])) {
$agent_ids[$jobstate_agent_id] = false;
}
}
}
// Cancel agents prepared but not in $agent_ids (like computer
// not in dynamic group)
$jobstates_tocancel = $jobstate->find([
'itemtype' => $item_type,
'items_id' => $item_id,
'plugin_glpiinventory_taskjobs_id' => $job_id,
'NOT' => [
'OR' => [
'state' => [
PluginGlpiinventoryTaskjobstate::FINISHED,
PluginGlpiinventoryTaskjobstate::IN_ERROR,
PluginGlpiinventoryTaskjobstate::CANCELLED,
],
'agents_id' => array_keys($agent_ids)]
]
]);
foreach ($jobstates_tocancel as $jobstate_tocancel) {
$jobstate->getFromDB($jobstate_tocancel['id']);
$jobstate->cancel(__('Device no longer defined in definition of job', 'glpiinventory'));
}
foreach ($agent_ids as $agent_id => $agent_not_running) {
if ($agent_not_running) {
$limit += 1;
if ($limit > 500) {
$limit = 0;
break;
}
$run = array_merge(
$run_base,
[
'itemtype' => $item_type,
'items_id' => $item_id,
'plugin_glpiinventory_taskjobs_id' => $job_id,
'agents_id' => $agent_id,
'uniqid' => uniqid(),
]
);
$run_id = $jobstate->add($run);
PluginGlpiinventoryToolbox::logIfExtradebug(
"pluginGlpiinventory-jobs",
"- prepared a job execution: " . print_r($run, true)
);
if ($run_id !== false) {
$log = array_merge(
$log_base,
[
'plugin_glpiinventory_taskjobstates_id' => $run_id
]
);
$joblog->add($log);
}
}
}
}
}
return true;
}
/**
* Get agents of Computers from Actors defined in taskjobs
* TODO: this method should be rewritten to call directly a getAgents() method in the
* corresponding itemtype classes.
*
* @param array $actors
* @param bool $use_cache retrieve agents from cache or not
* @return array list of agents
*/
public function getAgentsFromActors($actors = [], $use_cache = false)
{
$agents = [];
$computers = [];
$computer = new Computer();
$agent = new Agent();
$pfToolbox = new PluginGlpiinventoryToolbox();
foreach ($actors as $actor) {
$itemtype = key($actor);
$itemid = $actor[$itemtype];
$item = getItemForItemtype($itemtype);
// If this item doesn't exists, we continue to the next actor item.
// TODO: remove this faulty actor from the list of job actor.
if ($item === false) {
trigger_error(
sprintf('Invalid itemtype "%s".', $itemtype),
E_USER_WARNING
);
continue;
}
$dbresult = $item->getFromDB($itemid);
if ($dbresult === false) {
trigger_error(
sprintf('Invalid item "%s" (%s).', $itemtype, $itemid),
E_USER_WARNING
);
continue;
}
switch ($itemtype) {
case 'Computer':
$computers[$itemid] = 1;
break;
case 'PluginGlpiinventoryDeployGroup':
$group_targets = $pfToolbox->executeAsGlpiinventoryUser(
'PluginGlpiinventoryDeployGroup::getTargetsForGroup',
[$itemid, $use_cache]
);
foreach ($group_targets as $computerid) {
$computers[$computerid] = 1;
}
break;
case 'Group':
//find computers by user associated with this group
$group_users = new Group_User();
$members = [];
$members = $group_users->getGroupUsers($itemid);
foreach ($members as $member) {
$computers_from_user = $computer->find(['users_id' => $member['id']]);
foreach ($computers_from_user as $computer_entry) {
$computers[$computer_entry['id']] = 1;
}
}
//find computers directly associated with this group
$computer_from_group = $computer->find(['groups_id' => $itemid]);
foreach ($computer_from_group as $computer_entry) {
$computers[$computer_entry['id']] = 1;
}
break;
/**
* TODO: The following should be replaced with Dynamic groups
*/
case Agent::class:
$agents[$itemid] = 1;
break;
}
}
//Get agents from the computer's ids list
if (count($computers)) {
$agents_entries = $agent->find(['itemtype' => 'Computer', 'items_id' => array_keys($computers)]);
foreach ($agents_entries as $agent_entry) {
$agents[$agent_entry['id']] = 1;
}
}
// Return the list of agent's ids.
// (We used hash keys to avoid duplicates in the list)
return array_keys($agents);
}
}