Compare commits
6 Commits
dd9cd5e2cf
...
7b9650d804
Author | SHA1 | Date |
---|---|---|
|
7b9650d804 | |
|
0002ea4ccc | |
|
7856741928 | |
|
2b90e2618d | |
|
e27e4b408f | |
|
0f52548284 |
|
@ -49,6 +49,20 @@ resources:
|
|||
uriTemplate: /clients/server/{uuid}/get-pxe
|
||||
controller: App\Controller\OgBoot\PxeBootFile\GetAction
|
||||
|
||||
reboot_client:
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: false
|
||||
uriTemplate: /clients/server/{uuid}/reboot
|
||||
controller: App\Controller\OgAgent\RebootAction
|
||||
|
||||
power_off_client:
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: false
|
||||
uriTemplate: /clients/server/{uuid}/power-off
|
||||
controller: App\Controller\OgAgent\PowerOffAction
|
||||
|
||||
|
||||
properties:
|
||||
App\Entity\Client:
|
||||
|
|
|
@ -30,6 +30,13 @@ resources:
|
|||
uriTemplate: /image-repositories/server/sync
|
||||
controller: App\Controller\OgRepository\SyncAction
|
||||
|
||||
wol_client:
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\WoLInput
|
||||
uriTemplate: /image-repositories/{uuid}/wol
|
||||
controller: App\Controller\OgRepository\WoLAction
|
||||
|
||||
get_collection_images_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
description: Get collection of image in OgRepository
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
resources:
|
||||
App\Entity\Partition:
|
||||
processor: App\State\Processor\PartitionProcessor
|
||||
input: App\Dto\Input\PartitionInput
|
||||
input: App\Dto\Input\PartitionPostInput
|
||||
output: App\Dto\Output\PartitionOutput
|
||||
orderBy:
|
||||
partitionNumber: 'ASC'
|
||||
|
@ -29,4 +29,4 @@ properties:
|
|||
id:
|
||||
identifier: false
|
||||
uuid:
|
||||
identifier: true
|
||||
identifier: true
|
||||
|
|
|
@ -135,7 +135,7 @@ services:
|
|||
api_platform.filter.partition.order:
|
||||
parent: 'api_platform.doctrine.orm.order_filter'
|
||||
arguments:
|
||||
$properties: { 'id': ~, 'usage': ~ }
|
||||
$properties: { 'id': ~, 'usage': ~, 'partitionNumber': 'ASC' }
|
||||
$orderParameterName: 'order'
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20241205110301 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE subnet ADD router VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE subnet DROP router');
|
||||
}
|
||||
}
|
|
@ -11,9 +11,11 @@ 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 Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -35,6 +37,12 @@ class CreateImageAction extends AbstractController
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(Image $image): JsonResponse
|
||||
{
|
||||
if (!$image->getClient()->getIp()) {
|
||||
|
@ -46,7 +54,7 @@ class CreateImageAction extends AbstractController
|
|||
$data = [
|
||||
'dsk' => (string) $partitionInfo['numDisk'],
|
||||
'par' => (string) $partitionInfo['numPartition'],
|
||||
'cpt' => "83",
|
||||
'cpt' => null,
|
||||
'idi' => $image->getUuid(),
|
||||
'nci' => $image->getName(),
|
||||
'ipr' => $image->getRepository()->getIp(),
|
||||
|
@ -54,6 +62,20 @@ class CreateImageAction extends AbstractController
|
|||
'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 Exception("El tipo de partición '$partitionCode' no se encontró en la lista.");
|
||||
}
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('POST', 'https://'.$image->getClient()->getIp().':8000/CloningEngine/CrearImagen', [
|
||||
'verify_peer' => false,
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Dto\Input\PartitionPostInput;
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
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 PartitionAssistantAction extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreateService $createService,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(PartitionPostInput $input): JsonResponse
|
||||
{
|
||||
$partitions = $input->partitions;
|
||||
|
||||
if (empty($partitions)) {
|
||||
throw new ValidatorException('Partitions is required');
|
||||
}
|
||||
|
||||
/** @var Client $client */
|
||||
$client = $input->partitions[0]->client->getEntity();
|
||||
|
||||
$disks = [];
|
||||
foreach ($partitions as $partition) {
|
||||
$diskNumber = $partition->diskNumber;
|
||||
|
||||
if (!isset($disks[$diskNumber])) {
|
||||
$disks[$diskNumber] = [
|
||||
'diskData' => [],
|
||||
'partitionData' => []
|
||||
];
|
||||
}
|
||||
|
||||
if ($partition->filesystem === 'CACHE') {
|
||||
$disks[$diskNumber]['diskData'] = [
|
||||
'dis' => (string) $diskNumber,
|
||||
'che' => "0",
|
||||
'tch' => (string) ($partition->size * 1024),
|
||||
];
|
||||
}
|
||||
|
||||
$disks[$diskNumber]['partitionData'][] = [
|
||||
'par' => (string) $partition->partitionNumber,
|
||||
'cpt' => $partition->partitionCode,
|
||||
'sfi' => $partition->filesystem,
|
||||
'tam' => (string) ($partition->size * 1024),
|
||||
'ope' => $partition->format ? "1" : "0",
|
||||
];
|
||||
}
|
||||
|
||||
// Hacer una llamada por cada disco
|
||||
foreach ($disks as $diskNumber => $diskInfo) {
|
||||
$data = [];
|
||||
if (!empty($diskInfo['diskData'])) {
|
||||
$data[] = $diskInfo['diskData'];
|
||||
}
|
||||
$data = array_merge($data, $diskInfo['partitionData']);
|
||||
|
||||
$result = [
|
||||
"nfn" => "Configurar",
|
||||
"dsk" => (string) $diskNumber,
|
||||
"cfg" => $data,
|
||||
"ids" => "0"
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/CloningEngine/Configurar', [
|
||||
'verify_peer' => false,
|
||||
'verify_host' => false,
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
],
|
||||
'json' => $result,
|
||||
]);
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
return new JsonResponse(
|
||||
data: ['error' => "Error en disco $diskNumber: " . $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$jobId = json_decode($response->getContent(), true)['job_id'];
|
||||
|
||||
$client->setStatus(ClientStatus::BUSY);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::PARTITION_AND_FORMAT, TraceStatus::IN_PROGRESS, $jobId, []);
|
||||
}
|
||||
|
||||
return new JsonResponse(data: $client, status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
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 PowerOffAction extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreateService $createService,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(Client $client): JsonResponse
|
||||
{
|
||||
if (!$client->getIp()) {
|
||||
throw new ValidatorException('IP is required');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'nfn' => 'Apagar',
|
||||
'ids' => '0'
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/ogAdmClient/Apagar', [
|
||||
'verify_peer' => false,
|
||||
'verify_host' => false,
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
],
|
||||
'json' => $data,
|
||||
]);
|
||||
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$jobId = json_decode($response->getContent(), true)['job_id'];
|
||||
|
||||
$client->setStatus(ClientStatus::OFF);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::SHUTDOWN, TraceStatus::SUCCESS, $jobId, []);
|
||||
|
||||
return new JsonResponse(data: $client, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
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 RebootAction extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreateService $createService,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(Client $client): JsonResponse
|
||||
{
|
||||
if (!$client->getIp()) {
|
||||
throw new ValidatorException('IP is required');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'nfn' => 'Reiniciar',
|
||||
'ids' => '0'
|
||||
];
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/ogAdmClient/Reiniciar', [
|
||||
'verify_peer' => false,
|
||||
'verify_host' => false,
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
],
|
||||
'json' => $data,
|
||||
]);
|
||||
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$jobId = json_decode($response->getContent(), true)['job_id'];
|
||||
|
||||
$client->setStatus(ClientStatus::INITIALIZING);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::REBOOT, TraceStatus::SUCCESS, $jobId, []);
|
||||
|
||||
return new JsonResponse(data: $client, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ use App\Model\ClientStatus;
|
|||
use App\Model\OgLiveStatus;
|
||||
use App\Service\CreatePartitionService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
use Symfony\Component\HttpClient\Internal\ClientState;
|
||||
|
@ -28,7 +29,8 @@ class StatusAction extends AbstractController
|
|||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreatePartitionService $createPartitionService
|
||||
protected readonly CreatePartitionService $createPartitionService,
|
||||
protected readonly LoggerInterface $logger,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
@ -61,6 +63,8 @@ class StatusAction extends AbstractController
|
|||
|
||||
public function getOgLiveStatus (Client $client): JsonResponse|int|string
|
||||
{
|
||||
$this->logger->info('Checking client status', ['client' => $client->getId()]);
|
||||
|
||||
try {
|
||||
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/status', [
|
||||
'verify_peer' => false,
|
||||
|
@ -76,6 +80,8 @@ class StatusAction extends AbstractController
|
|||
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
$client->setStatus(ClientStatus::OFF);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
@ -83,6 +89,7 @@ class StatusAction extends AbstractController
|
|||
$data = json_decode($response->getContent(), true);
|
||||
|
||||
if (isset($data['cfg'])) {
|
||||
$this->logger->info('Creating partitions', ['data' => $data['cfg']]);
|
||||
$this->createPartitionService->__invoke($data, $client);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ class AgentController extends AbstractController
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
#[Route('/opengnsys/rest/ogAdmClient/InclusionCliente', methods: ['POST'])]
|
||||
public function processClient(Request $request): JsonResponse
|
||||
{
|
||||
|
|
|
@ -53,7 +53,7 @@ class ClientsController extends AbstractController
|
|||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$data = $request->toArray();
|
||||
$requiredFields = ['nfn', 'idi', 'dsk', 'par', 'ids', 'res', 'der', 'job_id'];
|
||||
$requiredFields = ['nfn', 'ids', 'res', 'der', 'job_id'];
|
||||
|
||||
foreach ($requiredFields as $field) {
|
||||
if (!isset($data[$field])) {
|
||||
|
@ -123,6 +123,10 @@ class ClientsController extends AbstractController
|
|||
$trace->setStatus(TraceStatus::SUCCESS);
|
||||
$trace->setFinishedAt(new \DateTime());
|
||||
$image->setStatus(ImageStatus::PENDING);
|
||||
$client->setStatus(ClientStatus::OG_LIVE);
|
||||
if (isset($data['cfg'])) {
|
||||
$this->createPartitionService->__invoke($data,$client);
|
||||
}
|
||||
} else {
|
||||
$trace->setStatus(TraceStatus::FAILED);
|
||||
$trace->setFinishedAt(new \DateTime());
|
||||
|
@ -136,6 +140,30 @@ class ClientsController extends AbstractController
|
|||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
if ($data['nfn'] === 'RESPUESTA_Configurar') {
|
||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||
|
||||
$client = $trace->getClient();
|
||||
|
||||
if ($data['res'] === 1) {
|
||||
$trace->setStatus(TraceStatus::SUCCESS);
|
||||
$trace->setFinishedAt(new \DateTime());
|
||||
if (isset($data['cfg'])) {
|
||||
$this->createPartitionService->__invoke($data,$client);
|
||||
}
|
||||
} else {
|
||||
$trace->setStatus(TraceStatus::FAILED);
|
||||
$trace->setFinishedAt(new \DateTime());
|
||||
$trace->setOutput($data['der']);
|
||||
}
|
||||
|
||||
$client->setStatus(ClientStatus::OG_LIVE);
|
||||
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->persist($trace);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return new JsonResponse(data: 'Webhook finished', status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
|
@ -170,4 +198,4 @@ class ClientsController extends AbstractController
|
|||
$this->entityManager->persist($softwareProfile);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class PostAction extends AbstractOgBootController
|
|||
'computer_name' => $client->getName(),
|
||||
'netiface' => $client->getNetiface(),
|
||||
'group' => $client->getOrganizationalUnit()->getName(),
|
||||
'ogrepo' => $client->getRepository()?->getIp() ,
|
||||
'ogrepo' => $client->getRepository() ? $client->getRepository()->getIp() : $client->getOrganizationalUnit()->getNetworkSettings()->getRepository()->getIp(),
|
||||
'ogcore' => $this->ogCoreIP,
|
||||
'oglive' => $this->ogBootApiUrl,
|
||||
'oglog' => $client->getOrganizationalUnit()->getNetworkSettings()?->getOgLog(),
|
||||
|
|
|
@ -41,6 +41,7 @@ class SyncAction extends AbstractOgBootController
|
|||
}
|
||||
|
||||
$templateContent = $this->createRequest('GET', 'http://'.$this->ogBootApiUrl . '/ogboot/v1/pxe-templates/'.$templateEntity->getName());
|
||||
|
||||
$templateEntity->setTemplateContent($templateContent['template_content']);
|
||||
$templateEntity->setSynchronized(true);
|
||||
|
||||
|
@ -50,4 +51,4 @@ class SyncAction extends AbstractOgBootController
|
|||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class PostAction extends AbstractOgDhcpController
|
|||
'address' => $data->getIpAddress(),
|
||||
'nextServer' => $data->getNextServer(),
|
||||
'bootFileName' => $data->getBootFileName(),
|
||||
'router' => $data->getRouter(),
|
||||
]
|
||||
];
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class PutAction extends AbstractOgDhcpController
|
|||
'address' => $data->getIpAddress(),
|
||||
'nextServer' => $data->getNextServer(),
|
||||
'bootFileName' => $data->getBootFileName(),
|
||||
'router' => $data->getRouter(),
|
||||
]
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgRepository;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\WoLInput;
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\ImageStatus;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
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 WoLAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(WoLInput $input, ImageRepository $repository): JsonResponse
|
||||
{
|
||||
/** @var Client $client */
|
||||
$client = $input->client->getEntity();
|
||||
|
||||
|
||||
if (!$repository->getIp()) {
|
||||
throw new ValidatorException('IP is required');
|
||||
}
|
||||
|
||||
$params = [
|
||||
'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::OFF);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::SHUTDOWN, TraceStatus::SUCCESS, '', []);
|
||||
|
||||
return new JsonResponse(data: $client, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -40,11 +40,11 @@ class DeployImageInput
|
|||
public ?string $mcastIp = null;
|
||||
|
||||
#[Groups(['image:write'])]
|
||||
public ?int $mcastSpeed = null;
|
||||
public ?string $mcastSpeed = null;
|
||||
|
||||
#[OrganizationalUnitMulticastPort]
|
||||
#[Groups(['image:write'])]
|
||||
public ?int $mcastPort = null;
|
||||
public ?string $mcastPort = null;
|
||||
|
||||
#[OrganizationalUnitMulticastMode]
|
||||
#[Groups(['image:write'])]
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Dto\Input;
|
|||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use App\Dto\Output\HardwareProfileOutput;
|
||||
use App\Dto\Output\ImageRepositoryOutput;
|
||||
use App\Dto\Output\MenuOutput;
|
||||
use App\Dto\Output\OgLiveOutput;
|
||||
use App\Entity\HardwareProfile;
|
||||
|
@ -73,6 +74,9 @@ class NetworkSettingsInput
|
|||
#[Groups(['organizational-unit:write'])]
|
||||
public ?OgLiveOutput $ogLive = null;
|
||||
|
||||
#[Groups(['organizational-unit:write'])]
|
||||
public ?ImageRepositoryOutput $repository = null;
|
||||
|
||||
#[Groups(['organizational-unit:write'])]
|
||||
public ?bool $validation = null;
|
||||
|
||||
|
@ -116,6 +120,10 @@ class NetworkSettingsInput
|
|||
$this->ogLive = new OgLiveOutput($networkSettings->getOgLive());
|
||||
}
|
||||
|
||||
if ($networkSettings->getRepository()) {
|
||||
$this->repository = new ImageRepositoryOutput($networkSettings->getRepository());
|
||||
}
|
||||
|
||||
$this->validation = $networkSettings->getValidation();
|
||||
}
|
||||
|
||||
|
@ -153,6 +161,10 @@ class NetworkSettingsInput
|
|||
$networkSettings->setOgLive($this->ogLive->getEntity());
|
||||
}
|
||||
|
||||
if ($this->repository) {
|
||||
$networkSettings->setRepository($this->repository->getEntity());
|
||||
}
|
||||
|
||||
$networkSettings->setValidation($this->validation);
|
||||
|
||||
return $networkSettings;
|
||||
|
|
|
@ -10,11 +10,21 @@ use App\Dto\Output\OrganizationalUnitOutput;
|
|||
use App\Entity\HardwareProfile;
|
||||
use App\Entity\Menu;
|
||||
use App\Entity\Partition;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
final class PartitionInput
|
||||
{
|
||||
#[Groups(['partition:write'])]
|
||||
public ?UuidInterface $uuid = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
public ?bool $removed = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
public ?bool $format = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
#[ApiProperty(description: 'The disk number of the partition', example: 1)]
|
||||
public ?int $diskNumber = null;
|
||||
|
@ -30,14 +40,18 @@ final class PartitionInput
|
|||
#[Assert\NotNull()]
|
||||
#[Groups(['partition:write'])]
|
||||
#[ApiProperty(description: 'The size of the partition', example: 100)]
|
||||
public ?int $size = null;
|
||||
public ?float $size = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
#[ApiProperty(description: 'The cache content of the partition', example: "cache content")]
|
||||
public ?string $cacheContent = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
#[ApiProperty(description: 'The filesystem of the partition', example: "filesystem")]
|
||||
#[ApiProperty(description: 'The type of the partition', example: "LINUX")]
|
||||
public ?string $type = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
#[ApiProperty(description: 'The filesystem of the partition', example: "EXT4")]
|
||||
public ?string $filesystem = null;
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
|
@ -109,4 +123,4 @@ final class PartitionInput
|
|||
|
||||
return $partition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\ClientOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
final class PartitionPostInput
|
||||
{
|
||||
/**
|
||||
* @var PartitionInput[]
|
||||
*/
|
||||
#[Groups(['partition:write'])]
|
||||
public array $partitions = [];
|
||||
}
|
||||
|
|
@ -32,6 +32,10 @@ final class SubnetInput
|
|||
#[ApiProperty(description: 'The next server of the subnet', example: "")]
|
||||
public ?string $nextServer = null;
|
||||
|
||||
#[Groups(['subnet:write'])]
|
||||
#[ApiProperty(description: 'The router of the subnet', example: "")]
|
||||
public ?string $router = null;
|
||||
|
||||
#[Groups(['subnet:write'])]
|
||||
#[ApiProperty(description: 'The boot file name of the subnet', example: "")]
|
||||
public ?string $bootFileName = null;
|
||||
|
@ -52,6 +56,7 @@ final class SubnetInput
|
|||
$this->name = $subnet->getName();
|
||||
$this->netmask = $subnet->getNetmask();
|
||||
$this->ipAddress = $subnet->getIpAddress();
|
||||
$this->router = $subnet->getRouter();
|
||||
$this->nextServer = $subnet->getNextServer();
|
||||
$this->bootFileName = $subnet->getBootFileName();
|
||||
|
||||
|
@ -73,6 +78,7 @@ final class SubnetInput
|
|||
$subnet->setIpAddress($this->ipAddress);
|
||||
$subnet->setNextServer($this->nextServer);
|
||||
$subnet->setBootFileName($this->bootFileName);
|
||||
$subnet->setRouter($this->router);
|
||||
|
||||
foreach ($this->organizationalUnits as $organizationalUnit) {
|
||||
$organizationalUnitToAdd[] = $organizationalUnit->getEntity();
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use App\Dto\Output\ClientOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
class WoLInput
|
||||
{
|
||||
#[Groups(['repository:write'])]
|
||||
#[ApiProperty(description: 'The client to wol')]
|
||||
public ?ClientOutput $client = null;
|
||||
}
|
|
@ -52,15 +52,15 @@ final class ClientOutput extends AbstractOutput
|
|||
#[ApiProperty(readableLink: true )]
|
||||
public ?ImageRepositoryOutput $repository = null;
|
||||
|
||||
#[Groups(['client:read', 'organizational-unit:read'])]
|
||||
#[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])]
|
||||
#[ApiProperty(readableLink: true )]
|
||||
public ?PxeTemplateOutput $template = null;
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
#[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])]
|
||||
#[ApiProperty(readableLink: true )]
|
||||
public ?OgLiveOutput $ogLive = null;
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
#[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])]
|
||||
public ?string $subnet = null;
|
||||
|
||||
#[Groups(['client:read', 'organizational-unit:read'])]
|
||||
|
@ -75,7 +75,7 @@ final class ClientOutput extends AbstractOutput
|
|||
#[Groups(['client:read'])]
|
||||
public ?string $createdBy = null;
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
#[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])]
|
||||
public ?bool $maintenance = false;
|
||||
|
||||
#[Groups(['client:read'])]
|
||||
|
|
|
@ -9,7 +9,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||
#[Get(shortName: 'ImageRepository')]
|
||||
class ImageRepositoryOutput extends AbstractOutput
|
||||
{
|
||||
#[Groups(['repository:read', 'image:read', 'client:read'])]
|
||||
#[Groups(['repository:read', 'image:read', 'client:read', "organizational-unit:read"])]
|
||||
public ?string $name = '';
|
||||
|
||||
#[Groups(['repository:read'])]
|
||||
|
|
|
@ -57,6 +57,9 @@ final class NetworkSettingsOutput extends AbstractOutput
|
|||
#[Groups(['network-settings:read', "organizational-unit:read", "client:read"])]
|
||||
public ?OgLiveOutput $ogLive = null;
|
||||
|
||||
#[Groups(['network-settings:read', "organizational-unit:read", "client:read"])]
|
||||
public ?ImageRepositoryOutput $repository = null;
|
||||
|
||||
#[Groups(['network-settings:read', "organizational-unit:read", "client:read"])]
|
||||
public ?string $oglog = null;
|
||||
|
||||
|
@ -104,6 +107,10 @@ final class NetworkSettingsOutput extends AbstractOutput
|
|||
$this->ogLive = new OgLiveOutput($networkSettings->getOgLive());
|
||||
}
|
||||
|
||||
if ($networkSettings->getRepository()) {
|
||||
$this->repository = new ImageRepositoryOutput($networkSettings->getRepository());
|
||||
}
|
||||
|
||||
$this->validation = $networkSettings->getValidation();
|
||||
$this->createdAt = $networkSettings->getCreatedAt();
|
||||
$this->createdBy = $networkSettings->getCreatedBy();
|
||||
|
|
|
@ -10,7 +10,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||
#[Get(shortName: 'OgLive')]
|
||||
final class OgLiveOutput extends AbstractOutput
|
||||
{
|
||||
#[Groups(['og-live:read', 'client:read'])]
|
||||
#[Groups(['og-live:read', 'client:read', "organizational-unit:read"])]
|
||||
public string $name;
|
||||
|
||||
#[Groups(['og-live:read'])]
|
||||
|
|
|
@ -11,7 +11,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||
#[Get(shortName: 'PxeTemplate')]
|
||||
final class PxeTemplateOutput extends AbstractOutput
|
||||
{
|
||||
#[Groups(['pxe-template:read', 'client:read'])]
|
||||
#[Groups(['pxe-template:read', 'client:read', 'organizational-unit:read'])]
|
||||
public string $name;
|
||||
|
||||
#[Groups(['pxe-template:read'])]
|
||||
|
|
|
@ -27,6 +27,9 @@ final class SubnetOutput extends AbstractOutput
|
|||
#[Groups(['subnet:read'])]
|
||||
public ?string $bootFileName = null;
|
||||
|
||||
#[Groups(['subnet:read'])]
|
||||
public ?string $router = null;
|
||||
|
||||
#[Groups(['subnet:read'])]
|
||||
public array $clients;
|
||||
|
||||
|
@ -50,6 +53,7 @@ final class SubnetOutput extends AbstractOutput
|
|||
$this->netmask = $subnet->getNetmask();
|
||||
$this->ipAddress = $subnet->getIpAddress();
|
||||
$this->nextServer = $subnet->getNextServer();
|
||||
$this->router = $subnet->getRouter();
|
||||
$this->bootFileName = $subnet->getBootFileName();
|
||||
$this->synchronized = $subnet->isSynchronized();
|
||||
$this->serverId = $subnet->getServerId();
|
||||
|
|
|
@ -45,6 +45,7 @@ class Client extends AbstractEntity
|
|||
* @var Collection<int, Partition>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'client', targetEntity: Partition::class)]
|
||||
#[ORM\OrderBy(['partitionNumber' => 'ASC'])]
|
||||
private Collection $partitions;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
|
|
|
@ -40,6 +40,9 @@ class Subnet extends AbstractEntity
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?int $serverId = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $router = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
@ -187,4 +190,16 @@ class Subnet extends AbstractEntity
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRouter(): ?string
|
||||
{
|
||||
return $this->router;
|
||||
}
|
||||
|
||||
public function setRouter(?string $router): static
|
||||
{
|
||||
$this->router = $router;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use ApiPlatform\Symfony\EventListener\EventPriorities;
|
||||
use App\Controller\OgBoot\PxeBootFile\PostAction;
|
||||
use App\Dto\Output\ClientOutput;
|
||||
use App\Entity\Client;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Event\ViewEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
final readonly class ClientSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private PostAction $postAction,
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
KernelEvents::VIEW => ['sendMail', EventPriorities::POST_WRITE],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function sendMail(ViewEvent $event): void
|
||||
{
|
||||
$clientOutput = $event->getControllerResult();
|
||||
$method = $event->getRequest()->getMethod();
|
||||
|
||||
if (!$clientOutput instanceof ClientOutput || (Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method && Request::METHOD_PATCH !== $method)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Client $client */
|
||||
$client = $clientOutput->getEntity();
|
||||
|
||||
if ($client->getTemplate() === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->postAction->__invoke($client, $client->getTemplate());
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ final class CommandTypes
|
|||
public const string SHUTDOWN = 'shutdown';
|
||||
public const string LOGIN = 'login';
|
||||
public const string LOGOUT = 'logout';
|
||||
public const string PARTITION_AND_FORMAT = 'partition-and-format';
|
||||
|
||||
private const array COMMAND_TYPES = [
|
||||
self::DEPLOY_IMAGE => 'Deploy Image',
|
||||
|
@ -24,6 +25,7 @@ final class CommandTypes
|
|||
self::SHUTDOWN => 'Apagar',
|
||||
self::LOGIN => 'Login',
|
||||
self::LOGOUT => 'Logout',
|
||||
self::PARTITION_AND_FORMAT => 'Partition and Format',
|
||||
];
|
||||
|
||||
public static function getCommandTypes(): array
|
||||
|
@ -35,4 +37,4 @@ final class CommandTypes
|
|||
{
|
||||
return self::COMMAND_TYPES[$type] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
final class PartitionTypes
|
||||
{
|
||||
private const array PARTITION_TYPES = [
|
||||
0 => ['name' => 'EMPTY', 'active' => false],
|
||||
1 => ['name' => 'FAT12', 'active' => true],
|
||||
5 => ['name' => 'EXTENDED', 'active' => false],
|
||||
6 => ['name' => 'FAT16', 'active' => true],
|
||||
7 => ['name' => 'NTFS', 'active' => true],
|
||||
11 => ['name' => 'FAT32', 'active' => true],
|
||||
17 => ['name' => 'HFAT12', 'active' => true],
|
||||
22 => ['name' => 'HFAT16', 'active' => true],
|
||||
23 => ['name' => 'HNTFS', 'active' => true],
|
||||
27 => ['name' => 'HFAT32', 'active' => true],
|
||||
130 => ['name' => 'LINUX-SWAP', 'active' => false],
|
||||
131 => ['name' => 'LINUX', 'active' => true],
|
||||
142 => ['name' => 'LINUX-LVM', 'active' => true],
|
||||
165 => ['name' => 'FREEBSD', 'active' => true],
|
||||
166 => ['name' => 'OPENBSD', 'active' => true],
|
||||
169 => ['name' => 'NETBSD', 'active' => true],
|
||||
175 => ['name' => 'HFS', 'active' => true],
|
||||
190 => ['name' => 'SOLARIS-BOOT', 'active' => true],
|
||||
191 => ['name' => 'SOLARIS', 'active' => true],
|
||||
202 => ['name' => 'CACHE', 'active' => false],
|
||||
218 => ['name' => 'DATA', 'active' => true],
|
||||
238 => ['name' => 'GPT', 'active' => false],
|
||||
239 => ['name' => 'EFI', 'active' => true],
|
||||
251 => ['name' => 'VMFS', 'active' => true],
|
||||
253 => ['name' => 'LINUX-RAID', 'active' => true],
|
||||
1792 => ['name' => 'WINDOWS', 'active' => true],
|
||||
3073 => ['name' => 'WIN-RESERV', 'active' => true],
|
||||
9984 => ['name' => 'WIN-RECOV', 'active' => true],
|
||||
32512 => ['name' => 'CHROMEOS-KRN', 'active' => true],
|
||||
32513 => ['name' => 'CHROMEOS', 'active' => true],
|
||||
32514 => ['name' => 'CHROMEOS-RESERV', 'active' => true],
|
||||
33280 => ['name' => 'LINUX-SWAP', 'active' => false],
|
||||
33536 => ['name' => 'LINUX', 'active' => true],
|
||||
33537 => ['name' => 'LINUX-RESERV', 'active' => true],
|
||||
33538 => ['name' => 'LINUX', 'active' => true],
|
||||
36352 => ['name' => 'LINUX-LVM', 'active' => true],
|
||||
42240 => ['name' => 'FREEBSD-DISK', 'active' => false],
|
||||
42241 => ['name' => 'FREEBSD-BOOT', 'active' => true],
|
||||
42242 => ['name' => 'FREEBSD-SWAP', 'active' => false],
|
||||
42243 => ['name' => 'FREEBSD', 'active' => true],
|
||||
42244 => ['name' => 'FREEBSD', 'active' => true],
|
||||
43265 => ['name' => 'NETBSD-SWAP', 'active' => false],
|
||||
43266 => ['name' => 'NETBSD', 'active' => true],
|
||||
43267 => ['name' => 'NETBSD', 'active' => true],
|
||||
43268 => ['name' => 'NETBSD', 'active' => true],
|
||||
43269 => ['name' => 'NETBSD', 'active' => true],
|
||||
43270 => ['name' => 'NETBSD-RAID', 'active' => true],
|
||||
43776 => ['name' => 'HFS-BOOT', 'active' => true],
|
||||
44800 => ['name' => 'HFS', 'active' => true],
|
||||
44801 => ['name' => 'HFS-RAID', 'active' => true],
|
||||
44802 => ['name' => 'HFS-RAID', 'active' => true],
|
||||
48640 => ['name' => 'SOLARIS-BOOT', 'active' => true],
|
||||
48896 => ['name' => 'SOLARIS', 'active' => true],
|
||||
48897 => ['name' => 'SOLARIS', 'active' => true],
|
||||
48898 => ['name' => 'SOLARIS-SWAP', 'active' => false],
|
||||
48899 => ['name' => 'SOLARIS-DISK', 'active' => true],
|
||||
48900 => ['name' => 'SOLARIS', 'active' => true],
|
||||
48901 => ['name' => 'SOLARIS', 'active' => true],
|
||||
51712 => ['name' => 'CACHE', 'active' => false],
|
||||
61184 => ['name' => 'EFI', 'active' => true],
|
||||
61185 => ['name' => 'MBR', 'active' => false],
|
||||
61186 => ['name' => 'BIOS-BOOT', 'active' => false],
|
||||
64256 => ['name' => 'VMFS', 'active' => true],
|
||||
64257 => ['name' => 'VMFS-RESERV', 'active' => true],
|
||||
64258 => ['name' => 'VMFS-KRN', 'active' => true],
|
||||
64768 => ['name' => 'LINUX-RAID', 'active' => true],
|
||||
65535 => ['name' => 'UNKNOWN', 'active' => true],
|
||||
65536 => ['name' => 'LVM-LV', 'active' => true],
|
||||
65552 => ['name' => 'ZFS-VOL', 'active' => true],
|
||||
39 => ['name' => 'HNTFS-WINRE', 'active' => true],
|
||||
];
|
||||
|
||||
public static function getPartitionTypes(): array
|
||||
{
|
||||
return self::PARTITION_TYPES;
|
||||
}
|
||||
|
||||
public static function getPartitionType(int $code): ?array
|
||||
{
|
||||
return self::PARTITION_TYPES[$code] ?? null;
|
||||
}
|
||||
|
||||
public static function getPartitionKeys(): array
|
||||
{
|
||||
return array_keys(self::PARTITION_TYPES);
|
||||
}
|
||||
}
|
|
@ -32,4 +32,4 @@ abstract class AbstractRepository extends ServiceEntityRepository
|
|||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,10 @@
|
|||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Partition;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Partition>
|
||||
* @extends AbstractRepository<Partition>
|
||||
*/
|
||||
class PartitionRepository extends AbstractRepository
|
||||
{
|
||||
|
|
|
@ -5,7 +5,9 @@ namespace App\Service;
|
|||
use App\Entity\Client;
|
||||
use App\Entity\OperativeSystem;
|
||||
use App\Entity\Partition;
|
||||
use App\Model\PartitionTypes;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
|
||||
class CreatePartitionService
|
||||
{
|
||||
|
@ -17,6 +19,11 @@ class CreatePartitionService
|
|||
|
||||
public function __invoke(array $data, Client $clientEntity): void
|
||||
{
|
||||
$currentPartitions = $this->entityManager->getRepository(Partition::class)
|
||||
->findBy(['client' => $clientEntity]);
|
||||
|
||||
$receivedPartitions = [];
|
||||
|
||||
foreach ($data['cfg'] as $cfg) {
|
||||
if (!isset($cfg['disk'], $cfg['par'], $cfg['tam'], $cfg['uso'], $cfg['fsi'])) {
|
||||
continue;
|
||||
|
@ -45,9 +52,42 @@ class CreatePartitionService
|
|||
$partitionEntity->setDiskNumber($cfg['disk']);
|
||||
$partitionEntity->setPartitionNumber($cfg['par']);
|
||||
$partitionEntity->setSize($cfg['tam']);
|
||||
|
||||
if (isset($cfg['cpt']) && $cfg['cpt'] !== '') {
|
||||
$decimalValue = hexdec($cfg['cpt']);
|
||||
$partitionType = PartitionTypes::getPartitionType($decimalValue);
|
||||
|
||||
if ($partitionType) {
|
||||
$partitionEntity->setPartitionCode($partitionType['name']);
|
||||
} else {
|
||||
throw new Exception("El tipo de partición con código {$decimalValue} no se encontró.");
|
||||
}
|
||||
} else {
|
||||
$partitionEntity->setPartitionCode(PartitionTypes::getPartitionType(0)['name']);
|
||||
}
|
||||
|
||||
|
||||
$partitionEntity->setFilesystem($cfg['fsi']);
|
||||
$partitionEntity->setMemoryUsage(((int) $cfg['uso']) * 100);
|
||||
$this->entityManager->persist($partitionEntity);
|
||||
|
||||
$receivedPartitions[] = ['disk' => $cfg['disk'], 'partition' => $cfg['par']];
|
||||
}
|
||||
|
||||
foreach ($currentPartitions as $currentPartition) {
|
||||
$exists = false;
|
||||
|
||||
foreach ($receivedPartitions as $receivedPartition) {
|
||||
if ($currentPartition->getDiskNumber() == $receivedPartition['disk'] &&
|
||||
$currentPartition->getPartitionNumber() == $receivedPartition['partition']) {
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$exists) {
|
||||
$this->entityManager->remove($currentPartition);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
|
|
@ -15,7 +15,7 @@ readonly class CreateService
|
|||
{
|
||||
}
|
||||
|
||||
public function __invoke(Client $client, ?string $command, string $status, string $jobId, ?array $input = []): Trace
|
||||
public function __invoke(Client $client, ?string $command, string $status, ?string $jobId = '', ?array $input = []): Trace
|
||||
{
|
||||
$trace = new Trace();
|
||||
$trace->setClient($client);
|
||||
|
|
|
@ -9,8 +9,10 @@ use ApiPlatform\Metadata\Post;
|
|||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Controller\OgAgent\PartitionAssistantAction;
|
||||
use App\Dto\Input\MenuInput;
|
||||
use App\Dto\Input\PartitionInput;
|
||||
use App\Dto\Input\PartitionPostInput;
|
||||
use App\Dto\Input\UserGroupInput;
|
||||
use App\Dto\Output\MenuOutput;
|
||||
use App\Dto\Output\PartitionOutput;
|
||||
|
@ -18,12 +20,15 @@ use App\Dto\Output\UserGroupOutput;
|
|||
use App\Repository\MenuRepository;
|
||||
use App\Repository\PartitionRepository;
|
||||
use App\Repository\UserGroupRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
readonly class PartitionProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private PartitionRepository $partitionRepository,
|
||||
private ValidatorInterface $validator
|
||||
private PartitionRepository $partitionRepository,
|
||||
private ValidatorInterface $validator,
|
||||
private PartitionAssistantAction $partitionAssistantAction
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -31,7 +36,7 @@ readonly class PartitionProcessor implements ProcessorInterface
|
|||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): PartitionOutput|null
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): JsonResponse
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof Post:
|
||||
|
@ -46,22 +51,32 @@ readonly class PartitionProcessor implements ProcessorInterface
|
|||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): PartitionOutput
|
||||
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): JsonResponse
|
||||
{
|
||||
if (!($data instanceof PartitionInput)) {
|
||||
throw new \Exception(sprintf('data is not instance of %s', PartitionInput::class));
|
||||
if (!($data instanceof PartitionPostInput)) {
|
||||
throw new \Exception(sprintf('data is not instance of %s', PartitionPostInput::class));
|
||||
}
|
||||
|
||||
$entity = null;
|
||||
if (isset($uriVariables['uuid'])) {
|
||||
$entity = $this->partitionRepository->findOneByUuid($uriVariables['uuid']);
|
||||
foreach ($data->partitions as $partition) {
|
||||
$entity = null;
|
||||
if (isset($partition->uuid)) {
|
||||
$entity = $this->partitionRepository->findOneByUuid($partition->uuid);
|
||||
|
||||
if ($partition->removed && $entity) {
|
||||
$this->partitionRepository->delete($entity);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$entity = $partition->createOrUpdateEntity($entity);
|
||||
$this->validator->validate($entity);
|
||||
|
||||
//$this->partitionRepository->save($entity);
|
||||
}
|
||||
|
||||
$partition = $data->createOrUpdateEntity($entity);
|
||||
$this->validator->validate($partition);
|
||||
$this->partitionRepository->save($partition);
|
||||
$this->partitionAssistantAction->__invoke($data);
|
||||
|
||||
return new PartitionOutput($partition);
|
||||
return new JsonResponse('OK', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
|
|
|
@ -54,72 +54,4 @@ class PartitionTest extends AbstractTest
|
|||
'hydra:totalItems' => 10,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function testCreatePartition(): void
|
||||
{
|
||||
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
$ou = OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT]);
|
||||
$hp = HardwareProfileFactory::createOne(['description' => self::HW_PROFILE]);
|
||||
|
||||
ClientFactory::createOne(['name' => self::CLIENT_CREATE, 'serialNumber' => '123abc', 'organizationalUnit' => $ou, 'hardwareProfile' => $hp]);
|
||||
$iri = $this->findIriBy(Client::class, ['name' => self::CLIENT_CREATE]);
|
||||
|
||||
OperativeSystemFactory::createOne(['name' => 'Ubuntu']);
|
||||
$osIri = $this->findIriBy(OperativeSystem::class, ['name' => 'Ubuntu']);
|
||||
|
||||
ImageFactory::createOne(['name' => 'Image 1']);
|
||||
$imageIri = $this->findIriBy(Image::class, ['name' => 'Image 1']);
|
||||
|
||||
$this->createClientWithCredentials()->request('POST', '/partitions',['json' => [
|
||||
'size' => 100,
|
||||
'operativeSystem' => $osIri,
|
||||
'image' => $imageIri,
|
||||
'client' => $iri,
|
||||
'memoryUsage' => 100
|
||||
]]);
|
||||
|
||||
$this->assertResponseStatusCodeSame(201);
|
||||
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
||||
$this->assertJsonContains([
|
||||
'@context' => '/contexts/PartitionOutput',
|
||||
'@type' => 'Partition',
|
||||
'size' => 100,
|
||||
'memoryUsage' => 100
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws DecodingExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function testUpdatePartition(): void
|
||||
{
|
||||
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||
|
||||
PartitionFactory::createOne(['size' => 100, 'memoryUsage' => 100]);
|
||||
$iri = $this->findIriBy(Partition::class, ['size' => 100, 'memoryUsage' => 100]);
|
||||
|
||||
$this->createClientWithCredentials()->request('PUT', $iri, ['json' => [
|
||||
'size' => 200,
|
||||
'memoryUsage' => 300
|
||||
]]);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
$this->assertJsonContains([
|
||||
'@id' => $iri,
|
||||
'size' => 200,
|
||||
'memoryUsage' => 300
|
||||
]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue