develop #26
27
CHANGELOG.md
27
CHANGELOG.md
|
@ -1,26 +1,38 @@
|
|||
# Changelog
|
||||
## [0.10.0] - 2025-03-25
|
||||
### Added
|
||||
- Nuevo endpoint ogRepository. Convertir imagen en imagen virtual.
|
||||
- Nuevo endpoint ogRepository. Importar imágenes externas al sistema.
|
||||
- Nuevo método para desplegar imagenes sin cache.
|
||||
|
||||
---
|
||||
## [0.9.5] - 2025-03-19
|
||||
### Added
|
||||
- Jenkinsfile updated to publish in repo
|
||||
|
||||
---
|
||||
## [0.9.4] - 2025-03-17
|
||||
### Fixed
|
||||
- Mercure service behind nginx server for containers, expose port in docker compose for nginx
|
||||
|
||||
---
|
||||
## [0.9.3] - 2025-03-17
|
||||
### Fixed
|
||||
- Mercure service behind nginx server for containers
|
||||
|
||||
---
|
||||
## [0.9.2] - 2025-03-12
|
||||
### Fixed
|
||||
- Added mercure service in docker compose file for deployments.
|
||||
|
||||
---
|
||||
## [0.9.1] - 2025-03-12
|
||||
### 🐛 Fixed
|
||||
### Fixed
|
||||
- Corrección en la cancelacion de transmisiones p2p.
|
||||
|
||||
---
|
||||
## [0.9.0] - 2025-03-04
|
||||
### 🔹 Added
|
||||
### Added
|
||||
- Nueva funcionalidad para tener notificaciones en tiempo real. Instalación de bundle "Mercure".
|
||||
- Creacion de EventListener en Symfony, para publicar mensajes en Mercure, cuando se realicen cambios en la base de datos ( cambio de estado en lo equipos, y trazas).
|
||||
- Nuevo endpoint "backup image". Integracion con ogRepository.
|
||||
|
@ -30,24 +42,24 @@
|
|||
- Nueva funcionalidad para cancelar despliegues de imagenes.
|
||||
- Añadido nuevo campo "cancelado" en trazas.
|
||||
|
||||
### ⚡ Changed
|
||||
### Changed
|
||||
- Cambios en logs. Cambios en salida (stderror -> file.log)
|
||||
- Modulo DHCP. Añadir equipos, ahora se gestiona con una unica llamada a la API.
|
||||
- Acciones masivas en equipos. Se ha cambiado la respuesta para que no fallen las peticiones si uno o mas equipos no da respuesta.
|
||||
|
||||
---
|
||||
## [0.8.1] - 2025-02-25
|
||||
### 🐛 Fixed
|
||||
### Fixed
|
||||
- Corrección de bug en el deploy de imágenes
|
||||
|
||||
---
|
||||
|
||||
## [0.8.0] - 2025-01-10
|
||||
### 🔹 Added
|
||||
### Added
|
||||
- Nuevos campos en "aulas" para la jerarquia en clientes.
|
||||
- Nueva funcionalidad "imagen global". Integracion con ogRepository.
|
||||
|
||||
### ⚡ Changed
|
||||
### Changed
|
||||
- Limpieza en campos "name" y "date" de ogLive. Es necesario parsear el campo "filename" para facilitar el uso al usuario en la web.
|
||||
### 🐛 Fixed
|
||||
- Corrección de bug que impedia borrar un cliente si tenia una traza enlazada.
|
||||
|
@ -55,7 +67,7 @@
|
|||
|
||||
|
||||
## [0.7.3] - 2025-01-03
|
||||
### 🔹 Added
|
||||
### Added
|
||||
- Adaptados cambios en los endpoints para multiseleccion de clientes.
|
||||
- Se agregó la funcionalidad de importar/exportar. Integración con ogRepository.
|
||||
- Se agregó la funcionalidad de borrar imágenes. Integración con ogRepository.
|
||||
|
@ -70,4 +82,5 @@
|
|||
- **Added**: Secciones con nuevas características.
|
||||
- **Fixed**: Corrección de errores y bugs.
|
||||
- **Changed**: Modificaciones o mejoras en funcionalidades existentes.
|
||||
- **Improved**: Mejoras en funcionalidades existentes.
|
||||
- **Removed**: Funcionalidades o dependencias eliminadas.
|
||||
|
|
|
@ -56,6 +56,14 @@ resources:
|
|||
uriTemplate: /image-image-repositories/{uuid}/backup-image
|
||||
controller: App\Controller\OgRepository\Image\BackupImageAction
|
||||
|
||||
convert_image_to_virtual_image_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\ConvertImageToVirtualInput
|
||||
uriTemplate: /image-image-repositories/{uuid}/convert-image-to-virtual
|
||||
controller: App\Controller\OgRepository\Image\ConvertImageToVirtualAction
|
||||
|
||||
trash_delete_image_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
description: Delete Image in OgRepository
|
||||
|
@ -88,7 +96,7 @@ resources:
|
|||
description: Export Image in OgRepository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\ExportImportImageRepositoryInput
|
||||
input: App\Dto\Input\TransferGlobalImageInput
|
||||
uriTemplate: /image-image-repositories/{uuid}/transfer-image
|
||||
controller: App\Controller\OgRepository\Image\TransferAction
|
||||
|
||||
|
@ -101,6 +109,15 @@ resources:
|
|||
uriTemplate: /image-image-repositories/server/{uuid}/status
|
||||
controller: App\Controller\OgRepository\Image\GetStatusAction
|
||||
|
||||
transfer_global_image_repository:
|
||||
shortName: OgRepository Server
|
||||
description: Transfer Global Image in OgRepository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: false
|
||||
uriTemplate: /image-image-repositories/server/{uuid}/transfer-global
|
||||
controller: App\Controller\OgRepository\Image\TransferGlobalAction
|
||||
|
||||
properties:
|
||||
App\Entity\ImageImageRepository:
|
||||
id:
|
||||
|
|
|
@ -57,14 +57,23 @@ resources:
|
|||
uriTemplate: /image-repositories/server/{uuid}/status
|
||||
controller: App\Controller\OgRepository\StatusAction
|
||||
|
||||
export_image_ogrepository:
|
||||
import_image_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
description: Export Image in OgRepository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\ExportImportImageRepositoryInput
|
||||
uriTemplate: /image-repositories/{uuid}/export-image
|
||||
controller: App\Controller\OgRepository\Image\ExportAction
|
||||
input: App\Dto\Input\ImportImageRepositoryInput
|
||||
uriTemplate: /image-repositories/{uuid}/import-image
|
||||
controller: App\Controller\OgRepository\Image\ImportAction
|
||||
|
||||
convert_image_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
description: Convert Image in OgRepository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\ConvertImageRepositoryInput
|
||||
uriTemplate: /image-repositories/{uuid}/convert-image
|
||||
controller: App\Controller\OgRepository\Image\ConvertAction
|
||||
|
||||
properties:
|
||||
App\Entity\ImageRepository:
|
||||
|
|
|
@ -12,6 +12,7 @@ framework:
|
|||
handler_id: null
|
||||
cookie_secure: auto
|
||||
cookie_samesite: lax
|
||||
storage_factory_id: session.storage.factory.native
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
|
|
|
@ -15,3 +15,11 @@ when@test:
|
|||
|
||||
framework:
|
||||
profiler: { collect: false }
|
||||
|
||||
when@prod:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
|
@ -82,7 +82,7 @@ services:
|
|||
|
||||
api_platform.filter.og_live.search:
|
||||
parent: 'api_platform.doctrine.orm.search_filter'
|
||||
arguments: [ { 'id': 'exact', 'name': 'partial', } ]
|
||||
arguments: [ { 'id': 'exact', 'name': 'partial', 'status': 'exact' } ]
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.og_live.boolean:
|
||||
|
|
|
@ -15,7 +15,7 @@ use Symfony\Component\HttpKernel\Attribute\AsController;
|
|||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[AsController]
|
||||
class OgAgentController extends AbstractController
|
||||
class AgentSessionController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager
|
|
@ -7,7 +7,7 @@ namespace App\Controller\OgBoot;
|
|||
use App\Controller\OgBoot\PxeBootFile\PostAction;
|
||||
use App\Service\Trace\CreateService;
|
||||
use App\Service\Utils\ExtractOgLiveFilenameDateService;
|
||||
use App\Service\Utils\SymflipyOgLiveFilenameService;
|
||||
use App\Service\Utils\SimplifyOgLiveFilenameService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||
|
@ -34,7 +34,7 @@ abstract class AbstractOgBootController extends AbstractController
|
|||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreateService $createService,
|
||||
protected readonly SymflipyOgLiveFilenameService $symflipyOgLiveFilenameService,
|
||||
protected readonly SimplifyOgLiveFilenameService $simplifyOgLiveFilenameService,
|
||||
protected readonly ExtractOgLiveFilenameDateService $extractOgLiveFilenameDateService,
|
||||
)
|
||||
{
|
||||
|
|
|
@ -30,7 +30,7 @@ class GetIsosAction extends AbstractOgBootController
|
|||
}
|
||||
|
||||
$isos = array_map(function ($iso) {
|
||||
$filename = $this->symflipyOgLiveFilenameService->__invoke($iso['filename']);
|
||||
$filename = $this->simplifyOgLiveFilenameService->__invoke($iso['filename']);
|
||||
|
||||
return [
|
||||
'id' => $iso['id'],
|
||||
|
|
|
@ -49,7 +49,7 @@ class InstallAction extends AbstractOgBootController
|
|||
|
||||
$this->createService->__invoke(null, CommandTypes::INSTALL_OGLIVE, TraceStatus::IN_PROGRESS, 'InstallOgLive_'.$data->getUuid(), $inputData);
|
||||
|
||||
$data->setName($this->symflipyOgLiveFilenameService->__invoke($data->getFilename()));
|
||||
$data->setName($this->simplifyOgLiveFilenameService->__invoke($data->getFilename()));
|
||||
$data->setDate(new \DateTime());
|
||||
$data->setStatus(OgLiveStatus::PENDING);
|
||||
$this->entityManager->persist($data);
|
||||
|
|
|
@ -20,16 +20,21 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|||
class SyncAction extends AbstractOgBootController
|
||||
{
|
||||
const string OG_BOOT_DIRECTORY = '/opt/opengnsys/ogboot/tftpboot//';
|
||||
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __invoke(): JsonResponse
|
||||
{
|
||||
$content = $this->createRequest('GET', 'http://'.$this->ogBootApiUrl . '/ogboot/v1/oglives');
|
||||
|
||||
$allOgLives = $this->entityManager->getRepository(OgLive::class)->findAll();
|
||||
$apiChecksums = array_map(fn($ogLive) => $ogLive['id'], $content['message']['installed_ogLives']);
|
||||
|
||||
foreach ($content['message']['installed_ogLives'] as $ogLive) {
|
||||
$ogLiveEntity = $this->entityManager->getRepository(OgLive::class)->findOneBy(['checksum' => $ogLive['id']]);
|
||||
|
||||
|
@ -43,6 +48,17 @@ class SyncAction extends AbstractOgBootController
|
|||
$this->extracted($ogLiveEntity, $ogLive);
|
||||
$this->entityManager->persist($ogLiveEntity);
|
||||
}
|
||||
|
||||
foreach ($allOgLives as $localOgLive) {
|
||||
if ($localOgLive->getStatus() === OgLiveStatus::PENDING ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!in_array($localOgLive->getChecksum(), $apiChecksums)) {
|
||||
$this->entityManager->remove($localOgLive);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
if (isset($content['message']['default_oglive'])) {
|
||||
|
@ -60,7 +76,7 @@ class SyncAction extends AbstractOgBootController
|
|||
*/
|
||||
private function extracted(OgLive $ogLiveEntity, mixed $ogLive): void
|
||||
{
|
||||
$ogLiveEntity->setName($this->symflipyOgLiveFilenameService->__invoke(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory'])));
|
||||
$ogLiveEntity->setName($this->simplifyOgLiveFilenameService->__invoke(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory'])));
|
||||
$ogLiveEntity->setDate(new \DateTime($this->extractOgLiveFilenameDateService->__invoke(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory']))));
|
||||
$ogLiveEntity->setInstalled(true);
|
||||
$ogLiveEntity->setArchitecture($ogLive['architecture']);
|
||||
|
@ -75,6 +91,13 @@ class SyncAction extends AbstractOgBootController
|
|||
|
||||
private function serDefaultOgLive(string $defaultOgLive): void
|
||||
{
|
||||
$oldDefaultOgLive = $this->entityManager->getRepository(OgLive::class)->findAll();
|
||||
|
||||
foreach ($oldDefaultOgLive as $oldOgLive) {
|
||||
$oldOgLive->setIsDefault(false);
|
||||
$this->entityManager->persist($oldOgLive);
|
||||
}
|
||||
|
||||
$ogLiveEntity = $this->entityManager->getRepository(OgLive::class)->findOneBy(['filename' => $defaultOgLive]);
|
||||
|
||||
if (!$ogLiveEntity) {
|
||||
|
|
|
@ -6,7 +6,9 @@ use App\Controller\OgBoot\AbstractOgBootController;
|
|||
use App\Entity\OgLive;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\OgLiveStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Utils\ExtractOgLiveFilenameDateService;
|
||||
use App\Service\Utils\SimplifyOgLiveFilenameService;
|
||||
use App\Service\Utils\SymflipyOgLiveFilenameService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
@ -33,7 +35,7 @@ class InstallOgLiveResponseAction extends AbstractController
|
|||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly LoggerInterface $logger,
|
||||
protected readonly SymflipyOgLiveFilenameService $symflipyOgLiveFilenameService,
|
||||
protected readonly SimplifyOgLiveFilenameService $simplifyOgLiveFilenameService,
|
||||
protected readonly ExtractOgLiveFilenameDateService $extractOgLiveFilenameDateService,
|
||||
)
|
||||
{
|
||||
|
@ -51,6 +53,8 @@ class InstallOgLiveResponseAction extends AbstractController
|
|||
return new JsonResponse(['error' => 'Invalid JSON data'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$this->logger->info('OgLive Webhook data received: '.json_encode($data));
|
||||
|
||||
$data = $data['webhookData'];
|
||||
|
||||
if ($data === null || !isset($data['message'], $data['ogCoreId'], $data['status'])) {
|
||||
|
@ -69,8 +73,9 @@ class InstallOgLiveResponseAction extends AbstractController
|
|||
}
|
||||
|
||||
if ($trace) {
|
||||
$trace->setStatus($status === self::OG_LIVE_INSTALL_SUCCESS ? 'success' : 'failure');
|
||||
$trace->setStatus($status === self::OG_LIVE_INSTALL_SUCCESS ? TraceStatus::SUCCESS : TraceStatus::FAILED);
|
||||
$this->entityManager->persist($trace);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
if ($ogLive->getStatus() === OgLiveStatus::ACTIVE) {
|
||||
|
@ -86,12 +91,12 @@ class InstallOgLiveResponseAction extends AbstractController
|
|||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function updateOgLive (OgLive $ogLive, array $details, string $status): void
|
||||
private function updateOgLive (OgLive $ogLive, mixed $details, string $status): void
|
||||
{
|
||||
if ($status === self::OG_LIVE_INSTALL_SUCCESS) {
|
||||
$ogLive->setName($this->symflipyOgLiveFilenameService->__invoke($details['filename']));
|
||||
$ogLive->setDate(new \DateTime($this->extractOgLiveFilenameDateService->__invoke($details['filename'])));
|
||||
$ogLive->setFilename(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory']));
|
||||
if ( is_array($details) && $status === self::OG_LIVE_INSTALL_SUCCESS) {
|
||||
$ogLive->setName($this->simplifyOgLiveFilenameService->__invoke($details['directory']));
|
||||
$ogLive->setDate(new \DateTime($this->extractOgLiveFilenameDateService->__invoke($details['directory'])));
|
||||
$ogLive->setFilename(str_replace(self::OG_BOOT_DIRECTORY, '', $details['directory']));
|
||||
$ogLive->setInstalled(true);
|
||||
$ogLive->setSynchronized(true);
|
||||
$ogLive->setChecksum($details['id']);
|
||||
|
@ -100,21 +105,20 @@ class InstallOgLiveResponseAction extends AbstractController
|
|||
$ogLive->setArchitecture($details['architecture']);
|
||||
$ogLive->setRevision($details['revision']);
|
||||
$ogLive->setDirectory($details['directory']);
|
||||
|
||||
$oldDefaultOgLive = $this->entityManager->getRepository(OgLive::class)->findAll();
|
||||
foreach ($oldDefaultOgLive as $oldOgLive) {
|
||||
$oldOgLive->setIsDefault(false);
|
||||
$this->entityManager->persist($oldOgLive);
|
||||
}
|
||||
|
||||
$ogLive->setIsDefault(true);
|
||||
$this->entityManager->persist($ogLive);
|
||||
}
|
||||
|
||||
$ogLive->setStatus($status === self::OG_LIVE_INSTALL_SUCCESS ? OgLiveStatus::ACTIVE : OgLiveStatus::FAILED);
|
||||
$ogLive->setInstalled($status === self::OG_LIVE_INSTALL_SUCCESS);
|
||||
|
||||
$oldDefaultOgLive = $this->entityManager->getRepository(OgLive::class)->findBy(['isDefault' => true]);
|
||||
|
||||
foreach ($oldDefaultOgLive as $oldOgLive) {
|
||||
$oldOgLive->setIsDefault(false);
|
||||
$this->entityManager->persist($oldOgLive);
|
||||
}
|
||||
|
||||
$ogLive->setIsDefault(true);
|
||||
$this->entityManager->persist($ogLive);
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
|
@ -55,7 +55,7 @@ class BackupImageAction extends AbstractOgRepositoryController
|
|||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'repositoryUuid' => $repository->getUuid(),
|
||||
'imageUuid' => $imageImageRepository->getUuid(),
|
||||
'imageImageRepositoryUuid' => $imageImageRepository->getUuid(),
|
||||
'ID_img' => $imageImageRepository->getImageFullsum(),
|
||||
'repo_ip' => $input->repoIp,
|
||||
'remote_path' => $input->remotePath
|
||||
|
|
|
@ -59,7 +59,7 @@ class CancelTransmissionAction extends AbstractOgRepositoryController
|
|||
$content = $this->createRequest('DELETE', 'http://'.$image->getRepository()->getIp().':8006/ogrepository/v1/'.$method.'/images/'.$image->getImageFullsum());
|
||||
}
|
||||
|
||||
if (isset($content['error']) && $content['error'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new ValidatorException('Error cancelling transmission');
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Image;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\ConvertImageRepositoryInput;
|
||||
use App\Dto\Input\ImportImageRepositoryInput;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
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;
|
||||
|
||||
#[AsController]
|
||||
class ConvertAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ConvertImageRepositoryInput $input, ImageRepository $repository): JsonResponse
|
||||
{
|
||||
$fileSystem = $input->filesystem;
|
||||
$image = pathinfo($input->name, PATHINFO_FILENAME);
|
||||
|
||||
$imageEntity = $this->entityManager->getRepository(Image::class)->findOneBy(['name' => $image]);
|
||||
|
||||
if (!$imageEntity){
|
||||
$imageEntity = new Image();
|
||||
$imageEntity->setName($image);
|
||||
$imageEntity->setRemotePc(false);
|
||||
$imageEntity->setIsGlobal(false);
|
||||
|
||||
$this->entityManager->persist($imageEntity);
|
||||
}
|
||||
|
||||
$imageImageRepositoryEntity = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['image' => $imageEntity, 'repository' => $repository]);
|
||||
|
||||
if ($imageImageRepositoryEntity){
|
||||
throw new ValidatorException('This image already exists in this repository');
|
||||
}
|
||||
|
||||
$imageImageRepositoryEntity = new ImageImageRepository();
|
||||
$imageImageRepositoryEntity->setStatus(ImageStatus::PENDING);
|
||||
$imageImageRepositoryEntity->setImage($imageEntity);
|
||||
$imageImageRepositoryEntity->setRepository($repository);
|
||||
|
||||
$this->entityManager->persist($imageImageRepositoryEntity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Converting image', ['image' => $image]);
|
||||
|
||||
$params = [
|
||||
'json' => [
|
||||
'filesystem' => $fileSystem,
|
||||
'virtual_image' => $input->name
|
||||
]
|
||||
];
|
||||
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/virtual', $params);
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new ValidatorException('Error converting image');
|
||||
}
|
||||
|
||||
$inputData = [
|
||||
'imageName' => $image,
|
||||
'imageImageRepositoryUuid' => $imageImageRepositoryEntity->getUuid(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke(null, CommandTypes::CONVERT_IMAGE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Image;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\BackupImageInput;
|
||||
use App\Dto\Input\ConvertImageToVirtualInput;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
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;
|
||||
|
||||
#[AsController]
|
||||
class ConvertImageToVirtualAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ConvertImageToVirtualInput $input, ImageImageRepository $imageImageRepository): JsonResponse
|
||||
{
|
||||
$image = $imageImageRepository->getImage();
|
||||
|
||||
if (!$image->getName()) {
|
||||
throw new ValidatorException('Name is required');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'json' => [
|
||||
'ID_img' => $imageImageRepository->getImageFullsum(),
|
||||
'vm_extension' => $input->extension,
|
||||
]
|
||||
];
|
||||
|
||||
$this->logger->info('Convert image to virtual', ['image' => $image->getName()]);
|
||||
|
||||
$repository = $imageImageRepository->getRepository();
|
||||
|
||||
$content = $this->createRequest('PUT', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/virtual', $params);
|
||||
|
||||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'repositoryUuid' => $repository->getUuid(),
|
||||
'imageImageRepositoryUuid' => $imageImageRepository->getUuid(),
|
||||
'ID_img' => $imageImageRepository->getImageFullsum(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($image->getClient(), CommandTypes::CONVERT_IMAGE_TO_VIRTUAL, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
||||
$imageImageRepository->setStatus(ImageStatus::TRANSFERRING);
|
||||
$this->entityManager->persist($imageImageRepository);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ class CreateAuxFilesAction extends AbstractOgRepositoryController
|
|||
|
||||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'imageUuid' => $data->getUuid(),
|
||||
'imageImageRepositoryUuid' => $data->getUuid(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($image->getClient(), CommandTypes::CREATE_IMAGE_AUX_FILE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Image;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\ExportImportImageRepositoryInput;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
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;
|
||||
|
||||
#[AsController]
|
||||
class ExportAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ExportImportImageRepositoryInput $input, ImageRepository $repository): JsonResponse
|
||||
{
|
||||
$images = $input->images;
|
||||
|
||||
foreach ($images as $imageEntity) {
|
||||
/** @var Image $image */
|
||||
$image = $imageEntity->getEntity();
|
||||
|
||||
if (!$image->getImageFullsum()) {
|
||||
throw new ValidatorException('Fullsum is required');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'json' => [
|
||||
'ID_img' => $image->getImageFullsum(),
|
||||
'repo_ip' => $repository->getIp(),
|
||||
'user' => 'opengnsys',
|
||||
]
|
||||
];
|
||||
|
||||
$this->logger->info('Exporting image', ['image' => $image->getName(), 'repository' => $repository->getIp()]);
|
||||
|
||||
$content = $this->createRequest('PUT', 'http://'.$image->getRepository()->getIp().':8006/ogrepository/v1/repo/images', $params);
|
||||
|
||||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'imageUuid' => $image->getUuid(),
|
||||
'repositoryUuid' => $repository->getUuid(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($image->getClient(), CommandTypes::EXPORT_IMAGE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
||||
$image->setStatus(ImageStatus::TRANSFERING);
|
||||
$this->entityManager->persist($image);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Image;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\ImportImageRepositoryInput;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
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;
|
||||
|
||||
#[AsController]
|
||||
class ImportAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ImportImageRepositoryInput $input, ImageRepository $repository): JsonResponse
|
||||
{
|
||||
$image = $input->name;
|
||||
|
||||
$imageEntity = $this->entityManager->getRepository(Image::class)->findOneBy(['name' => $image]);
|
||||
|
||||
if (!$imageEntity){
|
||||
$imageEntity = new Image();
|
||||
$imageEntity->setName($image);
|
||||
$imageEntity->setRemotePc(false);
|
||||
$imageEntity->setIsGlobal(false);
|
||||
|
||||
$this->entityManager->persist($imageEntity);
|
||||
}
|
||||
|
||||
$imageImageRepositoryEntity = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['image' => $imageEntity, 'repository' => $repository]);
|
||||
|
||||
if ($imageImageRepositoryEntity){
|
||||
throw new ValidatorException('This image already exists in this repository');
|
||||
}
|
||||
|
||||
$imageImageRepositoryEntity = new ImageImageRepository();
|
||||
$imageImageRepositoryEntity->setStatus(ImageStatus::AUX_FILES_PENDING);
|
||||
$imageImageRepositoryEntity->setImage($imageEntity);
|
||||
$imageImageRepositoryEntity->setRepository($repository);
|
||||
|
||||
$this->entityManager->persist($imageImageRepositoryEntity);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Creating aux files', ['image' => $image]);
|
||||
|
||||
$params = [
|
||||
'json' => [
|
||||
'image' => $image.'.img'
|
||||
]
|
||||
];
|
||||
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/torrentsum', $params);
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new ValidatorException('Error importing image');
|
||||
}
|
||||
|
||||
$inputData = [
|
||||
'imageName' => $image,
|
||||
'imageUuid' => $imageImageRepositoryEntity->getUuid(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke(null, CommandTypes::CREATE_IMAGE_AUX_FILE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace App\Controller\OgRepository\Image;
|
|||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\ExportImportImageRepositoryInput;
|
||||
use App\Dto\Input\TransferGlobalImageInput;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
|
@ -28,7 +29,7 @@ class TransferAction extends AbstractOgRepositoryController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ExportImportImageRepositoryInput $input, ImageImageRepository $imageImageRepository): JsonResponse
|
||||
public function __invoke(TransferGlobalImageInput $input, ImageImageRepository $imageImageRepository): JsonResponse
|
||||
{
|
||||
$repositories = $input->repositories;
|
||||
|
||||
|
@ -45,7 +46,7 @@ class TransferAction extends AbstractOgRepositoryController
|
|||
$params = [
|
||||
'json' => [
|
||||
'image' => $image->getName().'.img',
|
||||
'repo_ip' => $image->getClient()->getRepository()->getIp(),
|
||||
'repo_ip' => $imageImageRepository->getRepository()->getIp(),
|
||||
'user' => 'opengnsys',
|
||||
]
|
||||
];
|
||||
|
|
|
@ -21,7 +21,7 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
|||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
#[AsController]
|
||||
class TransferIsGlobalAction extends AbstractOgRepositoryController
|
||||
class TransferGlobalAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
|
@ -29,26 +29,25 @@ class TransferIsGlobalAction extends AbstractOgRepositoryController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(?array $repositories = [], Image $image): JsonResponse
|
||||
public function __invoke(ImageImageRepository $imageImageRepository): JsonResponse
|
||||
{
|
||||
$repositories = $this->entityManager->getRepository(ImageRepository::class)->findAll();
|
||||
|
||||
foreach ($repositories as $repository) {
|
||||
try {
|
||||
$imageImageRepository = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['image' => $image, 'repository' => $repository]);
|
||||
|
||||
if ($imageImageRepository) {
|
||||
$content = $this->createRequest('GET', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/'.$imageImageRepository->getImageFullsum());
|
||||
|
||||
$this->logger->info('Image already exists', ['image' => $imageImageRepository->getImage()->getName(), 'repository' => $repository->getIp()]);
|
||||
continue;
|
||||
}
|
||||
} catch ( \Exception $e) {
|
||||
$hasImage = $this->entityManager->getRepository(ImageImageRepository::class)
|
||||
->findOneBy(['image' => $imageImageRepository->getImage(), 'repository' => $repository]);
|
||||
|
||||
if ($hasImage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$image = $imageImageRepository->getImage();
|
||||
|
||||
$params = [
|
||||
'json' => [
|
||||
'image' => $image->getName().'.img',
|
||||
'repo_ip' => $image->getClient()->getRepository()->getIp(),
|
||||
'repo_ip' => $imageImageRepository->getRepository()->getIp(),
|
||||
'user' => 'opengnsys',
|
||||
]
|
||||
];
|
||||
|
@ -64,14 +63,18 @@ class TransferIsGlobalAction extends AbstractOgRepositoryController
|
|||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'imageUuid' => $image->getUuid(),
|
||||
//'imageImageRepositoryUuid' => $imageImageRepository?->getUuid(),
|
||||
'imageImageRepositoryUuid' => $imageImageRepository?->getUuid(),
|
||||
'repositoryUuid' => $repository->getUuid(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($image->getClient(), CommandTypes::TRANSFER_IMAGE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||
|
||||
//$imageImageRepository->setStatus(ImageStatus::TRANSFERRING);
|
||||
$image->setIsGlobal(true);
|
||||
$this->entityManager->persist($image);
|
||||
|
||||
$imageImageRepository->setStatus(ImageStatus::TRANSFERRING);
|
||||
$this->entityManager->persist($imageImageRepository);
|
||||
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
|
@ -25,14 +25,24 @@ class SyncAction extends AbstractOgRepositoryController
|
|||
*/
|
||||
public function __invoke(ImageRepository $input): JsonResponse
|
||||
{
|
||||
$content = $this->createRequest('GET', 'http://'.$input->getIp(). ':8006/ogrepository/v1/images');
|
||||
$content = $this->createRequest('GET', 'http://' . $input->getIp() . ':8006/ogrepository/v1/images');
|
||||
|
||||
if (!isset($content['output']['REPOSITORY']['images'])) {
|
||||
return new JsonResponse(data: 'No images found', status: Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$repository = $this->entityManager->getRepository(ImageImageRepository::class);
|
||||
|
||||
$existingImages = $repository->findBy(['repository' => $input]);
|
||||
|
||||
$newImageFullsums = array_column($content['output']['REPOSITORY']['images'], 'fullsum');
|
||||
|
||||
foreach ($content['output']['REPOSITORY']['images'] as $image) {
|
||||
$imageImageRepositoryEntity = $this->entityManager->getRepository(ImageImageRepository::class)->findOneBy(['imageFullsum' => $image['fullsum'], 'repository' => $input]);
|
||||
$imageImageRepositoryEntity = $repository->findOneBy([
|
||||
'imageFullsum' => $image['fullsum'],
|
||||
'repository' => $input
|
||||
]);
|
||||
|
||||
$imageEntity = $this->entityManager->getRepository(Image::class)->findOneBy(['name' => $image['name']]);
|
||||
|
||||
if (!$imageEntity) {
|
||||
|
@ -53,10 +63,17 @@ class SyncAction extends AbstractOgRepositoryController
|
|||
|
||||
$this->entityManager->persist($imageImageRepositoryEntity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach ($existingImages as $existingImage) {
|
||||
if (!in_array($existingImage->getImageFullsum(), $newImageFullsums)) {
|
||||
$this->entityManager->remove($existingImage);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
}
|
|
@ -37,6 +37,8 @@ class ResponseController extends AbstractOgRepositoryController
|
|||
str_starts_with($action, "CreateAuxiliarFiles_") => $this->handleImageRepositoryAction($data, true),
|
||||
str_starts_with($action, "TransferImage_"), str_starts_with($action, "ExportImage_") => $this->processImageAction($data),
|
||||
str_starts_with($action, "BackupImage_") => $this->handleImageRepositoryAction($data),
|
||||
str_starts_with($action, "ConvertImageToVirtual") => $this->handleImageRepositoryAction($data),
|
||||
str_starts_with($action, "ConvertImageFromVirtual") => $this->handleImageRepositoryAction($data),
|
||||
default => $this->jsonResponseError('Invalid action', Response::HTTP_BAD_REQUEST),
|
||||
};
|
||||
}
|
||||
|
@ -65,15 +67,21 @@ class ResponseController extends AbstractOgRepositoryController
|
|||
$trace = $this->getTrace($data['job_id']);
|
||||
if (!$trace) return $this->jsonResponseError('Trace not found');
|
||||
|
||||
$image = $this->getImage($trace);
|
||||
$repository = $this->getRepository($trace);
|
||||
$originImageImageRepository = $this->getImageImageRepository($trace);
|
||||
if (!$image) return $this->jsonResponseError('Image not found', Response::HTTP_NOT_FOUND, $trace);
|
||||
if (!$repository) return $this->jsonResponseError('Repository not found', Response::HTTP_NOT_FOUND, $trace);
|
||||
if (!$originImageImageRepository) return $this->jsonResponseError('ImageImageRepository not found', Response::HTTP_NOT_FOUND, $trace);
|
||||
|
||||
$originImageImageRepository->setStatus(ImageStatus::SUCCESS);
|
||||
$this->entityManager->persist($originImageImageRepository);
|
||||
$this->entityManager->flush();
|
||||
|
||||
if ($data['success'] !== true) {
|
||||
return $this->jsonResponseError('Action failed', Response::HTTP_BAD_REQUEST, $trace);
|
||||
}
|
||||
|
||||
$image = $this->getImage($trace);
|
||||
$repository = $this->getRepository($trace);
|
||||
if (!$image) return $this->jsonResponseError('Image not found', Response::HTTP_NOT_FOUND, $trace);
|
||||
if (!$repository) return $this->jsonResponseError('Repository not found', Response::HTTP_NOT_FOUND, $trace);
|
||||
|
||||
$newImageRepo = new ImageImageRepository();
|
||||
$newImageRepo->setImage($image);
|
||||
$newImageRepo->setRepository($repository);
|
||||
|
@ -127,7 +135,7 @@ class ResponseController extends AbstractOgRepositoryController
|
|||
private function getImageImageRepository(Trace $trace): ?ImageImageRepository
|
||||
{
|
||||
return $this->entityManager->getRepository(ImageImageRepository::class)
|
||||
->findOneBy(['uuid' => $trace->getInput()['imageUuid']]);
|
||||
->findOneBy(['uuid' => $trace->getInput()['imageImageRepositoryUuid']]);
|
||||
}
|
||||
|
||||
private function jsonResponseError(string $message, int $status = Response::HTTP_BAD_REQUEST, ?Trace $trace = null): JsonResponse
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class ConvertImageRepositoryInput
|
||||
{
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['repository:write'])]
|
||||
public ?string $name = '';
|
||||
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['repository:write'])]
|
||||
public ?string $filesystem = '';
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class ConvertImageToVirtualInput
|
||||
{
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
public ?string $extension = '';
|
||||
}
|
|
@ -13,6 +13,6 @@ class ExportImportImageRepositoryInput
|
|||
* @var ImageOutput[]
|
||||
*/
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
public array $repositories = [];
|
||||
#[Groups(['repository:write'])]
|
||||
public array $images = [];
|
||||
}
|
|
@ -16,10 +16,13 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
|
||||
final class ImageRepositoryInput
|
||||
{
|
||||
#[Assert\NotBlank]
|
||||
#[Groups(['repository:write'])]
|
||||
#[ApiProperty(description: 'The name of the repository', example: "Repository 1")]
|
||||
public ?string $name = null;
|
||||
|
||||
#[Assert\NotBlank]
|
||||
#[Assert\Ip]
|
||||
#[Groups(['repository:write'])]
|
||||
#[ApiProperty(description: 'The IP of the repository', example: "")]
|
||||
public ?string $ip = null;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class ImportImageRepositoryInput
|
||||
{
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['repository:write'])]
|
||||
public ?string $name = '';
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
class TransferGlobalImageInput
|
||||
{
|
||||
/**
|
||||
* @var ImageOutput[]
|
||||
*/
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
public array $repositories = [];
|
||||
}
|
|
@ -21,10 +21,10 @@ final class ImageOutput extends AbstractOutput
|
|||
#[Groups(['image:read'])]
|
||||
public ?string $comments = '';
|
||||
|
||||
#[Groups(['image:read'])]
|
||||
#[Groups(['image:read', 'image-image-repository:read'])]
|
||||
public ?bool $remotePc = null;
|
||||
|
||||
#[Groups(['image:read'])]
|
||||
#[Groups(['image:read', 'image-image-repository:read'])]
|
||||
public ?bool $isGlobal = null;
|
||||
|
||||
#[Groups(['image:read'])]
|
||||
|
|
|
@ -18,9 +18,6 @@ class ImageRepositoryOutput extends AbstractOutput
|
|||
#[Groups(['repository:read'])]
|
||||
public ?string $comments = '';
|
||||
|
||||
#[Groups(['repository:read'])]
|
||||
public ?bool $status = true;
|
||||
|
||||
#[Groups(['repository:read'])]
|
||||
public \DateTime $createdAt;
|
||||
|
||||
|
@ -34,7 +31,6 @@ class ImageRepositoryOutput extends AbstractOutput
|
|||
$this->name = $imageRepository->getName();
|
||||
$this->ip = $imageRepository->getIp();
|
||||
$this->comments = $imageRepository->getComments();
|
||||
$this->status = $status;
|
||||
$this->createdAt = $imageRepository->getCreatedAt();
|
||||
$this->createdBy = $imageRepository->getCreatedBy();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace App\EventSubscriber;
|
||||
|
||||
use ApiPlatform\Symfony\EventListener\EventPriorities;
|
||||
use App\Controller\OgRepository\Image\TransferIsGlobalAction;
|
||||
use App\Controller\OgRepository\Image\TransferGlobalAction;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use App\Dto\Output\OrganizationalUnitOutput;
|
||||
use App\Entity\Image;
|
||||
|
@ -21,8 +21,8 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
|||
final readonly class ImageRepositorySubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private EntityManagerInterface $entityManager,
|
||||
private readonly TransferIsGlobalAction $transferIsGlobalAction,
|
||||
private EntityManagerInterface $entityManager,
|
||||
private readonly TransferGlobalAction $transferIsGlobalAction,
|
||||
)
|
||||
{
|
||||
|
||||
|
@ -54,7 +54,7 @@ final readonly class ImageRepositorySubscriber implements EventSubscriberInterfa
|
|||
$imagesToImport = $this->entityManager->getRepository(Image::class)->findBy(['isGlobal' => true]);
|
||||
|
||||
foreach($imagesToImport as $imageToImport) {
|
||||
$this->transferIsGlobalAction->__invoke([$imageToImport], $imageRepositoryOutput->getEntity());
|
||||
//$this->transferIsGlobalAction->__invoke($imageRepositoryOutput->getEntity());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,10 +7,12 @@ final class CommandTypes
|
|||
public const string DEPLOY_IMAGE = 'deploy-image';
|
||||
public const string RESTORE_IMAGE = 'restore-image';
|
||||
public const string CREATE_IMAGE = 'create-image';
|
||||
public const string CONVERT_IMAGE = 'convert-image';
|
||||
public const string CREATE_IMAGE_AUX_FILE = 'create-image-aux-file';
|
||||
public const string BACKUP_IMAGE = 'backup-image';
|
||||
public const string IMPORT_IMAGE = 'import-image';
|
||||
public const string EXPORT_IMAGE = 'export-image';
|
||||
public const string CONVERT_IMAGE_TO_VIRTUAL = 'convert-image-to-virtual';
|
||||
public const string TRANSFER_IMAGE = 'transfer-image';
|
||||
public const string POWER_ON = 'power-on';
|
||||
public const string REBOOT = 'reboot';
|
||||
|
@ -18,17 +20,18 @@ final class CommandTypes
|
|||
public const string LOGIN = 'login';
|
||||
public const string LOGOUT = 'logout';
|
||||
public const string PARTITION_AND_FORMAT = 'partition-and-format';
|
||||
|
||||
public const string INSTALL_OGLIVE = 'install-oglive';
|
||||
|
||||
private const array COMMAND_TYPES = [
|
||||
self::DEPLOY_IMAGE => 'Deploy Image',
|
||||
self::RESTORE_IMAGE => 'Update Cache',
|
||||
self::CREATE_IMAGE => 'Create Image',
|
||||
self::CREATE_IMAGE_AUX_FILE => 'Crear fichero auxiliar en repositorio',
|
||||
self::BACKUP_IMAGE => 'Crear backup de imagen',
|
||||
self::IMPORT_IMAGE => 'Importar imagen',
|
||||
self::EXPORT_IMAGE => 'Exportar imagen',
|
||||
self::CONVERT_IMAGE => 'Convert Image',
|
||||
self::CONVERT_IMAGE_TO_VIRTUAL => 'Convert Image to Virtual',
|
||||
self::CREATE_IMAGE_AUX_FILE => 'Create Image Aux File',
|
||||
self::BACKUP_IMAGE => 'Backup Image',
|
||||
self::IMPORT_IMAGE => 'Import image',
|
||||
self::EXPORT_IMAGE => 'Export image',
|
||||
self::POWER_ON => 'Encender',
|
||||
self::REBOOT => 'Reiniciar',
|
||||
self::SHUTDOWN => 'Apagar',
|
||||
|
|
|
@ -8,7 +8,7 @@ final class DeployMethodTypes
|
|||
public const string MULTICAST_UFTP = 'uftp';
|
||||
public const string MULTICAST_UFTP_DIRECT = 'uftp-direct';
|
||||
public const string MULTICAST_UDPCAST = 'udpcast';
|
||||
public const string MULTICAST_UDPCAST_DIRECT = 'udp-direct';
|
||||
public const string MULTICAST_UDPCAST_DIRECT = 'udpcast-direct';
|
||||
public const string UNICAST = 'unicast';
|
||||
public const string UNICAST_DIRECT = 'unicast-direct';
|
||||
public const string TORRENT = 'p2p';
|
||||
|
|
|
@ -8,13 +8,12 @@ final class OgLiveStatus
|
|||
public const string ACTIVE = 'active';
|
||||
public const string INACTIVE = 'inactive';
|
||||
public const string DELETED = 'deleted';
|
||||
|
||||
public const string FAILED = 'failed';
|
||||
|
||||
private const array OG_LIVE_STATUSES = [
|
||||
self::PENDING => 'Pendiente',
|
||||
self::ACTIVE => 'Activo',
|
||||
self::INACTIVE => 'Inactivo',
|
||||
self::PENDING => 'Instalando',
|
||||
self::ACTIVE => 'Instalada',
|
||||
self::INACTIVE => 'Sin instalar',
|
||||
self::DELETED => 'Eliminado',
|
||||
self::FAILED => 'Fallido',
|
||||
];
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\Utils;
|
||||
|
||||
class SimplifyOgLiveFilenameService
|
||||
{
|
||||
private const string PATTERN = '/^ogLive-([^-]+)-(.+)-([^-]+)-r([0-9]+)(?:\.([a-f0-9]+))?_([0-9]+)(?:\.iso)?$/';
|
||||
|
||||
public function __invoke(string $filename): ?string
|
||||
{
|
||||
if (!preg_match(self::PATTERN, $filename, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$distro = $matches[1];
|
||||
$kernelFull = $matches[2];
|
||||
$arch = $matches[3];
|
||||
$revision = $matches[4];
|
||||
$commit = $matches[5] ?? null;
|
||||
$date = $matches[6];
|
||||
|
||||
|
||||
$kernel = in_array($arch, ['amd64', 'i386']) ? $kernelFull : "$kernelFull-$arch";
|
||||
$arch = in_array($arch, ['amd64', 'i386']) ? $arch : 'i386';
|
||||
|
||||
return 'ogLive-'.$kernelFull.'-'.$date;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\Utils;
|
||||
|
||||
class SymflipyOgLiveFilenameService
|
||||
{
|
||||
public function __invoke(string $filename): string
|
||||
{
|
||||
if (preg_match('/^(.+)-r\d+\.[a-f0-9]+_(\d{8})(?:\.iso)?$/', $filename, $matches)) {
|
||||
return "{$matches[1]}-{$matches[2]}";
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ use ApiPlatform\State\ProcessorInterface;
|
|||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Controller\OgAgent\CreateImageAction;
|
||||
use App\Controller\OgRepository\Image\TransferAction;
|
||||
use App\Controller\OgRepository\Image\TransferIsGlobalAction;
|
||||
use App\Dto\Input\ImageInput;
|
||||
use App\Dto\Input\ImageRepositoryInput;
|
||||
use App\Dto\Output\ImageOutput;
|
||||
|
@ -27,7 +26,6 @@ readonly class ImageProcessor implements ProcessorInterface
|
|||
private ImageRepository $imageRepository,
|
||||
private ValidatorInterface $validator,
|
||||
private CreateImageAction $createImageActionController,
|
||||
private TransferIsGlobalAction $transferActionController
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -68,11 +66,6 @@ readonly class ImageProcessor implements ProcessorInterface
|
|||
|
||||
if ($data->source !== 'input') {
|
||||
$response = $this->createImageActionController->__invoke($image);
|
||||
} else {
|
||||
if ($data->isGlobal === true) {
|
||||
$repositories = $this->imageRepositoryRepository->findAll();
|
||||
$this->transferActionController->__invoke($repositories, $image);
|
||||
}
|
||||
}
|
||||
|
||||
$this->imageRepository->save($image);
|
||||
|
|
|
@ -9,23 +9,17 @@ use ApiPlatform\Metadata\Patch;
|
|||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\Pagination\TraversablePaginator;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Controller\OgRepository\StatusAction;
|
||||
use App\Dto\Input\ImageInput;
|
||||
use App\Dto\Input\ImageRepositoryInput;
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
readonly class ImageRepositoryProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ProviderInterface $collectionProvider,
|
||||
private ProviderInterface $itemProvider,
|
||||
private StatusAction $statusAction
|
||||
private ProviderInterface $collectionProvider,
|
||||
private ProviderInterface $itemProvider
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -43,23 +37,13 @@ readonly class ImageRepositoryProvider implements ProviderInterface
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||
{
|
||||
$paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
$items = new \ArrayObject();
|
||||
foreach ($paginator->getIterator() as $item){
|
||||
$statusResponse = $this->statusAction->__invoke($item);
|
||||
$content = json_decode($statusResponse->getContent(), true);
|
||||
$status = !isset($content['error']);
|
||||
|
||||
$items[] = new ImageRepositoryOutput($item, $status);
|
||||
$items[] = new ImageRepositoryOutput($item);
|
||||
}
|
||||
|
||||
return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
|
||||
|
|
Loading…
Reference in New Issue