ogRepo new endpoints. Export/Import image
testing/ogcore-api/pipeline/head This commit looks good
Details
testing/ogcore-api/pipeline/head This commit looks good
Details
parent
e421a38079
commit
3c7fa26e32
|
@ -34,7 +34,7 @@ resources:
|
||||||
class: ApiPlatform\Metadata\Post
|
class: ApiPlatform\Metadata\Post
|
||||||
method: POST
|
method: POST
|
||||||
input: App\Dto\Input\WoLInput
|
input: App\Dto\Input\WoLInput
|
||||||
uriTemplate: /image-repositories/{uuid}/wol
|
uriTemplate: /image-repositories/wol
|
||||||
controller: App\Controller\OgRepository\WoLAction
|
controller: App\Controller\OgRepository\WoLAction
|
||||||
|
|
||||||
get_collection_images_ogrepository:
|
get_collection_images_ogrepository:
|
||||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Controller\OgRepository;
|
||||||
|
|
||||||
use App\Service\Trace\CreateService;
|
use App\Service\Trace\CreateService;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
@ -24,6 +25,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
|
||||||
protected readonly EntityManagerInterface $entityManager,
|
protected readonly EntityManagerInterface $entityManager,
|
||||||
protected readonly HttpClientInterface $httpClient,
|
protected readonly HttpClientInterface $httpClient,
|
||||||
protected readonly CreateService $createService,
|
protected readonly CreateService $createService,
|
||||||
|
protected readonly LoggerInterface $logger,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||||
use App\Dto\Input\ExportImportImageRepositoryInput;
|
use App\Dto\Input\ExportImportImageRepositoryInput;
|
||||||
use App\Entity\Image;
|
use App\Entity\Image;
|
||||||
use App\Entity\ImageRepository;
|
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\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||||
|
@ -44,9 +47,18 @@ class ExportAction extends AbstractOgRepositoryController
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$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);
|
$content = $this->createRequest('PUT', 'http://'.$image->getRepository()->getIp().':8006/ogrepository/v1/repo/images', $params);
|
||||||
|
|
||||||
$image->setRepository($repository);
|
$inputData = [
|
||||||
|
'imageName' => $image->getName(),
|
||||||
|
'imageUuid' => $image->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->persist($image);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||||
use App\Dto\Input\ExportImportImageRepositoryInput;
|
use App\Dto\Input\ExportImportImageRepositoryInput;
|
||||||
use App\Entity\Image;
|
use App\Entity\Image;
|
||||||
use App\Entity\ImageRepository;
|
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\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||||
|
@ -46,7 +49,14 @@ class ImportAction extends AbstractOgRepositoryController
|
||||||
|
|
||||||
$content = $this->createRequest('POST', 'http://'.$image->getRepository()->getIp().':8006/ogrepository/v1/repo/images', $params);
|
$content = $this->createRequest('POST', 'http://'.$image->getRepository()->getIp().':8006/ogrepository/v1/repo/images', $params);
|
||||||
|
|
||||||
$image->setRepository($repository);
|
$inputData = [
|
||||||
|
'imageName' => $image->getName(),
|
||||||
|
'imageUuid' => $image->getUuid(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->createService->__invoke($image->getClient(), CommandTypes::IMPORT_IMAGE, TraceStatus::IN_PROGRESS, $content['job_id'], $inputData);
|
||||||
|
|
||||||
|
$image->setStatus(ImageStatus::TRANSFERING);
|
||||||
$this->entityManager->persist($image);
|
$this->entityManager->persist($image);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Entity\Trace;
|
||||||
use App\Model\ImageStatus;
|
use App\Model\ImageStatus;
|
||||||
use App\Model\TraceStatus;
|
use App\Model\TraceStatus;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -18,7 +19,8 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||||
class ResponseController extends AbstractController
|
class ResponseController extends AbstractController
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
protected readonly EntityManagerInterface $entityManager
|
protected readonly EntityManagerInterface $entityManager,
|
||||||
|
protected readonly LoggerInterface $logger,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -28,6 +30,27 @@ class ResponseController extends AbstractController
|
||||||
{
|
{
|
||||||
$data = json_decode($request->getContent(), true);
|
$data = json_decode($request->getContent(), true);
|
||||||
|
|
||||||
|
if (!isset($data['job_id'])) {
|
||||||
|
return new JsonResponse(['message' => 'Invalid request'], Response::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = $data['job_id'];
|
||||||
|
|
||||||
|
if (str_starts_with($action, "CreateAuxiliarFiles_")) {
|
||||||
|
$this->handleCreateAuxFiles($action, $data);
|
||||||
|
} elseif (str_starts_with($action, "ExportImage_")) {
|
||||||
|
$this->handleExportImage($action, $data);
|
||||||
|
} elseif (str_starts_with($action, "ImportImage_")) {
|
||||||
|
$this->handleImportImage($action, $data);
|
||||||
|
} else {
|
||||||
|
return new JsonResponse(['message' => 'Invalid action'], Response::HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResponse($data, Response::HTTP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleCreateAuxFiles(string $action, array $data): void
|
||||||
|
{
|
||||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||||
$imageUuid = $trace->getInput()['imageUuid'];
|
$imageUuid = $trace->getInput()['imageUuid'];
|
||||||
|
|
||||||
|
@ -40,7 +63,8 @@ class ResponseController extends AbstractController
|
||||||
$this->entityManager->persist($trace);
|
$this->entityManager->persist($trace);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
||||||
return new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND);
|
new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$image->setImageFullsum($data['image_id']);
|
$image->setImageFullsum($data['image_id']);
|
||||||
|
@ -52,8 +76,69 @@ class ResponseController extends AbstractController
|
||||||
|
|
||||||
$this->entityManager->persist($trace);
|
$this->entityManager->persist($trace);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonResponse($data, Response::HTTP_OK);
|
private function handleExportImage(string $action, array $data): void
|
||||||
|
{
|
||||||
|
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||||
|
|
||||||
|
$imageUuid = $trace->getInput()['imageUuid'];
|
||||||
|
|
||||||
|
$image = $this->entityManager->getRepository(Image::class)->findOneBy(['uuid' => $imageUuid]);
|
||||||
|
|
||||||
|
if ($image === null) {
|
||||||
|
$trace->setStatus(TraceStatus::FAILED);
|
||||||
|
$trace->setFinishedAt(new \DateTime());
|
||||||
|
$trace->setOutput('Image not found');
|
||||||
|
$this->entityManager->persist($trace);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info('Image exported', ['image' => $image->getName()]);
|
||||||
|
|
||||||
|
$image->setStatus(ImageStatus::SUCCESS);
|
||||||
|
$this->entityManager->persist($image);
|
||||||
|
|
||||||
|
|
||||||
|
$trace->setStatus(TraceStatus::SUCCESS);
|
||||||
|
$trace->setFinishedAt(new \DateTime());
|
||||||
|
|
||||||
|
$this->entityManager->persist($trace);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleImportImage(string $action, array $data): void
|
||||||
|
{
|
||||||
|
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||||
|
|
||||||
|
$imageUuid = $trace->getInput()['imageUuid'];
|
||||||
|
|
||||||
|
$image = $this->entityManager->getRepository(Image::class)->findOneBy(['uuid' => $imageUuid]);
|
||||||
|
|
||||||
|
if ($image === null) {
|
||||||
|
$trace->setStatus(TraceStatus::FAILED);
|
||||||
|
$trace->setFinishedAt(new \DateTime());
|
||||||
|
$trace->setOutput('Image not found');
|
||||||
|
$this->entityManager->persist($trace);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->info('Image imported', ['image' => $image->getName()]);
|
||||||
|
|
||||||
|
$image->setStatus(ImageStatus::SUCCESS);
|
||||||
|
$this->entityManager->persist($image);
|
||||||
|
|
||||||
|
|
||||||
|
$trace->setStatus(TraceStatus::SUCCESS);
|
||||||
|
$trace->setFinishedAt(new \DateTime());
|
||||||
|
|
||||||
|
$this->entityManager->persist($trace);
|
||||||
|
$this->entityManager->flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -36,31 +36,35 @@ class WoLAction extends AbstractOgRepositoryController
|
||||||
* @throws RedirectionExceptionInterface
|
* @throws RedirectionExceptionInterface
|
||||||
* @throws ClientExceptionInterface
|
* @throws ClientExceptionInterface
|
||||||
*/
|
*/
|
||||||
public function __invoke(WoLInput $input, ImageRepository $repository): JsonResponse
|
public function __invoke(WoLInput $input): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var Client $client */
|
foreach ($input->clients as $client) {
|
||||||
$client = $input->client->getEntity();
|
/** @var Client $client */
|
||||||
|
$client = $client->getEntity();
|
||||||
|
$repository = $client->getRepository();
|
||||||
|
|
||||||
|
if (!$repository->getIp()) {
|
||||||
|
throw new ValidatorException('IP is required');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$repository->getIp()) {
|
$params = [
|
||||||
throw new ValidatorException('IP is required');
|
'json' => [
|
||||||
|
'broadcast_ip' => '255.255.255.255',
|
||||||
|
'mac' => $client->getMac()
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->logger->info('Sending WoL to client', ['mac' => $client->getMac()]);
|
||||||
|
|
||||||
|
$content = $this->createRequest('POST', 'http://'.$repository->getIp(). ':8006/ogrepository/v1/wol', $params);
|
||||||
|
|
||||||
|
$client->setStatus(ClientStatus::INITIALIZING);
|
||||||
|
$this->entityManager->persist($client);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->createService->__invoke($client, CommandTypes::SHUTDOWN, TraceStatus::SUCCESS, '', []);
|
||||||
}
|
}
|
||||||
|
|
||||||
$params = [
|
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||||
'json' => [
|
|
||||||
'broadcast_ip' => '255.255.255.255',
|
|
||||||
'mac' => $client->getMac()
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp(). ':8006/ogrepository/v1/wol', $params);
|
|
||||||
|
|
||||||
$client->setStatus(ClientStatus::INITIALIZING);
|
|
||||||
$this->entityManager->persist($client);
|
|
||||||
$this->entityManager->flush();
|
|
||||||
|
|
||||||
$this->createService->__invoke($client, CommandTypes::SHUTDOWN, TraceStatus::SUCCESS, '', []);
|
|
||||||
|
|
||||||
return new JsonResponse(data: $client, status: Response::HTTP_OK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ final class ImageInput
|
||||||
#[ApiProperty(description: 'The type of the image', example: "Server")]
|
#[ApiProperty(description: 'The type of the image', example: "Server")]
|
||||||
public ?string $source = 'input';
|
public ?string $source = 'input';
|
||||||
|
|
||||||
|
#[Groups(['image:write'])]
|
||||||
|
#[ApiProperty(description: 'The status of the image', example: "PENDING")]
|
||||||
|
public ?string $status = ImageStatus::PENDING;
|
||||||
|
|
||||||
#[Groups(['image:write'])]
|
#[Groups(['image:write'])]
|
||||||
#[ApiProperty(description: 'The software profile of the image')]
|
#[ApiProperty(description: 'The software profile of the image')]
|
||||||
public ?SoftwareProfileOutput $softwareProfile = null;
|
public ?SoftwareProfileOutput $softwareProfile = null;
|
||||||
|
@ -73,6 +77,7 @@ final class ImageInput
|
||||||
$this->comments = $image->getComments();
|
$this->comments = $image->getComments();
|
||||||
$this->type = $image->getType();
|
$this->type = $image->getType();
|
||||||
$this->remotePc = $image->isRemotePc();
|
$this->remotePc = $image->isRemotePc();
|
||||||
|
$this->status = $image->getStatus();
|
||||||
|
|
||||||
if ($image->getSoftwareProfile()) {
|
if ($image->getSoftwareProfile()) {
|
||||||
$this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile());
|
$this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile());
|
||||||
|
@ -95,13 +100,13 @@ final class ImageInput
|
||||||
{
|
{
|
||||||
if (!$image) {
|
if (!$image) {
|
||||||
$image = new Image();
|
$image = new Image();
|
||||||
|
$image->setStatus(ImageStatus::PENDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
$image->setName($this->name);
|
$image->setName($this->name);
|
||||||
$image->setDescription($this->description);
|
$image->setDescription($this->description);
|
||||||
$image->setComments($this->comments);
|
$image->setComments($this->comments);
|
||||||
$image->setType($this->type);
|
$image->setType($this->type);
|
||||||
$image->setStatus(ImageStatus::PENDING);
|
|
||||||
|
|
||||||
if ($this->softwareProfile) {
|
if ($this->softwareProfile) {
|
||||||
$image->setSoftwareProfile($this->softwareProfile->getEntity());
|
$image->setSoftwareProfile($this->softwareProfile->getEntity());
|
||||||
|
|
|
@ -8,7 +8,10 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
class WoLInput
|
class WoLInput
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var ClientOutput[]|null
|
||||||
|
*/
|
||||||
#[Groups(['repository:write'])]
|
#[Groups(['repository:write'])]
|
||||||
#[ApiProperty(description: 'The client to wol')]
|
#[ApiProperty(description: 'The client to wol')]
|
||||||
public ?ClientOutput $client = null;
|
public ?array $clients = null;
|
||||||
}
|
}
|
|
@ -8,6 +8,8 @@ final class CommandTypes
|
||||||
public const string RESTORE_IMAGE = 'restore-image';
|
public const string RESTORE_IMAGE = 'restore-image';
|
||||||
public const string CREATE_IMAGE = 'create-image';
|
public const string CREATE_IMAGE = 'create-image';
|
||||||
public const string CREATE_IMAGE_AUX_FILE = 'create-image-aux-file';
|
public const string CREATE_IMAGE_AUX_FILE = 'create-image-aux-file';
|
||||||
|
public const string IMPORT_IMAGE = 'import-image';
|
||||||
|
public const string EXPORT_IMAGE = 'export-image';
|
||||||
public const string POWER_ON = 'power-on';
|
public const string POWER_ON = 'power-on';
|
||||||
public const string REBOOT = 'reboot';
|
public const string REBOOT = 'reboot';
|
||||||
public const string SHUTDOWN = 'shutdown';
|
public const string SHUTDOWN = 'shutdown';
|
||||||
|
@ -20,6 +22,8 @@ final class CommandTypes
|
||||||
self::RESTORE_IMAGE => 'Update Cache',
|
self::RESTORE_IMAGE => 'Update Cache',
|
||||||
self::CREATE_IMAGE => 'Create Image',
|
self::CREATE_IMAGE => 'Create Image',
|
||||||
self::CREATE_IMAGE_AUX_FILE => 'Crear fichero auxiliar en repositorio',
|
self::CREATE_IMAGE_AUX_FILE => 'Crear fichero auxiliar en repositorio',
|
||||||
|
self::IMPORT_IMAGE => 'Importar imagen',
|
||||||
|
self::EXPORT_IMAGE => 'Exportar imagen',
|
||||||
self::POWER_ON => 'Encender',
|
self::POWER_ON => 'Encender',
|
||||||
self::REBOOT => 'Reiniciar',
|
self::REBOOT => 'Reiniciar',
|
||||||
self::SHUTDOWN => 'Apagar',
|
self::SHUTDOWN => 'Apagar',
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class ImageStatus
|
||||||
public const string SUCCESS = 'success';
|
public const string SUCCESS = 'success';
|
||||||
public const string TRASH = 'trash';
|
public const string TRASH = 'trash';
|
||||||
public const string FAILED = 'failed';
|
public const string FAILED = 'failed';
|
||||||
|
public const string TRANSFERING = 'transfering';
|
||||||
|
|
||||||
private const array STATUS = [
|
private const array STATUS = [
|
||||||
self::PENDING => 'Pendiente',
|
self::PENDING => 'Pendiente',
|
||||||
|
@ -18,6 +19,7 @@ final class ImageStatus
|
||||||
self::TRASH => 'Papelera',
|
self::TRASH => 'Papelera',
|
||||||
self::SUCCESS => 'Completado',
|
self::SUCCESS => 'Completado',
|
||||||
self::FAILED => 'Fallido',
|
self::FAILED => 'Fallido',
|
||||||
|
self::TRANSFERING => 'Transferiendo',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getStatus(): array
|
public static function getStatus(): array
|
||||||
|
|
Loading…
Reference in New Issue