diff --git a/config/packages/nelmio_api_doc.yaml b/config/packages/nelmio_api_doc.yaml index 79d6609..880cf3e 100644 --- a/config/packages/nelmio_api_doc.yaml +++ b/config/packages/nelmio_api_doc.yaml @@ -1,9 +1,32 @@ nelmio_api_doc: documentation: info: - title: My App - description: This is an awesome app! + title: OgDHCP API + description: OgDHCP API documentation version: 1.0.0 + components: + schemas: + Subnet: + type: object + properties: + id: + type: integer + description: The ID of the subnet + subnet: + type: string + description: The name of the subnet + nextServer: + type: string + description: The next server in the subnet + bootFileName: + type: string + description: The boot file name for the subnet + reservations: + type: array + items: + type: object + description: The reservations in the subnet + 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 4bb588c..dbddbc2 100644 --- a/src/DhcpBundle/Controller/DhcpController.php +++ b/src/DhcpBundle/Controller/DhcpController.php @@ -16,25 +16,7 @@ use Exception; class DhcpController { private $logger; - /** - * @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) @@ -42,6 +24,8 @@ class DhcpController $this->curlKeaService = $curlKeaService; $this->logger = $logger; } + + /** * @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"}) * @OA\Get( @@ -337,22 +321,27 @@ public function getSubnets(): JsonResponse * @OA\JsonContent( * oneOf={ * @OA\Schema( - * @OA\Property(property="error", type="string", example="Error: La subred con el nombre 'subnetName' ya existe.") + * @OA\Property(property="error", type="string", example="La subred con el nombre 'subnetName' ya existe.") * ), * @OA\Schema( - * @OA\Property(property="error", type="string", example="Error: La subred con el ID 'subnetId' ya existe.") + * @OA\Property(property="error", type="string", example="La subred con el ID 'subnetId' ya existe.") * ) * } * ), * @OA\Examples( * example="nameConflict", * summary="Subnet name already exists", - * value={"error": "Error: La subred con el nombre 'subnetName' ya existe."} + * value={"error": "La subred con la ip 'subnetName' ya existe."} * ), * @OA\Examples( * example="idConflict", * summary="Subnet ID already exists", - * value={"error": "Error: La subred con el ID 'subnetId' ya existe."} + * value={"error": "La subred con el ID 'subnetId' ya existe."} + * ), + * @OA\Examples( + * example="subnetCreatedNotFound", + * summary="Subnet created not found", + * value={"error": "No se pudo encontrar la subred creada"} * ) * ), * @OA\Response( @@ -408,9 +397,9 @@ public function addDhcpSubnet(Request $request): JsonResponse }, false); if ($subnetNameExists) { - return new JsonResponse(['error' => "Error: La subred con el nombre '$subnetName' ya existe."], 400); + return new JsonResponse(['error' => "La subred con la ip '$subnetName' ya existe."], 400); } elseif ($subnetIdExists) { - return new JsonResponse(['error' => "Error: La subred con el ID '$subnetId' ya existe."], 400); + return new JsonResponse(['error' => "La subred con el ID '$subnetId' ya existe."], 400); } else { $response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet; @@ -446,7 +435,7 @@ public function addDhcpSubnet(Request $request): JsonResponse } if ($createdSubnet === null) { - return new JsonResponse(['error' => "Error: No se pudo encontrar la subred creada."], 400); + return new JsonResponse(['error' => "No se pudo encontrar la subred creada"], 400); } return new JsonResponse(['success' => "Subred agregada correctamente", 'message' => $createdSubnet], 200); @@ -525,7 +514,7 @@ public function addDhcpSubnet(Request $request): JsonResponse * description="Subnet not found", * @OA\JsonContent( * type="object", - * @OA\Property(property="error", type="string", example="Error: La subred con el id '2' no existe") + * @OA\Property(property="error", type="string", example="La subred con el id '2' no existe") * ) * ), * @OA\Response( @@ -556,7 +545,7 @@ public function addDhcpSubnet(Request $request): JsonResponse $subnetIndex = array_search($subnetId, array_column($response[0]['arguments']['Dhcp4']['subnet4'], 'id')); if ($subnetIndex === false) { - $responseError = "Error: La subred con el id '$subnetId' no existe"; + $responseError = "La subred con el id '$subnetId' no existe"; return new JsonResponse(['error' => $responseError], 404); } else { //Borramos la subred con ese id @@ -726,9 +715,14 @@ public function addDhcpSubnet(Request $request): JsonResponse "boot-file-name" => $bootFileName, "reservations" => [] ]; + // Eliminar el campo 'hash' si existe + if (isset($response[0]['arguments']['hash'])) { + unset($response[0]['arguments']['hash']); + } $array_encoded = json_encode($response[0]['arguments']); $configurationParsed = str_replace('\\', '', $array_encoded); $configuration = json_decode($configurationParsed); + $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration); if ($responseTest[0]["result"] == 0) { @@ -742,8 +736,14 @@ public function addDhcpSubnet(Request $request): JsonResponse $responseError = "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"]; return new JsonResponse(['error' => $responseError], 400); } else { + // Volvemos a consultar la configuración para devolver la subred modificada + $updatedResponse = $this->curlKeaService->executeCurlCommand('config-get'); + $updatedSubnet = array_filter($updatedResponse[0]['arguments']['Dhcp4']['subnet4'], function ($subnet) use ($subnetId) { + return $subnet['id'] == $subnetId; + }); + $responseSuccess = "Subred modificada correctamente"; - return new JsonResponse(['success' => $responseSuccess], 200); + return new JsonResponse(['success' => $responseSuccess,'subnet' => reset($updatedSubnet)], 200); } } } else { @@ -1262,7 +1262,7 @@ public function updateDhcpHost(Request $request, $subnetId): JsonResponse { try { $input = json_decode($request->getContent()); - $host = htmlspecialchars($input->host); + $host = htmlspecialchars($input->hostname); $oldMacAddress = htmlspecialchars($input->oldMacAddress); $macAddress = htmlspecialchars($input->macAddress); $address = htmlspecialchars($input->address); @@ -1422,27 +1422,44 @@ public function getLatestBackupConfiguration(): JsonResponse * @OA\Post( * path="/ogdhcp/v1/backup/restore", * summary="Restore the latest DHCP configuration from backup", - * description="This endpoint restores the last saved DHCP configuration from a backup file and applies it to the Kea DHCP server.", + * description="This endpoint restores the last saved DHCP configuration from a backup file and applies it to the Kea DHCP server, returning all currently loaded subnets.", * @OA\Response( * response=200, * description="Configuration restored successfully", * @OA\JsonContent( * type="object", - * @OA\Property(property="success", type="string", example="Configuración cargada correctamente") + * @OA\Property(property="success", type="string", example="Configuración cargada correctamente"), + * @OA\Property(property="subnets", type="array", + * @OA\Items( + * type="object", + * @OA\Property(property="id", type="integer", example=1), + * @OA\Property(property="subnet", type="string", example="192.168.1.0/24"), + * @OA\Property(property="pools", type="array", + * @OA\Items( + * type="object", + * @OA\Property(property="pool", type="string", example="192.168.1.10-192.168.1.100") + * ) + * ), + * @OA\Property(property="reservations", type="array", + * @OA\Items( + * type="object", + * @OA\Property(property="ip-address", type="string", example="192.168.1.20"), + * @OA\Property(property="hw-address", type="string", example="00:0c:29:6b:5e:71") + * ) + * ) + * ) + * ) * ) * ), -* @OA\Response( + * @OA\Response( * response=400, - * description="Error occurred while adding the host", + * description="Error occurred while restoring the configuration", * @OA\JsonContent( * oneOf={ * @OA\Schema( * @OA\Property(property="error", type="string", example="No se encontraron archivos de backup") * ), * @OA\Schema( - * @OA\Property(property="error", type="string", example="El host con la MAC '$mac' no existe en las reservaciones") - * ), - * @OA\Schema( * @OA\Property(property="error", type="string", example="Error configuracion de kea invalido") * ), * @OA\Schema( @@ -1459,11 +1476,6 @@ public function getLatestBackupConfiguration(): JsonResponse * value={"error": "No se encontraron archivos de backup"} * ), * @OA\Examples( - * example="hostNotFound", - * summary="Host not found", - * value={"error": "El host con la MAC '$mac' no existe en las reservaciones"} - * ), - * @OA\Examples( * example="invalidKea", * summary="Error in config-test in kea", * value={"error": "Error configuracion de kea invalido"} @@ -1478,55 +1490,66 @@ public function getLatestBackupConfiguration(): JsonResponse * summary="Error in config-write in kea", * value={"error": "Error al escribir en la configuración en Kea DHCP"} * ) - * ), + * ) * ) * @Route("/ogdhcp/v1/backup/restore", methods={"POST"}) */ +public function restoreDhcpConfiguration(): JsonResponse +{ + $backup_dir = '/opt/ogdhcp/etc/kea/backup'; + try { + $backup_files = glob($backup_dir . '/*.conf'); + if (empty($backup_files)) { + $response = "No se encontraron archivos de backup"; + return new JsonResponse(['error' => $response], 400); + } else { + usort($backup_files, function ($a, $b) { + return filemtime($b) - filemtime($a); + }); + $backup_file = reset($backup_files); + $config = file_get_contents($backup_file); + // Eliminar el campo 'hash' si existe + $configuration = json_decode($config); + if (isset($configuration->hash)) { + unset($configuration->hash); + } - public function restoreDhcpConfiguration(): JsonResponse - { - $backup_dir = '/opt/opengnsys/etc/kea/backup'; - try { - $backup_files = glob($backup_dir . '/*.conf'); - if (empty($backup_files)) { - $response = "No se encontraron archivos de backup"; - return new JsonResponse(['error' => $response], 400); + $test_command = 'config-test'; + $test_output = $this->curlKeaService->executeCurlCommand($test_command, $configuration); + if ($test_output == false || $test_output[0]["result"] != 0) { + $responseError = "Error al comprobar la configuración de Kea: " . $test_output[0]["text"]; + return new JsonResponse(['error' => $responseError], 400); } else { - usort($backup_files, function ($a, $b) { - return filemtime($b) - filemtime($a); - }); - $backup_file = reset($backup_files); - $config = file_get_contents($backup_file); - $configuration = json_decode($config); - $test_command = 'config-test'; - $test_output = $this->curlKeaService->executeCurlCommand($test_command, $configuration); - if ($test_output == false || $test_output[0]["result"] != 0) { - $responseError = "Error al comprobar la configuración de Kea: " . $test_output[0]["text"]; + $set_command = 'config-set'; + $set_output = $this->curlKeaService->executeCurlCommand($set_command, $configuration, false); + if ($set_output == false || $set_output[0]["result"] != 0) { + $responseError = "Error al guardar la última configuración de Kea: " . $set_output[0]["text"]; return new JsonResponse(['error' => $responseError], 400); } else { - $set_command = 'config-set'; - $set_output = $this->curlKeaService->executeCurlCommand($set_command, $configuration, false); - if ($set_output == false || $set_output[0]["result"] != 0) { - $responseError = "Error al guardar la última configuración de Kea: " . $set_output[0]["text"]; - return new JsonResponse(['error' => $responseError], 400); + unlink($backup_file); + $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration); + if ($responseWrite == false || $responseWrite[0]["result"] != 0) { + $responseError = "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"]; + return new JsonResponse(['error' => $responseError], 400); } else { - unlink($backup_file); - $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration); - if ($responseWrite == false || $responseWrite[0]["result"] != 0) { - $responseError = "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"]; - return new JsonResponse(['error' => $responseError], 400); - } else { - $responseSuccess = "Configuración cargada correctamente"; - return new JsonResponse(['success' => $responseSuccess], 200); + // Consultar las subredes cargadas + $config_get = $this->curlKeaService->executeCurlCommand('config-get'); + if ($config_get == false || $config_get[0]["result"] != 0) { + return new JsonResponse(['error' => 'Error al obtener la configuración de Kea DHCP'], 500); } + + $subnets = $config_get[0]['arguments']['Dhcp4']['subnet4'] ?? []; + return new JsonResponse(['success' => "Configuración cargada correctamente", 'subnets' => $subnets], 200); } } } - } catch (Exception $e) { - $responseError = "Error al restaurar la configuración: " . $e->getMessage(); - return new JsonResponse(['error' => $responseError], 400); } + } catch (Exception $e) { + $responseError = "Error al restaurar la configuración: " . $e->getMessage(); + return new JsonResponse(['error' => $responseError], 400); } +} + } diff --git a/src/DhcpBundle/Service/CurlKeaService.php b/src/DhcpBundle/Service/CurlKeaService.php index 6ecfa76..0f3bdb8 100644 --- a/src/DhcpBundle/Service/CurlKeaService.php +++ b/src/DhcpBundle/Service/CurlKeaService.php @@ -28,7 +28,8 @@ class CurlKeaService } else { return "Error: Comando no válido"; } - if (($command == 'config-set' || $command == 'config-write') && $create_backup) { + //f (($command == 'config-set' || $command == 'config-write') && $create_backup) { + if ($command == 'config-set' && $create_backup) { $this->backupConfig(); } $jsonData = json_encode($requestData);