diff --git a/composer.json b/composer.json index 7b5857e..718373a 100644 --- a/composer.json +++ b/composer.json @@ -4,17 +4,16 @@ "minimum-stability": "stable", "prefer-stable": true, "require": { - "php": ">=7.2.0", + "php": ">=8.1", "ext-ctype": "*", "ext-iconv": "*", "doctrine/annotations": "^1.6", "doctrine/doctrine-bundle": "^2.0", "doctrine/doctrine-migrations-bundle": "^3.0", "doctrine/orm": "^2.7", + "nelmio/api-doc-bundle": "^4.9", "phpdocumentor/reflection-docblock": "^5.0", "phpstan/phpdoc-parser": "^0.4", - "zircote/swagger-php": "3.*", - "symfony/runtime": "5.*", "symfony/asset": "5.*", "symfony/console": "5.*", "symfony/doctrine-messenger": "5.*", @@ -32,6 +31,7 @@ "symfony/process": "5.*", "symfony/property-access": "5.*", "symfony/property-info": "5.*", + "symfony/runtime": "5.*", "symfony/security-bundle": "5.*", "symfony/serializer": "5.*", "symfony/string": "5.*", @@ -41,7 +41,8 @@ "symfony/web-link": "5.*", "symfony/yaml": "5.*", "twig/extra-bundle": "^2.12|^3.0", - "twig/twig": "^2.12|^3.0" + "twig/twig": "^2.12|^3.0", + "zircote/swagger-php": "3.*" }, "require-dev": { "phpunit/phpunit": "^8.5", diff --git a/config/packages/nelmio_api_doc.yaml b/config/packages/nelmio_api_doc.yaml new file mode 100644 index 0000000..79d6609 --- /dev/null +++ b/config/packages/nelmio_api_doc.yaml @@ -0,0 +1,9 @@ +nelmio_api_doc: + documentation: + info: + title: My App + description: This is an awesome app! + version: 1.0.0 + areas: # to filter documented areas + path_patterns: + - ^/ogdhcp/ # Accepts routes under /api except /api/doc diff --git a/src/DhcpBundle/Controller/DhcpController.php b/src/DhcpBundle/Controller/DhcpController.php index 525835d..496f7b4 100644 --- a/src/DhcpBundle/Controller/DhcpController.php +++ b/src/DhcpBundle/Controller/DhcpController.php @@ -20,6 +20,21 @@ class DhcpController * @OA\Info(title="Ogdhcp API", version="1.0") */ + /** + * @OA\Schema( + * schema="Subnet", + * type="object", + * @OA\Property(property="id", type="integer", description="The ID of the subnet"), + * @OA\Property(property="subnet", type="string", description="The name of the subnet"), + * @OA\Property(property="next-server", type="string", description="The next server in the subnet"), + * @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"), + * @OA\Property( + * property="reservations", + * type="array", + * @OA\Items(type="object", description="The reservations in the subnet") + * ) + * ) + */ private $curlKeaService; public function __construct(CurlKeaService $curlKeaService, LoggerInterface $logger) @@ -27,39 +42,148 @@ class DhcpController $this->curlKeaService = $curlKeaService; $this->logger = $logger; } - /** - * - * @OA\Schema( - * schema="Subnet", - * type="object", - * @OA\Property(property="id", type="integer", description="The ID of the subnet"), - * @OA\Property(property="subnet", type="string", description="The name of the subnet"), - * @OA\Property(property="next-server", type="string", description="The next server in the subnet"), - * @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"), - * @OA\Property( - * property="reservations", - * type="array", - * @OA\Items(type="object", description="The reservations in the subnet") - * ) - * ) + * @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"}) * @OA\Get( - * path="/opengnsys3/rest/dhcp/subnets", + * path="/ogdhcp/v1/status", + * summary="Get ogDHCP status", * @OA\Response( * response=200, - * description="Devuelve todas las subredes", + * description="Status retrieved successfully", * @OA\JsonContent( - * type="array", - * @OA\Items(ref="#/components/schemas/Subnet") + * type="object", + * @OA\Property(property="disk_usage", type="object", + * @OA\Property(property="total", type="string"), + * @OA\Property(property="used", type="string"), + * @OA\Property(property="available", type="string"), + * @OA\Property(property="percentage", type="string") + * ), + * @OA\Property(property="default_oglive", type="string"), + * @OA\Property(property="installed_oglives", type="array", @OA\Items(type="string")), + * @OA\Property(property="services_status", type="object", + * @OA\Property(property="dhcp_daemon", type="string"), + * @OA\Property(property="nginx", type="string"), + * @OA\Property(property="tftpboot", type="string") + * ) * ) - * ), - * @OA\Response( - * response=400, - * description="Error al obtener las subredes", * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets", methods={"GET"}) */ + public function getDhcpStatus(): Response + { + // Obtener el uso de disco + $diskUsageResult = $this->getDiskUsage(); + if (!$diskUsageResult) { + return new JsonResponse(['error' => 'Failed to retrieve disk usage'], Response::HTTP_INTERNAL_SERVER_ERROR); + } + + // Obtener el estado de los servicios de ogDHCP (similar a check_services_status en ogboot) + $servicesStatusResult = $this->getServicesStatus(); + if (!$servicesStatusResult) { + return new JsonResponse(['error' => 'Failed to retrieve services status'], Response::HTTP_INTERNAL_SERVER_ERROR); + } + // Obtener las subredes y las reservas asociadas + $subnetsResult = $this->getSubnetsService(); + if (!$subnetsResult) { + return new JsonResponse(['error' => 'Failed to retrieve subnets'], Response::HTTP_INTERNAL_SERVER_ERROR); + } + // Componer la respuesta + $response = [ + 'disk_usage' => $diskUsageResult, + 'subnets' => $subnetsResult, + 'services_status' => $servicesStatusResult + ]; + + return new JsonResponse($response, Response::HTTP_OK); + } + + private function getDiskUsage(): array + { + // Simular la salida del comando df para obtener el uso del disco + $output = shell_exec("df -h /opt/ogdhcp | tail -1 | awk '{print $2, $3, $4, $5}'"); + if (!$output) { + $this->logger->error("Failed to execute disk usage command"); + return null; + } + + list($total, $used, $available, $percentage) = explode(' ', $output); + return [ + 'total' => trim($total), + 'used' => trim($used), + 'available' => trim($available), + 'percentage' => trim($percentage), + ]; + } + + + private function getServicesStatus(): array + { + $services = [ + 'tftpboot' => 'active', + 'nginx' => 'active', + ]; + + return $services; + } + private function getSubnetsService(): ?array + { + try { + $response = $this->curlRequestService->executeCurlCommand('config-get'); + + if (!$response) { + $this->logger->error('Error: No se pudo acceder al archivo de configuración Kea.'); + return null; + } + + $result_code = $response[0]["result"]; + if ($result_code == 0) { + if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) { + $this->logger->error("El campo 'subnet4' no está inicializado"); + return null; + } else { + return $response[0]['arguments']['Dhcp4']['subnet4']; // Subredes y sus reservas + } + } else { + $this->logger->error("Error en la configuración Kea: " . $response[0]["text"]); + return null; + } + } catch (\Exception $e) { + $this->logger->error("Error al obtener la configuración de Kea DHCP: " . $e->getMessage()); + return null; + } + } + + /** + * @OA\Schema( + * schema="Subnet", + * type="object", + * @OA\Property(property="id", type="integer", description="The ID of the subnet"), + * @OA\Property(property="subnet", type="string", description="The name of the subnet"), + * @OA\Property(property="next-server", type="string", description="The next server in the subnet"), + * @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"), + * @OA\Property( + * property="reservations", + * type="array", + * @OA\Items(type="object", description="The reservations in the subnet") + * ) + * ) + */ + + +/** + * @OA\Get( + * path="/ogdhcp/v1/subnets", + * @OA\Response( + * response=200, + * description="Devuelve todas las subredes", + * ), + * @OA\Response( + * response=400, + * description="Error al obtener las subredes", + * ) + * ) + * @Route("/ogdhcp/v1/subnets", methods={"GET"}) + */ public function getSubnets(): JsonResponse { try { @@ -91,7 +215,7 @@ class DhcpController /** * @OA\Post( - * path="/opengnsys3/rest/dhcp/subnets", + * path="/ogdhcp/v1/subnets", * summary="Add a new DHCP subnet", * @OA\RequestBody( * description="JSON payload", @@ -122,7 +246,7 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets", methods={"POST"}) + * @Route("/ogdhcp/v1/subnets", methods={"POST"}) */ public function addDhcpSubnet(Request $request): JsonResponse { @@ -160,11 +284,11 @@ class DhcpController if ($exists) { $responseError = "Error: La subred el subnet '$subnetName' ya existe en las subredes"; return new JsonResponse(['error' => $responseError], 400); - } else { - $response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet; - $array_encoded = json_encode($response[0]['arguments']); + } else { + $response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet; + $array_encoded = json_encode($response[0]['arguments']); $configurationParsed = str_replace('\\', '', $array_encoded); - $configuration = json_decode($configurationParsed); + $configuration = json_decode($configurationParsed); $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration); if ($responseTest[0]["result"] == 0) { @@ -192,13 +316,11 @@ class DhcpController return new JsonResponse(['error' => $responseError], 400); } } - - - + /** - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"DELETE"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"DELETE"}) * @OA\Delete( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}", + * path="/ogdhcp/v1/subnets/{subnetId}", * summary="Delete a DHCP subnet", * @OA\Parameter( * name="subnetId", @@ -226,8 +348,9 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"DELETE"}) */ + + public function deleteDhcpSubnet(Request $request): JsonResponse { $subnetId = (int) $request->get('subnetId'); @@ -281,9 +404,9 @@ class DhcpController /** - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"PUT"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"PUT"}) * @OA\Put( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}", + * path="/ogdhcp/v1/subnets/{subnetId}", * summary="Modify a DHCP subnet", * @OA\Parameter( * name="subnetId", @@ -322,7 +445,6 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"PUT"}) */ public function modifyDhcpSubnet(Request $request): JsonResponse { @@ -392,17 +514,9 @@ class DhcpController } } - /** - * @OA\Schema( - * schema="Host", - * type="object", - * @OA\Property(property="host", type="string", example="pc11"), - * @OA\Property(property="macAddress", type="string", example="56:6f:c7:4f:00:4f"), - * @OA\Property(property="address", type="string", example="172.30.4.11") - * ) * @OA\Get( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", + * path="/ogdhcp/v1/subnets/{subnetId}/hosts", * summary="Get all hosts in a subnet", * @OA\Parameter( * name="subnetId", @@ -414,10 +528,6 @@ class DhcpController * @OA\Response( * response=200, * description="List of hosts in the subnet", - * @OA\JsonContent( - * type="array", - * @OA\Items(ref="#/components/schemas/Host") - * ) * ), * @OA\Response( * response=400, @@ -436,7 +546,7 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"GET"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"GET"}) */ public function getHosts($subnetId): JsonResponse { @@ -475,9 +585,8 @@ class DhcpController /** - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"POST"}) * @OA\Post( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", + * path="/ogdhcp/v1/subnets/{subnetId}/hosts", * summary="Add a DHCP host to a subnet", * @OA\Parameter( * name="subnetId", @@ -515,7 +624,7 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"POST"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"POST"}) */ public function addDhcpHost(Request $request): JsonResponse { @@ -597,7 +706,7 @@ class DhcpController /** * @OA\Delete( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", + * path="/ogdhcp/v1/subnets/{subnetId}/hosts", * summary="Delete a DHCP host from a specific subnet", * @OA\Parameter( * name="subnetId", @@ -631,7 +740,7 @@ class DhcpController * ) * ) * ) - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"DELETE"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"DELETE"}) */ public function deleteDhcpHost(Request $request, $subnetId): JsonResponse { @@ -702,7 +811,7 @@ class DhcpController /** * @OA\Put( - * path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", + * path="/ogdhcp/v1/subnets/{subnetId}/hosts", * summary="Update a DHCP host", * @OA\Parameter( * name="subnetId", @@ -741,7 +850,7 @@ class DhcpController * ) * ) * - * @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"PUT"}) + * @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"PUT"}) */ public function updateDhcpHost(Request $request, $subnetId): JsonResponse { @@ -824,9 +933,6 @@ class DhcpController } } - /** - * @Route("/opengnsys3/rest/dhcp/backup", methods={"POST"}) - */ public function restoreDhcpConfiguration(): JsonResponse { $backup_dir = '/opt/opengnsys/etc/kea/backup';