diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 1e9928e..568ba93 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -29,7 +29,7 @@ security: - { path: ^/$, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI - { path: ^/docs, roles: PUBLIC_ACCESS } # Allows accessing the Swagger UI docs - { path: ^/auth/login, roles: PUBLIC_ACCESS } - - { path: ^/opengnsys/rest/, roles: PUBLIC_ACCESS } + - { path: ^/opengnsys/rest, roles: PUBLIC_ACCESS } - { path: ^/og-lives/install/webhook, roles: PUBLIC_ACCESS } - { path: ^/auth/refresh, roles: PUBLIC_ACCESS } - { path: ^/, roles: IS_AUTHENTICATED_FULLY } diff --git a/migrations/Version20241008080902.php b/migrations/Version20241008080902.php new file mode 100644 index 0000000..dc61c00 --- /dev/null +++ b/migrations/Version20241008080902.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE `partition` ADD image_id INT NOT NULL'); + $this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E43DA5256D FOREIGN KEY (image_id) REFERENCES image (id)'); + $this->addSql('CREATE INDEX IDX_9EB910E43DA5256D ON `partition` (image_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E43DA5256D'); + $this->addSql('DROP INDEX IDX_9EB910E43DA5256D ON `partition`'); + $this->addSql('ALTER TABLE `partition` DROP image_id'); + } +} diff --git a/migrations/Version20241008081013.php b/migrations/Version20241008081013.php new file mode 100644 index 0000000..87b726c --- /dev/null +++ b/migrations/Version20241008081013.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE client ADD maintenance TINYINT(1) NOT 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 maintenance'); + } +} diff --git a/migrations/Version20241008092247.php b/migrations/Version20241008092247.php new file mode 100644 index 0000000..033c6bc --- /dev/null +++ b/migrations/Version20241008092247.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE image CHANGE software_profile_id software_profile_id INT DEFAULT NULL, CHANGE path path VARCHAR(255) DEFAULT NULL, CHANGE type type VARCHAR(255) DEFAULT NULL, CHANGE size size INT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image CHANGE software_profile_id software_profile_id INT NOT NULL, CHANGE path path VARCHAR(255) NOT NULL, CHANGE type type VARCHAR(255) NOT NULL, CHANGE size size INT NOT NULL'); + } +} diff --git a/migrations/Version20241008092849.php b/migrations/Version20241008092849.php new file mode 100644 index 0000000..5c39be2 --- /dev/null +++ b/migrations/Version20241008092849.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE image ADD organizational_unit_id INT NOT NULL'); + $this->addSql('ALTER TABLE image ADD CONSTRAINT FK_C53D045FFB84408A FOREIGN KEY (organizational_unit_id) REFERENCES organizational_unit (id)'); + $this->addSql('CREATE INDEX IDX_C53D045FFB84408A ON image (organizational_unit_id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE image DROP FOREIGN KEY FK_C53D045FFB84408A'); + $this->addSql('DROP INDEX IDX_C53D045FFB84408A ON image'); + $this->addSql('ALTER TABLE image DROP organizational_unit_id'); + } +} diff --git a/src/Command/Migration/MigrateImagesCommand.php b/src/Command/Migration/MigrateImagesCommand.php new file mode 100644 index 0000000..17de59c --- /dev/null +++ b/src/Command/Migration/MigrateImagesCommand.php @@ -0,0 +1,91 @@ +doctrine->getManager('og_1'); + + $imagesRepository = $this->entityManager->getRepository(Image::class); + $clientRepository = $this->entityManager->getRepository(Client::class); + $ouRepository = $this->entityManager->getRepository(OrganizationalUnit::class); + + /** Obtener las imágenes de la base de datos antigua **/ + $rsmOperativeSystems = new ResultSetMapping(); + $rsmOperativeSystems->addScalarResult('idimagen', 'idimagen'); + $rsmOperativeSystems->addScalarResult('nombreca', 'nombreca'); + $rsmOperativeSystems->addScalarResult('idcentro', 'centros.idcentro'); + $rsmOperativeSystems->addScalarResult('idordenador', 'ordenadores.idordenador'); + $rsmOperativeSystems->addScalarResult('numdisk', 'numdisk'); + $rsmOperativeSystems->addScalarResult('ruta', 'ruta'); + $rsmOperativeSystems->addScalarResult('numpar', 'numpar'); + $rsmOperativeSystems->addScalarResult('revision', 'revision'); + $rsmOperativeSystems->addScalarResult('descripcion', 'descripcion'); + $rsmOperativeSystems->addScalarResult('comentarios', 'comentarios'); + + $imagesQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idimagen, nombreca, ruta, ordenadores.idordenador, centros.idcentro, numdisk, numpar, revision, descripcion, imagenes.comentarios FROM imagenes LEFT JOIN ordenadores ON imagenes.idordenador = ordenadores.idordenador LEFT JOIN centros ON imagenes.idcentro = imagenes.idcentro', $rsmOperativeSystems); + $images = $imagesQuery->getResult(); + + /** Imágenes **/ + $output->writeln("IMÁGENES TOTAL: ". count($images)); + + foreach ($images as $image){ + $ouEntity = $ouRepository->findOneBy(['migrationId' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT.'-'.$image['centros.idcentro']]); + + if (!$ouEntity) { + $output->writeln("No se ha encontrado la OU con id: ". $image['centros.idcentro']); + continue; + } + + $clientEntity = $clientRepository->findOneBy(['migrationId' => $image['ordenadores.idordenador']]); + if(!$clientEntity){ + $output->writeln("No se ha encontrado el cliente con id: ". $image['ordenadores.idordenador']); + continue; + } + + $imageEntity = $imagesRepository->findOneBy(['migrationId' => $image['idimagen']]); + if(!$imageEntity) { + $imageEntity = new Image(); + $imageEntity->setMigrationId((string) $image['idimagen']); + $imageEntity->setName($image['nombreca']); + $imageEntity->setClient($clientEntity); + $imageEntity->setOrganizationalUnit($ouEntity); + $imageEntity->setRevision((string) $image['revision']); + $imageEntity->setDescription($image['descripcion']); + $imageEntity->setComments($image['comentarios']); + } + + $this->entityManager->persist($imageEntity); + } + + $this->entityManager->flush(); + + return Command::SUCCESS; + } +} diff --git a/src/Controller/UDS/OrganizationalUnitController.php b/src/Controller/UDS/OrganizationalUnitController.php new file mode 100644 index 0000000..e68c0e8 --- /dev/null +++ b/src/Controller/UDS/OrganizationalUnitController.php @@ -0,0 +1,87 @@ +entityManager + ->getRepository(OrganizationalUnit::class) + ->findBy(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT], ['name' => 'ASC']); + + $data = []; + foreach ($organizationalUnits as $center) { + $data[] = [ + 'id' => $center->getId(), + 'name' => $center->getName(), + 'description' => $center->getDescription(), + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } + + #[Route('/opengnsys/rest//ous/{centerId}/labs', methods: ['GET'])] + public function getClassrooms(Request $request, int $centerId): JsonResponse + { + $classrooms = $this->entityManager + ->getRepository(OrganizationalUnit::class) + ->findBy([ + 'type' => OrganizationalUnitTypes::CLASSROOM, + 'parent' => $centerId + ], ['name' => 'ASC']); + + $data = []; + + foreach ($classrooms as $classroom) { + $data[] = [ + 'id' => $classroom->getId(), + 'name' => $classroom->getName(), + 'description' => $classroom->getDescription(), + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } + + #[Route('/opengnsys/rest//ous/{centerId}/images', methods: ['GET'])] + public function getImages(Request $request, int $centerId): JsonResponse + { + $images = $this->entityManager + ->getRepository(Image::class) + ->findBy([ + 'organizationalUnit' => $centerId, + ], ['name' => 'ASC']); + + $data = []; + + foreach ($images as $image) { + $data[] = [ + 'id' => $image->getId(), + 'name' => $image->getName(), + ]; + } + + return new JsonResponse($data, Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Dto/Input/ClientInput.php b/src/Dto/Input/ClientInput.php index 32abc29..9d3a98f 100644 --- a/src/Dto/Input/ClientInput.php +++ b/src/Dto/Input/ClientInput.php @@ -102,6 +102,13 @@ final class ClientInput )] public ?OgRepository $repository = null; + #[Groups(['client:write'])] + #[ApiProperty( + description: 'descriptions.client.validation' + )] + public ?bool $maintenance = false; + + public function __construct(?Client $client = null) { if (!$client) { @@ -149,6 +156,7 @@ final class ClientInput $client->setHardwareProfile($this->hardwareProfile?->getEntity()); $client->setPosition($this->position); $client->setStatus($this->status); + $client->setMaintenance($this->maintenance); return $client; } diff --git a/src/Dto/Input/ImageInput.php b/src/Dto/Input/ImageInput.php index 10c46a5..7bab121 100644 --- a/src/Dto/Input/ImageInput.php +++ b/src/Dto/Input/ImageInput.php @@ -4,8 +4,10 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\OrganizationalUnitOutput; use App\Dto\Output\SoftwareProfileOutput; use App\Entity\Image; +use App\Entity\OrganizationalUnit; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Validator\Constraints as Assert; @@ -52,6 +54,10 @@ final class ImageInput #[ApiProperty(description: 'The software profile of the image')] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:write'])] + #[ApiProperty(description: 'The organizational unit of the image')] + public ?OrganizationalUnitOutput $organizationalUnit = null; + public function __construct(?Image $image = null) { if (!$image) { @@ -68,6 +74,7 @@ final class ImageInput $this->size = $image->getSize(); $this->client = new ClientOutput($image->getClient()); $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); + $this->organizationalUnit = new OrganizationalUnitOutput($image->getOrganizationalUnit()); } public function createOrUpdateEntity(?Image $image = null): Image @@ -87,6 +94,12 @@ final class ImageInput $image->setClient($this->client->getEntity()); $image->setSoftwareProfile($this->softwareProfile->getEntity()); + if ($this->organizationalUnit) { + $image->setOrganizationalUnit($this->organizationalUnit->getEntity()); + } else { + $image->setOrganizationalUnit($this->client->getEntity()->getOrganizationalUnit()); + } + return $image; } } \ No newline at end of file diff --git a/src/Dto/Input/PartitionInput.php b/src/Dto/Input/PartitionInput.php index 03d633a..c7477a5 100644 --- a/src/Dto/Input/PartitionInput.php +++ b/src/Dto/Input/PartitionInput.php @@ -4,6 +4,7 @@ namespace App\Dto\Input; use ApiPlatform\Metadata\ApiProperty; use App\Dto\Output\ClientOutput; +use App\Dto\Output\ImageOutput; use App\Dto\Output\OperativeSystemOutput; use App\Dto\Output\OrganizationalUnitOutput; use App\Entity\HardwareProfile; @@ -54,6 +55,10 @@ final class PartitionInput #[ApiProperty(description: 'The memory usage of the partition', example: 100)] public ?int $memoryUsage = null; + #[Groups(['partition:write'])] + #[ApiProperty(description: 'The image of the partition')] + public ?ImageOutput $image = null; + public function __construct(?Partition $partition = null) { if (!$partition) { @@ -69,6 +74,7 @@ final class PartitionInput $this->operativeSystem = new OperativeSystemOutput($partition->getOperativeSystem()); $this->client = new ClientOutput($partition->getClient()); $this->memoryUsage = $partition->getMemoryUsage(); + $this->image = new ImageOutput($partition->getImage()); } public function createOrUpdateEntity(?Partition $partition = null): Partition @@ -86,6 +92,7 @@ final class PartitionInput $partition->setOperativeSystem($this->operativeSystem->getEntity()); $partition->setClient($this->client->getEntity()); $partition->setMemoryUsage($this->memoryUsage * 100); + $partition->setImage($this->image->getEntity()); return $partition; } diff --git a/src/Dto/Output/ClientOutput.php b/src/Dto/Output/ClientOutput.php index 78ee199..a43f212 100644 --- a/src/Dto/Output/ClientOutput.php +++ b/src/Dto/Output/ClientOutput.php @@ -64,6 +64,9 @@ final class ClientOutput extends AbstractOutput #[Groups(['client:read'])] public ?string $createdBy = null; + #[Groups(['client:read'])] + public ?bool $maintenance = false; + public function __construct(Client $client) { parent::__construct($client); @@ -90,5 +93,6 @@ final class ClientOutput extends AbstractOutput $this->status = $client->getStatus(); $this->createdAt = $client->getCreatedAt(); $this->createdBy = $client->getCreatedBy(); + $this->maintenance = $client->isMaintenance(); } } \ No newline at end of file diff --git a/src/Dto/Output/ImageOutput.php b/src/Dto/Output/ImageOutput.php index f14e16a..acbdff7 100644 --- a/src/Dto/Output/ImageOutput.php +++ b/src/Dto/Output/ImageOutput.php @@ -19,7 +19,7 @@ final class ImageOutput extends AbstractOutput public ?string $comments = ''; #[Groups(['image:read'])] - public ?string $type = ''; + public ?string $type = null; #[Groups(['image:read'])] public ?string $path = ''; @@ -39,6 +39,9 @@ final class ImageOutput extends AbstractOutput #[Groups(['image:read'])] public ?SoftwareProfileOutput $softwareProfile = null; + #[Groups(['image:read'])] + public ?OrganizationalUnitOutput $organizationalUnit = null; + public function __construct(Image $image) { parent::__construct($image); @@ -53,5 +56,6 @@ final class ImageOutput extends AbstractOutput $this->size = $image->getSize(); $this->clientOutput = new ClientOutput($image->getClient()); $this->softwareProfile = new SoftwareProfileOutput($image->getSoftwareProfile()); + $this->organizationalUnit = new OrganizationalUnitOutput($image->getOrganizationalUnit()); } } \ No newline at end of file diff --git a/src/Entity/Client.php b/src/Entity/Client.php index 0c7a20f..4c4a2ce 100644 --- a/src/Entity/Client.php +++ b/src/Entity/Client.php @@ -68,6 +68,9 @@ class Client extends AbstractEntity #[ORM\ManyToOne(inversedBy: 'clients')] private ?OgLive $ogLive = null; + #[ORM\Column] + private ?bool $maintenance = null; + public function __construct() { parent::__construct(); @@ -283,4 +286,16 @@ class Client extends AbstractEntity return $this; } + + public function isMaintenance(): ?bool + { + return $this->maintenance; + } + + public function setMaintenance(bool $maintenance): static + { + $this->maintenance = $maintenance; + + return $this; + } } diff --git a/src/Entity/Image.php b/src/Entity/Image.php index 5d41052..bd25a0a 100644 --- a/src/Entity/Image.php +++ b/src/Entity/Image.php @@ -3,6 +3,8 @@ namespace App\Entity; use App\Repository\ImageRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: ImageRepository::class)] @@ -16,10 +18,10 @@ class Image extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $comments = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $path = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 255, nullable: true)] private ?string $type = null; #[ORM\Column(length: 255, nullable: true)] @@ -28,7 +30,7 @@ class Image extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $info = null; - #[ORM\Column] + #[ORM\Column(length: 255, nullable: true)] private ?int $size = null; #[ORM\ManyToOne] @@ -36,9 +38,25 @@ class Image extends AbstractEntity private ?Client $client = null; #[ORM\ManyToOne] - #[ORM\JoinColumn(nullable: false)] + #[ORM\JoinColumn(nullable: true)] private ?SoftwareProfile $softwareProfile = null; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'image', targetEntity: Partition::class)] + private Collection $partitions; + + #[ORM\ManyToOne(inversedBy: 'images')] + #[ORM\JoinColumn(nullable: false)] + private ?OrganizationalUnit $organizationalUnit = null; + + public function __construct() + { + parent::__construct(); + $this->partitions = new ArrayCollection(); + } + public function getDescription(): ?string { return $this->description; @@ -68,7 +86,7 @@ class Image extends AbstractEntity return $this->path; } - public function setPath(string $path): static + public function setPath(?string $path): static { $this->path = $path; @@ -80,7 +98,7 @@ class Image extends AbstractEntity return $this->type; } - public function setType(string $type): static + public function setType(?string $type): static { $this->type = $type; @@ -116,7 +134,7 @@ class Image extends AbstractEntity return $this->size; } - public function setSize(int $size): static + public function setSize(?int $size): static { $this->size = $size; @@ -146,4 +164,46 @@ class Image extends AbstractEntity return $this; } + + /** + * @return Collection + */ + public function getPartitions(): Collection + { + return $this->partitions; + } + + public function addPartition(Partition $partition): static + { + if (!$this->partitions->contains($partition)) { + $this->partitions->add($partition); + $partition->setImage($this); + } + + return $this; + } + + public function removePartition(Partition $partition): static + { + if ($this->partitions->removeElement($partition)) { + // set the owning side to null (unless already changed) + if ($partition->getImage() === $this) { + $partition->setImage(null); + } + } + + return $this; + } + + public function getOrganizationalUnit(): ?OrganizationalUnit + { + return $this->organizationalUnit; + } + + public function setOrganizationalUnit(?OrganizationalUnit $organizationalUnit): static + { + $this->organizationalUnit = $organizationalUnit; + + return $this; + } } diff --git a/src/Entity/OrganizationalUnit.php b/src/Entity/OrganizationalUnit.php index b0d5596..a7d2756 100644 --- a/src/Entity/OrganizationalUnit.php +++ b/src/Entity/OrganizationalUnit.php @@ -97,6 +97,12 @@ class OrganizationalUnit extends AbstractEntity #[ORM\Column] private ?bool $reserved = false; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'organizationalUnit', targetEntity: Image::class)] + private Collection $images; + public function __construct() { parent::__construct(); @@ -104,6 +110,7 @@ class OrganizationalUnit extends AbstractEntity $this->users = new ArrayCollection(); $this->clients = new ArrayCollection(); $this->softwareProfiles = new ArrayCollection(); + $this->images = new ArrayCollection(); } public function getDescription(): ?string @@ -429,4 +436,34 @@ class OrganizationalUnit extends AbstractEntity return $this; } + + /** + * @return Collection + */ + public function getImages(): Collection + { + return $this->images; + } + + public function addImage(Image $image): static + { + if (!$this->images->contains($image)) { + $this->images->add($image); + $image->setOrganizationalUnit($this); + } + + return $this; + } + + public function removeImage(Image $image): static + { + if ($this->images->removeElement($image)) { + // set the owning side to null (unless already changed) + if ($image->getOrganizationalUnit() === $this) { + $image->setOrganizationalUnit(null); + } + } + + return $this; + } } diff --git a/src/Entity/Partition.php b/src/Entity/Partition.php index 7795315..d96409b 100644 --- a/src/Entity/Partition.php +++ b/src/Entity/Partition.php @@ -37,6 +37,10 @@ class Partition extends AbstractEntity #[ORM\ManyToOne(inversedBy: 'partitions')] private ?OperativeSystem $operativeSystem = null; + #[ORM\ManyToOne(inversedBy: 'partitions')] + #[ORM\JoinColumn(nullable: false)] + private ?Image $image = null; + public function getDiskNumber(): ?int { return $this->diskNumber; @@ -144,4 +148,16 @@ class Partition extends AbstractEntity return $this; } + + public function getImage(): ?Image + { + return $this->image; + } + + public function setImage(?Image $image): static + { + $this->image = $image; + + return $this; + } } diff --git a/src/Factory/ClientFactory.php b/src/Factory/ClientFactory.php index 56e28da..b8f4b89 100644 --- a/src/Factory/ClientFactory.php +++ b/src/Factory/ClientFactory.php @@ -32,6 +32,7 @@ final class ClientFactory extends ModelFactory 'createdAt' => self::faker()->dateTime(), 'name' => self::faker()->text(255), 'updatedAt' => self::faker()->dateTime(), + 'maintenance' => self::faker()->boolean(), ]; } diff --git a/src/Factory/ImageFactory.php b/src/Factory/ImageFactory.php index 3a4962d..7e068af 100644 --- a/src/Factory/ImageFactory.php +++ b/src/Factory/ImageFactory.php @@ -3,6 +3,7 @@ namespace App\Factory; use App\Entity\Image; +use App\Model\OrganizationalUnitTypes; use App\Repository\ImageRepository; use Zenstruck\Foundry\ModelFactory; use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory; @@ -38,7 +39,7 @@ final class ImageFactory extends ModelFactory 'path' => self::faker()->text(255), 'size' => self::faker()->randomNumber(), 'softwareProfile' => SoftwareProfileFactory::new(), - 'type' => self::faker()->text(255), + 'organizationalUnit' => OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT])->_save(), 'updatedAt' => self::faker()->dateTime(), ]; } diff --git a/src/Factory/PartitionFactory.php b/src/Factory/PartitionFactory.php index bb3d736..d791b7c 100644 --- a/src/Factory/PartitionFactory.php +++ b/src/Factory/PartitionFactory.php @@ -43,6 +43,7 @@ final class PartitionFactory extends ModelFactory 'updatedAt' => self::faker()->dateTime(), 'operativeSystem' => OperativeSystemFactory::new(), 'client' => ClientFactory::new(), + 'image' => ImageFactory::new(), ]; } diff --git a/src/OpenApi/OpenApiFactory.php b/src/OpenApi/OpenApiFactory.php index 8889728..76165c1 100644 --- a/src/OpenApi/OpenApiFactory.php +++ b/src/OpenApi/OpenApiFactory.php @@ -20,6 +20,7 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface $this->addRefreshToken($openApi); $this->addOgAgentEndpoints($openApi); + $this->addUDsEndpoints($openApi); $this->addStatusEndpoint($openApi); $this->addInstallOgLiveWebhookEndpoint($openApi); @@ -704,6 +705,89 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface )); } + private function addUDsEndpoints(OpenApi $openApi): void + { + $openApi->getPaths()->addPath('/opengnsys/rest//ous', (new Model\PathItem())->withGet( + (new Model\Operation('getOUs')) + ->withTags(['Organizational Unit']) + ->withSummary('Obtener todas las Unidades Organizacionales') + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Lista de Unidades Organizacionales', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'name' => [ + 'type' => 'string', + 'example' => 'Nombre de la Unidad Organizacional', + ], + 'description' => [ + 'type' => 'string', + 'example' => 'Descripción de la Unidad Organizacional', + ] + ] + ] + ] + ] + ] + ] + ]) + )); + + $openApi->getPaths()->addPath('/opengnsys/rest//ous/{centerId}/labs', (new Model\PathItem())->withGet( + (new Model\Operation('getClassrooms')) + ->withTags(['Organizational Unit']) + ->withSummary('Obtener los laboratorios de una Unidad Organizacional específica') + ->withParameters([ + new Model\Parameter( + 'centerId', + 'path', + 'El ID de la Unidad Organizacional', + true, + false, + ) + ]) + ->withResponses([ + Response::HTTP_OK => [ + 'description' => 'Lista de Laboratorios', + 'content' => [ + 'application/json' => [ + 'schema' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'type' => 'integer', + 'example' => 1, + ], + 'name' => [ + 'type' => 'string', + 'example' => 'Nombre del Laboratorio', + ], + 'description' => [ + 'type' => 'string', + 'example' => 'Descripción del Laboratorio', + ] + ] + ] + ] + ] + ] + ] + ]) + )); + } + + private function addInstallOgLiveWebhookEndpoint(OpenApi $openApi): void { $openApi diff --git a/src/Service/UDS/UDSClient.php b/src/Service/UDS/UDSClient.php index 071cc56..23f9286 100644 --- a/src/Service/UDS/UDSClient.php +++ b/src/Service/UDS/UDSClient.php @@ -47,7 +47,7 @@ class UDSClient continue; } - $classroom = $servicePoolInfo['ou']; + $classroom = $servicePoolInfo['lab']; $maxAvailableSeats = $this->getMaxAvailableSeats($classroom); $servicePool['max_srvs'] = $maxAvailableSeats; $servicePool['osmanager_id'] = null; @@ -156,6 +156,9 @@ class UDSClient $totalAvailableClients = 0; foreach ($organizationalUnit->getClients() as $client) { + if ($client->isMaintenance()) { + continue; + } $status = $client->getStatus(); $clientAvailable = in_array($status, ['active', 'windows', 'linux']); diff --git a/tests/Functional/ImageTest.php b/tests/Functional/ImageTest.php index b4e95fc..93eb45d 100644 --- a/tests/Functional/ImageTest.php +++ b/tests/Functional/ImageTest.php @@ -8,8 +8,10 @@ use App\Entity\OrganizationalUnit; use App\Entity\SoftwareProfile; use App\Factory\ClientFactory; use App\Factory\ImageFactory; +use App\Factory\OrganizationalUnitFactory; use App\Factory\SoftwareProfileFactory; use App\Factory\UserFactory; +use App\Model\OrganizationalUnitTypes; use App\Model\UserGroupPermissions; use Symfony\Component\HttpFoundation\Response; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; @@ -68,13 +70,16 @@ class ImageTest extends AbstractTest SoftwareProfileFactory::createOne(['description' => self::SOFTWARE_PROFILE]); $swPIri = $this->findIriBy(SoftwareProfile::class, ['description' => self::SOFTWARE_PROFILE]); + OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT]); + $ouIri = $this->findIriBy(OrganizationalUnit::class, ['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT]); + $this->createClientWithCredentials()->request('POST', '/images',['json' => [ 'name' => self::IMAGE_CREATE, 'size' => 123, 'path' => '/path/to/image', - 'type' => 'type', 'client' => $clientIri, - 'softwareProfile' => $swPIri + 'softwareProfile' => $swPIri, + 'organizationalUnit' => $ouIri, ]]); $this->assertResponseStatusCodeSame(201); diff --git a/tests/Functional/PartitionTest.php b/tests/Functional/PartitionTest.php index 39debe4..e587484 100644 --- a/tests/Functional/PartitionTest.php +++ b/tests/Functional/PartitionTest.php @@ -3,11 +3,13 @@ namespace Functional; use App\Entity\Client; +use App\Entity\Image; use App\Entity\Menu; use App\Entity\OperativeSystem; use App\Entity\Partition; use App\Factory\ClientFactory; use App\Factory\HardwareProfileFactory; +use App\Factory\ImageFactory; use App\Factory\MenuFactory; use App\Factory\OperativeSystemFactory; use App\Factory\OrganizationalUnitFactory; @@ -73,9 +75,13 @@ class PartitionTest extends AbstractTest OperativeSystemFactory::createOne(['name' => 'Ubuntu']); $osIri = $this->findIriBy(OperativeSystem::class, ['name' => 'Ubuntu']); + ImageFactory::createOne(['name' => 'Image 1']); + $imageIri = $this->findIriBy(Image::class, ['name' => 'Image 1']); + $this->createClientWithCredentials()->request('POST', '/partitions',['json' => [ 'size' => 100, 'operativeSystem' => $osIri, + 'image' => $imageIri, 'client' => $iri, 'memoryUsage' => 100 ]]);