Compare commits

...

9 Commits

Author SHA1 Message Date
Manuel Aranda Rosales bc036b65cf refs #1740. Run assistant logic
testing/ogcore-api/pipeline/head This commit looks good Details
2025-04-01 10:58:55 +02:00
Manuel Aranda Rosales 2d6b058eaf refs #1794. Updted assistants endpoints 2025-04-01 10:58:11 +02:00
Manuel Aranda Rosales 3eca490d0a Updated load default user command
testing/ogcore-api/pipeline/head There was a failure building this commit Details
ogcore-debian-package/pipeline/tag This commit looks good Details
2025-03-26 21:54:39 +01:00
Manuel Aranda Rosales 52a0493285 Updated load default user command 2025-03-26 21:54:39 +01:00
Nicolas Arenas 24a414ab66 Add ogcore
testing/ogcore-api/pipeline/head This commit looks good Details
ogcore-debian-package/pipeline/tag This commit looks good Details
2025-03-26 18:17:40 +01:00
Nicolas Arenas 6b228b146b Updated ogcore
testing/ogcore-api/pipeline/head This commit looks good Details
2025-03-26 13:48:45 +01:00
Nicolas Arenas e646b4b1e9 Creates repo at install
testing/ogcore-api/pipeline/head This commit looks good Details
ogcore-debian-package/pipeline/tag This commit looks good Details
2025-03-26 13:46:16 +01:00
Manuel Aranda Rosales fbe20ba735 Fixed prod env web_profiler
testing/ogcore-api/pipeline/head This commit looks good Details
ogcore-debian-package/pipeline/tag This commit looks good Details
2025-03-26 08:42:07 +01:00
Manuel Aranda Rosales 9c8697740e Merge pull request 'develop' (#26) from develop into main
testing/ogcore-api/pipeline/head This commit looks good Details
ogcore-debian-package/pipeline/tag There was a failure building this commit Details
Reviewed-on: #26
2025-03-26 06:42:34 +01:00
36 changed files with 430 additions and 55 deletions

View File

@ -1,4 +1,8 @@
# Changelog
## [0.10.1] - 2025-03-25
### Improved
- Se ha modificado el script de creación de usuarios, añadiendole la opcion del tipo de visionalizacion por defecto de la vista "grupos".
## [0.10.0] - 2025-03-25
### Added
- Nuevo endpoint ogRepository. Convertir imagen en imagen virtual.

View File

@ -70,6 +70,7 @@ pipeline {
agent { label 'debian-repo' }
steps {
sh "aptly repo add opengnsys-devel /var/tmp/opengnsys/debian-repo/ogcore/*.deb"
sh "rm -rf /var/tmp/opengnsys/debian-repo/ogcore/*"
}
}
}

View File

@ -50,6 +50,13 @@ resources:
uriTemplate: /clients/server/{uuid}/get-pxe
controller: App\Controller\OgBoot\PxeBootFile\GetAction
login_client:
class: ApiPlatform\Metadata\Post
method: POST
input: App\Dto\Input\MultipleClientsInput
uriTemplate: /clients/server/login-client
controller: App\Controller\OgAgent\LoginAction
reboot_client:
class: ApiPlatform\Metadata\Post
method: POST

View File

@ -28,9 +28,8 @@ resources:
class: ApiPlatform\Metadata\Post
method: POST
input: App\Dto\Input\CommandExecuteInput
uriTemplate: /commands/{uuid}/execute
controller: App\Controller\CommandExecuteAction
uriTemplate: /commands/run-script
controller: App\Controller\OgAgent\RunScriptAction
properties:
App\Entity\Command:
id:

View File

@ -13,13 +13,5 @@ when@test:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }
when@prod:
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }

View File

@ -42,7 +42,7 @@ services:
api_platform.filter.command.boolean:
parent: 'api_platform.doctrine.orm.boolean_filter'
arguments: [ { 'enabled': ~ } ]
arguments: [ { 'enabled': ~, 'readOnly': ~ } ]
tags: [ 'api_platform.filter' ]
api_platform.filter.hardware.order:

View File

@ -8,6 +8,9 @@ USER="opengnsys"
# Detectar si es una instalación nueva o una actualización
if [ "$1" = "configure" ] && [ -z "$2" ]; then
# Detectar IP de la interfaz de red asociad a la ruta por defecto.
IP=$(ip -4 route get 8.8.8.8 | grep -oP '(?<=src )[\d.]+')
echo ">>> Instalación nueva detectada."
# Solicitar credenciales solo en instalación nueva
@ -25,7 +28,8 @@ if [ "$1" = "configure" ] && [ -z "$2" ]; then
# Configuración inicial
echo ">>> Configurando base de datos y permisos"
mariadb -e "GRANT ALL ON *.* to 'root'@'localhost' IDENTIFIED BY 'root' WITH GRANT OPTION;"
mariadb -e "ALTER USER 'root'@'localhost' IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('root');"
echo ">>> Creando par de claves para JWT"
php bin/console lexik:jwt:generate-keypair --overwrite
@ -54,29 +58,31 @@ if [ "$1" = "configure" ] && [ -z "$2" ]; then
systemctl restart og-mercure
systemctl restart nginx
systemctl restart php8.3-fpm
#Obteniendo bearer token
BEARER=$(curl -sk -X 'POST' 'https://localhost:8443/auth/login' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{ "username": "ogadmin", "password": "12345678" }' | jq -r .token)
# Creando nuevo repo
curl -skL -X POST 'https://localhost:8443/image-repositories' \
-H "Authorization: Bearer $BEARER" \
-H 'Content-Type: application/json' \
-d "{ \"name\": \"Repository 1\", \"ip\": \"$IP\", \"comments\": \"Repositorio creado automaticamente por oginstaller\" }"
# Solo gestionar credenciales en instalación nueva
if [ "$ADMIN_USER" == "ogadmin" ]; then
BEARER=$(curl -sk -X 'POST' 'https://localhost:8443/auth/login' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{ "username": "ogadmin", "password": "12345678" }' | jq -r .token)
echo ">>> Cambiando contraseña de ogadmin"
echo ">>> Cambiando contraseña de ogadmin"¡
OGADMIN_UUID=$(curl -skL "https://localhost:8443/users/?username=ogadmin" \
-H 'accept: application/json' \
-H "Authorization: Bearer $BEARER" | jq -r '.[0].uuid')
curl -skL -X PUT "https://localhost:8443/users/$OGADMIN_UUID/reset-password" \
-H 'accept: application/ld+json' \
-H 'Content-Type: application/ld+json' \
-H "Authorization: Bearer $BEARER" \
-d "{ \"currentPassword\": \"12345678\", \"newPassword\": \"$ADMIN_PASS\", \"repeatNewPassword\": \"$ADMIN_PASS\" }"
echo ">>> Contraseña de ogadmin cambiada."
else
echo ">>> Creando nuevo usuario administrador: $ADMIN_USER"
curl -skL --location 'https://localhost:8443/users' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer $BEARER" \

View File

@ -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 Version20250325075647 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 client ADD firmware_type 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 client DROP firmware_type');
}
}

View File

@ -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 Version20250326061450 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 command ADD parameters TINYINT(1) DEFAULT NULL');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE command DROP parameters');
}
}

View File

@ -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 Version20250331144522 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 image_image_repository ADD datasize 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 image_image_repository DROP datasize');
}
}

View File

@ -20,6 +20,8 @@ class LoadDefaultUserAdminCommand extends Command
CONST string PLAIN_PASSWORD = '12345678';
const string USERNAME = 'ogadmin';
const string DEFAULT_GROUPS_VIEW = 'card';
public function __construct(
private readonly EntityManagerInterface $entityManager
)
@ -37,6 +39,7 @@ class LoadDefaultUserAdminCommand extends Command
$user = new User();
$user->setUsername(self::USERNAME);
$user->setGroupsView(self::DEFAULT_GROUPS_VIEW);
$user->setRoles([UserGroupPermissions::ROLE_SUPER_ADMIN]);
$user->setPassword($hash);

View File

@ -90,7 +90,7 @@ class CreateImageAction extends AbstractController
try {
$this->logger->info('Creating image', ['image' => $image->getId()]);
$response = $this->httpClient->request('POST', 'https://'.$image->getClient()->getIp().':8000/CloningEngine/CrearImagen', [
$response = $this->httpClient->request('POST', 'https://'.$image->getClient()->getIp().':8000/opengnsys/CrearImagen', [
'verify_peer' => false,
'verify_host' => false,
'headers' => [

View File

@ -92,7 +92,7 @@ class DeployImageAction extends AbstractController
];
try {
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/CloningEngine/RestaurarImagen', [
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen', [
'verify_peer' => false,
'verify_host' => false,
'headers' => [

View File

@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
namespace App\Controller\OgAgent;
use App\Dto\Input\MultipleClientsInput;
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 Psr\Log\LoggerInterface;
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 LoginAction extends AbstractController
{
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreateService $createService,
protected readonly LoggerInterface $logger,
)
{
}
public function __invoke(MultipleClientsInput $input): JsonResponse
{
foreach ($input->clients as $clientEntity) {
/** @var Client $client */
$client = $clientEntity->getEntity();
if (!$client->getIp()) {
throw new ValidatorException('IP is required');
}
if ($client->getStatus() !== ClientStatus::OG_LIVE) {
throw new ValidatorException('Client is not in OG_LIVE status');
}
$data = [
'nfn' => 'IniciarSesion',
'dsk' => '1',
'par' => '1',
'ids' => '0'
];
try {
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/IniciarSesion', [
'verify_peer' => false,
'verify_host' => false,
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data,
]);
$this->logger->info('Login client', ['client' => $client->getId()]);
} catch (TransportExceptionInterface $e) {
$this->logger->error('Login 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'];
$client->setStatus(ClientStatus::INITIALIZING);
$this->entityManager->persist($client);
$this->entityManager->flush();
$this->createService->__invoke($client, CommandTypes::REBOOT, TraceStatus::SUCCESS, $jobId, []);
}
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
}

View File

@ -48,6 +48,7 @@ class PartitionAssistantAction extends AbstractController
}
foreach ($input->clients as $clientInput) {
/** @var Client $client */
$client = $clientInput->getEntity();
$disks = [];
@ -72,13 +73,10 @@ class PartitionAssistantAction extends AbstractController
];
}
if ($partition->filesystem === 'CACHE') {
$disks[$diskNumber]['diskData'] = [
'dis' => (string) $diskNumber,
'che' => "0",
'tch' => (string) ($partition->size * 1024),
];
}
$disks[$diskNumber]['diskData'] = [
'dis' => (string) $diskNumber,
'tch' => (string) ($partition->size * 1024),
];
$disks[$diskNumber]['partitionData'][] = [
'par' => (string) $partition->partitionNumber,
@ -104,7 +102,7 @@ class PartitionAssistantAction extends AbstractController
];
try {
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/CloningEngine/Configurar', [
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/opengnsys/Configurar', [
'verify_peer' => false,
'verify_host' => false,
'headers' => [
@ -130,5 +128,4 @@ class PartitionAssistantAction extends AbstractController
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
}

View File

@ -53,13 +53,15 @@ class PowerOffAction extends AbstractController
continue;
}
$endpoint = $client->getStatus() === ClientStatus::OG_LIVE ? 'opengnsys/Apagar' : 'opengnsys/poweroff';
$data = [
'nfn' => 'Apagar',
'ids' => '0'
];
try {
$response = $this->httpClient->request('POST', 'https://'.$client->getIp().':8000/ogAdmClient/Apagar', [
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/'.$endpoint, [
'verify_peer' => false,
'verify_host' => false,
'headers' => [

View File

@ -41,6 +41,7 @@ class RebootAction extends AbstractController
public function __invoke(MultipleClientsInput $input): JsonResponse
{
foreach ($input->clients as $clientEntity) {
/** @var Client $client */
$client = $clientEntity->getEntity();
@ -48,13 +49,15 @@ class RebootAction extends AbstractController
throw new ValidatorException('IP is required');
}
$endpoint = $client->getStatus() === ClientStatus::OG_LIVE ? 'opengnsys/Reiniciar' : '/opengnsys/reboot';
$data = [
'nfn' => 'Reiniciar',
'ids' => '0'
];
try {
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/Reiniciar', [
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/'.$endpoint, [
'verify_peer' => false,
'verify_host' => false,
'headers' => [
@ -62,6 +65,7 @@ class RebootAction extends AbstractController
],
'json' => $data,
]);
$this->logger->info('Rebooting client', ['client' => $client->getId()]);
} catch (TransportExceptionInterface $e) {

View File

@ -0,0 +1,78 @@
<?php
namespace App\Controller\OgAgent;
use App\Dto\Input\CommandExecuteInput;
use App\Dto\Input\MultipleClientsInput;
use App\Entity\Client;
use App\Model\ClientStatus;
use App\Model\CommandTypes;
use App\Model\TraceStatus;
use App\Service\Trace\CreateService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class RunScriptAction extends AbstractController
{
public function __construct(
protected readonly EntityManagerInterface $entityManager,
protected readonly HttpClientInterface $httpClient,
protected readonly CreateService $createService,
protected readonly LoggerInterface $logger,
)
{
}
public function __invoke(CommandExecuteInput $input): JsonResponse
{
/** @var Client $clientEntity */
foreach ($input->clients as $clientEntity) {
$client = $clientEntity->getEntity();
if (!$client->getIp()) {
throw new ValidatorException('IP is required');
}
//TODO: base64 script content
$data = [
'nfn' => 'EjecutarScript',
'scp' => $input->script,
'ids' => '0'
];
try {
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/EjecutarScript', [
'verify_peer' => false,
'verify_host' => false,
'headers' => [
'Content-Type' => 'application/json',
],
'json' => $data,
]);
$this->logger->info('Rebooting client', ['client' => $client->getId()]);
} 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->entityManager->persist($client);
$this->entityManager->flush();
$this->createService->__invoke($client, CommandTypes::RUN_SCRIPT, TraceStatus::SUCCESS, $jobId, []);
}
return new JsonResponse(data: [], status: Response::HTTP_OK);
}
}

View File

@ -70,6 +70,10 @@ class StatusAction extends AbstractController
{
$this->logger->info('Checking client status', ['client' => $client->getId()]);
$params = [
'full-config' => true,
];
try {
$response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/status', [
'verify_peer' => false,
@ -78,7 +82,7 @@ class StatusAction extends AbstractController
'headers' => [
'Content-Type' => 'application/json',
],
'json' => [],
'json' => $params,
]);
$statusCode = $response->getStatusCode();
$client->setStatus($statusCode === Response::HTTP_OK ? ClientStatus::OG_LIVE : ClientStatus::OFF);

View File

@ -32,7 +32,7 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
#[AsController]
class ClientsController extends AbstractController
class StatusController extends AbstractController
{
const string CREATE_IMAGE = 'RESPUESTA_CrearImagen';
const string RESTORE_IMAGE = 'RESPUESTA_RestaurarImagen';
@ -72,7 +72,7 @@ class ClientsController extends AbstractController
if (isset($data['progress'])){
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
if ($trace){
$trace->setProgress($data['progress'] * 1000);
$trace->setProgress($data['progress'] * 100);
$this->entityManager->persist($trace);
$this->entityManager->flush();
}

View File

@ -40,7 +40,7 @@ class PostAction extends AbstractOgBootController
'json' => [
'template_name' => $pxeTemplate->getName(),
'mac' => strtolower($client->getMac()),
'lang' => 'es_ES.UTF_8',
'lang' => 'es_ES.UTF-8',
'ip' => $client->getIp(),
'server_ip' => $this->ogBootApiUrl,
'router' => $client->getOrganizationalUnit()->getNetworkSettings()->getRouter(),

View File

@ -45,9 +45,9 @@ class DeployImageAction extends AbstractOgRepositoryController
];
$type = match ($input->method) {
'udpcast', 'udpcast_direct' => DeployMethodTypes::MULTICAST_UDPCAST,
'udpcast', 'udpcast-direct' => DeployMethodTypes::MULTICAST_UDPCAST,
'p2p' => DeployMethodTypes::TORRENT,
default => DeployMethodTypes::MULTICAST_UFTP,
default => null,
};
$repository = $client->getRepository();

View File

@ -56,13 +56,16 @@ class SyncAction extends AbstractOgRepositoryController
if (!$imageImageRepositoryEntity) {
$imageImageRepositoryEntity = new ImageImageRepository();
$imageImageRepositoryEntity->setImageFullsum($image['fullsum']);
$imageImageRepositoryEntity->setStatus(ImageStatus::SUCCESS);
$imageImageRepositoryEntity->setImage($imageEntity);
$imageImageRepositoryEntity->setRepository($input);
$this->entityManager->persist($imageImageRepositoryEntity);
}
$imageImageRepositoryEntity->setImageFullsum($image['fullsum']);
$imageImageRepositoryEntity->setDatasize($image['datasize']);
$imageImageRepositoryEntity->setStatus(ImageStatus::SUCCESS);
$imageImageRepositoryEntity->setImage($imageEntity);
$imageImageRepositoryEntity->setRepository($input);
$this->entityManager->persist($imageImageRepositoryEntity);
}
foreach ($existingImages as $existingImage) {

View File

@ -14,4 +14,9 @@ final class CommandExecuteInput
#[Assert\NotNull]
#[Groups(['command:write'])]
public array $clients = [];
#[Assert\NotNull]
#[Groups(['command:write'])]
public string $script = '';
}

View File

@ -40,6 +40,13 @@ final class CommandInput
)]
public ?bool $enabled = true;
#[Groups(['command:write'])]
#[ApiProperty(
description: 'Tiene parámetros?',
example: 'true',
)]
public ?bool $parameters = true;
#[Groups(['command:write'])]
#[ApiProperty(
description: 'Los comentarios del comando',
@ -57,6 +64,7 @@ final class CommandInput
$this->script = $command->getScript();
$this->enabled = $command->isEnabled();
$this->readOnly = $command->isReadOnly();
$this->parameters = $command->isParameters();
$this->comments = $command->getComments();
}
@ -70,6 +78,7 @@ final class CommandInput
$command->setScript($this->script);
$command->setEnabled($this->enabled);
$command->setReadOnly($this->readOnly);
$command->setParameters($this->parameters);
$command->setComments($this->comments);
return $command;

View File

@ -25,6 +25,9 @@ final class ClientOutput extends AbstractOutput
#[Groups(['client:read', 'organizational-unit:read', 'pxe-template:read', 'trace:read', 'subnet:read'])]
public ?string $mac = '';
#[Groups(['client:read'])]
public ?string $firmwareType = '';
#[Groups(['client:read', 'organizational-unit:read', 'trace:read'])]
public ?string $serialNumber = '';
@ -91,6 +94,7 @@ final class ClientOutput extends AbstractOutput
$this->ip = $client->getIp();
$this->netiface = $client->getNetiface();
$this->netDriver = $client->getNetDriver();
$this->firmwareType = $client->getFirmwareType();
if ($client->getOrganizationalUnit()) {
$this->organizationalUnit = new OrganizationalUnitOutput($client->getOrganizationalUnit());

View File

@ -21,6 +21,9 @@ final class CommandOutput extends AbstractOutput
#[Groups(['command:read'])]
public ?bool $enabled = true;
#[Groups(['command:read'])]
public ?bool $parameters = true;
#[Groups(['command:read'])]
public ?string $comments = '';
@ -37,6 +40,7 @@ final class CommandOutput extends AbstractOutput
$this->name = $command->getName();
$this->script = $command->getScript();
$this->readOnly = $command->isReadOnly();
$this->parameters = $command->isParameters();
$this->enabled = $command->isEnabled();
$this->comments = $command->getComments();
$this->createdAt = $command->getCreatedAt();

View File

@ -21,6 +21,9 @@ class ImageImageRepositoryOutput extends AbstractOutput
#[Groups(['image-image-repository:read', 'image:read'])]
public ?string $imageFullsum = null;
#[Groups(['image-image-repository:read', 'image:read'])]
public ?string $datasize = null;
#[Groups(['image-image-repository:read', 'image:read'])]
public \DateTime $createdAt;
@ -43,6 +46,7 @@ class ImageImageRepositoryOutput extends AbstractOutput
$this->status = $imageImageRepository->getStatus();
$this->imageFullsum = $imageImageRepository->getImageFullsum();
$this->datasize = $imageImageRepository->getDatasize();
$this->createdAt = $imageImageRepository->getCreatedAt();
$this->createdBy = $imageImageRepository->getCreatedBy();
}

View File

@ -59,7 +59,7 @@ final class TraceOutput extends AbstractOutput
$this->output = $trace->getOutput();
$this->input = $trace->getInput();
$this->finishedAt = $trace->getFinishedAt();
$this->progress = $trace->getProgress() / 100;
$this->progress = $trace->getProgress();
$this->createdAt = $trace->getCreatedAt();
$this->createdBy = $trace->getCreatedBy();
}

View File

@ -82,6 +82,9 @@ class Client extends AbstractEntity
#[ORM\Column(nullable: true)]
private ?bool $pxeSync = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $firmwareType = null;
public function __construct()
{
parent::__construct();
@ -335,4 +338,16 @@ class Client extends AbstractEntity
return $this;
}
public function getFirmwareType(): ?string
{
return $this->firmwareType;
}
public function setFirmwareType(?string $firmwareType): static
{
$this->firmwareType = $firmwareType;
return $this;
}
}

View File

@ -35,6 +35,9 @@ class Command extends AbstractEntity
#[ORM\ManyToMany(targetEntity: CommandTask::class, mappedBy: 'commands')]
private Collection $commandTasks;
#[ORM\Column(nullable: true)]
private ?bool $parameters = null;
public function __construct()
{
parent::__construct();
@ -131,4 +134,16 @@ class Command extends AbstractEntity
return $this;
}
public function isParameters(): ?bool
{
return $this->parameters;
}
public function setParameters(?bool $parameters): static
{
$this->parameters = $parameters;
return $this;
}
}

View File

@ -28,6 +28,9 @@ class ImageImageRepository extends AbstractEntity
#[ORM\Column(length: 255, nullable: true)]
private ?string $imageFullsum = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $datasize = null;
public function getImage(): ?Image
{
return $this->image;
@ -87,4 +90,16 @@ class ImageImageRepository extends AbstractEntity
return $this;
}
public function getDatasize(): ?string
{
return $this->datasize;
}
public function setDatasize(?string $datasize): static
{
$this->datasize = $datasize;
return $this;
}
}

View File

@ -42,7 +42,7 @@ class TraceStatusProgressNotifier
{
$update = new Update(
'traces',
json_encode(['@id' => '/traces/' . $trace->getUuid(), 'status' => $trace->getStatus(), 'progress' => $trace->getProgress() / 100])
json_encode(['@id' => '/traces/' . $trace->getUuid(), 'status' => $trace->getStatus(), 'progress' => $trace->getProgress()])
);
$this->hub->publish($update);

View File

@ -58,12 +58,18 @@ final readonly class OrganizationalUnitSubscriber implements EventSubscriberInte
{
/** @var OrganizationalUnit $childUnit */
foreach ($parentUnit->getOrganizationalUnits() as $childUnit) {
//var_dump($childUnit->getNetworkSettings()->getMcastPort());
if ($childUnit->isExcludeParentChanges()) {
$childUnit->setNetworkSettings(null);
} else{
$childUnit->setNetworkSettings($networkSettings);
foreach ($childUnit->getClients() as $client) {
$client->setOgLive($networkSettings->getOgLive());
$client->setMenu($networkSettings->getMenu());
$client->setRepository($networkSettings->getRepository());
$this->entityManager->persist($client);
}
}
$this->entityManager->persist($childUnit);

View File

@ -21,6 +21,7 @@ final class CommandTypes
public const string LOGOUT = 'logout';
public const string PARTITION_AND_FORMAT = 'partition-and-format';
public const string INSTALL_OGLIVE = 'install-oglive';
public const string RUN_SCRIPT = 'run-script';
private const array COMMAND_TYPES = [
self::DEPLOY_IMAGE => 'Deploy Image',
@ -40,6 +41,7 @@ final class CommandTypes
self::PARTITION_AND_FORMAT => 'Partition and Format',
self::TRANSFER_IMAGE => 'Transfer Image',
self::INSTALL_OGLIVE => 'Instalar OgLive',
self::RUN_SCRIPT => 'Run Script',
];
public static function getCommandTypes(): array

View File

@ -26,11 +26,19 @@ class CreatePartitionService
$receivedPartitions = [];
foreach ($data['cfg'] as $cfg) {
if (!isset($cfg['disk'], $cfg['par'], $cfg['tam'], $cfg['uso'], $cfg['fsi'])) {
continue;
}
$filteredCfg = array_filter($data['cfg'], function ($cfg) {
return isset($cfg['disk'], $cfg['par'], $cfg['tam'], $cfg['uso'], $cfg['fsi']);
});
foreach ($data['cfg'] as $cfg) {
if (!empty($cfg['fwt'])) {
$clientEntity->setFirmwareType($cfg['fwt']);
$this->entityManager->persist($clientEntity);
break;
}
}
foreach ($filteredCfg as $cfg) {
$partitionEntity = $this->entityManager->getRepository(Partition::class)
->findOneBy(['client' => $clientEntity, 'diskNumber' => $cfg['disk'], 'partitionNumber' => $cfg['par']]);
@ -38,6 +46,8 @@ class CreatePartitionService
$partitionEntity = new Partition();
}
$partitionEntity->setOperativeSystem(null);
if (isset($cfg['soi']) && $cfg['soi'] !== '') {
$operativeSystem = $this->entityManager->getRepository(OperativeSystem::class)
->findOneBy(['name' => $cfg['soi']]);