%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); } }