refs #1975. Integration ogGit. Crete image and deploy
testing/ogcore-api/pipeline/head There was a failure building this commit Details

pull/37/head
Manuel Aranda Rosales 2025-06-26 17:04:50 +02:00
parent af5ad81199
commit e51e1e13ea
11 changed files with 424 additions and 194 deletions

View File

@ -42,7 +42,14 @@ class ChangeOrganizationalUnitAction extends AbstractController
$clientEntity->setOrganizationalUnit($organizationalUnit);
$this->entityManager->persist($clientEntity);
$this->postAction->__invoke($clientEntity, $clientEntity->getTemplate());
$template = $clientEntity->getTemplate() ?? $clientEntity->getOrganizationalUnit()->getNetworkSettings()?->getTemplate();
if (!$template) {
throw new BadRequestHttpException('No template found for client');
}
$this->postAction->__invoke($clientEntity, $template);
}
$this->entityManager->flush();

View File

@ -8,6 +8,7 @@ use ApiPlatform\Validator\ValidatorInterface;
use App\Dto\Input\DeployImageInput;
use App\Entity\Command;
use App\Entity\Image;
use App\Model\ClientStatus;
use App\Entity\ImageImageRepository;
use App\Entity\OrganizationalUnit;
use App\Entity\Partition;
@ -31,11 +32,10 @@ class DeployImageAction extends AbstractController
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreateService $createService,
protected readonly ValidatorInterface $validator,
protected readonly ValidatorInterface $validator,
public readonly \App\Controller\OgAgent\DeployImageAction $deployImageOgAgentAction,
public readonly \App\Controller\OgRepository\Image\DeployImageAction $deployImageOgRepositoryAction,
)
{
) {
}
/**
@ -47,90 +47,117 @@ class DeployImageAction extends AbstractController
{
$this->validator->validate($input);
switch ($input->method){
case DeployMethodTypes::UNICAST:
case DeployMethodTypes::UNICAST_DIRECT:
foreach ($input->clients as $client) {
$inputData = [
'method' => $input->method,
'client' => $client->getEntity()->getUuid(),
'image' => $image->getUuid(),
'imageName' => $image->getName(),
'numDisk' => (string) $input->diskNumber,
'numPartition' => (string) $input->partitionNumber,
];
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::UNICAST);
if (!$agentJobId){
continue;
}
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
}
break;
case DeployMethodTypes::MULTICAST_UFTP:
case DeployMethodTypes::MULTICAST_UFTP_DIRECT:
case DeployMethodTypes::MULTICAST_UDPCAST:
case DeployMethodTypes::MULTICAST_UDPCAST_DIRECT:
foreach ($input->clients as $client) {
$inputData = [
'method' => $input->method,
'client' => $client->getEntity()->getUuid(),
'image' => $image->getUuid(),
'mcastIp' => $input->mcastIp,
'mcastPort' => $input->mcastPort,
'mcastSpeed' => $input->mcastSpeed,
'mcastMode' => $input->mcastMode,
'numDisk' => (string) $input->diskNumber,
'numPartition' => (string) $input->partitionNumber,
];
try {
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity());
} catch (\Exception $e) {
continue;
}
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::MULTICAST);
if (!$agentJobId){
continue;
}
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
}
break;
case DeployMethodTypes::TORRENT:
foreach ($input->clients as $client) {
$inputData = [
'method' => $input->method,
'client' => $client->getEntity()->getUuid(),
'image' => $image->getUuid(),
'p2pMode' => $input->p2pMode,
'p2pTime' => $input->p2pTime,
'numDisk' => (string) $input->diskNumber,
'numPartition' => (string) $input->partitionNumber,
];
try {
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity(), $this->httpClient);
} catch (\Exception $e) {
continue;
}
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::TORRENT);
if (!$agentJobId){
continue;
}
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
}
break;
if ($input->type === 'monolithic') {
$this->handleMonolithicDeployment($input, $image);
}
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
private function handleMonolithicDeployment(DeployImageInput $input, ImageImageRepository $image): void
{
switch ($input->method) {
case DeployMethodTypes::UNICAST:
case DeployMethodTypes::UNICAST_DIRECT:
$this->handleUnicastDeployment($input, $image);
break;
case DeployMethodTypes::MULTICAST_UFTP:
case DeployMethodTypes::MULTICAST_UFTP_DIRECT:
case DeployMethodTypes::MULTICAST_UDPCAST:
case DeployMethodTypes::MULTICAST_UDPCAST_DIRECT:
$this->handleMulticastDeployment($input, $image);
break;
case DeployMethodTypes::TORRENT:
$this->handleTorrentDeployment($input, $image);
break;
}
}
private function handleUnicastDeployment(DeployImageInput $input, ImageImageRepository $image): void
{
foreach ($input->clients as $client) {
$inputData = $this->createInputData($input, $image, $client->getEntity());
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::UNICAST);
}
}
private function handleMulticastDeployment(DeployImageInput $input, ImageImageRepository $image): void
{
foreach ($input->clients as $client) {
$inputData = $this->createMulticastInputData($input, $image, $client->getEntity());
try {
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity());
} catch (\Exception $e) {
continue;
}
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::MULTICAST);
}
}
private function handleTorrentDeployment(DeployImageInput $input, ImageImageRepository $image): void
{
foreach ($input->clients as $client) {
$inputData = $this->createTorrentInputData($input, $image, $client->getEntity());
try {
$response = $this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity(), $this->httpClient);
if (is_array($response) && isset($response['code']) && $response['code'] === 500) {
throw new \Exception('Error del servidor OgRepository: ' . ($response['error'] ?? 'Error desconocido') . ' - ' . ($response['details'] ?? ''));
}
} catch (\Exception $e) {
throw $e;
}
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::TORRENT);
}
}
private function processDeployment($client, DeployImageInput $input, ImageImageRepository $image, array $inputData, string $deployType): void
{
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client, $deployType);
if (!$agentJobId) {
if ($input->queue) {
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::PENDING, null, $inputData);
}
return;
}
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
}
private function createInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
{
return [
'method' => $input->method,
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'imageName' => $image->getName(),
'numDisk' => (string) $input->diskNumber,
'numPartition' => (string) $input->partitionNumber,
'type' => $input->type,
];
}
private function createMulticastInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
{
return array_merge($this->createInputData($input, $image, $client), [
'mcastIp' => $input->mcastIp,
'mcastPort' => $input->mcastPort,
'mcastSpeed' => $input->mcastSpeed,
'mcastMode' => $input->mcastMode,
]);
}
private function createTorrentInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
{
return array_merge($this->createInputData($input, $image, $client), [
'p2pMode' => $input->p2pMode,
'p2pTime' => $input->p2pTime,
]);
}
}

View File

@ -4,6 +4,7 @@ namespace App\Controller\OgAgent;
use App\Controller\OgRepository\Git\CreateRepositoryAction;
use App\Controller\OgRepository\Git\CreateTagAction;
use App\Controller\OgRepository\Git\SshKeyAction;
use App\Service\CreatePartitionService;
use App\Service\Trace\CreateService;
use Doctrine\ORM\EntityManagerInterface;
@ -28,7 +29,7 @@ abstract class AbstractOgAgentController extends AbstractController
protected readonly LoggerInterface $logger,
protected readonly CreateService $createService,
protected readonly CreateRepositoryAction $createRepositoryAction,
protected readonly CreateTagAction $createTagAction,
protected readonly SshKeyAction $sshKeyAction,
#[Autowire(env: 'SSL_ENABLED')]
private readonly string $sslEnabled,
)

View File

@ -5,10 +5,9 @@ declare(strict_types=1);
namespace App\Controller\OgAgent;
use App\Controller\OgRepository\Git\CreateRepositoryAction;
use App\Controller\OgRepository\Git\CreateTagAction;
use App\Entity\Client;
use App\Entity\Command;
use App\Entity\GitImageRepository;
use App\Entity\GitRepository;
use App\Entity\Image;
use App\Entity\ImageImageRepository;
use App\Entity\ImageRepository;
@ -43,9 +42,11 @@ class CreateImageAction extends AbstractOgAgentController
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function __invoke(Image $image, ?Partition $partition = null, ?Client $client = null): JsonResponse
public function __invoke(bool $queue, Image $image, ?Partition $partition = null, ?Client $client = null, ?string $gitRepositoryName = null): JsonResponse
{
if (!$image->getClient()->getIp()) {
$client = $client ?? $image->getClient();
if (!$client->getIp()) {
throw new BadRequestHttpException('IP is required');
}
@ -76,25 +77,13 @@ class CreateImageAction extends AbstractOgAgentController
$this->entityManager->persist($imageImageRepository);
return $this->createMonolithicImage($imageImageRepository, $partitionInfo, $image, $repository, $client);
return $this->createMonolithicImage($imageImageRepository, $partitionInfo, $image, $repository, $client, $queue);
} else {
$repository = $image->getClient()->getRepository();
$latestImageRepo = $this->entityManager->getRepository(GitImageRepository::class)->findLatestVersionByImageAndRepository($image, $repository);
$gitImageRepository = new GitImageRepository();
$gitImageRepository->setName($image->getName().'_v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
$gitImageRepository->setImage($image);
$gitImageRepository->setRepository($repository);
$gitImageRepository->setStatus(ImageStatus::IN_PROGRESS);
$gitImageRepository->setVersion($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1);
$gitImageRepository->setTag('v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
$gitImageRepository->setCreated(false);
$this->entityManager->persist($gitImageRepository);
$this->entityManager->persist($image);
$this->entityManager->flush();
return $this->createGitImage($gitImageRepository, $partitionInfo, $image, $repository);
// Para imágenes Git, no necesitamos crear entidades en la base de datos
// ya que los repositorios Git son datos externos
return $this->createGitImage($image, $partitionInfo, $repository, $queue, $gitRepositoryName);
}
}
@ -109,9 +98,19 @@ class CreateImageAction extends AbstractOgAgentController
array $partitionInfo,
Image $image,
ImageRepository $repository,
?Client $client = null
?Client $client = null,
bool $queue = false
): JsonResponse
{
if (!isset($partitionInfo['numDisk'], $partitionInfo['numPartition'], $partitionInfo['partitionCode'], $partitionInfo['filesystem'])) {
throw new BadRequestHttpException('Missing required partition information');
}
$client = $client ?? $image->getClient();
if (!$client->getIp() || !$client->getToken()) {
throw new BadRequestHttpException('Client IP or token is missing');
}
$data = [
'dsk' => (string) $partitionInfo['numDisk'],
'par' => (string) $partitionInfo['numPartition'],
@ -134,85 +133,219 @@ class CreateImageAction extends AbstractOgAgentController
$data['cpt'] = dechex($partitionTypeCode);
} else {
throw new Exception("El tipo de partición '$partitionCode' no se encontró en la lista.");
throw new BadRequestHttpException("Invalid partition code: {$partitionCode}");
}
$client = $client ?? $image->getClient();
$this->logger->info('Creating image', ['image' => $image->getId()]);
$response = $this->createRequest(
method: 'POST',
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagen',
params: [
'json' => $data,
],
token: $client->getToken(),
);
try {
$response = $this->createRequest(
method: 'POST',
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagen',
params: [
'json' => $data,
],
token: $client->getToken(),
);
$this->logger->info('Creating image', ['image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
$this->logger->info('Creating image', ['image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
throw new BadRequestHttpException('Error creating image');
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
if ($queue) {
$inputData = [
'method' => 'CrearImagen',
'type' => 'monolithic',
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'partitionCode' => $partitionInfo['partitionCode'],
'partitionType' => $partitionInfo['filesystem'],
'repository' => $repository->getIp(),
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
];
$this->createService->__invoke($client, CommandTypes::CREATE_IMAGE, TraceStatus::PENDING, null, $inputData);
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
throw new BadRequestHttpException('Error creating image: ' . ($response['message'] ?? 'Unknown error'));
}
if (!isset($response['job_id'])) {
throw new BadRequestHttpException('No job ID received from server');
}
$jobId = $response['job_id'];
try {
$client->setStatus(ClientStatus::BUSY);
$imageImageRepository->setStatus(ImageStatus::IN_PROGRESS);
$this->entityManager->persist($client);
$this->entityManager->persist($imageImageRepository);
$this->entityManager->flush();
$inputData = [
'method' => 'CrearImagen',
'type' => 'monolithic',
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'partitionCode' => $partitionInfo['partitionCode'],
'partitionType' => $partitionInfo['filesystem'],
'repository' => $repository->getIp(),
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
];
$this->createService->__invoke(
$image->getClient(),
CommandTypes::CREATE_IMAGE,
TraceStatus::IN_PROGRESS,
$jobId,
$inputData
);
return new JsonResponse(data: $image, status: Response::HTTP_OK);
} catch (Exception $e) {
$client->setStatus(ClientStatus::OG_LIVE);
$this->entityManager->persist($client);
$this->entityManager->flush();
throw $e;
}
} catch (Exception $e) {
$this->logger->error('Error in monolithic image creation process', [
'repository' => $repository->getId(),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
}
$jobId = $response['job_id'];
$client->setStatus(ClientStatus::BUSY);
$this->entityManager->persist($client);
$this->entityManager->flush();
$inputData = [
'method' => 'CrearImagen',
'type' => 'monolithic',
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'partitionCode' => $partitionInfo['partitionCode'],
'partitionType' => $partitionInfo['filesystem'],
'repository' => $repository->getIp(),
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
];
$this->createService->__invoke($image->getClient(), CommandTypes::CREATE_IMAGE, TraceStatus::IN_PROGRESS, $jobId, $inputData);
return new JsonResponse(data: $image, status: Response::HTTP_OK);
}
public function createGitImage(
GitImageRepository $gitImageRepository,
array $partitionInfo,
Image $image,
ImageRepository $repository
array $partitionInfo,
ImageRepository $repository,
bool $queue = false,
?string $gitRepositoryName = null
): JsonResponse
{
if (!isset($partitonInfo)) {
try {
$this->createRepositoryAction->__invoke($image, $repository);
} catch (Exception $e) {
$this->logger->error('Error creating repository', ['repository' => $repository->getId(), 'error' => $e->getMessage()]);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
}
} else {
try {
$this->createTagAction->__invoke($image, $repository, $gitImageRepository);
} catch (Exception $e) {
$this->logger->error('Error creating tag', ['repository' => $repository->getId(), 'error' => $e->getMessage()]);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
}
if (!isset($partitionInfo['numDisk'], $partitionInfo['numPartition'], $partitionInfo['partitionCode'], $partitionInfo['filesystem'])) {
throw new BadRequestHttpException('Missing required partition information');
}
return new JsonResponse(
data: ['message' => 'Repository created successfully'],
status: Response::HTTP_OK
);
$client = $image->getClient();
if (!$client->getIp() || !$client->getToken()) {
throw new BadRequestHttpException('Client IP or token is missing');
}
//TODO: llamar al endpoint del agente.
try {
$data = [
'dsk' => (string) $partitionInfo['numDisk'],
'par' => (string) $partitionInfo['numPartition'],
'cpt' => null,
'idi' => $gitRepositoryName ?: $image->getUuid(),
'nci' => $gitRepositoryName ?: $image->getName(),
'ipr' => $repository->getIp(),
'nfn' => 'CrearImagenGit',
'tag' => '',
'ids' => '0'
];
$partitionTypes = PartitionTypes::getPartitionTypes();
$partitionCode = $partitionInfo['partitionCode'];
$cptKey = array_search($partitionCode, array_column($partitionTypes, 'name'), true);
if ($cptKey !== false) {
$keys = array_keys($partitionTypes);
$partitionTypeCode = $keys[$cptKey];
$data['cpt'] = dechex($partitionTypeCode);
} else {
throw new BadRequestHttpException("Invalid partition code: {$partitionCode}");
}
//$this->sshKeyAction->__invoke($repository, $client);
$response = $this->createRequest(
method: 'POST',
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagenGit',
params: [
'json' => $data,
],
token: $client->getToken(),
);
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
if ($queue) {
$inputData = [
'method' => 'CrearImagenGit',
'type' => 'git',
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'partitionCode' => $partitionInfo['partitionCode'],
'partitionType' => $partitionInfo['filesystem'],
'repository' => $repository->getIp(),
'name' => $image->getName(),
];
$this->createService->__invoke($client, CommandTypes::CREATE_IMAGE_GIT, TraceStatus::PENDING, null, $inputData);
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
throw new BadRequestHttpException('Error creating image: ' . ($response['message'] ?? 'Unknown error'));
}
if (!isset($response['job_id'])) {
throw new BadRequestHttpException('No job ID received from server');
}
$jobId = $response['job_id'];
try {
$client->setStatus(ClientStatus::BUSY);
$this->entityManager->persist($client);
$this->entityManager->flush();
$inputData = [
'method' => 'CrearImagenGit',
'type' => 'git',
'client' => $client->getUuid(),
'image' => $image->getUuid(),
'partitionCode' => $partitionInfo['partitionCode'],
'partitionType' => $partitionInfo['filesystem'],
'repository' => $repository->getIp(),
'name' => $image->getName(),
];
$this->createService->__invoke(
$image->getClient(),
CommandTypes::CREATE_IMAGE_GIT,
TraceStatus::IN_PROGRESS,
$jobId,
$inputData
);
return new JsonResponse(data: $image, status: Response::HTTP_OK);
} catch (Exception $e) {
$client->setStatus(ClientStatus::OG_LIVE);
$this->entityManager->persist($client);
$this->entityManager->flush();
throw $e;
}
} catch (Exception $e) {
$this->logger->error('Error in git image creation process', [
'repository' => $repository->getId(),
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
}
}
}

View File

@ -38,7 +38,7 @@ class DeployImageAction extends AbstractOgAgentController
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function __invoke(ImageImageRepository $imageImageRepository, DeployImageInput $input, Client $client, string $method)
public function __invoke(ImageImageRepository $imageImageRepository, DeployImageInput $input, Client $client, ?string $method = null)
{
$image = $imageImageRepository->getImage();
@ -46,6 +46,10 @@ class DeployImageAction extends AbstractOgAgentController
throw new BadRequestHttpException('IP is required');
}
if ($input->type === 'git') {
throw new BadRequestHttpException('Use DeployGitImageAction for Git images');
}
$method = match ($input->method) {
DeployMethodTypes::MULTICAST_UFTP_DIRECT, DeployMethodTypes::MULTICAST_UDPCAST_DIRECT, => 'multicast-direct',
DeployMethodTypes::MULTICAST, DeployMethodTypes::MULTICAST_UFTP, DeployMethodTypes::MULTICAST_UDPCAST => 'multicast',
@ -83,16 +87,22 @@ class DeployImageAction extends AbstractOgAgentController
'ids' => '0'
];
$url = 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen';
$response = $this->createRequest(
method: 'POST',
url: 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen',
url: $url,
params: [
'json' => $data,
],
token: $client->getToken(),
);
$this->logger->info('Deploying image', [ 'image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
$this->logger->info('Deploying image', [
'image' => $imageImageRepository->getName(),
'repository' => $repository->getIp(),
'client' => $client->getIp()
]);
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
throw new BadRequestHttpException('Error deploying image');

View File

@ -166,14 +166,16 @@ class AgentSessionController extends AbstractController
return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
}
switch ($data['ostype']) {
case 'Linux':
$status = $client->getStatus();
switch ($status) {
case ClientStatus::LINUX_SESSION:
$client->setStatus(ClientStatus::LINUX);
break;
case 'Windows':
case ClientStatus::WINDOWS_SESSION:
$client->setStatus(ClientStatus::WINDOWS);
break;
case 'MacOS':
case ClientStatus::MACOS_SESSION:
$client->setStatus(ClientStatus::MACOS);
break;
@ -187,7 +189,7 @@ class AgentSessionController extends AbstractController
$this->logger->info('Client logged out', [
'ip' => $data['ip'],
'user' => $data['user'],
'ostype' => $data['ostype'],
'status' => $status,
]);
return new JsonResponse([], Response::HTTP_OK);

View File

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace App\Controller\OgAgent\Webhook;
use App\Controller\OgRepository\Image\CreateAuxFilesAction;
@ -36,7 +38,9 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
class StatusController extends AbstractController
{
const string CREATE_IMAGE = 'RESPUESTA_CrearImagen';
const string CREATE_IMAGE_GIT = 'RESPUESTA_CrearImagenGit';
const string RESTORE_IMAGE = 'RESPUESTA_RestaurarImagen';
const string RESTORE_IMAGE_GIT = 'RESPUESTA_RestaurarImagenGit';
const string CONFIGURE_IMAGE = 'RESPUESTA_Configurar';
const string HARDWARE_INVENTORY = 'RESPUESTA_InventarioHardware';
const string SOFTWARE_INVENTORY = 'RESPUESTA_InventarioSoftware';
@ -65,7 +69,6 @@ class StatusController extends AbstractController
$this->logger->info('Webhook data received', $data);
// Esta parte del codigo nos indica si el cliente se encuentra activo
if (isset($data['iph']) && isset($data['timestamp'])) {
$client = $this->entityManager->getRepository(Client::class)->findOneBy(['ip' => $data['iph']]);
if (!$client) {
@ -81,11 +84,37 @@ class StatusController extends AbstractController
if (isset($data['progress'])){
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
if ($trace){
$trace->setProgress($data['progress'] * 100);
$trace->setProgress((int)($data['progress'] * 100));
$this->entityManager->persist($trace);
$this->entityManager->flush();
}
}
if (isset($data['nfn']) && $data['nfn'] === self::CREATE_IMAGE_GIT) {
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
if (!$trace) {
$this->logger->error('Trace not found', $data);
return new JsonResponse(['message' => 'Trace not found'], Response::HTTP_NOT_FOUND);
}
if ($data['res'] === 1) {
$trace->setStatus(TraceStatus::SUCCESS);
$trace->setFinishedAt(new \DateTime());
} else {
$trace->setStatus(TraceStatus::FAILED);
$trace->setFinishedAt(new \DateTime());
$trace->setOutput($data['der']);
}
$client = $trace->getClient();
$client->setStatus(ClientStatus::OG_LIVE);
$this->entityManager->persist($client);
$this->entityManager->persist($trace);
$this->entityManager->flush();
$this->logger->info('Git image creation completed.', ['job_id' => $data['job_id'], 'success' => $data['res'] === 1]);
}
if (isset($data['nfn']) && $data['nfn'] === self::CREATE_IMAGE) {
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
@ -142,7 +171,7 @@ class StatusController extends AbstractController
$this->logger->info('Image updated. Success.', ['image' => (string) $imageImageRepository->getUuid()]);
}
if (isset($data['nfn']) && ($data['nfn'] === self::RESTORE_IMAGE || $data['nfn'] === self::CONFIGURE_IMAGE)) {
if (isset($data['nfn']) && ($data['nfn'] === self::RESTORE_IMAGE || $data['nfn'] === self::CONFIGURE_IMAGE || $data['nfn'] === self::RESTORE_IMAGE_GIT)) {
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
$client = $trace->getClient();

View File

@ -45,7 +45,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
'accept' => 'application/json',
'Content-Type' => 'application/json'
],
'timeout' => 10,
'timeout' => 30,
]);
try {
@ -56,7 +56,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
return [
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
'error' => 'Client/Server error',
'error' => $e->getMessage(),
'details' => $e->getMessage(),
];
} catch (TransportExceptionInterface $e) {
@ -64,7 +64,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
return [
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
'error' => 'Transport error',
'error' => $e->getMessage(),
'details' => $e->getMessage(),
];
}

View File

@ -4,8 +4,6 @@ namespace App\Dto\Input;
use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\ClientOutput;
use App\Dto\Output\ImageOutput;
use App\Dto\Output\PartitionOutput;
use App\Validator\Constraints\ClientsHaveSamePartitionCount;
use App\Validator\Constraints\OrganizationalUnitMulticastMode;
use App\Validator\Constraints\OrganizationalUnitMulticastPort;
@ -17,49 +15,63 @@ class DeployImageInput
{
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'The type of the image deployment', example: "")]
public ?string $type = null;
public ?string $type = 'monolithic';
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'The type of the image deployment', example: "")]
#[ApiProperty(description: 'The deployment method', example: "unicast")]
public ?string $method = null;
/**
* @var ClientOutput[]
*/
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'The client to deploy the image')]
#[ApiProperty(description: 'The clients to deploy the image to')]
public ?array $clients = [];
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'The disk number to deploy to', example: 1)]
public ?int $diskNumber = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'The partition number to deploy to', example: 1)]
public ?int $partitionNumber = null;
#[OrganizationalUnitP2PMode]
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'P2P mode for torrent deployment', example: "seed")]
public ?string $p2pMode = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'P2P time for torrent deployment', example: 3600)]
public ?int $p2pTime = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Multicast IP address', example: "239.255.255.250")]
public ?string $mcastIp = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Multicast speed in Mbps', example: 100)]
public ?int $mcastSpeed = null;
#[OrganizationalUnitMulticastPort]
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Multicast port', example: 8000)]
public ?int $mcastPort = null;
#[OrganizationalUnitMulticastMode]
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Multicast mode', example: "full")]
public ?string $mcastMode = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Maximum number of clients for multicast', example: 50)]
public ?int $maxClients = null;
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Maximum time for deployment in seconds', example: 3600)]
public ?int $maxTime = null;
}
#[Groups(['image-image-repository:write'])]
#[ApiProperty(description: 'Whether to queue the deployment', example: false)]
public bool $queue = false;
}

View File

@ -21,7 +21,6 @@ use Symfony\Component\Validator\Constraints as Assert;
final class ImageInput
{
#[Assert\NotBlank(message: 'validators.image.name.not_blank')]
#[Groups(['image:write'])]
#[ApiProperty(description: 'The name of the image', example: "Image 1")]
public ?string $name = null;
@ -73,6 +72,14 @@ final class ImageInput
#[ApiProperty(description: 'The global property of the image')]
public ?bool $isGlobal = false;
#[Groups(['image:write'])]
#[ApiProperty(description: 'The queue property of the image')]
public bool $queue = false;
#[Groups(['image:write'])]
#[ApiProperty(description: 'The name of the Git repository to use for this image', example: "mi-repositorio")]
public ?string $gitRepository = null;
public function __construct(?Image $image = null)
{
if (!$image) {

View File

@ -12,11 +12,13 @@ final class DeployMethodTypes
public const string UNICAST = 'unicast';
public const string UNICAST_DIRECT = 'unicast-direct';
public const string TORRENT = 'p2p';
public const string GIT = 'git';
private const array DEPLOYMENT_METHOD_TYPES = [
self::MULTICAST => 'Multicast',
self::UNICAST => 'Unicast',
self::TORRENT => 'Torrent',
self::GIT => 'Git',
];
public static function getDeploymentMethodTypes(): array