refs #812 adds some unset hash, fix a bug in restore backup, adds in the 200 response the new subnets in the backup restore endpoint. Adds a new schema in nelmio yaml configuration and changes the project name
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details

nginx_conf
Luis Gerardo Romero Garcia 2024-10-08 16:55:13 +02:00
parent d68208357c
commit db9ce9c90e
3 changed files with 126 additions and 79 deletions

View File

@ -1,9 +1,32 @@
nelmio_api_doc: nelmio_api_doc:
documentation: documentation:
info: info:
title: My App title: OgDHCP API
description: This is an awesome app! description: OgDHCP API documentation
version: 1.0.0 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 areas: # to filter documented areas
path_patterns: path_patterns:
- ^/ogdhcp/ # Accepts routes under /api except /api/doc - ^/ogdhcp/ # Accepts routes under /api except /api/doc

View File

@ -16,25 +16,7 @@ use Exception;
class DhcpController class DhcpController
{ {
private $logger; 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; private $curlKeaService;
public function __construct(CurlKeaService $curlKeaService, LoggerInterface $logger) public function __construct(CurlKeaService $curlKeaService, LoggerInterface $logger)
@ -42,6 +24,8 @@ class DhcpController
$this->curlKeaService = $curlKeaService; $this->curlKeaService = $curlKeaService;
$this->logger = $logger; $this->logger = $logger;
} }
/** /**
* @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"}) * @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"})
* @OA\Get( * @OA\Get(
@ -337,22 +321,27 @@ public function getSubnets(): JsonResponse
* @OA\JsonContent( * @OA\JsonContent(
* oneOf={ * oneOf={
* @OA\Schema( * @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\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( * @OA\Examples(
* example="nameConflict", * example="nameConflict",
* summary="Subnet name already exists", * 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( * @OA\Examples(
* example="idConflict", * example="idConflict",
* summary="Subnet ID already exists", * 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( * @OA\Response(
@ -408,9 +397,9 @@ public function addDhcpSubnet(Request $request): JsonResponse
}, false); }, false);
if ($subnetNameExists) { 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) { } 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 { } else {
$response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet; $response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;
@ -446,7 +435,7 @@ public function addDhcpSubnet(Request $request): JsonResponse
} }
if ($createdSubnet === null) { 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); return new JsonResponse(['success' => "Subred agregada correctamente", 'message' => $createdSubnet], 200);
@ -525,7 +514,7 @@ public function addDhcpSubnet(Request $request): JsonResponse
* description="Subnet not found", * description="Subnet not found",
* @OA\JsonContent( * @OA\JsonContent(
* type="object", * 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( * @OA\Response(
@ -556,7 +545,7 @@ public function addDhcpSubnet(Request $request): JsonResponse
$subnetIndex = array_search($subnetId, array_column($response[0]['arguments']['Dhcp4']['subnet4'], 'id')); $subnetIndex = array_search($subnetId, array_column($response[0]['arguments']['Dhcp4']['subnet4'], 'id'));
if ($subnetIndex === false) { 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); return new JsonResponse(['error' => $responseError], 404);
} else { } else {
//Borramos la subred con ese id //Borramos la subred con ese id
@ -726,9 +715,14 @@ public function addDhcpSubnet(Request $request): JsonResponse
"boot-file-name" => $bootFileName, "boot-file-name" => $bootFileName,
"reservations" => [] "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']); $array_encoded = json_encode($response[0]['arguments']);
$configurationParsed = str_replace('\\', '', $array_encoded); $configurationParsed = str_replace('\\', '', $array_encoded);
$configuration = json_decode($configurationParsed); $configuration = json_decode($configurationParsed);
$responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration); $responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);
if ($responseTest[0]["result"] == 0) { 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"]; $responseError = "Error al escribir en la configuración en Kea DHCP: " . $responseWrite[0]["text"];
return new JsonResponse(['error' => $responseError], 400); return new JsonResponse(['error' => $responseError], 400);
} else { } 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"; $responseSuccess = "Subred modificada correctamente";
return new JsonResponse(['success' => $responseSuccess], 200); return new JsonResponse(['success' => $responseSuccess,'subnet' => reset($updatedSubnet)], 200);
} }
} }
} else { } else {
@ -1262,7 +1262,7 @@ public function updateDhcpHost(Request $request, $subnetId): JsonResponse
{ {
try { try {
$input = json_decode($request->getContent()); $input = json_decode($request->getContent());
$host = htmlspecialchars($input->host); $host = htmlspecialchars($input->hostname);
$oldMacAddress = htmlspecialchars($input->oldMacAddress); $oldMacAddress = htmlspecialchars($input->oldMacAddress);
$macAddress = htmlspecialchars($input->macAddress); $macAddress = htmlspecialchars($input->macAddress);
$address = htmlspecialchars($input->address); $address = htmlspecialchars($input->address);
@ -1422,27 +1422,44 @@ public function getLatestBackupConfiguration(): JsonResponse
* @OA\Post( * @OA\Post(
* path="/ogdhcp/v1/backup/restore", * path="/ogdhcp/v1/backup/restore",
* summary="Restore the latest DHCP configuration from backup", * 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( * @OA\Response(
* response=200, * response=200,
* description="Configuration restored successfully", * description="Configuration restored successfully",
* @OA\JsonContent( * @OA\JsonContent(
* type="object", * 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, * response=400,
* description="Error occurred while adding the host", * description="Error occurred while restoring the configuration",
* @OA\JsonContent( * @OA\JsonContent(
* oneOf={ * oneOf={
* @OA\Schema( * @OA\Schema(
* @OA\Property(property="error", type="string", example="No se encontraron archivos de backup") * @OA\Property(property="error", type="string", example="No se encontraron archivos de backup")
* ), * ),
* @OA\Schema( * @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\Property(property="error", type="string", example="Error configuracion de kea invalido")
* ), * ),
* @OA\Schema( * @OA\Schema(
@ -1459,11 +1476,6 @@ public function getLatestBackupConfiguration(): JsonResponse
* value={"error": "No se encontraron archivos de backup"} * value={"error": "No se encontraron archivos de backup"}
* ), * ),
* @OA\Examples( * @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", * example="invalidKea",
* summary="Error in config-test in kea", * summary="Error in config-test in kea",
* value={"error": "Error configuracion de kea invalido"} * value={"error": "Error configuracion de kea invalido"}
@ -1478,55 +1490,66 @@ public function getLatestBackupConfiguration(): JsonResponse
* summary="Error in config-write in kea", * summary="Error in config-write in kea",
* value={"error": "Error al escribir en la configuración en Kea DHCP"} * value={"error": "Error al escribir en la configuración en Kea DHCP"}
* ) * )
* ), * )
* ) * )
* @Route("/ogdhcp/v1/backup/restore", methods={"POST"}) * @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 $test_command = 'config-test';
{ $test_output = $this->curlKeaService->executeCurlCommand($test_command, $configuration);
$backup_dir = '/opt/opengnsys/etc/kea/backup'; if ($test_output == false || $test_output[0]["result"] != 0) {
try { $responseError = "Error al comprobar la configuración de Kea: " . $test_output[0]["text"];
$backup_files = glob($backup_dir . '/*.conf'); return new JsonResponse(['error' => $responseError], 400);
if (empty($backup_files)) {
$response = "No se encontraron archivos de backup";
return new JsonResponse(['error' => $response], 400);
} else { } else {
usort($backup_files, function ($a, $b) { $set_command = 'config-set';
return filemtime($b) - filemtime($a); $set_output = $this->curlKeaService->executeCurlCommand($set_command, $configuration, false);
}); if ($set_output == false || $set_output[0]["result"] != 0) {
$backup_file = reset($backup_files); $responseError = "Error al guardar la última configuración de Kea: " . $set_output[0]["text"];
$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"];
return new JsonResponse(['error' => $responseError], 400); return new JsonResponse(['error' => $responseError], 400);
} else { } else {
$set_command = 'config-set'; unlink($backup_file);
$set_output = $this->curlKeaService->executeCurlCommand($set_command, $configuration, false); $responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
if ($set_output == false || $set_output[0]["result"] != 0) { if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
$responseError = "Error al guardar la última configuración de Kea: " . $set_output[0]["text"]; $responseError = "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"];
return new JsonResponse(['error' => $responseError], 400); return new JsonResponse(['error' => $responseError], 400);
} else { } else {
unlink($backup_file); // Consultar las subredes cargadas
$responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration); $config_get = $this->curlKeaService->executeCurlCommand('config-get');
if ($responseWrite == false || $responseWrite[0]["result"] != 0) { if ($config_get == false || $config_get[0]["result"] != 0) {
$responseError = "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"]; return new JsonResponse(['error' => 'Error al obtener la configuración de Kea DHCP'], 500);
return new JsonResponse(['error' => $responseError], 400);
} else {
$responseSuccess = "Configuración cargada correctamente";
return new JsonResponse(['success' => $responseSuccess], 200);
} }
$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);
} }
}
} }

View File

@ -28,7 +28,8 @@ class CurlKeaService
} else { } else {
return "Error: Comando no válido"; 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(); $this->backupConfig();
} }
$jsonData = json_encode($requestData); $jsonData = json_encode($requestData);