first commit
This commit is contained in:
213
inc/console/task/unlockcommand.class.php
Normal file
213
inc/console/task/unlockcommand.class.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/**
|
||||
* ---------------------------------------------------------------------
|
||||
* GLPI - Gestionnaire Libre de Parc Informatique
|
||||
* Copyright (C) 2015-2020 Teclib' and contributors.
|
||||
*
|
||||
* http://glpi-project.org
|
||||
*
|
||||
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
||||
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This file is part of GLPI.
|
||||
*
|
||||
* GLPI is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GLPI 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace Glpi\Console\Task;
|
||||
|
||||
if (!defined('GLPI_ROOT')) {
|
||||
die("Sorry. You can't access this file directly");
|
||||
}
|
||||
|
||||
use CronTask;
|
||||
use Glpi\Console\AbstractCommand;
|
||||
use Glpi\Event;
|
||||
use QueryExpression;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
|
||||
class UnlockCommand extends AbstractCommand {
|
||||
|
||||
protected function configure() {
|
||||
parent::configure();
|
||||
|
||||
$this->setName('glpi:task:unlock');
|
||||
$this->setAliases(['task:unlock']);
|
||||
$this->setDescription(__('Unlock automatic tasks'));
|
||||
|
||||
$this->addOption(
|
||||
'all',
|
||||
'a',
|
||||
InputOption::VALUE_NONE,
|
||||
__('Unlock all tasks')
|
||||
);
|
||||
|
||||
$this->addOption(
|
||||
'cycle',
|
||||
'c',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
__('Execution time (in cycles) from which the task is considered as stuck (delay = task frequency * cycle)'),
|
||||
null // Has to be null to detect lack of definition of both 'cycle' and 'delay' to set default delay (see self::validateInput())
|
||||
);
|
||||
|
||||
$this->addOption(
|
||||
'delay',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
__('Execution time (in seconds) from which the task is considered as stuck (default: 1800)'),
|
||||
null // Has to be null to detect lack of definition of both 'cycle' and 'delay' to set default delay (see self::validateInput())
|
||||
);
|
||||
|
||||
$this->addOption(
|
||||
'task',
|
||||
't',
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
__('Itemtype::name of task to unlock (e.g: "MailCollector::mailgate")')
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
|
||||
$this->validateInput($input);
|
||||
|
||||
$all = $input->getOption('all');
|
||||
$cycle = $input->getOption('cycle');
|
||||
$delay = $input->getOption('delay');
|
||||
$tasks = $input->getOption('task');
|
||||
|
||||
if (null !== $cycle) {
|
||||
$delay = $cycle . ' * ' . $this->db->quoteName('frequency');
|
||||
}
|
||||
|
||||
$task_iterator = $this->db->request(
|
||||
[
|
||||
'SELECT' => [
|
||||
'id',
|
||||
new QueryExpression(
|
||||
'CONCAT('
|
||||
. $this->db->quoteName('itemtype')
|
||||
. ', ' . $this->db->quoteValue('::')
|
||||
. ', ' . $this->db->quoteName('name')
|
||||
. ') AS ' . $this->db->quoteName('task')
|
||||
)
|
||||
],
|
||||
'FROM' => CronTask::getTable(),
|
||||
'WHERE' => [
|
||||
'state' => CronTask::STATE_RUNNING,
|
||||
new QueryExpression(
|
||||
'UNIX_TIMESTAMP(' . $this->db->quoteName('lastrun') . ') + ' . $delay
|
||||
. ' < UNIX_TIMESTAMP(NOW())'
|
||||
)
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
$crontask = new CronTask();
|
||||
$unlocked_count = 0;
|
||||
|
||||
foreach ($task_iterator as $task) {
|
||||
if (!$all && !in_array($task['task'], $tasks)) {
|
||||
$output->writeln(
|
||||
'<comment>' . sprintf(__('Task "%s" is still running but not in the whitelist.'), $task['task']) . '</comment>',
|
||||
OutputInterface::VERBOSITY_VERBOSE
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$input = [
|
||||
'id' => $task['id'],
|
||||
'state' => CronTask::STATE_WAITING,
|
||||
];
|
||||
if ($crontask->update($input)) {
|
||||
$unlocked_count++;
|
||||
$message = sprintf(__('Task "%s" unlocked.'), $task['task']);
|
||||
$output->writeln('<info>' . $message . '</info>');
|
||||
Event::log($task['id'], 'CronTask', 5, 'Configuration', $message);
|
||||
} else {
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
'<error>' . __('An error occurs while trying to unlock "%s" task.') . '</error>',
|
||||
$task['task']
|
||||
),
|
||||
OutputInterface::VERBOSITY_QUIET
|
||||
);
|
||||
}
|
||||
}
|
||||
$output->writeln(
|
||||
'<info>' .sprintf(__('Number of tasks unlocked: %d.'), $unlocked_count) . '</info>'
|
||||
);
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate command input.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function validateInput(InputInterface $input) {
|
||||
|
||||
$all = $input->getOption('all');
|
||||
$cycle = $input->getOption('cycle');
|
||||
$delay = $input->getOption('delay');
|
||||
$tasks = $input->getOption('task');
|
||||
|
||||
if (null !== $cycle && null !== $delay) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Option --cycle is not compatible with option --delay.')
|
||||
);
|
||||
}
|
||||
|
||||
if (null !== $cycle && !preg_match('/^\d+$/', $cycle)) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Option --cycle has to be an integer.')
|
||||
);
|
||||
}
|
||||
|
||||
if (null !== $delay && !preg_match('/^\d+$/', $delay)) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Option --delay has to be an integer.')
|
||||
);
|
||||
}
|
||||
|
||||
if (null === $cycle && null === $delay) {
|
||||
$input->setOption('delay', 1800); // Default delay
|
||||
}
|
||||
|
||||
if ($all && !empty($tasks)) {
|
||||
throw new InvalidArgumentException(
|
||||
__('Option --all is not compatible with option --task.')
|
||||
);
|
||||
}
|
||||
|
||||
if (!$all && empty($tasks)) {
|
||||
throw new InvalidArgumentException(
|
||||
__('You have to specify which tasks to unlock using --all or --task options.')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user