diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c41b04..47a0fa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ # Changelog +## [1.1.0] - 2025-10-16 +### Added +- Se ha añadido un nuevo campo en el cliente, para guardar la resolucion del menu browser. +- Se ha añadido un validador en el asistente "deploy", el cual comprueba que el tamaño de la partition destino de todos los clientes sea igual. + +### Fixed +- Se ha corregido un bug a la hora de mover clientes cuando el aula destino no tiene plantilla PXE asignada. + +--- ## [1.0.0] - 2025-10-09 ### Added - Se ha añadido nuevo readme diff --git a/README.md b/README.md index 1a52c11..559fd35 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ 4. [Tecnologías Utilizadas](#4-tecnologías-utilizadas) 5. [Requisitos del Sistema](#5-requisitos-del-sistema) 6. [Instalación y Configuración](#6-instalación-y-configuración) -7. [Modelo de Datos](#7-modelo-de-datos) -8. [Componentes del Sistema](#8-componentes-del-sistema) +7. [Componentes del Sistema](#7-componentes-del-sistema) +8. [Guía de Desarrollo - Crear Nueva Entidad](#8-guía-de-desarrollo---crear-nueva-entidad) 9. [API RESTful](#9-api-restful) 10. [Seguridad y Autenticación](#10-seguridad-y-autenticación) 11. [Servicios Principales](#11-servicios-principales) @@ -71,8 +71,7 @@ ogCore es el núcleo central de OpenGnsys desarrollado con tecnologías modernas - **Arquitectura basada en eventos** con notificaciones en tiempo real (Mercure) - **Sistema de colas** para la ejecución de tareas programadas - **Integración con múltiples servicios** externos -- **Migraciones automatizadas** desde OpenGnsys 1.1 -- **Versionado de imágenes** con integración Git +- **Creación de imágenes** con integración Git y sistema monolítico - **Sistema de trazabilidad** completo - **Gestión de hardware** con inventario automático - **Despliegues masivos** de imágenes (unicast, multicast, torrent, p2p) @@ -81,7 +80,7 @@ ogCore es el núcleo central de OpenGnsys desarrollado con tecnologías modernas ### 2.3 Versión Actual -- **Versión**: 0.5.0 +- **Versión**: 1.0.0 - **Estado**: En desarrollo activo - **Última actualización**: Octubre 2025 @@ -103,7 +102,7 @@ ogCore sigue una arquitectura de **microservicios** basada en el patrón **API-F +---------------------------v---------------------------------+ | ogCore API (Symfony) | | +------------------------------------------------------+ | -| | Controllers | States | DTOs | Validators | Filters | | +| | Controllers | States | DTOs | Validators | Filters | | | +------------------------------------------------------+ | | +------------------------------------------------------+ | | | Business Logic (Services) | | @@ -248,7 +247,7 @@ ogCore sigue una arquitectura de **microservicios** basada en el patrón **API-F ## 6. Instalación y Configuración -### 6.1 Instalación con Docker (Recomendado) +### 6.1 Instalación con Docker #### 6.1.1 Clonar el Repositorio @@ -380,275 +379,9 @@ Asegúrate de: --- -## 7. Modelo de Datos +## 7. Componentes del Sistema -### 7.1 Diagrama de Entidades - -El sistema cuenta con 35 entidades principales agrupadas en los siguientes dominios: - -### 7.2 Entidades Principales - -#### 7.2.1 Client (Cliente) - -Representa un equipo físico en el sistema. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del cliente -- `serialNumber`: Número de serie -- `mac`: Dirección MAC (única) -- `ip`: Dirección IP (única) -- `status`: Estado del cliente (active, inactive, busy, windows, linux, etc.) -- `netiface`: Interfaz de red -- `netDriver`: Driver de red -- `validation`: Estado de validación -- `maintenance`: Modo mantenimiento -- `position`: Posición en el aula (x, y) -- `firmwareType`: Tipo de firmware (BIOS/UEFI) -- `agentJobId`: ID del trabajo del agente en ejecución -- `pxeSync`: Sincronización PXE -- `token`: Token de autenticación del cliente - -**Relaciones:** -- `organizationalUnit`: Pertenece a una unidad organizativa (aula/grupo) -- `partitions`: Tiene múltiples particiones -- `menu`: Menú de arranque asignado -- `hardwareProfile`: Perfil de hardware asociado -- `template`: Plantilla PXE asignada -- `repository`: Repositorio de imágenes -- `subnet`: Subred a la que pertenece -- `ogLive`: Imagen Live asignada - -#### 7.2.2 OrganizationalUnit (Unidad Organizativa) - -Representa aulas o grupos de equipos. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre de la unidad -- `description`: Descripción -- `type`: Tipo (aula, grupo, etc.) - -**Relaciones:** -- `parent`: Unidad organizativa padre (jerarquía) -- `children`: Unidades hijas -- `clients`: Clientes pertenecientes -- `networkSettings`: Configuración de red heredable -- `remoteCalendar`: Calendario remoto asociado - -#### 7.2.3 Image (Imagen) - -Representa una imagen de sistema operativo. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre de la imagen -- `description`: Descripción -- `type`: Tipo de imagen -- `size`: Tamaño en bytes -- `partition`: Partición de origen -- `status`: Estado (creating, success, failed, etc.) -- `isGlobal`: Imagen global compartida -- `isVirtual`: Imagen virtual -- `version`: Versión de la imagen - -**Relaciones:** -- `operativeSystem`: Sistema operativo -- `softwareProfile`: Perfil de software -- `repositories`: Repositorios que contienen la imagen -- `originClient`: Cliente origen de la imagen - -#### 7.2.4 Command (Comando) - -Comandos ejecutables en el sistema. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del comando -- `description`: Descripción -- `script`: Script a ejecutar - -**Relaciones:** -- `commandGroups`: Grupos de comandos a los que pertenece - -#### 7.2.5 CommandTask (Tarea de Comando) - -Tarea programada para ejecutar comandos. - -**Campos principales:** -- `id`: UUID único -- `datetime`: Fecha y hora de ejecución -- `parameters`: Parámetros de ejecución -- `status`: Estado de la tarea - -**Relaciones:** -- `commands`: Comandos a ejecutar -- `commandGroups`: Grupos de comandos -- `clients`: Clientes objetivo -- `schedule`: Programación recurrente - -#### 7.2.6 Trace (Traza) - -Registro de ejecución de comandos. - -**Campos principales:** -- `id`: UUID único -- `command`: Nombre del comando ejecutado -- `input`: Parámetros de entrada -- `output`: Resultado de ejecución -- `status`: Estado (pending, processing, success, failed, cancelled) -- `executedAt`: Fecha de ejecución -- `finishedAt`: Fecha de finalización -- `cancelled`: Indica si fue cancelada -- `jobId`: ID del trabajo en el agente - -**Relaciones:** -- `client`: Cliente donde se ejecutó - -#### 7.2.7 HardwareProfile (Perfil de Hardware) - -Inventario de hardware de un cliente. - -**Campos principales:** -- `id`: UUID único -- `cpu`: Información de CPU -- `ram`: Memoria RAM -- `storage`: Almacenamiento -- `networkCards`: Tarjetas de red - -**Relaciones:** -- `client`: Cliente asociado -- `hardwareTypes`: Tipos de hardware detectados - -#### 7.2.8 SoftwareProfile (Perfil de Software) - -Software instalado en una imagen. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del perfil - -**Relaciones:** -- `software`: Software incluido -- `images`: Imágenes que usan este perfil - -#### 7.2.9 ImageRepository (Repositorio de Imágenes) - -Servidor de almacenamiento de imágenes. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del repositorio (único) -- `ip`: Dirección IP o DNS (único) -- `port`: Puerto -- `sshPort`: Puerto SSH -- `sshUser`: Usuario SSH -- `apiKey`: Clave API -- `status`: Estado del repositorio - -**Relaciones:** -- `images`: Imágenes almacenadas - -#### 7.2.10 Subnet (Subred) - -Configuración de red. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre de la subred -- `cidr`: Notación CIDR -- `gateway`: Puerta de enlace -- `dns`: Servidores DNS -- `dhcpStart`: Inicio rango DHCP -- `dhcpEnd`: Fin rango DHCP - -**Relaciones:** -- `clients`: Clientes en la subred - -#### 7.2.11 Partition (Partición) - -Partición de disco de un cliente. - -**Campos principales:** -- `id`: UUID único -- `partitionNumber`: Número de partición -- `partitionType`: Tipo de partición -- `partitionSize`: Tamaño -- `partitionCode`: Código de partición -- `usedSize`: Tamaño usado -- `filesystem`: Sistema de archivos - -**Relaciones:** -- `client`: Cliente propietario -- `image`: Imagen desplegada -- `operativeSystem`: Sistema operativo instalado - -#### 7.2.12 PxeTemplate (Plantilla PXE) - -Plantilla de arranque PXE. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre de la plantilla -- `content`: Contenido de la plantilla -- `default`: Plantilla por defecto - -**Relaciones:** -- `clients`: Clientes que usan la plantilla - -#### 7.2.13 RemoteCalendar (Calendario Remoto) - -Integración con sistemas de reservas remotas. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del calendario -- `url`: URL del servicio -- `available`: Disponibilidad - -**Relaciones:** -- `organizationalUnits`: Unidades organizativas asociadas -- `rules`: Reglas del calendario - -#### 7.2.14 User (Usuario) - -Usuario del sistema. - -**Campos principales:** -- `id`: UUID único -- `username`: Nombre de usuario (único) -- `password`: Contraseña (hasheada) -- `email`: Correo electrónico -- `roles`: Roles del usuario - -**Relaciones:** -- `userGroups`: Grupos de usuarios -- `view`: Vista preferida - -#### 7.2.15 GitRepository (Repositorio Git) - -Repositorio Git para versionado de imágenes. - -**Campos principales:** -- `id`: UUID único -- `name`: Nombre del repositorio -- `url`: URL del repositorio -- `branch`: Rama -- `credentials`: Credenciales de acceso - -### 7.3 Índices y Optimizaciones - -La base de datos está optimizada con índices en: -- Campos de búsqueda frecuente (status, updatedAt) -- Campos únicos (IP, MAC, username) -- Claves foráneas -- Índices compuestos para consultas complejas - ---- - -## 8. Componentes del Sistema - -### 8.1 Controllers (Controladores) +### 7.1 Controllers (Controladores) El sistema cuenta con **102 controladores** organizados por dominio: @@ -662,7 +395,7 @@ El sistema cuenta con **102 controladores** organizados por dominio: - **SubnetController**: Gestión de subredes - **RepositoryController**: Gestión de repositorios -### 8.2 States (Procesadores de Estado) +### 7.2 States (Procesadores de Estado) Los States implementan el patrón State de API Platform: @@ -671,7 +404,7 @@ Los States implementan el patrón State de API Platform: - **Processors**: Procesamiento de escritura - **Custom States**: Lógica personalizada -### 8.3 DTOs (Data Transfer Objects) +### 7.3 DTOs (Data Transfer Objects) **93 DTOs** para transferencia de datos: @@ -680,7 +413,7 @@ Los States implementan el patrón State de API Platform: - **Output DTOs**: Para envío de datos - **Transformation DTOs**: Para transformaciones -### 8.4 Validators (Validadores) +### 7.4 Validators (Validadores) **18 validadores personalizados** para: - Validación de IPs y MACs @@ -690,7 +423,7 @@ Los States implementan el patrón State de API Platform: - Validación de comandos - Validación de usuarios -### 8.5 EventSubscribers (Suscriptores de Eventos) +### 7.5 EventSubscribers (Suscriptores de Eventos) **8 suscriptores** para: - Publicación en Mercure al cambiar estados @@ -698,7 +431,7 @@ Los States implementan el patrón State de API Platform: - Validaciones pre/post persistencia - Logging de eventos -### 8.6 Factories (Fábricas) +### 7.6 Factories (Fábricas) **24 factories** para testing con Foundry: - Creación de entidades para tests @@ -707,9 +440,970 @@ Los States implementan el patrón State de API Platform: --- +## 8. Guía de Desarrollo - Crear Nueva Entidad + +Esta sección proporciona una guía paso a paso para añadir una nueva entidad al sistema ogCore, incluyendo todos los componentes necesarios. + +### 8.1 Visión General + +Para añadir una nueva entidad completa al sistema necesitarás crear: + +1. **Entity** - La entidad Doctrine +2. **Repository** - Repositorio personalizado +3. **DTOs** - Input y Output DTOs +4. **Configuración YAML** - Para API Platform +5. **States** - Providers y Processors +6. **Validators** - Validaciones personalizadas (opcional) +7. **Factory** - Para testing +8. **Migración** - Cambios en base de datos + +### 8.2 Paso 1: Crear la Entidad + +Crea la entidad en `src/Entity/`. Ejemplo: `Product.php` + +```php +description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + return $this; + } + + public function getPrice(): ?float + { + return $this->price; + } + + public function setPrice(float $price): static + { + $this->price = $price; + return $this; + } + + public function getStock(): ?int + { + return $this->stock; + } + + public function setStock(int $stock): static + { + $this->stock = $stock; + return $this; + } + + public function isActive(): ?bool + { + return $this->active; + } + + public function setActive(bool $active): static + { + $this->active = $active; + return $this; + } + + public function getCategory(): ?Category + { + return $this->category; + } + + public function setCategory(?Category $category): static + { + $this->category = $category; + return $this; + } +} +``` + +### 8.3 Paso 2: Crear el Repository + +Crea el repositorio en `src/Repository/ProductRepository.php`: + +```php + + */ +class ProductRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Product::class); + } + + /** + * Encuentra productos activos por categoría + */ + public function findActiveByCategory(int $categoryId): array + { + return $this->createQueryBuilder('p') + ->where('p.category = :categoryId') + ->andWhere('p.active = true') + ->setParameter('categoryId', $categoryId) + ->orderBy('p.name', 'ASC') + ->getQuery() + ->getResult(); + } + + /** + * Encuentra productos con stock bajo + */ + public function findLowStock(int $threshold = 10): array + { + return $this->createQueryBuilder('p') + ->where('p.stock <= :threshold') + ->andWhere('p.active = true') + ->setParameter('threshold', $threshold) + ->getQuery() + ->getResult(); + } +} +``` + +### 8.4 Paso 3: Crear los DTOs + +#### 8.4.1 Input DTO + +Crea `src/Dto/Input/ProductInput.php`: + +```php +name = $product->getName(); + $this->description = $product->getDescription(); + $this->price = $product->getPrice(); + $this->stock = $product->getStock(); + $this->active = $product->isActive(); + $this->category = $product->getCategory() + ? CategoryOutput::fromEntity($product->getCategory()) + : null; + } + } + + /** + * Crea o actualiza una entidad Product desde este DTO + */ + public function createOrUpdateEntity(?Product $product = null): Product + { + if (!$product) { + $product = new Product(); + } + + $product->setName($this->name); + $product->setDescription($this->description); + $product->setPrice($this->price); + $product->setStock($this->stock); + $product->setActive($this->active ?? true); + + // La categoría se asigna en el Processor después de validarla + + return $product; + } +} +``` + +#### 8.4.2 Output DTO + +Crea `src/Dto/Output/ProductOutput.php`: + +```php +name = $product->getName(); + $this->description = $product->getDescription(); + $this->price = $product->getPrice(); + $this->stock = $product->getStock(); + $this->active = $product->isActive(); + $this->category = new CategoryOutput($product->getCategory()); + $this->createdAt = $product->getCreatedAt(); + $this->updatedAt = $product->getUpdatedAt(); + } +} +``` + +### 8.5 Paso 4: Configuración YAML de API Platform + +Crea `config/api_platform/Product.yaml`: + +```yaml +App\Entity\Product: + operations: + get: + provider: App\State\Provider\ProductProvider + output: App\Dto\Output\ProductOutput + getCollection: + provider: App\State\Provider\ProductProvider + output: App\Dto\Output\ProductOutput + filters: + - 'App\Filter\SearchFilter' + post: + input: App\Dto\Input\ProductInput + processor: App\State\Processor\ProductProcessor + output: App\Dto\Output\ProductOutput + security: "is_granted('ROLE_ADMIN')" + put: + input: App\Dto\Input\ProductInput + provider: App\State\Provider\ProductProvider + processor: App\State\Processor\ProductProcessor + output: App\Dto\Output\ProductOutput + security: "is_granted('ROLE_ADMIN')" + patch: + input: App\Dto\Input\ProductInput + provider: App\State\Provider\ProductProvider + processor: App\State\Processor\ProductProcessor + output: App\Dto\Output\ProductOutput + security: "is_granted('ROLE_ADMIN')" + delete: + processor: App\State\Processor\ProductProcessor + security: "is_granted('ROLE_ADMIN')" + + properties: + id: + identifier: true + name: + required: true + price: + required: true + stock: + required: true + active: + required: true + category: + required: true + description: + required: false + createdAt: + required: false + updatedAt: + required: false +``` + +### 8.6 Paso 5: Crear States (Provider y Processor) + +ogCore usa **un único Provider** y **un único Processor** por entidad que manejan todas las operaciones HTTP. + +#### 8.6.1 Provider + +Crea `src/State/Provider/ProductProvider.php`: + +```php +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Patch: + case $operation instanceof Put: + return $this->provideInput($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + /** + * Proporciona la colección de productos + */ + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $filters = $context['filters'] ?? []; + + // Usar el provider de API Platform para paginación automática + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + // Convertir entidades a DTOs + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $product) { + $items[] = new ProductOutput($product); + } + + return new TraversablePaginator( + $items, + $paginator->getCurrentPage(), + $paginator->getItemsPerPage(), + $paginator->getTotalItems() + ); + } + + /** + * Proporciona un producto individual + */ + private function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $product = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$product) { + throw new NotFoundHttpException('Producto no encontrado'); + } + + return new ProductOutput($product); + } + + /** + * Proporciona el Input DTO para PUT/PATCH + */ + private function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + if (isset($uriVariables['id'])) { + $product = $this->itemProvider->provide($operation, $uriVariables, $context); + + return $product !== null ? new ProductInput($product) : null; + } + + return new ProductInput(); + } +} +``` + +#### 8.6.2 Processor + +Crea `src/State/Processor/ProductProcessor.php`: + +```php +processCreateOrUpdate($data, $operation, $uriVariables, $context); + case $operation instanceof Delete: + return $this->processDelete($data, $operation, $uriVariables, $context); + } + } + + /** + * Procesa creación y actualización (POST, PUT, PATCH) + */ + private function processCreateOrUpdate( + mixed $data, + Operation $operation, + array $uriVariables = [], + array $context = [] + ): ProductOutput { + if (!($data instanceof ProductInput)) { + throw new \Exception(sprintf('Data is not instance of %s', ProductInput::class)); + } + + $product = null; + + // Si es actualización, obtener la entidad existente + if (isset($uriVariables['id'])) { + $product = $this->productRepository->find($uriVariables['id']); + } + + // Buscar categoría desde el Output DTO + $category = $data->category ? $data->category->getEntity() : null; + if (!$category) { + throw new BadRequestHttpException('Categoría no encontrada'); + } + + // Crear o actualizar usando método del Input DTO + $product = $data->createOrUpdateEntity($product); + $product->setCategory($category); + + // Validar la entidad + $this->validator->validate($product); + + // Guardar + $this->productRepository->save($product); + + return new ProductOutput($product); + } + + /** + * Procesa eliminación (DELETE) + */ + private function processDelete( + mixed $data, + Operation $operation, + array $uriVariables = [], + array $context = [] + ): null { + $product = $this->productRepository->find($uriVariables['id']); + + if (!$product) { + throw new BadRequestHttpException('Producto no encontrado'); + } + + $this->productRepository->delete($product); + + return null; + } +} +``` + +### 8.7 Paso 6: Crear Validadores Personalizados (Opcional) + +Si necesitas validaciones complejas, crea un validador. Ejemplo: `src/Validator/ProductStockValidator.php`: + +```php +context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $value) + ->addViolation(); + } + + // Validación adicional: stock máximo + if ($value > $constraint->maxStock) { + $this->context->buildViolation('El stock no puede exceder {{ limit }}') + ->setParameter('{{ limit }}', $constraint->maxStock) + ->addViolation(); + } + } +} +``` + +Y la constraint `src/Validator/ProductStock.php`: + +```php + + */ +final class ProductFactory extends ModelFactory +{ + protected function getDefaults(): array + { + return [ + 'name' => self::faker()->words(3, true), + 'description' => self::faker()->sentence(), + 'price' => self::faker()->randomFloat(2, 1, 1000), + 'stock' => self::faker()->numberBetween(0, 100), + 'active' => self::faker()->boolean(80), // 80% activos + 'category' => CategoryFactory::new(), + ]; + } + + protected static function getClass(): string + { + return Product::class; + } + + /** + * Estado: producto sin stock + */ + public function outOfStock(): self + { + return $this->addState(['stock' => 0]); + } + + /** + * Estado: producto inactivo + */ + public function inactive(): self + { + return $this->addState(['active' => false]); + } + + /** + * Estado: producto de lujo (precio alto) + */ + public function luxury(): self + { + return $this->addState([ + 'price' => self::faker()->randomFloat(2, 500, 5000) + ]); + } +} +``` + +### 8.9 Paso 8: Crear Migración + +Genera la migración automáticamente: + +```bash +docker exec ogcore-php php bin/console make:migration +``` + +Revisa y edita la migración generada en `migrations/`: + +```php +addSql('CREATE TABLE product ( + id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', + category_id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', + name VARCHAR(255) NOT NULL, + description VARCHAR(500) DEFAULT NULL, + price DOUBLE PRECISION NOT NULL, + stock INT NOT NULL, + active TINYINT(1) NOT NULL, + created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', + updated_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', + INDEX IDX_PRODUCT_CATEGORY (category_id), + INDEX IDX_PRODUCT_ACTIVE (active), + PRIMARY KEY(id) + ) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + + $this->addSql('ALTER TABLE product ADD CONSTRAINT FK_PRODUCT_CATEGORY + FOREIGN KEY (category_id) REFERENCES category (id) ON DELETE CASCADE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE product DROP FOREIGN KEY FK_PRODUCT_CATEGORY'); + $this->addSql('DROP TABLE product'); + } +} +``` + +Ejecuta la migración: + +```bash +docker exec ogcore-php php bin/console doctrine:migrations:migrate --no-interaction +``` + +### 8.10 Paso 9: Crear Tests + +Crea `tests/Functional/ProductTest.php`: + +```php +request('GET', '/products', [ + 'headers' => ['Accept' => 'application/json'] + ]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains(['hydra:totalItems' => 5]); + } + + public function testPostProduct(): void + { + $client = static::createClient(); + $category = CategoryFactory::createOne(); + + $client->request('POST', '/products', [ + 'json' => [ + 'name' => 'Producto Test', + 'description' => 'Descripción de prueba', + 'price' => 99.99, + 'stock' => 50, + 'active' => true, + 'categoryId' => $category->getId() + ], + 'headers' => ['Content-Type' => 'application/json'] + ]); + + $this->assertResponseStatusCodeSame(201); + $this->assertJsonContains([ + 'name' => 'Producto Test', + 'price' => 99.99 + ]); + } + + public function testPutProduct(): void + { + $client = static::createClient(); + $product = ProductFactory::createOne(); + $newCategory = CategoryFactory::createOne(); + + $client->request('PUT', '/products/' . $product->getId(), [ + 'json' => [ + 'name' => 'Producto Actualizado', + 'price' => 149.99, + 'stock' => 30, + 'categoryId' => $newCategory->getId() + ], + 'headers' => ['Content-Type' => 'application/json'] + ]); + + $this->assertResponseIsSuccessful(); + $this->assertJsonContains([ + 'name' => 'Producto Actualizado', + 'price' => 149.99 + ]); + } + + public function testDeleteProduct(): void + { + $client = static::createClient(); + $product = ProductFactory::createOne(); + + $client->request('DELETE', '/products/' . $product->getId()); + + $this->assertResponseStatusCodeSame(204); + } + + public function testValidation(): void + { + $client = static::createClient(); + + $client->request('POST', '/products', [ + 'json' => [ + 'name' => 'AB', // Muy corto + 'price' => -10, // Negativo + ], + 'headers' => ['Content-Type' => 'application/json'] + ]); + + $this->assertResponseStatusCodeSame(422); + } +} +``` + +### 8.11 Paso 10: Documentar en Swagger + +La configuración YAML de API Platform generará automáticamente la documentación en Swagger. Puedes añadir descripciones adicionales: + +```yaml +App\Entity\Product: + description: 'Entidad que representa un producto del catálogo' + operations: + get: + summary: 'Obtener un producto por ID' + description: 'Retorna la información detallada de un producto' + provider: App\State\Product\ProductProvider + output: App\Dto\Output\ProductOutput + getCollection: + summary: 'Obtener listado de productos' + description: 'Retorna una colección paginada de productos' + provider: App\State\Product\ProductCollectionProvider + output: App\Dto\Output\ProductOutput + # ... resto de operaciones +``` + +### 8.12 Checklist de Creación de Entidad + +Usa este checklist para asegurarte de no olvidar ningún paso: + +- [ ] **Entidad creada** en `src/Entity/` +- [ ] **Repository creado** en `src/Repository/` +- [ ] **Input DTO creado** en `src/Dto/Input/` con constructor y método `createOrUpdateEntity()` +- [ ] **Output DTO creado** en `src/Dto/Output/` con método estático `fromEntity()` +- [ ] **Configuración YAML** en `config/api_platform/` +- [ ] **Provider creado** en `src/State/Provider/` (un solo archivo que maneja Get y GetCollection) +- [ ] **Processor creado** en `src/State/Processor/` (un solo archivo que maneja Post, Put, Patch, Delete) +- [ ] **Validators** personalizados (si aplica) en `src/Validator/` +- [ ] **Factory** para testing en `src/Factory/` +- [ ] **Migración generada** con `make:migration` y ejecutada +- [ ] **Tests funcionales** creados en `tests/Functional/` +- [ ] **Documentación Swagger** verificada en `/docs` +- [ ] **Permisos de seguridad** configurados en YAML con `security: "is_granted('ROLE_X')"` + +### 8.13 Comandos Útiles + +```bash +# Generar entidad con maker +docker exec ogcore-php php bin/console make:entity Product + +# Generar migración +docker exec ogcore-php php bin/console make:migration + +# Ejecutar migración +docker exec ogcore-php php bin/console doctrine:migrations:migrate + +# Validar esquema +docker exec ogcore-php php bin/console doctrine:schema:validate + +# Ejecutar tests +docker exec ogcore-php php bin/phpunit tests/Functional/ProductTest.php + +# Ver rutas de API +docker exec ogcore-php php bin/console debug:router | grep product +``` + +### 8.14 Buenas Prácticas + +1. **Nomenclatura consistente**: Usa el mismo nombre base para entidad, DTOs, States y Factory +2. **Validaciones**: Siempre valida en el Input DTO y en el Processor si es necesario +3. **Seguridad**: Define permisos en la configuración YAML (`security: "is_granted('ROLE_ADMIN')"`) +4. **Tests**: Crea tests para todos los endpoints (GET, POST, PUT, DELETE) +5. **DTOs separados**: Nunca expongas la entidad directamente, siempre usa DTOs +6. **Transacciones**: Doctrine maneja transacciones automáticamente, pero para operaciones complejas considera usar `$entityManager->transactional()` +7. **Lazy loading**: Configura correctamente las relaciones (fetch LAZY/EAGER) +8. **Índices**: Añade índices en campos que se usan frecuentemente en WHERE/ORDER BY +9. **Soft Delete**: Si necesitas "borrado suave", usa `SoftDeleteableTrait` de Gedmo +10. **Eventos**: Usa EventSubscribers para lógica transversal (logging, notificaciones Mercure) + +--- + ## 9. API RESTful -### 9.1 Documentación +### 8.1 Documentación La API está completamente documentada con **OpenAPI 3.0** y accesible en: @@ -717,7 +1411,7 @@ La API está completamente documentada con **OpenAPI 3.0** y accesible en: http://127.0.0.1:8080/docs ``` -### 9.2 Formato de Respuestas +### 8.2 Formato de Respuestas #### Formato estándar (JSON-LD): @@ -746,7 +1440,7 @@ http://127.0.0.1:8080/docs } ``` -### 9.3 Paginación +### 8.3 Paginación Todas las colecciones soportan paginación: @@ -773,7 +1467,7 @@ Respuesta: } ``` -### 9.4 Filtrado +### 8.4 Filtrado Soporta filtros avanzados: @@ -783,14 +1477,14 @@ GET /clients?organizationalUnit.name=Aula1 GET /traces?client.id=123&status=pending ``` -### 9.5 Ordenamiento +### 8.5 Ordenamiento ``` GET /clients?order[name]=asc GET /traces?order[createdAt]=desc ``` -### 9.6 Endpoints Principales +### 8.6 Endpoints Principales #### 9.6.1 Autenticación @@ -848,7 +1542,7 @@ PATCH /traces/{id}/complete PATCH /traces/{id}/cancel ``` -### 9.7 Códigos de Estado HTTP +### 8.7 Códigos de Estado HTTP | Código | Significado | |--------|-------------| @@ -865,9 +1559,9 @@ PATCH /traces/{id}/cancel --- -## 10. Seguridad y Autenticación +## 9. Seguridad y Autenticación -### 10.1 Sistema de Autenticación JWT +### 9.1 Sistema de Autenticación JWT ogCore utiliza **JSON Web Tokens (JWT)** para autenticación: @@ -912,7 +1606,7 @@ Content-Type: application/json } ``` -### 10.2 Control de Acceso +### 9.2 Control de Acceso #### Rutas Públicas: - `/auth/login` @@ -925,7 +1619,7 @@ Content-Type: application/json #### Rutas Protegidas: - Todo lo demás requiere `IS_AUTHENTICATED_FULLY` -### 10.3 Roles de Usuario +### 9.3 Roles de Usuario Los roles se gestionan en la entidad `User`: @@ -934,17 +1628,17 @@ $user->setRoles(['ROLE_USER']); $user->setRoles(['ROLE_ADMIN']); ``` -### 10.4 Seguridad de Contraseñas +### 9.4 Seguridad de Contraseñas - Hashing con **bcrypt** automático - Validación de fortaleza - Cambio de contraseña seguro -### 10.5 CORS (Cross-Origin Resource Sharing) +### 9.5 CORS (Cross-Origin Resource Sharing) Configurado en `nelmio_cors.yaml` para permitir acceso desde frontend. -### 10.6 SSL/TLS +### 9.6 SSL/TLS Para producción, habilitar SSL: @@ -956,9 +1650,9 @@ Configurar certificados en `/certs/`. --- -## 11. Servicios Principales +## 10. Servicios Principales -### 11.1 CreatePartitionService +### 10.1 CreatePartitionService **Propósito**: Crear y actualizar particiones de clientes. @@ -968,7 +1662,7 @@ Configurar certificados en `/certs/`. - Detecta tipo de firmware (BIOS/UEFI) - Calcula códigos de partición -### 11.2 CreateTraceService +### 10.2 CreateTraceService **Propósito**: Crear trazas de ejecución para tareas programadas. @@ -977,7 +1671,7 @@ Configurar certificados en `/certs/`. - Gestiona comandos agrupados - Establece estado inicial y fecha de ejecución -### 11.3 ChangeClientNetworkSettingsService +### 10.3 ChangeClientNetworkSettingsService **Propósito**: Cambiar configuración de red de clientes. @@ -985,7 +1679,7 @@ Configurar certificados en `/certs/`. - Actualiza subnet, IP, configuración de red - Sincroniza con servicios externos (DHCP) -### 11.4 ExternalGitRepositoryService +### 10.4 ExternalGitRepositoryService **Propósito**: Gestión de repositorios Git para imágenes. @@ -994,7 +1688,7 @@ Configurar certificados en `/certs/`. - Versionado de imágenes - Sincronización con repositorios remotos -### 11.5 StatusService (OgBoot/OgDhcp/OgRepository) +### 10.5 StatusService (OgBoot/OgDhcp/OgRepository) **Propósito**: Verificar estado de servicios externos. @@ -1003,7 +1697,7 @@ Configurar certificados en `/certs/`. - Manejo de errores de conexión - Logging de estado -### 11.6 UDSClient +### 10.6 UDSClient **Propósito**: Integración con UDS (Universal Desktop Services). @@ -1013,7 +1707,7 @@ Configurar certificados en `/certs/`. - Cálculo de asientos disponibles - Gestión de calendarios remotos -### 11.7 Trace/CreateService +### 10.7 Trace/CreateService **Propósito**: Servicio especializado para creación de trazas. @@ -1021,25 +1715,25 @@ Configurar certificados en `/certs/`. - Validación de parámetros de entrada - Creación de trazas individuales o masivas -### 11.8 Utils/GetPartitionCodeService +### 10.8 Utils/GetPartitionCodeService **Propósito**: Obtener código de partición según tipo y filesystem. -### 11.9 Utils/SimplifyOgLiveFilenameService +### 10.9 Utils/SimplifyOgLiveFilenameService **Propósito**: Simplificar nombres de archivos OgLive para mostrar al usuario. -### 11.10 Utils/GetIpAddressAndNetmaskFromCIDRService +### 10.10 Utils/GetIpAddressAndNetmaskFromCIDRService **Propósito**: Convertir notación CIDR a IP y máscara de red. --- -## 12. Comandos de Consola +## 11. Comandos de Consola ogCore incluye **18 comandos de consola** para tareas administrativas: -### 12.1 Comandos de Inicialización +### 11.1 Comandos de Inicialización #### 12.1.1 Cargar Grupos de Usuario por Defecto @@ -1089,7 +1783,7 @@ php bin/console app:load-organizational-unit-default Crea la unidad organizativa raíz. -### 12.2 Comandos de Operación +### 11.2 Comandos de Operación #### 12.2.1 Verificar Disponibilidad de Clientes @@ -1121,7 +1815,7 @@ php bin/console app:run-scheduled-command-tasks Ejecuta tareas programadas que han llegado a su hora de ejecución. -### 12.3 Comandos de Migración +### 11.3 Comandos de Migración Comandos para migrar datos desde OpenGnsys 1.1: @@ -1167,7 +1861,7 @@ php bin/console opengnsys:migration:software-profile php bin/console opengnsys:migration:partition-client ``` -### 12.4 Comandos de Desarrollo +### 11.4 Comandos de Desarrollo #### 12.4.1 Crear Repositorios de Imágenes @@ -1185,7 +1879,7 @@ php bin/console app:charge-example-trace Carga trazas de ejemplo para testing. -### 12.5 Configuración de Cron +### 11.5 Configuración de Cron Agregar al crontab: @@ -1197,9 +1891,9 @@ Agregar al crontab: --- -## 13. Migraciones de Datos +## 12. Migraciones de Datos -### 13.1 Sistema de Migraciones de Doctrine +### 12.1 Sistema de Migraciones de Doctrine ogCore utiliza Doctrine Migrations para gestionar cambios en el esquema de base de datos. @@ -1227,7 +1921,7 @@ docker exec ogcore-php php bin/console doctrine:migrations:status docker exec ogcore-php php bin/console doctrine:migrations:migrate prev ``` -### 13.2 Migración desde OpenGnsys 1.1 +### 12.2 Migración desde OpenGnsys 1.1 Para migrar datos desde una instalación de OpenGnsys 1.1: @@ -1256,7 +1950,7 @@ docker exec ogcore-php php bin/console opengnsys:migration:image docker exec ogcore-php php bin/console opengnsys:migration:software-profile ``` -### 13.3 Backup y Restauración +### 12.3 Backup y Restauración #### 13.3.1 Backup de Base de Datos @@ -1272,13 +1966,13 @@ docker exec -i ogcore-database mysql -u user -p ogcore < backup_20251008.sql --- -## 14. Testing +## 13. Testing -### 14.1 Framework de Testing +### 13.1 Framework de Testing ogCore utiliza **PHPUnit** con integración de Symfony y Doctrine. -### 14.2 Ejecutar Tests +### 13.2 Ejecutar Tests #### 14.2.1 Todos los Tests @@ -1298,7 +1992,7 @@ docker compose exec php bin/phpunit tests/Functional/ClientTest.php docker compose exec php bin/phpunit --coverage-html coverage/ ``` -### 14.3 Tipos de Tests +### 13.3 Tipos de Tests #### 14.3.1 Tests Funcionales @@ -1327,7 +2021,7 @@ public function testCreateClient(): void } ``` -### 14.4 Factories para Testing +### 13.4 Factories para Testing Se utilizan **Zenstruck Foundry** factories (24 factories) para crear datos de prueba: @@ -1338,7 +2032,7 @@ ClientFactory::createOne([ ]); ``` -### 14.5 Base de Datos de Testing +### 13.5 Base de Datos de Testing Los tests utilizan **DAMA Doctrine Test Bundle** para: - Ejecutar cada test en una transacción @@ -1347,9 +2041,9 @@ Los tests utilizan **DAMA Doctrine Test Bundle** para: --- -## 15. Despliegue +## 14. Despliegue -### 15.1 Despliegue con Docker Compose +### 14.1 Despliegue con Docker Compose #### 15.1.1 Desarrollo @@ -1363,7 +2057,7 @@ docker compose up -d docker compose -f docker-compose-deploy.yml up -d ``` -### 15.2 Despliegue con Jenkins +### 14.2 Despliegue con Jenkins El proyecto incluye **Jenkinsfile** para CI/CD. @@ -1374,7 +2068,7 @@ El proyecto incluye **Jenkinsfile** para CI/CD. 4. **Package**: Crear paquete Debian 5. **Deploy**: Desplegar en servidor -### 15.3 Paquete Debian +### 14.3 Paquete Debian El proyecto puede empaquetarse como `.deb`: @@ -1388,7 +2082,7 @@ Estructura del paquete en `debian/`: - Systemd service file - Configuración -### 15.4 Configuración de Producción +### 14.4 Configuración de Producción #### 15.4.1 Variables de Entorno @@ -1414,7 +2108,7 @@ docker exec ogcore-php php bin/console cache:warmup --env=prod docker exec ogcore-php composer dump-autoload --optimize --classmap-authoritative ``` -### 15.5 Monitoreo +### 14.5 Monitoreo #### 15.5.1 Logs @@ -1427,7 +2121,7 @@ Logs ubicados en `var/log/`: Los logs también se envían a syslog para centralización. -### 15.6 Escalabilidad +### 14.6 Escalabilidad Para escalar horizontalmente: @@ -1439,9 +2133,9 @@ Para escalar horizontalmente: --- -## 16. Mantenimiento y Operaciones +## 15. Mantenimiento y Operaciones -### 16.1 Reiniciar Base de Datos +### 15.1 Reiniciar Base de Datos ```bash docker exec ogcore-php php bin/console doctrine:database:drop --force @@ -1450,26 +2144,26 @@ docker exec ogcore-php php bin/console doctrine:migrations:migrate --no-interact docker exec ogcore-php php bin/console doctrine:fixtures:load --no-interaction ``` -### 16.2 Limpiar Caché +### 15.2 Limpiar Caché ```bash docker exec ogcore-php php bin/console cache:clear docker exec ogcore-php php bin/console cache:warmup ``` -### 16.3 Actualizar Dependencias +### 15.3 Actualizar Dependencias ```bash docker exec ogcore-php composer update ``` -### 16.4 Regenerar Claves JWT +### 15.4 Regenerar Claves JWT ```bash docker exec ogcore-php php bin/console lexik:jwt:generate-keypair --overwrite ``` -### 16.5 Backups Automáticos +### 15.5 Backups Automáticos Script ejemplo para backup automático: @@ -1489,7 +2183,7 @@ find $BACKUP_DIR -name "*.sql" -mtime +30 -delete find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete ``` -### 16.6 Monitoreo de Salud +### 15.6 Monitoreo de Salud #### Health Check Endpoint @@ -1510,7 +2204,7 @@ docker exec ogcore-nginx nginx -t docker exec ogcore-database mysqladmin -u user -p status ``` -### 16.7 Rotación de Logs +### 15.7 Rotación de Logs Configurar logrotate: @@ -1528,9 +2222,9 @@ Configurar logrotate: --- -## 17. Integración con Otros Servicios +## 16. Integración con Otros Servicios -### 17.1 ogRepository +### 16.1 ogRepository **Propósito**: Gestión de repositorios de imágenes. @@ -1546,7 +2240,7 @@ Configurar logrotate: **Webhook**: `/og-repository/webhook` -### 17.2 ogDhcp +### 16.2 ogDhcp **Propósito**: Gestión de DHCP dinámico. @@ -1556,7 +2250,7 @@ Configurar logrotate: - Actualizar configuración - Gestión de subredes -### 17.3 ogBoot +### 16.3 ogBoot **Propósito**: Gestión de archivos de arranque PXE. @@ -1566,7 +2260,7 @@ Configurar logrotate: - Eliminar configuraciones - Sincronización de menús -### 17.4 ogAgent +### 16.4 ogAgent **Propósito**: Agente instalado en clientes para ejecutar comandos. @@ -1579,7 +2273,7 @@ Configurar logrotate: - Verificar tamaño de particiones - Kill jobs -### 17.5 UDS (Universal Desktop Services) +### 16.5 UDS (Universal Desktop Services) **Propósito**: Integración con sistema de escritorios remotos. @@ -1589,7 +2283,7 @@ Configurar logrotate: - Calcular disponibilidad - Gestión de reservas -### 17.6 Git (Versionado de Imágenes) +### 16.6 Git (Versionado de Imágenes) **Propósito**: Versionado de imágenes con Git. @@ -1599,7 +2293,7 @@ Configurar logrotate: - Recuperación de versiones - Sincronización -### 17.7 Mercure (Notificaciones en Tiempo Real) +### 16.7 Mercure (Notificaciones en Tiempo Real) **Propósito**: Notificaciones push en tiempo real. @@ -1621,11 +2315,11 @@ eventSource.onmessage = event => { --- -## 18. Roadmap y Changelog +## 17. Roadmap y Changelog -### 18.1 Versión Actual: 0.5.0 +### 17.1 Versión Actual: 0.5.0 -### 18.2 Últimas Características (v0.25.1 - Octubre 2025) +### 17.2 Últimas Características (v0.25.1 - Octubre 2025) - **Tareas programadas**: Sistema completo de colas y scheduling - **Inventario hardware**: Obtención automática de inventario @@ -1640,7 +2334,7 @@ eventSource.onmessage = event => { - **Mercure**: Notificaciones en tiempo real - **Despliegue multicast**: Modos torrent y UDPCAST -### 18.3 Próximas Características (Roadmap) +### 17.3 Próximas Características (Roadmap) #### v0.6.0 (Q4 2025) - [ ] Dashboard de administración mejorado @@ -1660,7 +2354,7 @@ eventSource.onmessage = event => { - [ ] Guías de migración finalizadas - [ ] Certificación de seguridad -### 18.4 Changelog Resumido +### 17.4 Changelog Resumido Ver `CHANGELOG.md` para el historial completo de cambios. @@ -1683,9 +2377,9 @@ Ver `CHANGELOG.md` para el historial completo de cambios. --- -## 19. Contribución +## 18. Contribución -### 19.1 Guía de Contribución +### 18.1 Guía de Contribución Para contribuir al proyecto: @@ -1695,7 +2389,7 @@ Para contribuir al proyecto: 4. **Push** a la rama: `git push origin feature/nueva-funcionalidad` 5. Crea un **Pull Request** -### 19.2 Estándares de Código +### 18.2 Estándares de Código - Seguir **PSR-12** para PHP - Usar **Type Hints** en PHP 8.3 @@ -1703,7 +2397,7 @@ Para contribuir al proyecto: - Tests para nuevas funcionalidades - Commits descriptivos en español -### 19.3 Proceso de Revisión +### 18.3 Proceso de Revisión 1. CI/CD ejecuta tests automáticamente 2. Revisión de código por maintainers @@ -1711,7 +2405,7 @@ Para contribuir al proyecto: 4. Merge a rama develop 5. Release periódicos a main -### 19.4 Reportar Bugs +### 18.4 Reportar Bugs Usar el sistema de Issues del repositorio: @@ -1739,25 +2433,25 @@ Si aplica, añadir screenshots. --- -## 20. Soporte y Contacto +## 19. Soporte y Contacto -### 20.1 Documentación Adicional +### 19.1 Documentación Adicional - **API Docs**: http://localhost:8080/docs - **Postman Collection**: `swagger-assets/ogCore.postman_collection.zip` - **Diagramas**: `swagger-assets/img_bbdd.png` -### 20.2 Recursos +### 19.2 Recursos - **Repositorio**: [URL del repositorio] - **Wiki**: [URL de la wiki] - **Issues**: [URL de issues] -### 20.3 Equipo de Desarrollo +### 19.3 Equipo de Desarrollo Proyecto desarrollado por el equipo de OpenGnsys en colaboración con universidades participantes. -### 20.4 Licencia +### 19.4 Licencia Proyecto propietario. Ver archivo `LICENSE` para más información. diff --git a/migrations/Version20251015080216.php b/migrations/Version20251015080216.php new file mode 100644 index 0000000..8592658 --- /dev/null +++ b/migrations/Version20251015080216.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE client ADD resolution 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 resolution'); + } +} diff --git a/ogCore_Documentacion_Tecnica.html b/ogCore_Documentacion_Tecnica.html index 6ccf54d..5c7c6b4 100644 --- a/ogCore_Documentacion_Tecnica.html +++ b/ogCore_Documentacion_Tecnica.html @@ -177,10 +177,10 @@ class="toc-section-number">1.6.3 5.3 Puertos Requeridos id="toc-instalación-y-configuración">1.7 6. Instalación y Configuración -
  • 1.8 7. Modelo de Datos -
  • 1.9 8. Componentes del Sistema +class="toc-section-number">1.8 7. Componentes del Sistema
  • 1.10 9. API RESTful +class="toc-section-number">1.9 8. API RESTful
  • 1.11 10. Seguridad y Autenticación +class="toc-section-number">1.10 9. Seguridad y Autenticación
  • 1.12 11. Servicios Principales +class="toc-section-number">1.11 10. Servicios Principales
  • 1.13 12. Comandos de Consola +class="toc-section-number">1.12 11. Comandos de Consola
  • 1.14 13. Migraciones de Datos +class="toc-section-number">1.13 12. Migraciones de Datos
  • 1.15 14. Testing +class="toc-section-number">1.14 13. Testing
  • 1.16 15. Despliegue +class="toc-section-number">1.15 14. Despliegue
  • 1.17 16. Mantenimiento y +class="toc-section-number">1.16 15. Mantenimiento y Operaciones
  • 1.18 17. Integración con Otros +class="toc-section-number">1.17 16. Integración con Otros Servicios
  • 1.19 18. Roadmap y Changelog +class="toc-section-number">1.18 17. Roadmap y Changelog
  • 1.20 19. Contribución +class="toc-section-number">1.19 18. Contribución
  • 1.21 20. Soporte y Contacto +class="toc-section-number">1.20 19. Soporte y Contacto
  • 1.22 Apéndices +class="toc-section-number">1.21 Apéndices
  • @@ -541,24 +525,23 @@ Sistema
  • Requisitos del Sistema
  • Instalación y Configuración
  • -
  • Modelo de Datos
  • -
  • Componentes del +
  • Componentes del Sistema
  • -
  • API RESTful
  • -
  • Seguridad y +
  • API RESTful
  • +
  • Seguridad y Autenticación
  • -
  • Servicios Principales
  • -
  • Comandos de Consola
  • -
  • Migraciones de Datos
  • -
  • Testing
  • -
  • Despliegue
  • -
  • Mantenimiento y +
  • Servicios Principales
  • +
  • Comandos de Consola
  • +
  • Migraciones de Datos
  • +
  • Testing
  • +
  • Despliegue
  • +
  • Mantenimiento y Operaciones
  • -
  • Integración con Otros +
  • Integración con Otros Servicios
  • -
  • Roadmap y Changelog
  • -
  • Contribución
  • -
  • Soporte y Contacto
  • +
  • Roadmap y Changelog
  • +
  • Contribución
  • +
  • Soporte y Contacto

  • Sistema de colas para la ejecución de tareas programadas
  • Integración con múltiples servicios externos
  • -
  • Migraciones automatizadas desde OpenGnsys 1.1
  • -
  • Versionado de imágenes con integración Git
  • +
  • Creación de imágenes con integración Git y sistema +monolítico
  • Sistema de trazabilidad completo
  • Gestión de hardware con inventario automático
  • Despliegues masivos de imágenes (unicast, @@ -629,7 +612,7 @@ multicast, torrent, p2p)
  • 1.3.3 2.3 Versión Actual

    @@ -641,35 +624,35 @@ Sistema

    class="header-section-number">1.4.1 3.1 Arquitectura General

    ogCore sigue una arquitectura de microservicios basada en el patrón API-First:

    -
    ┌─────────────────────────────────────────────────────────────┐
    -│                      Frontend (Web UI)                       │
    -└────────────────────────┬────────────────────────────────────┘
    -                         │
    -                         │ HTTP/REST
    -                         │
    -┌────────────────────────▼────────────────────────────────────┐
    -│                     ogCore API (Symfony)                     │
    -│  ┌──────────────────────────────────────────────────────┐   │
    -│  │  Controllers │ States │ DTOs │ Validators │ Filters  │   │
    -│  └──────────────────────────────────────────────────────┘   │
    -│  ┌──────────────────────────────────────────────────────┐   │
    -│  │              Business Logic (Services)                │   │
    -│  └──────────────────────────────────────────────────────┘   │
    -│  ┌──────────────────────────────────────────────────────┐   │
    -│  │        Entities │ Repositories │ Doctrine ORM         │   │
    -│  └──────────────────────────────────────────────────────┘   │
    -└────────────────────┬───────────────┬───────────────────────┘
    -                     │               │
    -         ┌───────────▼──┐    ┌──────▼──────┐
    -         │   MariaDB    │    │   Mercure   │
    -         │   Database   │    │  (WebSocket)│
    -         └──────────────┘    └─────────────┘
    +
    +-------------------------------------------------------------+
    +|                      Frontend (Web UI)                      |
    ++---------------------------+----------------------------------+
    +                            |
    +                            | HTTP/REST
    +                            |
    ++---------------------------v---------------------------------+
    +|                     ogCore API (Symfony)                    |
    +|  +------------------------------------------------------+   |
    +|  |  Controllers | States | DTOs | Validators | Filters  |   |
    +|  +------------------------------------------------------+   |
    +|  +------------------------------------------------------+   |
    +|  |              Business Logic (Services)               |   |
    +|  +------------------------------------------------------+   |
    +|  +------------------------------------------------------+   |
    +|  |        Entities | Repositories | Doctrine ORM        |   |
    +|  +------------------------------------------------------+   |
    ++---------------------------+----------------+----------------+
    +                            |                |
    +         +------------------v--+    +--------v--------+
    +         |   MariaDB           |    |   Mercure       |
    +         |   Database          |    |  (WebSocket)    |
    +         +---------------------+    +-----------------+
     
    -┌─────────────────────────────────────────────────────────────┐
    -│              Servicios Externos Integrados                   │
    -├──────────────┬──────────────┬──────────────┬────────────────┤
    -│  ogRepository│   ogDhcp     │   ogBoot     │   UDS/Git      │
    -└──────────────┴──────────────┴──────────────┴────────────────┘
    ++-------------------------------------------------------------+ +| Servicios Externos Integrados | ++--------------+--------------+--------------+----------------+ +| ogRepository | ogDhcp | ogBoot | UDS/Git | ++--------------+--------------+--------------+----------------+

    1.4.2 3.2 Capas de la Aplicación

    @@ -989,9 +972,9 @@ class="header-section-number">1.6.3 5.3 Puertos Requeridos

    1.7 6. Instalación y Configuración

    -

    1.7.1 6.1 Instalación con Docker -(Recomendado)

    +

    1.7.1 6.1 Instalación con +Docker

    1.7.1.1 6.1.1 Clonar el Repositorio

    @@ -1103,209 +1086,15 @@ Configurar SSL/TLS - Configurar backups automáticos de base de datos - Configurar monitoreo y alertas - Revisar los límites de recursos de Docker


    -

    1.8 7. Modelo de Datos

    -

    1.8.1 7.1 Diagrama de -Entidades

    -

    El sistema cuenta con 35 entidades principales agrupadas en los -siguientes dominios:

    -

    1.8.2 7.2 Entidades -Principales

    -

    1.8.2.1 7.2.1 Client (Cliente)

    -

    Representa un equipo físico en el sistema.

    -

    Campos principales: - id: UUID único - -name: Nombre del cliente - serialNumber: -Número de serie - mac: Dirección MAC (única) - -ip: Dirección IP (única) - status: Estado del -cliente (active, inactive, busy, windows, linux, etc.) - -netiface: Interfaz de red - netDriver: Driver -de red - validation: Estado de validación - -maintenance: Modo mantenimiento - position: -Posición en el aula (x, y) - firmwareType: Tipo de firmware -(BIOS/UEFI) - agentJobId: ID del trabajo del agente en -ejecución - pxeSync: Sincronización PXE - -token: Token de autenticación del cliente

    -

    Relaciones: - organizationalUnit: -Pertenece a una unidad organizativa (aula/grupo) - -partitions: Tiene múltiples particiones - -menu: Menú de arranque asignado - -hardwareProfile: Perfil de hardware asociado - -template: Plantilla PXE asignada - repository: -Repositorio de imágenes - subnet: Subred a la que pertenece -- ogLive: Imagen Live asignada

    -

    1.8.2.2 7.2.2 OrganizationalUnit -(Unidad Organizativa)

    -

    Representa aulas o grupos de equipos.

    -

    Campos principales: - id: UUID único - -name: Nombre de la unidad - description: -Descripción - type: Tipo (aula, grupo, etc.)

    -

    Relaciones: - parent: Unidad -organizativa padre (jerarquía) - children: Unidades hijas - -clients: Clientes pertenecientes - -networkSettings: Configuración de red heredable - -remoteCalendar: Calendario remoto asociado

    -

    1.8.2.3 7.2.3 Image (Imagen)

    -

    Representa una imagen de sistema operativo.

    -

    Campos principales: - id: UUID único - -name: Nombre de la imagen - description: -Descripción - type: Tipo de imagen - size: -Tamaño en bytes - partition: Partición de origen - -status: Estado (creating, success, failed, etc.) - -isGlobal: Imagen global compartida - -isVirtual: Imagen virtual - version: Versión -de la imagen

    -

    Relaciones: - operativeSystem: Sistema -operativo - softwareProfile: Perfil de software - -repositories: Repositorios que contienen la imagen - -originClient: Cliente origen de la imagen

    -

    1.8.2.4 7.2.4 Command -(Comando)

    -

    Comandos ejecutables en el sistema.

    -

    Campos principales: - id: UUID único - -name: Nombre del comando - description: -Descripción - script: Script a ejecutar

    -

    Relaciones: - commandGroups: Grupos de -comandos a los que pertenece

    -

    1.8.2.5 7.2.5 CommandTask (Tarea de -Comando)

    -

    Tarea programada para ejecutar comandos.

    -

    Campos principales: - id: UUID único - -datetime: Fecha y hora de ejecución - -parameters: Parámetros de ejecución - status: -Estado de la tarea

    -

    Relaciones: - commands: Comandos a -ejecutar - commandGroups: Grupos de comandos - -clients: Clientes objetivo - schedule: -Programación recurrente

    -

    1.8.2.6 7.2.6 Trace (Traza)

    -

    Registro de ejecución de comandos.

    -

    Campos principales: - id: UUID único - -command: Nombre del comando ejecutado - input: -Parámetros de entrada - output: Resultado de ejecución - -status: Estado (pending, processing, success, failed, -cancelled) - executedAt: Fecha de ejecución - -finishedAt: Fecha de finalización - cancelled: -Indica si fue cancelada - jobId: ID del trabajo en el -agente

    -

    Relaciones: - client: Cliente donde se -ejecutó

    -

    1.8.2.7 7.2.7 HardwareProfile -(Perfil de Hardware)

    -

    Inventario de hardware de un cliente.

    -

    Campos principales: - id: UUID único - -cpu: Información de CPU - ram: Memoria RAM - -storage: Almacenamiento - networkCards: -Tarjetas de red

    -

    Relaciones: - client: Cliente asociado -- hardwareTypes: Tipos de hardware detectados

    -

    1.8.2.8 7.2.8 SoftwareProfile -(Perfil de Software)

    -

    Software instalado en una imagen.

    -

    Campos principales: - id: UUID único - -name: Nombre del perfil

    -

    Relaciones: - software: Software -incluido - images: Imágenes que usan este perfil

    -

    1.8.2.9 7.2.9 ImageRepository -(Repositorio de Imágenes)

    -

    Servidor de almacenamiento de imágenes.

    -

    Campos principales: - id: UUID único - -name: Nombre del repositorio (único) - ip: -Dirección IP o DNS (único) - port: Puerto - -sshPort: Puerto SSH - sshUser: Usuario SSH - -apiKey: Clave API - status: Estado del -repositorio

    -

    Relaciones: - images: Imágenes -almacenadas

    -

    1.8.2.10 7.2.10 Subnet -(Subred)

    -

    Configuración de red.

    -

    Campos principales: - id: UUID único - -name: Nombre de la subred - cidr: Notación -CIDR - gateway: Puerta de enlace - dns: -Servidores DNS - dhcpStart: Inicio rango DHCP - -dhcpEnd: Fin rango DHCP

    -

    Relaciones: - clients: Clientes en la -subred

    -

    1.8.2.11 7.2.11 Partition -(Partición)

    -

    Partición de disco de un cliente.

    -

    Campos principales: - id: UUID único - -partitionNumber: Número de partición - -partitionType: Tipo de partición - -partitionSize: Tamaño - partitionCode: Código -de partición - usedSize: Tamaño usado - -filesystem: Sistema de archivos

    -

    Relaciones: - client: Cliente -propietario - image: Imagen desplegada - -operativeSystem: Sistema operativo instalado

    -

    1.8.2.12 7.2.12 PxeTemplate -(Plantilla PXE)

    -

    Plantilla de arranque PXE.

    -

    Campos principales: - id: UUID único - -name: Nombre de la plantilla - content: -Contenido de la plantilla - default: Plantilla por -defecto

    -

    Relaciones: - clients: Clientes que -usan la plantilla

    -

    1.8.2.13 7.2.13 RemoteCalendar -(Calendario Remoto)

    -

    Integración con sistemas de reservas remotas.

    -

    Campos principales: - id: UUID único - -name: Nombre del calendario - url: URL del -servicio - available: Disponibilidad

    -

    Relaciones: - organizationalUnits: -Unidades organizativas asociadas - rules: Reglas del -calendario

    -

    1.8.2.14 7.2.14 User (Usuario)

    -

    Usuario del sistema.

    -

    Campos principales: - id: UUID único - -username: Nombre de usuario (único) - -password: Contraseña (hasheada) - email: -Correo electrónico - roles: Roles del usuario

    -

    Relaciones: - userGroups: Grupos de -usuarios - view: Vista preferida

    -

    1.8.2.15 7.2.15 GitRepository -(Repositorio Git)

    -

    Repositorio Git para versionado de imágenes.

    -

    Campos principales: - id: UUID único - -name: Nombre del repositorio - url: URL del -repositorio - branch: Rama - credentials: -Credenciales de acceso

    -

    1.8.3 7.3 Índices y -Optimizaciones

    -

    La base de datos está optimizada con índices en: - Campos de búsqueda -frecuente (status, updatedAt) - Campos únicos (IP, MAC, username) - -Claves foráneas - Índices compuestos para consultas complejas

    -
    -

    1.9 8. Componentes del Sistema

    -

    1.9.1 8.1 Controllers +

    1.8 7. Componentes del Sistema

    +

    1.8.1 7.1 Controllers (Controladores)

    El sistema cuenta con 102 controladores organizados por dominio:

    -

    1.9.1.1 Controladores +

    1.8.1.1 Controladores principales:

    -

    1.9.2 8.2 States (Procesadores de +

    1.8.2 7.2 States (Procesadores de Estado)

    Los States implementan el patrón State de API Platform:

    -

    1.9.2.1 States principales (55 +

    1.8.2.1 States principales (55 procesadores):

    -

    1.9.3 8.3 DTOs (Data Transfer +

    1.8.3 7.3 DTOs (Data Transfer Objects)

    93 DTOs para transferencia de datos:

    -

    1.9.3.1 Tipos de DTOs:

    +

    1.8.3.1 Tipos de DTOs:

    -

    1.9.4 8.4 Validators +

    1.8.4 7.4 Validators (Validadores)

    18 validadores personalizados para: - Validación de IPs y MACs - Validación de rangos DHCP - Validación de particiones - Validación de imágenes - Validación de comandos - Validación de usuarios

    -

    1.9.5 8.5 EventSubscribers +class="header-section-number">1.8.5 7.5 EventSubscribers (Suscriptores de Eventos)

    8 suscriptores para: - Publicación en Mercure al cambiar estados - Limpieza de recursos - Validaciones pre/post persistencia - Logging de eventos

    -

    1.9.6 8.6 Factories (Fábricas)

    +

    1.8.6 7.6 Factories (Fábricas)

    24 factories para testing con Foundry: - Creación de entidades para tests - Datos de prueba realistas - Estados predefinidos


    -

    1.10 9. API RESTful

    -

    1.10.1 9.1 Documentación

    +

    1.9 8. API RESTful

    +

    1.9.1 8.1 Documentación

    La API está completamente documentada con OpenAPI 3.0 y accesible en:

    http://127.0.0.1:8080/docs
    -

    1.10.2 9.2 Formato de +

    1.9.2 8.2 Formato de Respuestas

    -

    1.10.2.1 Formato estándar +

    1.9.2.1 Formato estándar (JSON-LD):

    {
    @@ -1385,8 +1174,8 @@ class="sourceCode json">  "ip": "192.168.1.100",
       "status": "active"
     }
    -

    1.10.2.2 Formato alternativo +

    1.9.2.2 Formato alternativo (JSON):

    {
    @@ -1396,8 +1185,8 @@ class="sourceCode json">  "ip": "192.168.1.100",
       "status": "active"
     }
    -

    1.10.3 9.3 Paginación

    +

    1.9.3 8.3 Paginación

    Todas las colecciones soportan paginación:

    GET /clients?page=1&itemsPerPage=30

    Respuesta:

    @@ -1416,25 +1205,25 @@ class="sourceCode json"> "hydra:next": "/clients?page=2" } } -

    1.10.4 9.4 Filtrado

    +

    1.9.4 8.4 Filtrado

    Soporta filtros avanzados:

    GET /clients?status=active
     GET /clients?organizationalUnit.name=Aula1
     GET /traces?client.id=123&status=pending
    -

    1.10.5 9.5 Ordenamiento

    +

    1.9.5 8.5 Ordenamiento

    GET /clients?order[name]=asc
     GET /traces?order[createdAt]=desc
    -

    1.10.6 9.6 Endpoints +

    1.9.6 8.6 Endpoints Principales

    -

    1.10.6.1 9.6.1 Autenticación

    +

    1.9.6.1 9.6.1 Autenticación

    POST /auth/login
     POST /auth/refresh
    -

    1.10.6.2 9.6.2 Clientes

    +

    1.9.6.2 9.6.2 Clientes

    GET    /clients
     POST   /clients
     GET    /clients/{id}
    @@ -1445,8 +1234,8 @@ POST   /clients/batch
     POST   /clients/{id}/power-on
     POST   /clients/{id}/power-off
     POST   /clients/{id}/reboot
    -

    1.10.6.3 9.6.3 Imágenes

    +

    1.9.6.3 9.6.3 Imágenes

    GET    /images
     POST   /images
     GET    /images/{id}
    @@ -1455,8 +1244,8 @@ DELETE /images/{id}
     POST   /images/{id}/deploy
     POST   /images/{id}/create
     POST   /images/{id}/backup
    -

    1.10.6.4 9.6.4 Comandos y +

    1.9.6.4 9.6.4 Comandos y Tareas

    GET    /commands
     POST   /commands
    @@ -1464,15 +1253,15 @@ GET    /command-tasks
     POST   /command-tasks
     PUT    /command-tasks/{id}
     DELETE /command-tasks/{id}
    -

    1.10.6.5 9.6.5 Trazas

    +

    1.9.6.5 9.6.5 Trazas

    GET    /traces
     GET    /traces/{id}
     PUT    /traces/{id}
     PATCH  /traces/{id}/complete
     PATCH  /traces/{id}/cancel
    -

    1.10.7 9.7 Códigos de Estado +

    1.9.7 8.7 Códigos de Estado HTTP

    @@ -1525,16 +1314,16 @@ HTTP

    -

    1.11 10. Seguridad y +

    1.10 9. Seguridad y Autenticación

    -

    1.11.1 10.1 Sistema de -Autenticación JWT

    +

    1.10.1 9.1 Sistema de Autenticación +JWT

    ogCore utiliza JSON Web Tokens (JWT) para autenticación:

    -

    1.11.1.1 10.1.1 Obtener Token

    +

    1.10.1.1 10.1.1 Obtener Token

    POST /auth/login
     Content-Type: application/json
    @@ -1549,14 +1338,14 @@ class="sourceCode json">  "token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
       "refresh_token": "def50200a54b7b..."
     }
    -

    1.11.1.2 10.1.2 Usar Token

    +

    1.10.1.2 10.1.2 Usar Token

    Incluir el token en el header Authorization:

    GET /clients
     Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
    -

    1.11.1.3 10.1.3 Refresh Token

    +

    1.10.1.3 10.1.3 Refresh Token

    POST /auth/refresh
     Content-Type: application/json
    @@ -1564,10 +1353,10 @@ class="sourceCode bash">{
       "refresh_token": "def50200a54b7b..."
     }
    -

    1.11.2 10.2 Control de Acceso

    -

    1.11.2.1 Rutas Públicas:

    +

    1.10.2 9.2 Control de Acceso

    +

    1.10.2.1 Rutas Públicas:

    • /auth/login
    • /auth/refresh
    • @@ -1576,236 +1365,236 @@ class="header-section-number">1.11.2.1 Rutas Públicas:
    • /og-repository/webhook
    • /menu-browser
    -

    1.11.2.2 Rutas Protegidas:

    +

    1.10.2.2 Rutas Protegidas:

    • Todo lo demás requiere IS_AUTHENTICATED_FULLY
    -

    1.11.3 10.3 Roles de Usuario

    +

    1.10.3 9.3 Roles de Usuario

    Los roles se gestionan en la entidad User:

    $user->setRoles(['ROLE_USER']);
     $user->setRoles(['ROLE_ADMIN']);
    -

    1.11.4 10.4 Seguridad de +

    1.10.4 9.4 Seguridad de Contraseñas

    • Hashing con bcrypt automático
    • Validación de fortaleza
    • Cambio de contraseña seguro
    -

    1.11.5 10.5 CORS (Cross-Origin +

    1.10.5 9.5 CORS (Cross-Origin Resource Sharing)

    Configurado en nelmio_cors.yaml para permitir acceso desde frontend.

    -

    1.11.6 10.6 SSL/TLS

    +

    1.10.6 9.6 SSL/TLS

    Para producción, habilitar SSL:

    SSL_ENABLED=true

    Configurar certificados en /certs/.


    -

    1.12 11. Servicios Principales

    -

    1.12.1 11.1 +

    1.11 10. Servicios Principales

    +

    1.11.1 10.1 CreatePartitionService

    Propósito: Crear y actualizar particiones de clientes.

    Funcionalidad: - Recibe información de particiones del agente - Crea/actualiza particiones en base de datos - Detecta tipo de firmware (BIOS/UEFI) - Calcula códigos de partición

    -

    1.12.2 11.2 CreateTraceService

    +

    1.11.2 10.2 CreateTraceService

    Propósito: Crear trazas de ejecución para tareas programadas.

    Funcionalidad: - Genera trazas para cada combinación cliente-comando - Gestiona comandos agrupados - Establece estado inicial y fecha de ejecución

    -

    1.12.3 11.3 +

    1.11.3 10.3 ChangeClientNetworkSettingsService

    Propósito: Cambiar configuración de red de clientes.

    Funcionalidad: - Actualiza subnet, IP, configuración de red - Sincroniza con servicios externos (DHCP)

    -

    1.12.4 11.4 +

    1.11.4 10.4 ExternalGitRepositoryService

    Propósito: Gestión de repositorios Git para imágenes.

    Funcionalidad: - Backup de imágenes a Git - Versionado de imágenes - Sincronización con repositorios remotos

    -

    1.12.5 11.5 StatusService +class="header-section-number">1.11.5 10.5 StatusService (OgBoot/OgDhcp/OgRepository)

    Propósito: Verificar estado de servicios externos.

    Funcionalidad: - Health checks de servicios - Manejo de errores de conexión - Logging de estado

    -

    1.12.6 11.6 UDSClient

    +

    1.11.6 10.6 UDSClient

    Propósito: Integración con UDS (Universal Desktop Services).

    Funcionalidad: - Autenticación con UDS - Obtención de service pools - Cálculo de asientos disponibles - Gestión de calendarios remotos

    -

    1.12.7 11.7 +

    1.11.7 10.7 Trace/CreateService

    Propósito: Servicio especializado para creación de trazas.

    Funcionalidad: - Validación de parámetros de entrada - Creación de trazas individuales o masivas

    -

    1.12.8 11.8 +

    1.11.8 10.8 Utils/GetPartitionCodeService

    Propósito: Obtener código de partición según tipo y filesystem.

    -

    1.12.9 11.9 +

    1.11.9 10.9 Utils/SimplifyOgLiveFilenameService

    Propósito: Simplificar nombres de archivos OgLive para mostrar al usuario.

    -

    1.12.10 11.10 +class="header-section-number">1.11.10 10.10 Utils/GetIpAddressAndNetmaskFromCIDRService

    Propósito: Convertir notación CIDR a IP y máscara de red.


    -

    1.13 12. Comandos de Consola

    +

    1.12 11. Comandos de Consola

    ogCore incluye 18 comandos de consola para tareas administrativas:

    -

    1.13.1 12.1 Comandos de +

    1.12.1 11.1 Comandos de Inicialización

    -

    1.13.1.1 12.1.1 Cargar Grupos de +class="header-section-number">1.12.1.1 12.1.1 Cargar Grupos de Usuario por Defecto

    php bin/console app:load-default-user-groups

    Crea los grupos de usuarios predeterminados del sistema.

    -

    1.13.1.2 12.1.2 Cargar Comandos por +

    1.12.1.2 12.1.2 Cargar Comandos por Defecto

    php bin/console app:load-default-commands

    Carga los comandos básicos del sistema.

    -

    1.13.1.3 12.1.3 Cargar Usuario +

    1.12.1.3 12.1.3 Cargar Usuario Admin

    php bin/console app:load-default-user-admin

    Crea el usuario administrador por defecto.

    -

    1.13.1.4 12.1.4 Cargar Menú por +

    1.12.1.4 12.1.4 Cargar Menú por Defecto

    php bin/console app:load-default-menu

    Carga menús de arranque predeterminados.

    -

    1.13.1.5 12.1.5 Cargar Tipos de +

    1.12.1.5 12.1.5 Cargar Tipos de Hardware

    php bin/console app:load-hardware-types

    Inicializa la tabla de tipos de hardware.

    -

    1.13.1.6 12.1.6 Cargar Unidad +class="header-section-number">1.12.1.6 12.1.6 Cargar Unidad Organizativa por Defecto

    php bin/console app:load-organizational-unit-default

    Crea la unidad organizativa raíz.

    -

    1.13.2 12.2 Comandos de +

    1.12.2 11.2 Comandos de Operación

    -

    1.13.2.1 12.2.1 Verificar +class="header-section-number">1.12.2.1 12.2.1 Verificar Disponibilidad de Clientes

    php bin/console app:check-client-availability

    Ejecución: Cada 1 minuto (cron)

    Verifica el estado de conectividad de los clientes y actualiza su estado si no responden en un tiempo determinado.

    -

    1.13.2.2 12.2.2 Ejecutar Trazas +

    1.12.2.2 12.2.2 Ejecutar Trazas Pendientes

    php bin/console app:execute-pending-traces

    Ejecución: Cada 1 minuto (cron)

    Procesa las trazas en estado PENDING y las ejecuta en los clientes correspondientes.

    -

    1.13.2.3 12.2.3 Ejecutar Tareas +

    1.12.2.3 12.2.3 Ejecutar Tareas Programadas

    php bin/console app:run-scheduled-command-tasks

    Ejecución: Cada 1 minuto (cron)

    Ejecuta tareas programadas que han llegado a su hora de ejecución.

    -

    1.13.3 12.3 Comandos de +

    1.12.3 11.3 Comandos de Migración

    Comandos para migrar datos desde OpenGnsys 1.1:

    -

    1.13.3.1 12.3.1 Migrar Unidades +

    1.12.3.1 12.3.1 Migrar Unidades Organizativas

    php bin/console opengnsys:migration:organizational-unit
    -

    1.13.3.2 12.3.2 Migrar Perfiles de +

    1.12.3.2 12.3.2 Migrar Perfiles de Hardware

    php bin/console opengnsys:migration:hardware-profile
    -

    1.13.3.3 12.3.3 Migrar +

    1.12.3.3 12.3.3 Migrar Clientes

    php bin/console opengnsys:migration:clients
    -

    1.13.3.4 12.3.4 Migrar Sistemas +

    1.12.3.4 12.3.4 Migrar Sistemas Operativos

    php bin/console opengnsys:migration:os
    -

    1.13.3.5 12.3.5 Migrar +

    1.12.3.5 12.3.5 Migrar Imágenes

    php bin/console opengnsys:migration:image
    -

    1.13.3.6 12.3.6 Migrar Perfiles de +

    1.12.3.6 12.3.6 Migrar Perfiles de Software

    php bin/console opengnsys:migration:software-profile
    -

    1.13.3.7 12.3.7 Migrar Particiones +

    1.12.3.7 12.3.7 Migrar Particiones de Clientes

    php bin/console opengnsys:migration:partition-client
    -

    1.13.4 12.4 Comandos de +

    1.12.4 11.4 Comandos de Desarrollo

    -

    1.13.4.1 12.4.1 Crear Repositorios +

    1.12.4.1 12.4.1 Crear Repositorios de Imágenes

    php bin/console app:create-image-repositories

    Crea repositorios de imágenes para desarrollo/testing.

    -

    1.13.4.2 12.4.2 Cargar Trazas de +

    1.12.4.2 12.4.2 Cargar Trazas de Ejemplo

    php bin/console app:charge-example-trace

    Carga trazas de ejemplo para testing.

    -

    1.13.5 12.5 Configuración de +

    1.12.5 11.5 Configuración de Cron

    Agregar al crontab:

    * * * * * docker exec ogcore-php php bin/console app:execute-pending-traces
     * * * * * docker exec ogcore-php php bin/console app:run-scheduled-command-tasks

    -

    1.14 13. Migraciones de Datos

    -

    1.14.1 13.1 Sistema de Migraciones +

    1.13 12. Migraciones de Datos

    +

    1.13.1 12.1 Sistema de Migraciones de Doctrine

    ogCore utiliza Doctrine Migrations para gestionar cambios en el esquema de base de datos.

    -

    1.14.1.1 13.1.1 Crear una +

    1.13.1.1 13.1.1 Crear una Migración

    docker exec ogcore-php php bin/console make:migration
    -

    1.14.1.2 13.1.2 Ejecutar +

    1.13.1.2 13.1.2 Ejecutar Migraciones

    docker exec ogcore-php php bin/console doctrine:migrations:migrate
    -

    1.14.1.3 13.1.3 Ver Estado de +

    1.13.1.3 13.1.3 Ver Estado de Migraciones

    docker exec ogcore-php php bin/console doctrine:migrations:status
    -

    1.14.1.4 13.1.4 Revertir +

    1.13.1.4 13.1.4 Revertir Migración

    docker exec ogcore-php php bin/console doctrine:migrations:migrate prev
    -

    1.14.2 13.2 Migración desde +

    1.13.2 12.2 Migración desde OpenGnsys 1.1

    Para migrar datos desde una instalación de OpenGnsys 1.1:

    -

    1.14.2.1 13.2.1 Crear Base de Datos +

    1.13.2.1 13.2.1 Crear Base de Datos Temporal

    docker exec ogcore-php php bin/console doctrine:database:create --connection=og_1
    -

    1.14.2.2 13.2.2 Cargar Dump de +

    1.13.2.2 13.2.2 Cargar Dump de OpenGnsys 1.1

    docker exec -i ogcore-database mysql -u user -p ogcore_old_og < dump_og_1.1.sql
    -

    1.14.2.3 13.2.3 Ejecutar +

    1.13.2.3 13.2.3 Ejecutar Migraciones

    Ejecutar los comandos de migración en orden:

    docker exec ogcore-php php bin/console opengnsys:migration:os
     docker exec ogcore-php php bin/console opengnsys:migration:image
     docker exec ogcore-php php bin/console opengnsys:migration:software-profile
    -

    1.14.3 13.3 Backup y +

    1.13.3 12.3 Backup y Restauración

    -

    1.14.3.1 13.3.1 Backup de Base de +

    1.13.3.1 13.3.1 Backup de Base de Datos

    docker exec ogcore-database mysqldump -u user -p ogcore > backup_$(date +%Y%m%d).sql
    -

    1.14.3.2 13.3.2 Restaurar Base de +

    1.13.3.2 13.3.2 Restaurar Base de Datos

    docker exec -i ogcore-database mysql -u user -p ogcore < backup_20251008.sql

    -

    1.15 14. Testing

    -

    1.15.1 14.1 Framework de +

    1.14 13. Testing

    +

    1.14.1 13.1 Framework de Testing

    ogCore utiliza PHPUnit con integración de Symfony y Doctrine.

    -

    1.15.2 14.2 Ejecutar Tests

    -

    1.15.2.1 14.2.1 Todos los +

    1.14.2 13.2 Ejecutar Tests

    +

    1.14.2.1 14.2.1 Todos los Tests

    docker compose exec php bin/phpunit
    -

    1.15.2.2 14.2.2 Tests +

    1.14.2.2 14.2.2 Tests Específicos

    docker compose exec php bin/phpunit tests/Functional/ClientTest.php
    -

    1.15.2.3 14.2.3 Tests con +

    1.14.2.3 14.2.3 Tests con Coverage

    docker compose exec php bin/phpunit --coverage-html coverage/
    -

    1.15.3 14.3 Tipos de Tests

    -

    1.15.3.1 14.3.1 Tests +

    1.14.3 13.3 Tipos de Tests

    +

    1.14.3.1 14.3.1 Tests Funcionales

    Ubicación: tests/Functional/

    20 archivos de tests funcionales que prueban: - Endpoints de API - @@ -1926,8 +1715,8 @@ class="sourceCode php"> $this->assertResponseStatusCodeSame(201); } -

    1.15.4 14.4 Factories para +

    1.14.4 13.4 Factories para Testing

    Se utilizan Zenstruck Foundry factories (24 factories) para crear datos de prueba:

    @@ -1936,32 +1725,32 @@ class="sourceCode php"> 'name' => 'Test PC', 'status' => 'active' ]); -

    1.15.5 14.5 Base de Datos de +

    1.14.5 13.5 Base de Datos de Testing

    Los tests utilizan DAMA Doctrine Test Bundle para: - Ejecutar cada test en una transacción - Rollback automático después de cada test - Aislamiento completo entre tests


    -

    1.16 15. Despliegue

    -

    1.16.1 15.1 Despliegue con Docker +

    1.15 14. Despliegue

    +

    1.15.1 14.1 Despliegue con Docker Compose

    -

    1.16.1.1 15.1.1 Desarrollo

    +

    1.15.1.1 15.1.1 Desarrollo

    docker compose up -d
    -

    1.16.1.2 15.1.2 Producción

    +

    1.15.1.2 15.1.2 Producción

    docker compose -f docker-compose-deploy.yml up -d
    -

    1.16.2 15.2 Despliegue con +

    1.15.2 14.2 Despliegue con Jenkins

    El proyecto incluye Jenkinsfile para CI/CD.

    -

    1.16.2.1 Pipeline stages:

    +

    1.15.2.1 Pipeline stages:

    1. Checkout: Clonar repositorio
    2. Build: Construir imagen Docker
    3. @@ -1969,18 +1758,18 @@ class="header-section-number">1.16.2.1 Pipeline stages:
    4. Package: Crear paquete Debian
    5. Deploy: Desplegar en servidor
    -

    1.16.3 15.3 Paquete Debian

    +

    1.15.3 14.3 Paquete Debian

    El proyecto puede empaquetarse como .deb:

    ./package.sh

    Estructura del paquete en debian/: - Control files - Postinst/preinst scripts - Systemd service file - Configuración

    -

    1.16.4 15.4 Configuración de +

    1.15.4 14.4 Configuración de Producción

    -

    1.16.4.1 15.4.1 Variables de +

    1.15.4.1 15.4.1 Variables de Entorno

    Crear .env.local con configuración de producción:

    APP_DEBUG=0
     DATABASE_URL="mysql://user:pass@localhost:3306/ogcore"
     # ... más configuración
    -

    1.16.4.2 15.4.2 Optimizaciones

    +

    1.15.4.2 15.4.2 Optimizaciones

    # Limpiar caché
     docker exec ogcore-php php bin/console cache:clear --env=prod
    @@ -1999,19 +1788,19 @@ class="sourceCode bash">
     # Optimizar autoloader
     docker exec ogcore-php composer dump-autoload --optimize --classmap-authoritative
    -

    1.16.5 15.5 Monitoreo

    -

    1.16.5.1 15.5.1 Logs

    +

    1.15.5 14.5 Monitoreo

    +

    1.15.5.1 15.5.1 Logs

    Logs ubicados en var/log/: - dev.log / prod.log: Logs de aplicación - nginx/access.log: Accesos a nginx - nginx/error.log: Errores de nginx

    -

    1.16.5.2 15.5.2 Syslog

    +

    1.15.5.2 15.5.2 Syslog

    Los logs también se envían a syslog para centralización.

    -

    1.16.6 15.6 Escalabilidad

    +

    1.15.6 14.6 Escalabilidad

    Para escalar horizontalmente:

    1. Base de datos: Usar MariaDB con replicación @@ -2023,34 +1812,34 @@ carga
    2. Mercure: Escalar hub de Mercure

    -

    1.17 16. Mantenimiento y +

    1.16 15. Mantenimiento y Operaciones

    -

    1.17.1 16.1 Reiniciar Base de +

    1.16.1 15.1 Reiniciar Base de Datos

    docker exec ogcore-php php bin/console doctrine:database:drop --force
     docker exec ogcore-php php bin/console doctrine:database:create
     docker exec ogcore-php php bin/console doctrine:migrations:migrate --no-interaction
     docker exec ogcore-php php bin/console doctrine:fixtures:load --no-interaction
    -

    1.17.2 16.2 Limpiar Caché

    +

    1.16.2 15.2 Limpiar Caché

    docker exec ogcore-php php bin/console cache:clear
     docker exec ogcore-php php bin/console cache:warmup
    -

    1.17.3 16.3 Actualizar +

    1.16.3 15.3 Actualizar Dependencias

    docker exec ogcore-php composer update
    -

    1.17.4 16.4 Regenerar Claves +

    1.16.4 15.4 Regenerar Claves JWT

    docker exec ogcore-php php bin/console lexik:jwt:generate-keypair --overwrite
    -

    1.17.5 16.5 Backups +

    1.16.5 15.5 Backups Automáticos

    Script ejemplo para backup automático:

    # Limpiar backups antiguos (>30 días)
     find $BACKUP_DIR -name "*.sql" -mtime +30 -delete
     find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
    -

    1.17.6 16.6 Monitoreo de Salud

    -

    1.17.6.1 Health Check Endpoint

    +

    1.16.6 15.6 Monitoreo de Salud

    +

    1.16.6.1 Health Check Endpoint

    GET /health
    -

    1.17.6.2 Verificar Estado de +

    1.16.6.2 Verificar Estado de Servicios

    # PHP
    @@ -2085,8 +1874,8 @@ class="sourceCode bash">
     # MariaDB
     docker exec ogcore-database mysqladmin -u user -p status
    -

    1.17.7 16.7 Rotación de Logs

    +

    1.16.7 15.7 Rotación de Logs

    Configurar logrotate:

    /var/www/html/ogcore/var/log/*.log {
    @@ -2099,51 +1888,51 @@ class="sourceCode bash">    sharedscripts
     }

    -

    1.18 17. Integración con Otros +

    1.17 16. Integración con Otros Servicios

    -

    1.18.1 17.1 ogRepository

    +

    1.17.1 16.1 ogRepository

    Propósito: Gestión de repositorios de imágenes.

    Endpoints integrados: - Crear imagen - Desplegar imagen - Backup imagen - Eliminar imagen - Convertir a imagen virtual - Importar imagen externa - Verificar integridad - Imagen global

    Webhook: /og-repository/webhook

    -

    1.18.2 17.2 ogDhcp

    +

    1.17.2 16.2 ogDhcp

    Propósito: Gestión de DHCP dinámico.

    Funcionalidades: - Agregar clientes a DHCP - Eliminar clientes de DHCP - Actualizar configuración - Gestión de subredes

    -

    1.18.3 17.3 ogBoot

    +

    1.17.3 16.3 ogBoot

    Propósito: Gestión de archivos de arranque PXE.

    Funcionalidades: - Crear archivos de arranque - Actualizar plantillas PXE - Eliminar configuraciones - Sincronización de menús

    -

    1.18.4 17.4 ogAgent

    +

    1.17.4 16.4 ogAgent

    Propósito: Agente instalado en clientes para ejecutar comandos.

    Operaciones: - Power on/off/reboot - Crear/desplegar imágenes - Particionar discos - Ejecutar scripts - Obtener inventario hardware - Verificar tamaño de particiones - Kill jobs

    -

    1.18.5 17.5 UDS (Universal Desktop +

    1.17.5 16.5 UDS (Universal Desktop Services)

    Propósito: Integración con sistema de escritorios remotos.

    Funcionalidades: - Autenticación - Obtener service pools - Calcular disponibilidad - Gestión de reservas

    -

    1.18.6 17.6 Git (Versionado de +

    1.17.6 16.6 Git (Versionado de Imágenes)

    Propósito: Versionado de imágenes con Git.

    Funcionalidades: - Backup a repositorio Git - Versionado automático - Recuperación de versiones - Sincronización

    -

    1.18.7 17.7 Mercure (Notificaciones +class="header-section-number">1.17.7 16.7 Mercure (Notificaciones en Tiempo Real)

    Propósito: Notificaciones push en tiempo real.

    Eventos publicados: - Cambio de estado de clientes - @@ -2157,14 +1946,14 @@ class="sourceCode javascript"> console.log('Client updated:', data); };


    -

    1.19 18. Roadmap y Changelog

    -

    1.19.1 18.1 Versión Actual: +

    1.18 17. Roadmap y Changelog

    +

    1.18.1 17.1 Versión Actual: 0.5.0

    -

    1.19.2 18.2 Últimas Características +class="header-section-number">1.18.2 17.2 Últimas Características (v0.25.1 - Octubre 2025)

    • Tareas programadas: Sistema completo de colas y @@ -2189,11 +1978,11 @@ imágenes
    • Mercure: Notificaciones en tiempo real
    • Despliegue multicast: Modos torrent y UDPCAST
    -

    1.19.3 18.3 Próximas +

    1.18.3 17.3 Próximas Características (Roadmap)

    -

    1.19.3.1 v0.6.0 (Q4 2025)

    +

    1.18.3.1 v0.6.0 (Q4 2025)

    • @@ -2204,8 +1993,8 @@ complementaria
    -

    1.19.3.2 v0.7.0 (Q1 2026)

    +

    1.18.3.2 v0.7.0 (Q1 2026)

    • @@ -2214,8 +2003,8 @@ class="header-section-number">1.19.3.2 v0.7.0 (Q1 2026)
    -

    1.19.3.3 v1.0.0 (Q2 2026)

    +

    1.18.3.3 v1.0.0 (Q2 2026)

    • @@ -2226,8 +2015,8 @@ finalizadas
    -

    1.19.4 18.4 Changelog Resumido

    +

    1.18.4 17.4 Changelog Resumido

    Ver CHANGELOG.md para el historial completo de cambios.

    Versiones destacadas:

    @@ -2260,10 +2049,10 @@ aulas torrent/udpcast
    -

    1.20 19. Contribución

    -

    1.20.1 19.1 Guía de +

    1.19 18. Contribución

    +

    1.19.1 18.1 Guía de Contribución

    Para contribuir al proyecto:

      @@ -2276,8 +2065,8 @@ Contribución git push origin feature/nueva-funcionalidad
    1. Crea un Pull Request
    -

    1.20.2 19.2 Estándares de +

    1.19.2 18.2 Estándares de Código

    • Seguir PSR-12 para PHP
    • @@ -2286,8 +2075,8 @@ Código
    • Tests para nuevas funcionalidades
    • Commits descriptivos en español
    -

    1.20.3 19.3 Proceso de +

    1.19.3 18.3 Proceso de Revisión

    1. CI/CD ejecuta tests automáticamente
    2. @@ -2296,8 +2085,8 @@ Revisión
    3. Merge a rama develop
    4. Release periódicos a main
    -

    1.20.4 19.4 Reportar Bugs

    +

    1.19.4 18.4 Reportar Bugs

    Usar el sistema de Issues del repositorio:

    Template de Bug:

    **Descripción del bug**
    @@ -2319,10 +2108,10 @@ Si aplica, añadir screenshots.
     - Versión: [ej. 0.5.0]
     - Browser: [ej. Firefox 118]

    -

    1.21 20. Soporte y Contacto

    -

    1.21.1 20.1 Documentación +

    1.20 19. Soporte y Contacto

    +

    1.20.1 19.1 Documentación Adicional

    • API Docs: http://localhost:8080/docs
    • @@ -2331,27 +2120,27 @@ Adicional
    • Diagramas: swagger-assets/img_bbdd.png
    -

    1.21.2 20.2 Recursos

    +

    1.20.2 19.2 Recursos

    • Repositorio: [URL del repositorio]
    • Wiki: [URL de la wiki]
    • Issues: [URL de issues]
    -

    1.21.3 20.3 Equipo de +

    1.20.3 19.3 Equipo de Desarrollo

    Proyecto desarrollado por el equipo de OpenGnsys en colaboración con universidades participantes.

    -

    1.21.4 20.4 Licencia

    +

    1.20.4 19.4 Licencia

    Proyecto propietario. Ver archivo LICENSE para más información.


    -

    1.22 Apéndices

    -

    1.22.1 Apéndice A: Glosario de +

    1.21 Apéndices

    +

    1.21.1 Apéndice A: Glosario de Términos

    • Cliente: Equipo físico gestionado por el @@ -2368,8 +2157,8 @@ red
    • Repositorio: Servidor de almacenamiento de imágenes
    -

    1.22.2 Apéndice B: Puertos y +

    1.21.2 Apéndice B: Puertos y Servicios

    @@ -2407,39 +2196,39 @@ Servicios
    -

    1.22.3 Apéndice C: Estructura de +

    1.21.3 Apéndice C: Estructura de Directorios

    ogcore/
    -├── bin/              # Ejecutables (console, phpunit)
    -├── config/           # Configuración de Symfony
    -│   ├── api_platform/ # Configuración de entidades API
    -│   ├── packages/     # Configuración de bundles
    -│   └── routes/       # Rutas
    -├── migrations/       # Migraciones de base de datos
    -├── public/           # Punto de entrada web
    -├── src/              # Código fuente
    -│   ├── Command/      # Comandos de consola
    -│   ├── Controller/   # Controladores
    -│   ├── Dto/          # Data Transfer Objects
    -│   ├── Entity/       # Entidades Doctrine
    -│   ├── EventListener/# Event Listeners
    -│   ├── EventSubscriber/ # Event Subscribers
    -│   ├── Factory/      # Factories para testing
    -│   ├── Filter/       # Filtros de API Platform
    -│   ├── Repository/   # Repositorios Doctrine
    -│   ├── Security/     # Seguridad y autenticación
    -│   ├── Service/      # Servicios de negocio
    -│   ├── State/        # States de API Platform
    -│   └── Validator/    # Validadores personalizados
    -├── tests/            # Tests
    -├── translations/     # Traducciones
    -├── var/              # Archivos variables (cache, logs)
    -└── vendor/           # Dependencias
    +|-- bin/              # Ejecutables (console, phpunit)
    +|-- config/           # Configuración de Symfony
    +|   |-- api_platform/ # Configuración de entidades API
    +|   |-- packages/     # Configuración de bundles
    +|   +-- routes/       # Rutas
    +|-- migrations/       # Migraciones de base de datos
    +|-- public/           # Punto de entrada web
    +|-- src/              # Código fuente
    +|   |-- Command/      # Comandos de consola
    +|   |-- Controller/   # Controladores
    +|   |-- Dto/          # Data Transfer Objects
    +|   |-- Entity/       # Entidades Doctrine
    +|   |-- EventListener/# Event Listeners
    +|   |-- EventSubscriber/ # Event Subscribers
    +|   |-- Factory/      # Factories para testing
    +|   |-- Filter/       # Filtros de API Platform
    +|   |-- Repository/   # Repositorios Doctrine
    +|   |-- Security/     # Seguridad y autenticación
    +|   |-- Service/      # Servicios de negocio
    +|   |-- State/        # States de API Platform
    +|   +-- Validator/    # Validadores personalizados
    +|-- tests/            # Tests
    +|-- translations/     # Traducciones
    +|-- var/              # Archivos variables (cache, logs)
    ++-- vendor/           # Dependencias
     
    -

    1.22.4 Apéndice D: Variables de +class="header-section-number">1.21.4 Apéndice D: Variables de Entorno Completas

    Ver archivo .env para todas las variables de entorno disponibles.

    diff --git a/ogCore_Documentacion_Tecnica.pdf b/ogCore_Documentacion_Tecnica.pdf index a3c6a00..7506a56 100644 Binary files a/ogCore_Documentacion_Tecnica.pdf and b/ogCore_Documentacion_Tecnica.pdf differ diff --git a/src/Command/LoadDefaultMenuCommand.php b/src/Command/LoadDefaultMenuCommand.php index 51c2be3..c870477 100644 --- a/src/Command/LoadDefaultMenuCommand.php +++ b/src/Command/LoadDefaultMenuCommand.php @@ -25,7 +25,7 @@ class LoadDefaultMenuCommand extends Command { $menu = new Menu(); $menu->setName('Default menu'); - $menu->setResolution('1920x1080'); + $menu->setResolution('791'); $menu->setComments('Default menu comments'); $menu->setPublicUrl('main'); $menu->setIsDefault(true); diff --git a/src/Controller/ChangeOrganizationalUnitAction.php b/src/Controller/ChangeOrganizationalUnitAction.php index ebf76b5..071ad64 100644 --- a/src/Controller/ChangeOrganizationalUnitAction.php +++ b/src/Controller/ChangeOrganizationalUnitAction.php @@ -4,18 +4,16 @@ namespace App\Controller; use App\Controller\OgBoot\PxeBootFile\PostAction; use App\Dto\Input\ChangeOrganizationalUnitInput; -use App\Dto\Output\ClientOutput; use App\Entity\Client; -use App\Repository\ClientRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; class ChangeOrganizationalUnitAction extends AbstractController { @@ -43,10 +41,10 @@ class ChangeOrganizationalUnitAction extends AbstractController $this->entityManager->persist($clientEntity); - $template = $clientEntity->getTemplate() ?? $clientEntity->getOrganizationalUnit()->getNetworkSettings()?->getTemplate(); + $template = $clientEntity->getTemplate() ?? $clientEntity->getOrganizationalUnit()->getNetworkSettings()?->getPxeTemplate(); if (!$template) { - throw new BadRequestHttpException('No template found for client'); + throw new BadRequestHttpException('No se han encontrado plantillas PXE asociadas al cliente o a la unidad organizativa.'); } $this->postAction->__invoke($clientEntity, $template); @@ -54,6 +52,6 @@ class ChangeOrganizationalUnitAction extends AbstractController $this->entityManager->flush(); - return new JsonResponse( data: 'Clients updated successfully', status: Response::HTTP_OK); + return new JsonResponse( data: 'Clientes actualizados correctamente', status: Response::HTTP_OK); } } \ No newline at end of file diff --git a/src/Controller/OgBoot/PxeBootFile/PostAction.php b/src/Controller/OgBoot/PxeBootFile/PostAction.php index 1c172b9..725dad7 100644 --- a/src/Controller/OgBoot/PxeBootFile/PostAction.php +++ b/src/Controller/OgBoot/PxeBootFile/PostAction.php @@ -58,7 +58,7 @@ class PostAction extends AbstractOgBootController 'ogntp' => $client->getOrganizationalUnit()->getNetworkSettings()?->getNtp(), 'ogdns' => $client->getOrganizationalUnit()->getNetworkSettings()?->getDns(), 'ogProxy' => $client->getOrganizationalUnit()->getNetworkSettings()?->getProxy(), - 'resolution' => '791' + 'resolution' => $client->getResolution() ?? '791' ] ]; diff --git a/src/Dto/Input/ClientInput.php b/src/Dto/Input/ClientInput.php index feb3a26..dcb4c40 100644 --- a/src/Dto/Input/ClientInput.php +++ b/src/Dto/Input/ClientInput.php @@ -101,16 +101,22 @@ final class ClientInput #[Groups(['client:write'])] #[ApiProperty( - description: 'descriptions.client.validation' + description: 'El repositorio del cliente' )] public ?ImageRepositoryOutput $repository = null; #[Groups(['client:write'])] #[ApiProperty( - description: 'descriptions.client.validation' + description: 'El mantenimiento del cliente' )] public ?bool $maintenance = false; + #[Groups(['client:write'])] + #[ApiProperty( + description: 'La resolución del cliente' + )] + public ?string $resolution = null; + public function __construct(?Client $client = null) { @@ -127,6 +133,7 @@ final class ClientInput $this->ip = $client->getIp(); $this->position = $client->getPosition(); $this->status = $client->getStatus(); + $this->resolution = $client->getResolution(); if ($client->getMenu()) { $this->menu = new MenuOutput($client->getMenu()); @@ -170,7 +177,8 @@ final class ClientInput $client->setPosition($this->position); $client->setStatus($this->status); $client->setMaintenance($this->maintenance); - + $client->setResolution($this->resolution); + return $client; } } diff --git a/src/Dto/Input/DeployGitImageInput.php b/src/Dto/Input/DeployGitImageInput.php index 130190f..4a0c73e 100644 --- a/src/Dto/Input/DeployGitImageInput.php +++ b/src/Dto/Input/DeployGitImageInput.php @@ -6,10 +6,10 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; -use App\Validator\Constraints\ClientsHaveSamePartitionCount; +use App\Validator\Constraints\ClientsHaveSamePartitionSize; use Symfony\Component\Serializer\Annotation\Groups; -#[ClientsHaveSamePartitionCount] +#[ClientsHaveSamePartitionSize] class DeployGitImageInput { #[Groups(['git-repository:write'])] diff --git a/src/Dto/Input/DeployImageInput.php b/src/Dto/Input/DeployImageInput.php index d2c021b..e76d77e 100644 --- a/src/Dto/Input/DeployImageInput.php +++ b/src/Dto/Input/DeployImageInput.php @@ -4,13 +4,13 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; -use App\Validator\Constraints\ClientsHaveSamePartitionCount; +use App\Validator\Constraints\ClientsHaveSamePartitionSize; use App\Validator\Constraints\OrganizationalUnitMulticastMode; use App\Validator\Constraints\OrganizationalUnitMulticastPort; use App\Validator\Constraints\OrganizationalUnitP2PMode; use Symfony\Component\Serializer\Annotation\Groups; -#[ClientsHaveSamePartitionCount] +#[ClientsHaveSamePartitionSize] class DeployImageInput { #[Groups(['image-image-repository:write'])] diff --git a/src/Dto/Input/OrganizationalUnitInput.php b/src/Dto/Input/OrganizationalUnitInput.php index d0d3bf6..b26c715 100644 --- a/src/Dto/Input/OrganizationalUnitInput.php +++ b/src/Dto/Input/OrganizationalUnitInput.php @@ -14,6 +14,8 @@ use Symfony\Component\Validator\Constraints as Assert; #[OrganizationalUnitParent] class OrganizationalUnitInput { + private ?OrganizationalUnit $originalEntity = null; + #[Assert\NotBlank(message: 'validators.organizational_unit.name.not_blank')] #[Groups(['organizational-unit:write'])] #[ApiProperty( @@ -113,6 +115,7 @@ class OrganizationalUnitInput return; } + $this->originalEntity = $organizationalUnit; $this->name = $organizationalUnit->getName(); if ($organizationalUnit->getParent()) { $this->parent = new OrganizationalUnitOutput($organizationalUnit->getParent()); @@ -164,4 +167,9 @@ class OrganizationalUnitInput return $organizationalUnit; } + + public function getOriginalEntity(): ?OrganizationalUnit + { + return $this->originalEntity; + } } \ No newline at end of file diff --git a/src/Dto/Output/ClientOutput.php b/src/Dto/Output/ClientOutput.php index a9d1b9b..bb7dc26 100644 --- a/src/Dto/Output/ClientOutput.php +++ b/src/Dto/Output/ClientOutput.php @@ -160,6 +160,13 @@ final class ClientOutput extends AbstractOutput )] public ?bool $pxeSync = false; + #[Groups(['client:read'])] + #[ApiProperty( + description: 'La resolución del cliente', + example: '1920x1080' + )] + public ?string $resolution = null; + public function __construct(Client $client) { parent::__construct($client); @@ -208,6 +215,7 @@ final class ClientOutput extends AbstractOutput $this->createdBy = $client->getCreatedBy(); $this->maintenance = $client->isMaintenance(); $this->pxeSync = $client->isPxeSync(); + $this->resolution = $client->getResolution(); } public function convertMaskToCIDR($mask): int diff --git a/src/Dto/Output/MenuOutput.php b/src/Dto/Output/MenuOutput.php index 661c766..3636b03 100644 --- a/src/Dto/Output/MenuOutput.php +++ b/src/Dto/Output/MenuOutput.php @@ -11,14 +11,14 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'Menu')] final class MenuOutput extends AbstractOutput { - #[Groups(['menu:read', 'organizational-unit:read'])] + #[Groups(['menu:read', 'client:read', 'organizational-unit:read'])] #[ApiProperty( description: 'El nombre del menú de arranque', example: 'Menú Principal' )] public string $name; - #[Groups(['menu:read'])] + #[Groups(['menu:read', 'client:read', 'organizational-unit:read'])] #[ApiProperty( description: 'La resolución del menú', example: '1024x768' diff --git a/src/Entity/Client.php b/src/Entity/Client.php index 89513db..51d5064 100644 --- a/src/Entity/Client.php +++ b/src/Entity/Client.php @@ -94,6 +94,9 @@ class Client extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $token = null; + #[ORM\Column(length: 255, nullable: true)] + private ?string $resolution = null; + public function __construct() { parent::__construct(); @@ -371,4 +374,15 @@ class Client extends AbstractEntity return $this; } + + public function getResolution(): ?string + { + return $this->resolution; + } + + public function setResolution(?string $resolution): static + { + $this->resolution = $resolution; + return $this; + } } diff --git a/src/State/Processor/ClientProcessor.php b/src/State/Processor/ClientProcessor.php index 15b35dc..2bcee18 100644 --- a/src/State/Processor/ClientProcessor.php +++ b/src/State/Processor/ClientProcessor.php @@ -75,6 +75,7 @@ readonly class ClientProcessor implements ProcessorInterface if ($defaultMenu && !$client->getMenu()) { $client->setMenu($defaultMenu); + $client->setResolution($defaultMenu->getResolution()); } if ($defaultPxe && !$client->getTemplate()) { diff --git a/src/Validator/Constraints/ClientsHaveSamePartitionCountValidator.php b/src/Validator/Constraints/ClientsHaveSamePartitionCountValidator.php deleted file mode 100644 index 896dc3e..0000000 --- a/src/Validator/Constraints/ClientsHaveSamePartitionCountValidator.php +++ /dev/null @@ -1,39 +0,0 @@ -clients) && is_array($value->clients)) { - $partitionCounts = []; - foreach ($value->clients as $client) { - $partitionCount = $client->getEntity()->getPartitions()->count(); - $partitionCounts[(string) $client->getEntity()->getIp()] = $partitionCount; - } - - if (count(array_unique($partitionCounts)) > 1) { - $errorDetails = []; - foreach ($partitionCounts as $clientIp => $partitionCount) { - $errorDetails[] = "Cliente $clientIp tiene $partitionCount particiones."; - } - - $detailedMessage = implode(" ", $errorDetails); - - $this->context->buildViolation($constraint->message . ' Detalles: ' . $detailedMessage) - ->addViolation(); - } - } - } -} \ No newline at end of file diff --git a/src/Validator/Constraints/ClientsHaveSamePartitionCount.php b/src/Validator/Constraints/ClientsHaveSamePartitionSize.php similarity index 69% rename from src/Validator/Constraints/ClientsHaveSamePartitionCount.php rename to src/Validator/Constraints/ClientsHaveSamePartitionSize.php index 9ea7093..64b5e19 100644 --- a/src/Validator/Constraints/ClientsHaveSamePartitionCount.php +++ b/src/Validator/Constraints/ClientsHaveSamePartitionSize.php @@ -5,7 +5,7 @@ namespace App\Validator\Constraints; use Symfony\Component\Validator\Constraint; #[\Attribute] -class ClientsHaveSamePartitionCount extends Constraint +class ClientsHaveSamePartitionSize extends Constraint { public string $message; @@ -13,7 +13,7 @@ class ClientsHaveSamePartitionCount extends Constraint { parent::__construct($options, $groups, $payload); - $this->message = 'All clients must have the same number of partitions.'; + $this->message = 'Todos los clientes deben tener el mismo tamaño de partición para la partición seleccionada.'; } public function getTargets(): string diff --git a/src/Validator/Constraints/ClientsHaveSamePartitionSizeValidator.php b/src/Validator/Constraints/ClientsHaveSamePartitionSizeValidator.php new file mode 100644 index 0000000..a0c0264 --- /dev/null +++ b/src/Validator/Constraints/ClientsHaveSamePartitionSizeValidator.php @@ -0,0 +1,76 @@ +clients) || !is_array($value->clients) || empty($value->clients)) { + return; + } + + if ($value->diskNumber === null || $value->partitionNumber === null) { + return; + } + + $partitionSizes = []; + + foreach ($value->clients as $client) { + $clientEntity = $client->getEntity(); + + if (!$clientEntity instanceof Client) { + continue; + } + + $clientIp = (string) $clientEntity->getIp(); + + $targetPartition = null; + foreach ($clientEntity->getPartitions() as $partition) { + if ($partition->getDiskNumber() === $value->diskNumber && + $partition->getPartitionNumber() === $value->partitionNumber) { + $targetPartition = $partition; + break; + } + } + + if ($targetPartition === null) { + $partitionSizes[$clientIp] = null; + } else { + $partitionSizes[$clientIp] = $targetPartition->getSize(); + } + } + + $validSizes = array_filter($partitionSizes, fn($size) => $size !== null); + + if (count($validSizes) !== count($partitionSizes)) { + $clientsWithoutPartition = array_keys(array_filter($partitionSizes, fn($size) => $size === null)); + $this->context->buildViolation('Algunos clientes no tienen la partición seleccionada (Disco: ' . $value->diskNumber . ', Partición: ' . $value->partitionNumber . '). Clientes sin partición: ' . implode(', ', $clientsWithoutPartition)) + ->addViolation(); + return; + } + + if (count(array_unique($validSizes)) > 1) { + $errorDetails = []; + foreach ($partitionSizes as $clientIp => $partitionSize) { + $errorDetails[] = "Cliente $clientIp tiene tamaño $partitionSize KB."; + } + + $detailedMessage = implode(" ", $errorDetails); + + $this->context->buildViolation($constraint->message . ' Detalles: ' . $detailedMessage) + ->addViolation(); + } + } +} \ No newline at end of file diff --git a/src/Validator/Constraints/OrganizationalUnitParent.php b/src/Validator/Constraints/OrganizationalUnitParent.php index 7950ac7..1c873f6 100644 --- a/src/Validator/Constraints/OrganizationalUnitParent.php +++ b/src/Validator/Constraints/OrganizationalUnitParent.php @@ -9,12 +9,14 @@ use Symfony\Component\Validator\Constraint; class OrganizationalUnitParent extends Constraint { public string $message; + public string $selfParentMessage; public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) { parent::__construct($options, $groups, $payload); - $this->message = 'Only the root organizational unit can not have a parent.'; + $this->message = 'validators.organizational_unit.parent.required'; + $this->selfParentMessage = 'validators.organizational_unit.parent.self_parent'; } public function getTargets(): array|string diff --git a/src/Validator/Constraints/OrganizationalUnitParentValidator.php b/src/Validator/Constraints/OrganizationalUnitParentValidator.php index dccef59..3ce8a4a 100644 --- a/src/Validator/Constraints/OrganizationalUnitParentValidator.php +++ b/src/Validator/Constraints/OrganizationalUnitParentValidator.php @@ -21,5 +21,14 @@ class OrganizationalUnitParentValidator extends ConstraintValidator $this->context->buildViolation($constraint->message)->addViolation(); return; } + + // Validar que el parent no sea la misma entidad que se está modificando + if ($value->parent && $value->getOriginalEntity()) { + if ($value->parent->getEntity()->getId() === $value->getOriginalEntity()->getId()) { + $this->context->buildViolation($constraint->selfParentMessage) + ->atPath('parent') + ->addViolation(); + } + } } } \ No newline at end of file diff --git a/translations/validators.en.yaml b/translations/validators.en.yaml index 2c58ac9..4e6e95e 100644 --- a/translations/validators.en.yaml +++ b/translations/validators.en.yaml @@ -57,6 +57,11 @@ validators: not_blank: 'The name should not be blank.' unique: 'The name should be unique.' + + organizational_unit: + parent: + self_parent: 'The parent should not be the same as the organizational unit.' + required: 'The parent should be required.' subnet: name: not_blank: 'The name should not be blank.' diff --git a/translations/validators.es.yaml b/translations/validators.es.yaml index 93dcaef..0248363 100644 --- a/translations/validators.es.yaml +++ b/translations/validators.es.yaml @@ -45,6 +45,11 @@ validators: not_blank: 'El nombre no debería estar vacío.' unique: 'El nombre debería ser único. Ya existe un archivo con ese nombre.' + organizational_unit: + parent: + self_parent: 'El padre no debería ser la misma unidad organizativa.' + required: 'El padre debería ser requerido.' + network_settings: ip_address: invalid: 'La dirección IP "{{ value }}" no es válida.'