ogcore/src/Command/RunScheduledCommandTasksCom...

224 lines
9.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Command;
use App\Controller\OgAgent\CreateImageAction;
use App\Controller\OgAgent\DeployImageAction;
use App\Controller\OgAgent\PartitionAssistantAction;
use App\Controller\OgAgent\RunScriptAction;
use App\Dto\Input\CommandExecuteInput;
use App\Dto\Input\DeployImageInput;
use App\Dto\Input\PartitionInput;
use App\Dto\Input\PartitionPostInput;
use App\Dto\Output\ClientOutput;
use App\Entity\CommandTask;
use App\Entity\Image;
use App\Entity\ImageImageRepository;
use App\Entity\Partition;
use App\Entity\Trace;
use App\Model\ClientStatus;
use App\Model\CommandTypes;
use App\Model\TraceStatus;
use App\Repository\CommandTaskRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
#[AsCommand(name: 'opengnsys:run-scheduled-command-tasks', description: 'Run scheduled command tasks')]
class RunScheduledCommandTasksCommand extends Command
{
public function __construct(
private readonly CommandTaskRepository $commandTaskRepository,
private readonly EntityManagerInterface $entityManager,
private readonly RunScriptAction $runScriptAction,
private readonly DeployImageAction $deployImageAction,
private readonly CreateImageAction $createImageAction,
private readonly PartitionAssistantAction $partitionAssistantAction,
)
{
parent::__construct();
}
/**
* @throws \Exception
* @throws TransportExceptionInterface
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$now = new \DateTimeImmutable('now');
$tasks = $this->commandTaskRepository->findAll();
foreach ($tasks as $task) {
/** @var CommandTask $task */
$nextExecution = $task->getNextExecution();
if (!$nextExecution) {
continue;
}
$difference = $now->getTimestamp() - $nextExecution->getTimestamp();
$output->writeln("Now: " . $now->format('Y-m-d H:i:s T'));
$output->writeln("NextExecution: " . $nextExecution->format('Y-m-d H:i:s T'));
$output->writeln("Diferencia: $difference segundos para la tarea {$task->getName()}");
if (abs($difference) < 30) {
$output->writeln("Ejecutando tarea: " . $task->getName());
$scripts = $task->getCommandTaskScripts()->toArray();
usort($scripts, fn($a, $b) => $a->getExecutionOrder() <=> $b->getExecutionOrder());
foreach ($scripts as $script) {
$output->writeln(" - Creando traza para script de tipo {$script->getType()} con orden {$script->getExecutionOrder()}");
$this->createTraceForScript($script, $task, $output);
}
$task->setLastExecution(new \DateTimeImmutable('now'));
$task->setNextExecution($task->calculateNextExecutionDate());
$this->entityManager->persist($task);
}
}
$this->entityManager->flush();
return Command::SUCCESS;
}
private function createTraceForScript($script, CommandTask $task, OutputInterface $output): void
{
$scriptParameters = $script->getParameters();
if ($task->getScope() !== 'clients') {
$clients = $task->getOrganizationalUnit()?->getClients();
} else {
$clients = $task->getClients();
}
foreach ($clients as $client) {
$trace = new Trace();
$trace->setClient($client);
$trace->setStatus(TraceStatus::PENDING);
$trace->setExecutedAt(new \DateTime());
switch ($script->getType()) {
case 'run-script':
$trace->setCommand(CommandTypes::RUN_SCRIPT);
$trace->setInput([
'script' => $script->getContent()
]);
break;
case 'deploy-image':
$trace->setCommand(CommandTypes::DEPLOY_IMAGE);
$trace->setInput([
'imageImageRepository' => $scriptParameters['imageImageRepositoryUuid'],
'method' => $scriptParameters['method'] ?? 'unicast',
'type' => $scriptParameters['type'] ?? 'monolithic',
'diskNumber' => $scriptParameters['diskNumber'] ?? 1,
'partitionNumber' => $scriptParameters['partitionNumber'] ?? 1,
'mcastMode' => $scriptParameters['mcastMode'] ?? 'duplex',
'mcastSpeed' => $scriptParameters['mcastSpeed'] ?? 100,
'mcastPort' => $scriptParameters['mcastPort'] ?? 8000,
'mcastIp' => $scriptParameters['mcastIp'] ?? '224.0.0.1',
'maxClients' => $scriptParameters['maxClients'] ?? 10,
'maxTime' => $scriptParameters['maxTime'] ?? 3600,
'p2pMode' => $scriptParameters['p2pMode'] ?? 'seed',
'p2pTime' => $scriptParameters['p2pTime'] ?? 300
]);
break;
case 'create-image':
$trace->setCommand(CommandTypes::CREATE_IMAGE);
$trace->setInput([
'image' => $scriptParameters['imageUuid'],
'diskNumber' => $scriptParameters['diskNumber'] ?? null,
'partitionNumber' => $scriptParameters['partitionNumber'] ?? null,
'gitRepositoryName' => $scriptParameters['gitRepositoryName'] ?? null
]);
break;
case 'partition-assistant':
$trace->setCommand(CommandTypes::PARTITION_AND_FORMAT);
$trace->setInput($scriptParameters);
break;
default:
$output->writeln(" - Tipo de script no soportado: {$script->getType()}");
continue 2; // Salta al siguiente cliente
}
$this->entityManager->persist($trace);
$output->writeln(" - Traza creada para cliente {$client->getUuid()} con comando {$trace->getCommand()}");
}
}
private function executePartitionAssistant($script, CommandTask $task, OutputInterface $output): void
{
$scriptParameters = $script->getParameters();
$output->writeln(" - Debug: Parameters = " . ($scriptParameters ? json_encode($scriptParameters) : 'null'));
if (!$scriptParameters) {
$output->writeln(" - Error: Parámetros del script vacíos o nulos");
return;
}
if (!is_array($scriptParameters)) {
$output->writeln(" - Error: Los parámetros deben ser un array");
return;
}
foreach ($task->getOrganizationalUnit()?->getClients() as $client) {
$partitionInput = new PartitionPostInput();
$partitionInput->clients = [new ClientOutput($client)];
$partitions = [];
foreach ($scriptParameters as $partitionData) {
if (isset($partitionData['removed']) && $partitionData['removed']) {
continue;
}
if (!isset($partitionData['size']) || $partitionData['size'] <= 0) {
continue;
}
$partitionInputObj = new PartitionInput();
$partitionInputObj->diskNumber = $partitionData['diskNumber'] ?? 1;
$partitionInputObj->partitionNumber = $partitionData['partitionNumber'] ?? 1;
$partitionInputObj->partitionCode = $partitionData['partitionCode'] ?? 'LINUX';
$partitionInputObj->size = (float)($partitionData['size'] / 1024);
$partitionInputObj->filesystem = $partitionData['filesystem'] ?? 'EXT4';
$partitionInputObj->format = $partitionData['format'] ?? false;
$partitionInputObj->memoryUsage = $partitionData['memoryUsage'] ?? 0;
$partitions[] = $partitionInputObj;
}
if (empty($partitions)) {
$output->writeln(" - Warning: No hay particiones válidas para procesar");
continue;
}
$partitionInput->partitions = $partitions;
$partitionInput->queue = false;
try {
$response = $this->partitionAssistantAction->__invoke($partitionInput, null);
$output->writeln(" - Partition assistant iniciado para cliente {$client->getUuid()}");
} catch (\Exception $e) {
$output->writeln(" - Error en partition assistant para cliente {$client->getUuid()}: " . $e->getMessage());
}
}
}
}