Merge pull request 'develop' (#33) from develop into main
ogcore-debian-package/pipeline/head This commit looks good Details
testing/ogcore-api/pipeline/head This commit looks good Details
ogcore-debian-package/pipeline/tag This commit looks good Details

Reviewed-on: #33
main 0.13.0
Manuel Aranda Rosales 2025-05-19 16:50:46 +02:00
commit 7e410e234c
19 changed files with 347 additions and 249 deletions

View File

@ -1,4 +1,15 @@
# Changelog # Changelog
## [0.13.0] - 2025-05-20
### Added
- Se ha creado la base para la comunicacion TLS con el agente.
### Improved
- Refactorizacion de la API para la gestion de llamadas al agente
### Fixed
- Se ha corregido un bug que hacia que no se eliminara la imagen al particionar.
---
## [0.12.1] - 2025-05-14 ## [0.12.1] - 2025-05-14
### Improved ### Improved
- Se ha eliminado la restriccion en el formulario de crear/editar repositorio, que hacia que la comprobara el formato de IP. Ahora tambien puede ser DNS. - Se ha eliminado la restriccion en el formulario de crear/editar repositorio, que hacia que la comprobara el formato de IP. Ahora tambien puede ser DNS.
@ -13,10 +24,10 @@
- Se ha añadido un nuevo campo en plantillas (defecto) el cual nos permite tener una plantilla por defecto en caso de que se elimine una. - Se ha añadido un nuevo campo en plantillas (defecto) el cual nos permite tener una plantilla por defecto en caso de que se elimine una.
- Se ha comenzado la integracion con ogGit. - Se ha comenzado la integracion con ogGit.
## Improved ### Improved
- Mejorado el comportamiento de la API al crear una imagen. Ahora se guardan datos del pc de origen. - Mejorado el comportamiento de la API al crear una imagen. Ahora se guardan datos del pc de origen.
## Fixed ### Fixed
- Se ha corregido el bug en la creacion de clientes masivos donde no se le asignaba la plantilla PXE. - Se ha corregido el bug en la creacion de clientes masivos donde no se le asignaba la plantilla PXE.
- Se ha corregido un bug en el DTO de clientes, que hacia que PHP diera un timeout por bucle infinito. - Se ha corregido un bug en el DTO de clientes, que hacia que PHP diera un timeout por bucle infinito.

View File

@ -26,7 +26,8 @@ services:
- 8443:443 # Añadir el puerto 443 - 8443:443 # Añadir el puerto 443
volumes: volumes:
- ./public:/var/www/html/public:cached - ./public:/var/www/html/public:cached
- ./docker/certs:/etc/nginx/certs # Montar certificados en Nginx - ./docker/certs:/etc/nginx/certs
- ./certs:/opt/opengnsys/ogcore/etc/certificates
networks: networks:
- ogcore-network - ogcore-network
@ -37,6 +38,7 @@ services:
dockerfile: ./docker/Dockerfile-php dockerfile: ./docker/Dockerfile-php
volumes: volumes:
- ./:/var/www/html - ./:/var/www/html
- ./certs:/opt/opengnsys/ogcore/etc/certificates
depends_on: depends_on:
- database - database
networks: networks:

View File

@ -12,11 +12,11 @@ server {
root /var/www/html/public; root /var/www/html/public;
index index.html index.php; index index.html index.php;
#ssl_certificate /opt/opengnsys/ogcore/etc/certificates/ogcore.crt;
#ssl_certificate_key /opt/opengnsys/ogcore/etc/certificates/ogcore.key;
ssl_certificate /etc/nginx/certs/ogcore.uds-test.net.crt.pem; ssl_certificate /etc/nginx/certs/ogcore.uds-test.net.crt.pem;
ssl_certificate_key /etc/nginx/certs/ogcore.uds-test.net.key.pem; ssl_certificate_key /etc/nginx/certs/ogcore.uds-test.net.key.pem;
location /opengnsys/rest/ous// { location /opengnsys/rest/ous// {
rewrite ^/opengnsys/rest/ous//([0-9]+)/images /opengnsys/rest/ous/$1/images; rewrite ^/opengnsys/rest/ous//([0-9]+)/images /opengnsys/rest/ous/$1/images;
rewrite ^/opengnsys/rest/ous//([0-9]+)/labs /opengnsys/rest/ous/$1/labs; rewrite ^/opengnsys/rest/ous//([0-9]+)/labs /opengnsys/rest/ous/$1/labs;
@ -44,6 +44,9 @@ server {
error_log /var/log/nginx/error.log debug; error_log /var/log/nginx/error.log debug;
access_log /var/log/nginx/access.log; access_log /var/log/nginx/access.log;
#ssl_client_certificate /opt/opengnsys/ogcore/etc/certificates/ca.crt;
#ssl_verify_client on;
} }
server { server {

View File

@ -1,12 +1,13 @@
{ {
"vars": { "vars": {
"OG_BOOT_API_URL": "192.168.68.51:8082", "OG_BOOT_API_URL": "127.0.0.1:8082",
"OG_DHCP_API_URL": "192.168.68.51:8081", "OG_DHCP_API_URL": "127.0.0.1:8081",
"OG_CORE_IP": "192.168.68.62", "OG_CORE_IP": "127.0.0.1",
"OG_LOG_IP": "192.168.68.51", "OG_LOG_IP": "127.0.0.1",
"UDS_AUTH_LOGIN": "test", "UDS_AUTH_LOGIN": "test",
"UDS_AUTH_USERNAME": "test", "UDS_AUTH_USERNAME": "test",
"UDS_AUTH_PASSWORD": "test", "UDS_AUTH_PASSWORD": "test",
"UDS_URL": "https:\/\/localhost:8087\/uds\/rest\/" "UDS_URL": "https:\/\/localhost:8087\/uds\/rest\/",
"SSL_ENABLED": "true"
} }
} }

0
ogagent.conf 100644
View File

View File

@ -0,0 +1,54 @@
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
class AuthValidatorController extends AbstractController
{
private JWTTokenManagerInterface $jwtManager;
public function __construct(JWTTokenManagerInterface $jwtManager)
{
$this->jwtManager = $jwtManager;
}
#[Route('/validate', name: 'auth_validate', methods: ['POST'])]
public function validate(Request $request): Response
{
$sslClientVerify = $request->headers->get('SSL_CLIENT_VERIFY');
$clientCertOk = $sslClientVerify === 'SUCCESS';
$authHeader = $request->headers->get('Authorization');
$hasValidJwt = $this->validateJwtToken($authHeader);
if ($clientCertOk || $hasValidJwt) {
return new Response('Authorized', Response::HTTP_OK);
}
return new Response('Unauthorized', Response::HTTP_UNAUTHORIZED);
}
private function validateJwtToken(?string $authHeader): bool
{
if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) {
return false;
}
$token = substr($authHeader, 7);
try {
$payload = $this->jwtManager->parse($token);
return true;
} catch (\Exception $e) {
return false;
}
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace App\Controller\OgAgent;
use App\Controller\OgRepository\Git\CreateRepositoryAction;
use App\Controller\OgRepository\Git\CreateTagAction;
use App\Service\CreatePartitionService;
use App\Service\Trace\CreateService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
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;
#[AsController]
abstract class AbstractOgAgentController extends AbstractController
{
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreatePartitionService $createPartitionService,
protected readonly LoggerInterface $logger,
protected readonly CreateService $createService,
protected readonly CreateRepositoryAction $createRepositoryAction,
protected readonly CreateTagAction $createTagAction,
#[Autowire(env: 'SSL_ENABLED')]
private readonly string $sslEnabled,
)
{
}
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function createRequest(string $method, string $url, array $params = [], string $token = null): array
{
$params = array_merge($params, [
'headers' => [
'accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => $token,
],
'verify_peer' => false,
'verify_host' => false,
'timeout' => 10
]);
if ($this->sslEnabled === 'true') {
$params['verify_peer'] = true;
$params['verify_host'] = false;
$params['cafile'] = '/opt/opengnsys/ogcore/etc/certificates/ca.crt';
$params['local_cert'] = '/opt/opengnsys/ogcore/etc/certificates/ogcore.crt';
$params['local_pk'] = '/opt/opengnsys/ogcore/etc/certificates/ogcore.key';
}
try {
$response = $this->httpClient->request($method, $url, $params);
return json_decode($response->getContent(), true);
} catch (ClientExceptionInterface | ServerExceptionInterface $e) {
$this->logger->error(sprintf('Client/Server error in request to %s: %s', $url, $e->getMessage()));
return [
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
'error' => 'Client/Server error',
'details' => $e->getMessage(),
];
} catch (TransportExceptionInterface $e) {
$this->logger->error(sprintf('Transport error in request to %s: %s', $url, $e->getMessage()));
return [
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
'error' => 'Client/Server error',
'details' => $e->getMessage(),
];
}
}
}

View File

@ -34,19 +34,8 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class CreateImageAction extends AbstractController class CreateImageAction extends AbstractOgAgentController
{ {
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreateService $createService,
protected readonly LoggerInterface $logger,
protected readonly CreateRepositoryAction $createRepositoryAction,
protected readonly CreateTagAction $createTagAction,
)
{
}
/** /**
* @throws TransportExceptionInterface * @throws TransportExceptionInterface
* @throws ServerExceptionInterface * @throws ServerExceptionInterface
@ -147,29 +136,25 @@ class CreateImageAction extends AbstractController
throw new Exception("El tipo de partición '$partitionCode' no se encontró en la lista."); throw new Exception("El tipo de partición '$partitionCode' no se encontró en la lista.");
} }
try { $client = $client ?? $image->getClient();
$this->logger->info('Creating image', ['image' => $image->getId()]);
$client = $client ?? $image->getClient(); $response = $this->createRequest(
$this->logger->info('Creating image', ['image' => $image->getId()]); method: 'POST',
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/opengnsys/CrearImagen', [ url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagen',
'verify_peer' => false, params: [
'verify_host' => false,
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ],
token: $client->getToken(),
);
$this->logger->info('Creating image', ['image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
} catch (TransportExceptionInterface $e) { if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
$this->logger->error('Error creating image', ['image' => $image->getId(), 'error' => $e->getMessage()]); throw new ValidatorException('Error creating image');
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
} }
$jobId = json_decode($response->getContent(), true)['job_id']; $jobId = $response['job_id'];
$client->setStatus(ClientStatus::BUSY); $client->setStatus(ClientStatus::BUSY);
$this->entityManager->persist($client); $this->entityManager->persist($client);

View File

@ -29,17 +29,8 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class DeployImageAction extends AbstractController class DeployImageAction extends AbstractOgAgentController
{ {
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreateService $createService,
protected readonly LoggerInterface $logger,
)
{
}
/** /**
* @throws RedirectionExceptionInterface * @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface * @throws ClientExceptionInterface
@ -91,26 +82,22 @@ class DeployImageAction extends AbstractController
'ids' => '0' 'ids' => '0'
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen', [ method: 'POST',
'verify_peer' => false, url: 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen',
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ],
$this->logger->info('Deploying image', ['image' => $image->getId()]); token: $client->getToken(),
);
$jobId = json_decode($response->getContent(), true)['job_id']; $this->logger->info('Deploying image', [ 'image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
} catch (ClientExceptionInterface | ServerExceptionInterface | TransportExceptionInterface | TransportException $e) {
$this->logger->error('Error deploying image', [ if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
'image' => $image->getId() ?? 'unknown', throw new ValidatorException('Error deploying image');
'error' => $e->getMessage()
]);
return null;
} }
$jobId = $response['job_id'];
$client->setStatus(ClientStatus::BUSY); $client->setStatus(ClientStatus::BUSY);
$this->entityManager->persist($client); $this->entityManager->persist($client);

View File

@ -27,17 +27,14 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class LoginAction extends AbstractController class LoginAction extends AbstractOgAgentController
{ {
public function __construct( /**
protected readonly EntityManagerInterface $entityManager, * @throws TransportExceptionInterface
protected readonly HttpClientInterface $httpClient, * @throws ServerExceptionInterface
protected readonly CreateService $createService, * @throws RedirectionExceptionInterface
protected readonly LoggerInterface $logger, * @throws ClientExceptionInterface
) */
{
}
public function __invoke(MultipleClientsInput $input): JsonResponse public function __invoke(MultipleClientsInput $input): JsonResponse
{ {
foreach ($input->clients as $clientEntity) { foreach ($input->clients as $clientEntity) {
@ -60,26 +57,21 @@ class LoginAction extends AbstractController
'ids' => '0' 'ids' => '0'
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/IniciarSesion', [ method: 'POST',
'verify_peer' => false, url: 'http://'.$client->getIp().':8000/opengnsys/IniciarSesion',
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ]
$this->logger->info('Login client', ['client' => $client->getId()]); );
} catch (TransportExceptionInterface $e) { if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
$this->logger->error('Login rebooting client', ['client' => $client->getId(), 'error' => $e->getMessage()]); throw new ValidatorException('Error logging in: '.$response['error']);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
} }
$jobId = json_decode($response->getContent(), true)['job_id']; $this->logger->info('Login client', ['client' => $client->getId()]);
$jobId = $response['job_id'];
$client->setStatus(ClientStatus::INITIALIZING); $client->setStatus(ClientStatus::INITIALIZING);
$this->entityManager->persist($client); $this->entityManager->persist($client);

View File

@ -28,17 +28,14 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class PartitionAssistantAction extends AbstractController class PartitionAssistantAction extends AbstractOgAgentController
{ {
public function __construct( /**
protected readonly EntityManagerInterface $entityManager, * @throws TransportExceptionInterface
protected readonly HttpClientInterface $httpClient, * @throws ServerExceptionInterface
protected readonly CreateService $createService, * @throws RedirectionExceptionInterface
protected readonly LoggerInterface $logger, * @throws ClientExceptionInterface
) */
{
}
public function __invoke(PartitionPostInput $input): JsonResponse public function __invoke(PartitionPostInput $input): JsonResponse
{ {
$partitions = $input->partitions; $partitions = $input->partitions;
@ -101,28 +98,28 @@ class PartitionAssistantAction extends AbstractController
"ids" => "0" "ids" => "0"
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/opengnsys/Configurar', [ method: 'POST',
'verify_peer' => false, url: 'https://'.$client->getIp().':8000/opengnsys/Configurar',
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $result, 'json' => $result,
]); ],
$this->logger->info('Partitioning disk', ['client' => $client->getId(), 'disk' => $diskNumber]); token: $client->getToken(),
} catch (TransportExceptionInterface $e) { );
$this->logger->error('Error partitioning disk', ['client' => $client->getId(), 'disk' => $diskNumber, 'error' => $e->getMessage()]);
continue; $this->logger->info('Partition assistant', ['client' => $client->getId()]);
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
throw new ValidatorException('Error occurred while partitioning');
} }
$jobId = json_decode($response->getContent(), true)['job_id']; $jobId = $response['job_id'];
$client->setStatus(ClientStatus::BUSY); $client->setStatus(ClientStatus::BUSY);
$this->entityManager->persist($client); $this->entityManager->persist($client);
$this->entityManager->flush(); $this->entityManager->flush();
$this->createService->__invoke($client, CommandTypes::PARTITION_AND_FORMAT, TraceStatus::IN_PROGRESS, $jobId, []); $this->createService->__invoke($client, CommandTypes::PARTITION_AND_FORMAT, TraceStatus::IN_PROGRESS, $jobId, $data);
} }
} }

View File

@ -28,17 +28,14 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class PowerOffAction extends AbstractController class PowerOffAction extends AbstractOgAgentController
{ {
public function __construct( /**
protected readonly EntityManagerInterface $entityManager, * @throws TransportExceptionInterface
protected readonly HttpClientInterface $httpClient, * @throws ServerExceptionInterface
protected readonly CreateService $createService, * @throws RedirectionExceptionInterface
protected readonly LoggerInterface $logger, * @throws ClientExceptionInterface
) */
{
}
public function __invoke(MultipleClientsInput $input): JsonResponse public function __invoke(MultipleClientsInput $input): JsonResponse
{ {
foreach ($input->clients as $clientEntity) { foreach ($input->clients as $clientEntity) {
@ -60,26 +57,23 @@ class PowerOffAction extends AbstractController
'ids' => '0' 'ids' => '0'
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/'.$endpoint, [ method: 'POST',
'verify_peer' => false, url: 'https://'.$client->getIp().':8000/'.$endpoint,
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ],
$this->logger->info('Powering off client', ['client' => $client->getId()]); token: $client->getToken(),
$jobId = json_decode($response->getContent(), true)['job_id']; );
} catch (ClientExceptionInterface | ServerExceptionInterface | TransportExceptionInterface | TransportException $e) { if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
$this->logger->error('Error power off client', [ throw new ValidatorException('Error deploying image');
'image' => $client->getIp(),
'error' => $e->getMessage()
]);
continue;
} }
$this->logger->info('Powering off client', ['client' => $client->getId()]);
$jobId = $response['job_id'];
$client->setStatus(ClientStatus::TURNING_OFF); $client->setStatus(ClientStatus::TURNING_OFF);
$this->entityManager->persist($client); $this->entityManager->persist($client);
$this->entityManager->flush(); $this->entityManager->flush();

View File

@ -27,17 +27,14 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class RebootAction extends AbstractController class RebootAction extends AbstractOgAgentController
{ {
public function __construct( /**
protected readonly EntityManagerInterface $entityManager, * @throws TransportExceptionInterface
protected readonly HttpClientInterface $httpClient, * @throws ServerExceptionInterface
protected readonly CreateService $createService, * @throws RedirectionExceptionInterface
protected readonly LoggerInterface $logger, * @throws ClientExceptionInterface
) */
{
}
public function __invoke(MultipleClientsInput $input): JsonResponse public function __invoke(MultipleClientsInput $input): JsonResponse
{ {
foreach ($input->clients as $clientEntity) { foreach ($input->clients as $clientEntity) {
@ -56,27 +53,22 @@ class RebootAction extends AbstractController
'ids' => '0' 'ids' => '0'
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/'.$endpoint, [ method: 'POST',
'verify_peer' => false, url: 'http://'.$client->getIp().':8000/'.$endpoint,
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ],
token: $client->getToken(),
);
$this->logger->info('Rebooting client', ['client' => $client->getId()]); if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
throw new ValidatorException('Error deploying image');
} catch (TransportExceptionInterface $e) {
$this->logger->error('Error rebooting client', ['client' => $client->getId(), 'error' => $e->getMessage()]);
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
} }
$jobId = json_decode($response->getContent(), true)['job_id']; $this->logger->info('Rebooting client', ['client' => $client->getId()]);
$jobId = $response['job_id'];
$client->setStatus(ClientStatus::INITIALIZING); $client->setStatus(ClientStatus::INITIALIZING);
$this->entityManager->persist($client); $this->entityManager->persist($client);

View File

@ -15,24 +15,25 @@ 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;
use Symfony\Component\Validator\Exception\ValidatorException; 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\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
class RunScriptAction extends AbstractController class RunScriptAction extends AbstractOgAgentController
{ {
public function __construct( /**
protected readonly EntityManagerInterface $entityManager, * @throws TransportExceptionInterface
protected readonly HttpClientInterface $httpClient, * @throws ServerExceptionInterface
protected readonly CreateService $createService, * @throws RedirectionExceptionInterface
protected readonly LoggerInterface $logger, * @throws ClientExceptionInterface
) */
{
}
public function __invoke(CommandExecuteInput $input): JsonResponse public function __invoke(CommandExecuteInput $input): JsonResponse
{ {
/** @var Client $clientEntity */ /** @var Client $clientEntity */
foreach ($input->clients as $clientEntity) { foreach ($input->clients as $clientEntity) {
/** @var Client $client */
$client = $clientEntity->getEntity(); $client = $clientEntity->getEntity();
if (!$client->getIp()) { if (!$client->getIp()) {
@ -45,26 +46,22 @@ class RunScriptAction extends AbstractController
'ids' => '0' 'ids' => '0'
]; ];
try { $response = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/opengnsys/EjecutarScript', [ method: 'POST',
'verify_peer' => false, url: 'https://'.$client->getIp().':8000/opengnsys/EjecutarScript',
'verify_host' => false, params: [
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data, 'json' => $data,
]); ],
$this->logger->info('Executing run-script', ['client' => $client->getId(), 'response' => $response->getContent()]); token: $client->getToken(),
);
} catch (TransportExceptionInterface $e) { if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
$this->logger->error('Error executing run-script', ['client' => $client->getId(), 'error' => $e->getMessage()]); throw new ValidatorException('Error deploying image');
return new JsonResponse(
data: ['error' => $e->getMessage()],
status: Response::HTTP_INTERNAL_SERVER_ERROR
);
} }
$jobId = json_decode($response->getContent(), true)['job_id']; $this->logger->info('Powering off client', ['client' => $client->getId()]);
$jobId = $response['job_id'];
$this->entityManager->persist($client); $this->entityManager->persist($client);
$this->entityManager->flush(); $this->entityManager->flush();

View File

@ -24,15 +24,8 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
#[AsController] #[AsController]
class StatusAction extends AbstractController class StatusAction extends AbstractOgAgentController
{ {
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreatePartitionService $createPartitionService,
protected readonly LoggerInterface $logger,
) {}
/** /**
* @throws TransportExceptionInterface * @throws TransportExceptionInterface
* @throws ServerExceptionInterface * @throws ServerExceptionInterface
@ -66,38 +59,37 @@ class StatusAction extends AbstractController
); );
} }
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function getOgLiveStatus (Client $client): JsonResponse|int|string public function getOgLiveStatus (Client $client): JsonResponse|int|string
{ {
$this->logger->info('Checking client status', ['client' => $client->getId()]); $this->logger->info('Checking client status', ['client' => $client->getId()]);
$params = [ $params = [
'full-config' => false, 'json' => [
'full-config' => false
]
]; ];
try { $data = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/opengnsys/status', [ method: 'POST',
'verify_peer' => false, url: 'https://' . $client->getIp() . ':8000/opengnsys/status',
'verify_host' => false, params: $params,
'timeout' => 10, token: $client->getToken(),
'headers' => [ );
'Content-Type' => 'application/json',
],
'json' => $params,
]);
$statusCode = $response->getStatusCode();
$client->setStatus($statusCode === Response::HTTP_OK ? ClientStatus::OG_LIVE : ClientStatus::OFF);
} catch (TransportExceptionInterface $e) { if (isset($data['error']) && $data['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
$this->logger->error('Error checking client status', ['client' => $client->getId(), 'error' => $e->getMessage()]); $this->logger->error('Error checking client status', ['client' => $client->getId()]);
$client->setStatus(ClientStatus::OFF); $client->setStatus(ClientStatus::OFF);
$this->entityManager->persist($client); $this->entityManager->persist($client);
$this->entityManager->flush(); $this->entityManager->flush();
throw new ValidatorException('Error deploying image');
return $e->getMessage();
} }
$data = json_decode($response->getContent(), true);
if (isset($data['cfg'])) { if (isset($data['cfg'])) {
$this->logger->info('Creating partitions', ['data' => $data['cfg']]); $this->logger->info('Creating partitions', ['data' => $data['cfg']]);
$this->createPartitionService->__invoke($data, $client); $this->createPartitionService->__invoke($data, $client);
@ -109,25 +101,22 @@ class StatusAction extends AbstractController
return Response::HTTP_OK; return Response::HTTP_OK;
} }
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function getSOStatus (Client $client): JsonResponse|int public function getSOStatus (Client $client): JsonResponse|int
{ {
try { $data = $this->createRequest(
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/opengnsys/status', [ method: 'POST',
'verify_peer' => false, url: 'https://' . $client->getIp() . ':8000/opengnsys/status',
'verify_host' => false, params: [
'timeout' => 10, 'full-config' => false,
'headers' => [ ],
'Content-Type' => 'application/json', token: $client->getToken(),
], );
'json' => [],
]);
} catch (TransportExceptionInterface $e) {
$client->setStatus(ClientStatus::OFF);
$this->logger->error('Error checking client status', ['client' => $client->getId(), 'error' => $e->getMessage()]);
return Response::HTTP_INTERNAL_SERVER_ERROR;
}
$data = json_decode($response->getContent(), true);
if (isset($data['cfg'])) { if (isset($data['cfg'])) {
$this->createPartitionService->__invoke($data, $client); $this->createPartitionService->__invoke($data, $client);

View File

@ -49,6 +49,7 @@ class AgentController extends AbstractController
} }
$clientEntity->setStatus(ClientStatus::OG_LIVE); $clientEntity->setStatus(ClientStatus::OG_LIVE);
$clientEntity->setToken($data['secret'] ?? null);
$this->entityManager->persist($clientEntity); $this->entityManager->persist($clientEntity);
if (isset($data['cfg'])) { if (isset($data['cfg'])) {

View File

@ -51,6 +51,7 @@ class SyncAction extends AbstractOgRepositoryController
$imageEntity->setName($image['name']); $imageEntity->setName($image['name']);
$imageEntity->setRemotePc(false); $imageEntity->setRemotePc(false);
$imageEntity->setIsGlobal(false); $imageEntity->setIsGlobal(false);
$imageEntity->setType('monolithic');
$this->entityManager->persist($imageEntity); $this->entityManager->persist($imageEntity);
} }
@ -59,6 +60,7 @@ class SyncAction extends AbstractOgRepositoryController
$imageImageRepositoryEntity = new ImageImageRepository(); $imageImageRepositoryEntity = new ImageImageRepository();
} }
$imageImageRepositoryEntity->setName($image['name']);
$imageImageRepositoryEntity->setImageFullsum($image['fullsum']); $imageImageRepositoryEntity->setImageFullsum($image['fullsum']);
$imageImageRepositoryEntity->setDatasize($image['datasize']); $imageImageRepositoryEntity->setDatasize($image['datasize']);
$imageImageRepositoryEntity->setStatus(ImageStatus::SUCCESS); $imageImageRepositoryEntity->setStatus(ImageStatus::SUCCESS);

View File

@ -49,15 +49,19 @@ class CreatePartitionService
$partitionEntity->setOperativeSystem(null); $partitionEntity->setOperativeSystem(null);
if (isset($cfg['soi']) && $cfg['soi'] !== '') { if (isset($cfg['soi']) && $cfg['soi'] !== '') {
$operativeSystem = $this->entityManager->getRepository(OperativeSystem::class) if ($cfg['soi'] === 'DATA') {
->findOneBy(['name' => $cfg['soi']]); $partitionEntity->setImage(null);
} else {
$operativeSystem = $this->entityManager->getRepository(OperativeSystem::class)
->findOneBy(['name' => $cfg['soi']]);
if (!$operativeSystem) { if (!$operativeSystem) {
$operativeSystem = new OperativeSystem(); $operativeSystem = new OperativeSystem();
$operativeSystem->setName($cfg['soi']); $operativeSystem->setName($cfg['soi']);
$this->entityManager->persist($operativeSystem); $this->entityManager->persist($operativeSystem);
}
$partitionEntity->setOperativeSystem($operativeSystem);
} }
$partitionEntity->setOperativeSystem($operativeSystem);
} }
$partitionEntity->setClient($clientEntity); $partitionEntity->setClient($clientEntity);

View File

@ -25,13 +25,13 @@ class UDSClient
public function __construct( public function __construct(
private HttpClientInterface $httpClient, private HttpClientInterface $httpClient,
private readonly EntityManagerInterface $entityManager, private readonly EntityManagerInterface $entityManager,
#[Autowire(env: 'UDS_URL')] #[Autowire(env: 'REMOTE_PC_URL')]
private readonly string $udsAPIurl, private readonly string $udsAPIurl,
#[Autowire(env: 'UDS_AUTH_LOGIN')] #[Autowire(env: 'REMOTE_PC_AUTH_LOGIN')]
private readonly string $udsAuthLogin, private readonly string $udsAuthLogin,
#[Autowire(env: 'UDS_AUTH_USERNAME')] #[Autowire(env: 'REMOTE_PC_AUTH_USERNAME')]
private readonly string $udsAuthUsername, private readonly string $udsAuthUsername,
#[Autowire(env: 'UDS_AUTH_PASSWORD')] #[Autowire(env: 'REMOTE_PC_AUTH_PASSWORD')]
private readonly string $udsAuthPassword, private readonly string $udsAuthPassword,
) )
{ {