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
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 |
++--------------+--------------+--------------+----------------+
El sistema cuenta con 35 entidades principales agrupadas en los -siguientes dominios:
-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
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
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
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
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
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ó
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
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
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
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
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
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
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
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
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
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
-El sistema cuenta con 102 controladores organizados por dominio:
-Los States implementan el patrón State de API Platform:
-93 DTOs para transferencia de datos:
-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
-8 suscriptores para: - Publicación en Mercure al cambiar estados - Limpieza de recursos - Validaciones pre/post persistencia - Logging de eventos
-24 factories para testing con Foundry: - Creación de entidades para tests - Datos de prueba realistas - Estados predefinidos
La API está completamente documentada con OpenAPI 3.0 y accesible en:
http://127.0.0.1:8080/docs
-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"
}
}
-Soporta filtros avanzados:
GET /clients?status=active
GET /clients?organizationalUnit.name=Aula1
GET /traces?client.id=123&status=pending
-GET /clients?order[name]=asc
GET /traces?order[createdAt]=desc
-POST /auth/login
POST /auth/refresh
-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
-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
-GET /commands
POST /commands
@@ -1464,15 +1253,15 @@ GET /command-tasks
POST /command-tasks
PUT /command-tasks/{id}
DELETE /command-tasks/{id}
-GET /traces
GET /traces/{id}
PUT /traces/{id}
PATCH /traces/{id}/complete
PATCH /traces/{id}/cancel
-ogCore utiliza JSON Web Tokens (JWT) para autenticación:
-POST /auth/login
Content-Type: application/json
@@ -1549,14 +1338,14 @@ class="sourceCode json"> "token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh_token": "def50200a54b7b..."
}Incluir el token en el header Authorization:
GET /clients
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...POST /auth/refresh
Content-Type: application/json
@@ -1564,10 +1353,10 @@ class="sourceCode bash">{
"refresh_token": "def50200a54b7b..."
}/auth/login/auth/refresh/og-repository/webhook/menu-browserIS_AUTHENTICATED_FULLYLos roles se gestionan en la entidad User:
$user->setRoles(['ROLE_USER']);
$user->setRoles(['ROLE_ADMIN']);Configurado en nelmio_cors.yaml para permitir acceso
desde frontend.
Para producción, habilitar SSL:
SSL_ENABLED=trueConfigurar certificados en /certs/.
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
-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
-Propósito: Cambiar configuración de red de clientes.
Funcionalidad: - Actualiza subnet, IP, configuración de red - Sincroniza con servicios externos (DHCP)
-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
-Propósito: Verificar estado de servicios externos.
Funcionalidad: - Health checks de servicios - Manejo de errores de conexión - Logging de estado
-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
-Propósito: Servicio especializado para creación de trazas.
Funcionalidad: - Validación de parámetros de entrada - Creación de trazas individuales o masivas
-Propósito: Obtener código de partición según tipo y filesystem.
-Propósito: Simplificar nombres de archivos OgLive para mostrar al usuario.
-Propósito: Convertir notación CIDR a IP y máscara de red.
ogCore incluye 18 comandos de consola para tareas administrativas:
-php bin/console app:load-default-user-groupsCrea los grupos de usuarios predeterminados del sistema.
-php bin/console app:load-default-commandsCarga los comandos básicos del sistema.
-php bin/console app:load-default-user-adminCrea el usuario administrador por defecto.
-php bin/console app:load-default-menuCarga menús de arranque predeterminados.
-php bin/console app:load-hardware-typesInicializa la tabla de tipos de hardware.
-php bin/console app:load-organizational-unit-defaultCrea la unidad organizativa raíz.
-php bin/console app:check-client-availabilityEjecución: Cada 1 minuto (cron)
Verifica el estado de conectividad de los clientes y actualiza su estado si no responden en un tiempo determinado.
-php bin/console app:execute-pending-tracesEjecución: Cada 1 minuto (cron)
Procesa las trazas en estado PENDING y las ejecuta en
los clientes correspondientes.
php bin/console app:run-scheduled-command-tasksEjecución: Cada 1 minuto (cron)
Ejecuta tareas programadas que han llegado a su hora de ejecución.
-Comandos para migrar datos desde OpenGnsys 1.1:
-php bin/console opengnsys:migration:organizational-unitphp bin/console opengnsys:migration:hardware-profilephp bin/console opengnsys:migration:clientsphp bin/console opengnsys:migration:osphp bin/console opengnsys:migration:imagephp bin/console opengnsys:migration:software-profilephp bin/console opengnsys:migration:partition-clientphp bin/console app:create-image-repositoriesCrea repositorios de imágenes para desarrollo/testing.
-php bin/console app:charge-example-traceCarga trazas de ejemplo para testing.
-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-tasksogCore utiliza Doctrine Migrations para gestionar cambios en el esquema de base de datos.
-docker exec ogcore-php php bin/console make:migrationdocker exec ogcore-php php bin/console doctrine:migrations:migratedocker exec ogcore-php php bin/console doctrine:migrations:statusdocker exec ogcore-php php bin/console doctrine:migrations:migrate prevPara migrar datos desde una instalación de OpenGnsys 1.1:
-docker exec ogcore-php php bin/console doctrine:database:create --connection=og_1docker exec -i ogcore-database mysql -u user -p ogcore_old_og < dump_og_1.1.sqlEjecutar 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-profiledocker exec ogcore-database mysqldump -u user -p ogcore > backup_$(date +%Y%m%d).sqldocker exec -i ogcore-database mysql -u user -p ogcore < backup_20251008.sqlogCore utiliza PHPUnit con integración de Symfony y Doctrine.
-docker compose exec php bin/phpunitdocker compose exec php bin/phpunit tests/Functional/ClientTest.phpdocker compose exec php bin/phpunit --coverage-html coverage/Ubicación: tests/Functional/
20 archivos de tests funcionales que prueban: - Endpoints de API -
@@ -1926,8 +1715,8 @@ class="sourceCode php">
$this->assertResponseStatusCodeSame(201);
}
-
Se utilizan Zenstruck Foundry factories (24 factories) para crear datos de prueba:
@@ -1936,32 +1725,32 @@ class="sourceCode php"> 'name' => 'Test PC',
'status' => 'active'
]);
-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
docker compose up -ddocker compose -f docker-compose-deploy.yml up -dEl proyecto incluye Jenkinsfile para CI/CD.
-El proyecto puede empaquetarse como .deb:
./package.shEstructura del paquete en debian/: - Control files -
Postinst/preinst scripts - Systemd service file - Configuración
Crear .env.local con configuración de producción:
# 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-authoritativeLogs ubicados en var/log/: - dev.log /
prod.log: Logs de aplicación -
nginx/access.log: Accesos a nginx -
nginx/error.log: Errores de nginx
Los logs también se envían a syslog para centralización.
-Para escalar horizontalmente:
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-interactiondocker exec ogcore-php php bin/console cache:clear
docker exec ogcore-php php bin/console cache:warmupdocker exec ogcore-php composer updatedocker exec ogcore-php php bin/console lexik:jwt:generate-keypair --overwriteScript 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 -deleteGET /health# PHP
@@ -2085,8 +1874,8 @@ class="sourceCode bash">
# MariaDB
docker exec ogcore-database mysqladmin -u user -p statusConfigurar logrotate:
/var/www/html/ogcore/var/log/*.log {
@@ -2099,51 +1888,51 @@ class="sourceCode bash"> sharedscripts
}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
Propósito: Gestión de DHCP dinámico.
Funcionalidades: - Agregar clientes a DHCP - Eliminar clientes de DHCP - Actualizar configuración - Gestión de subredes
-Propósito: Gestión de archivos de arranque PXE.
Funcionalidades: - Crear archivos de arranque - Actualizar plantillas PXE - Eliminar configuraciones - Sincronización de menús
-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
-Propósito: Integración con sistema de escritorios remotos.
Funcionalidades: - Autenticación - Obtener service pools - Calcular disponibilidad - Gestión de reservas
-Propósito: Versionado de imágenes con Git.
Funcionalidades: - Backup a repositorio Git - Versionado automático - Recuperación de versiones - Sincronización
-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);
};
Ver CHANGELOG.md para el historial completo de
cambios.
Versiones destacadas:
@@ -2260,10 +2049,10 @@ aulasPara contribuir al proyecto:
git push origin feature/nueva-funcionalidad
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]
swagger-assets/img_bbdd.pngProyecto desarrollado por el equipo de OpenGnsys en colaboración con universidades participantes.
-Proyecto propietario. Ver archivo LICENSE para más
información.
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
-Ver archivo .env para todas las variables de entorno
disponibles.