352 lines
14 KiB
PHP
352 lines
14 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controller\OgAgent;
|
|
|
|
use App\Controller\OgRepository\Git\CreateRepositoryAction;
|
|
use App\Entity\Client;
|
|
use App\Entity\Command;
|
|
use App\Entity\GitRepository;
|
|
use App\Entity\Image;
|
|
use App\Entity\ImageImageRepository;
|
|
use App\Entity\ImageRepository;
|
|
use App\Entity\Partition;
|
|
use App\Entity\Trace;
|
|
use App\Model\ClientStatus;
|
|
use App\Model\CommandTypes;
|
|
use App\Model\ImageStatus;
|
|
use App\Model\PartitionTypes;
|
|
use App\Model\TraceStatus;
|
|
use App\Service\Trace\CreateService;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Exception;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
use Symfony\Component\Validator\Exception\ValidatorException;
|
|
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
|
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
|
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
|
|
class CreateImageAction extends AbstractOgAgentController
|
|
{
|
|
/**
|
|
* @throws TransportExceptionInterface
|
|
* @throws ServerExceptionInterface
|
|
* @throws RedirectionExceptionInterface
|
|
* @throws ClientExceptionInterface
|
|
*/
|
|
public function __invoke(bool $queue, Image $image, ?Partition $partition = null, ?Client $client = null, ?string $gitRepositoryName = null): JsonResponse
|
|
{
|
|
$client = $client ?? $image->getClient();
|
|
|
|
if (!$client->getIp()) {
|
|
throw new BadRequestHttpException('IP is required');
|
|
}
|
|
|
|
$partitionInfo = [];
|
|
|
|
if ($partition) {
|
|
$partitionInfo["numPartition"] = $partition->getPartitionNumber();
|
|
$partitionInfo["numDisk"] = $partition->getDiskNumber();
|
|
$partitionInfo["partitionCode"] = $partition->getPartitionCode();
|
|
$partitionInfo["filesystem"] = $partition->getFilesystem();
|
|
$partitionInfo["osName"] = $partition->getOperativeSystem()?->getName();
|
|
$image->setPartitionInfo(json_encode($partitionInfo));
|
|
} else {
|
|
$partitionInfo = json_decode($image->getPartitionInfo(), true);
|
|
}
|
|
|
|
if ($image->getType() === 'monolithic') {
|
|
$repository = $image->getClient()->getRepository();
|
|
$latestImageRepo = $this->entityManager->getRepository(ImageImageRepository::class)->findLatestVersionByImageAndRepository($image, $repository);
|
|
|
|
$imageImageRepository = new ImageImageRepository();
|
|
$imageImageRepository->setName($image->getName().'_v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
|
|
$imageImageRepository->setImage($image);
|
|
$imageImageRepository->setRepository($repository);
|
|
$imageImageRepository->setStatus(ImageStatus::IN_PROGRESS);
|
|
$imageImageRepository->setVersion($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1);
|
|
$imageImageRepository->setPartitionInfo(json_encode($partitionInfo));
|
|
|
|
$this->entityManager->persist($imageImageRepository);
|
|
|
|
return $this->createMonolithicImage($imageImageRepository, $partitionInfo, $image, $repository, $client, $queue);
|
|
} else {
|
|
$repository = $image->getClient()->getRepository();
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws TransportExceptionInterface
|
|
* @throws ServerExceptionInterface
|
|
* @throws RedirectionExceptionInterface
|
|
* @throws ClientExceptionInterface
|
|
*/
|
|
public function createMonolithicImage(
|
|
ImageImageRepository $imageImageRepository,
|
|
array $partitionInfo,
|
|
Image $image,
|
|
ImageRepository $repository,
|
|
?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'],
|
|
'cpt' => null,
|
|
'idi' => $imageImageRepository->getUuid(),
|
|
'nci' => $image->getName().'_v'.$imageImageRepository->getVersion(),
|
|
'ipr' => $repository->getIp(),
|
|
'nfn' => 'CrearImagen',
|
|
'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->logger->info('Creating image', ['image' => $image->getId()]);
|
|
|
|
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()]);
|
|
|
|
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
|
|
);
|
|
}
|
|
}
|
|
|
|
public function createGitImage(
|
|
Image $image,
|
|
array $partitionInfo,
|
|
ImageRepository $repository,
|
|
bool $queue = false,
|
|
?string $gitRepositoryName = null
|
|
): JsonResponse
|
|
{
|
|
if (!isset($partitionInfo['numDisk'], $partitionInfo['numPartition'], $partitionInfo['partitionCode'], $partitionInfo['filesystem'])) {
|
|
throw new BadRequestHttpException('Missing required partition information');
|
|
}
|
|
|
|
$client = $image->getClient();
|
|
if (!$client->getIp() || !$client->getToken()) {
|
|
throw new BadRequestHttpException('Client IP or token is missing');
|
|
}
|
|
|
|
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
|
|
);
|
|
}
|
|
}
|
|
}
|