refs #812 #814 adds some 500 code exits, adds new endpoint to get last backup content. Adds swagger documentation of restoreBackup.
testing/og-dhcp-API/pipeline/head There was a failure building this commit
Details
testing/og-dhcp-API/pipeline/head There was a failure building this commit
Details
parent
ff1449ff33
commit
b1d2f2eb22
|
|
@ -276,139 +276,149 @@ public function getSubnets(): JsonResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @OA\Post(
|
* @OA\Post(
|
||||||
* path="/ogdhcp/v1/subnets",
|
* path="/ogdhcp/v1/subnets",
|
||||||
* summary="Add a new DHCP subnet",
|
* summary="Add a new DHCP subnet",
|
||||||
* @OA\RequestBody(
|
* @OA\RequestBody(
|
||||||
* description="JSON payload to create a new subnet",
|
* description="JSON payload to create a new subnet",
|
||||||
* required=true,
|
* required=true,
|
||||||
* @OA\JsonContent(
|
* @OA\JsonContent(
|
||||||
* type="object",
|
* type="object",
|
||||||
* @OA\Property(property="subnetId", type="integer", example=2),
|
* @OA\Property(property="subnetId", type="integer", example=2),
|
||||||
* @OA\Property(property="mask", type="string", example="255.255.255.0"),
|
* @OA\Property(property="mask", type="string", example="255.255.255.0"),
|
||||||
* @OA\Property(property="address", type="string", example="192.168.1.0"),
|
* @OA\Property(property="address", type="string", example="192.168.1.0"),
|
||||||
* @OA\Property(property="nextServer", type="string", example="192.168.1.1"),
|
* @OA\Property(property="nextServer", type="string", example="192.168.1.1"),
|
||||||
* @OA\Property(property="bootFileName", type="string", example="pxelinux.0")
|
* @OA\Property(property="bootFileName", type="string", example="pxelinux.0")
|
||||||
* )
|
* )
|
||||||
* ),
|
* ),
|
||||||
* @OA\Response(
|
* @OA\Response(
|
||||||
* response=200,
|
* response=200,
|
||||||
* description="Subnet added successfully",
|
* description="Subnet added successfully and returns the created subnet",
|
||||||
* @OA\JsonContent(
|
* @OA\JsonContent(
|
||||||
* type="object",
|
* type="object",
|
||||||
* @OA\Property(property="success", type="string", example="Subnet added successfully"),
|
* @OA\Property(property="success", type="string", example="Subnet added successfully"),
|
||||||
* @OA\Property(property="message", type="object",
|
* @OA\Property(property="message", type="object",
|
||||||
* @OA\Property(property="subnetId", type="integer", example=2),
|
* @OA\Property(property="subnetId", type="integer", example=2),
|
||||||
* @OA\Property(property="subnet", type="string", example="192.168.1.0/24"),
|
* @OA\Property(property="subnet", type="string", example="192.168.1.0/24"),
|
||||||
* @OA\Property(property="nextServer", type="string", example="192.168.1.1"),
|
* @OA\Property(property="nextServer", type="string", example="192.168.1.1"),
|
||||||
* @OA\Property(property="bootFileName", type="string", example="pxelinux.0"),
|
* @OA\Property(property="bootFileName", type="string", example="pxelinux.0"),
|
||||||
* @OA\Property(property="reservations", type="array", @OA\Items(type="object"))
|
* @OA\Property(property="reservations", type="array", @OA\Items(type="object"))
|
||||||
* )
|
* )
|
||||||
* )
|
* )
|
||||||
* ),
|
* ),
|
||||||
* @OA\Response(
|
* @OA\Response(
|
||||||
* response=400,
|
* response=400,
|
||||||
* description="Error occurred while adding the subnet",
|
* description="Error occurred while adding the subnet",
|
||||||
* @OA\JsonContent(
|
* @OA\JsonContent(
|
||||||
* type="object",
|
* type="object",
|
||||||
* @OA\Property(property="error", type="string", example="Error: La subred con el nombre 'subnetName' ya existe.")
|
* @OA\Property(property="error", type="string", example="Error: La subred con el nombre 'subnetName' ya existe.")
|
||||||
* )
|
* )
|
||||||
* ),
|
* ),
|
||||||
* @OA\Response(
|
* @OA\Response(
|
||||||
* response=400,
|
* response=400,
|
||||||
* description="Error occurred while adding the subnet",
|
* description="Error occurred while adding the subnet",
|
||||||
* @OA\JsonContent(
|
* @OA\JsonContent(
|
||||||
* type="object",
|
* type="object",
|
||||||
* @OA\Property(property="error", type="string", example="Error: La subred con el ID 'subnetId' ya existe.")
|
* @OA\Property(property="error", type="string", example="Error: La subred con el ID 'subnetId' ya existe.")
|
||||||
* )
|
* )
|
||||||
* )
|
* )
|
||||||
* )
|
* )
|
||||||
* @Route("/ogdhcp/v1/subnets", methods={"POST"})
|
* @Route("/ogdhcp/v1/subnets", methods={"POST"})
|
||||||
*/
|
*/
|
||||||
|
public function addDhcpSubnet(Request $request): JsonResponse
|
||||||
public function addDhcpSubnet(Request $request): JsonResponse
|
{
|
||||||
{
|
try {
|
||||||
try {
|
$input = json_decode($request->getContent());
|
||||||
$input = json_decode($request->getContent());
|
$subnetId = (int) htmlspecialchars($input->subnetId);
|
||||||
$subnetId = (int) htmlspecialchars($input->subnetId);
|
$mask = htmlspecialchars($input->mask);
|
||||||
$mask = htmlspecialchars($input->mask);
|
$address = htmlspecialchars($input->address);
|
||||||
$address = htmlspecialchars($input->address);
|
$nextServer = htmlspecialchars($input->nextServer);
|
||||||
$nextServer = htmlspecialchars($input->nextServer);
|
$bootFileName = htmlspecialchars($input->bootFileName);
|
||||||
$bootFileName = htmlspecialchars($input->bootFileName);
|
} catch (Exception $e) {
|
||||||
} catch (Exception $e) {
|
return new JsonResponse(['error' => $e->getMessage()], 400);
|
||||||
$response["message"] = $e->getMessage();
|
|
||||||
return new JsonResponse(['error' => $response], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$response = $this->curlKeaService->executeCurlCommand('config-get');
|
|
||||||
$subnetName = $address . '/' . $this->curlKeaService->convertMaskToCIDR($mask);
|
|
||||||
$newSubnet = [
|
|
||||||
"id" => $subnetId,
|
|
||||||
"subnet" => $subnetName,
|
|
||||||
"next-server" => $nextServer,
|
|
||||||
"boot-file-name" => $bootFileName,
|
|
||||||
"reservations" => []
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
|
|
||||||
$response[0]['arguments']['Dhcp4']['subnet4'] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$subnets = $response[0]['arguments']['Dhcp4']['subnet4'];
|
|
||||||
|
|
||||||
// Verificar si el nombre de la subred o el ID ya existe
|
|
||||||
$subnetNameExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetName) {
|
|
||||||
return $exists || ($subnetElement['subnet'] === $subnetName);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
$subnetIdExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetId) {
|
|
||||||
return $exists || ($subnetElement['id'] === $subnetId);
|
|
||||||
}, false);
|
|
||||||
if ($subnetNameExists) {
|
|
||||||
$responseError = "Error: La subred con el nombre '$subnetName' ya existe.";
|
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
|
||||||
} elseif ($subnetIdExists) {
|
|
||||||
$responseError = "Error: La subred con el ID '$subnetId' ya existe.";
|
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
|
||||||
} else {
|
|
||||||
$response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;
|
|
||||||
// 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) {
|
|
||||||
$responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
|
|
||||||
if ($responseSet == false || $responseSet[0]["result"] != 0) {
|
|
||||||
$responseError = "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"];
|
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
|
||||||
} else {
|
|
||||||
$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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$responseError = "Error kea configuration invalid: " . $responseTest[0]["text"];
|
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$responseError = "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
|
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $this->curlKeaService->executeCurlCommand('config-get');
|
||||||
|
$subnetName = $address . '/' . $this->curlKeaService->convertMaskToCIDR($mask);
|
||||||
|
$newSubnet = [
|
||||||
|
"id" => $subnetId,
|
||||||
|
"subnet" => $subnetName,
|
||||||
|
"next-server" => $nextServer,
|
||||||
|
"boot-file-name" => $bootFileName,
|
||||||
|
"reservations" => []
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
|
||||||
|
$response[0]['arguments']['Dhcp4']['subnet4'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$subnets = $response[0]['arguments']['Dhcp4']['subnet4'];
|
||||||
|
|
||||||
|
// Verificar si el nombre de la subred o el ID ya existe
|
||||||
|
$subnetNameExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetName) {
|
||||||
|
return $exists || ($subnetElement['subnet'] === $subnetName);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
$subnetIdExists = array_reduce($subnets, function ($exists, $subnetElement) use ($subnetId) {
|
||||||
|
return $exists || ($subnetElement['id'] === $subnetId);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if ($subnetNameExists) {
|
||||||
|
return new JsonResponse(['error' => "Error: La subred con el nombre '$subnetName' ya existe."], 400);
|
||||||
|
} elseif ($subnetIdExists) {
|
||||||
|
return new JsonResponse(['error' => "Error: La subred con el ID '$subnetId' ya existe."], 400);
|
||||||
|
} else {
|
||||||
|
$response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
$responseSet = $this->curlKeaService->executeCurlCommand('config-set', $configuration);
|
||||||
|
if ($responseSet == false || $responseSet[0]["result"] != 0) {
|
||||||
|
return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseSet[0]["text"]], 400);
|
||||||
|
} else {
|
||||||
|
$responseWrite = $this->curlKeaService->executeCurlCommand('config-write', $configuration);
|
||||||
|
if ($responseWrite == false || $responseWrite[0]["result"] != 0) {
|
||||||
|
return new JsonResponse(['error' => "Error al guardar la configuración en Kea DHCP: " . $responseWrite[0]["text"]], 400);
|
||||||
|
} else {
|
||||||
|
// Realizar una nueva consulta a Kea para obtener la subred recién creada
|
||||||
|
$configGetResponse = $this->curlKeaService->executeCurlCommand('config-get');
|
||||||
|
|
||||||
|
// Buscar la subred creada
|
||||||
|
$createdSubnet = null;
|
||||||
|
foreach ($configGetResponse[0]['arguments']['Dhcp4']['subnet4'] as $subnet) {
|
||||||
|
if ($subnet['id'] == $subnetId) {
|
||||||
|
$createdSubnet = $subnet;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($createdSubnet === null) {
|
||||||
|
return new JsonResponse(['error' => "Error: No se pudo encontrar la subred creada."], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResponse(['success' => "Subred agregada correctamente", 'message' => $createdSubnet], 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new JsonResponse(['error' => "Error en la configuración de Kea: " . $responseTest[0]["text"]], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return new JsonResponse(['error' => "Error al obtener la configuración de Kea DHCP: " . $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @OA\Delete(
|
* @OA\Delete(
|
||||||
* path="/ogdhcp/v1/subnets/{subnetId}",
|
* path="/ogdhcp/v1/subnets/{subnetId}",
|
||||||
|
|
@ -508,7 +518,7 @@ public function getSubnets(): JsonResponse
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$responseError = "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
|
$responseError = "Error al obtener la configuración de Kea DHCP: " . $e->getMessage();
|
||||||
return new JsonResponse(['error' => $responseError], 400);
|
return new JsonResponse(['error' => $responseError], 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1090,6 +1100,140 @@ public function updateDhcpHost(Request $request, $subnetId): JsonResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Get(
|
||||||
|
* path="/ogdhcp/v1/subnets/backup",
|
||||||
|
* summary="Get the latest backup configuration of Kea DHCP (only subnet4)",
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Latest backup configuration of Kea DHCP",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="success", type="string", example="Backup configuration retrieved successfully"),
|
||||||
|
* @OA\Property(property="message", type="object",
|
||||||
|
* @OA\Property(property="subnet4", 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(
|
||||||
|
* response=400,
|
||||||
|
* description="Error occurred while retrieving the backup",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="error", type="string", example="No se encontraron archivos de backup")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* @Route("/ogdhcp/v1/subnets/backup", methods={"GET"})
|
||||||
|
*/
|
||||||
|
public function getLatestBackupConfiguration(): JsonResponse
|
||||||
|
{
|
||||||
|
$backup_dir = '/opt/ogdhcp/etc/kea/backup';
|
||||||
|
try {
|
||||||
|
// Obtener los archivos de backup
|
||||||
|
$backup_files = glob($backup_dir . '/*.conf');
|
||||||
|
if (empty($backup_files)) {
|
||||||
|
$responseError = "No se encontraron archivos de backup";
|
||||||
|
return new JsonResponse(['error' => $responseError], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ordenar por fecha de modificación y obtener el más reciente
|
||||||
|
usort($backup_files, function ($a, $b) {
|
||||||
|
return filemtime($b) - filemtime($a);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Leer el archivo más reciente
|
||||||
|
$backup_file = reset($backup_files);
|
||||||
|
$config = file_get_contents($backup_file);
|
||||||
|
$configuration = json_decode($config, true); // Decodificar como arreglo
|
||||||
|
|
||||||
|
if (!isset($configuration['Dhcp4']['subnet4'])) {
|
||||||
|
$responseError = "No se encontró el parámetro 'subnet4' en el backup";
|
||||||
|
return new JsonResponse(['error' => $responseError], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devolver solo el parámetro 'subnet4'
|
||||||
|
$responseSuccess = "Backup configuration retrieved successfully";
|
||||||
|
return new JsonResponse(['success' => $responseSuccess, 'message' => ['subnet4' => $configuration['Dhcp4']['subnet4']]], 200);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$responseError = "Error al obtener la configuración de backup: " . $e->getMessage();
|
||||||
|
return new JsonResponse(['error' => $responseError], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.",
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Configuration restored successfully",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="success", type="string", example="Configuración cargada correctamente")
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=400,
|
||||||
|
* description="Error occurred during the restore process",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="error", type="string", example="No se encontraron archivos de backup")
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=400,
|
||||||
|
* description="Error occurred during Kea configuration validation",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="error", type="string", example="Error al comprobar la configuración de Kea: unable to forward command to the dhcp4 service")
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=400,
|
||||||
|
* description="Error en el proceso de restauración",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* type="object",
|
||||||
|
* @OA\Property(property="error", type="string"),
|
||||||
|
* ),
|
||||||
|
* examples={
|
||||||
|
* "errorBackupNotFound": {
|
||||||
|
* "summary": "No se encontraron archivos de backup",
|
||||||
|
* "value": {
|
||||||
|
* "error": "No se encontraron archivos de backup"
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* "errorConfigTest": {
|
||||||
|
* "summary": "Error en la configuración de Kea",
|
||||||
|
* "value": {
|
||||||
|
* "error": "Error al comprobar la configuración de Kea: Error específico"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
* @Route("/ogdhcp/v1/backup/restore", methods={"POST"})
|
||||||
|
*/
|
||||||
|
|
||||||
public function restoreDhcpConfiguration(): JsonResponse
|
public function restoreDhcpConfiguration(): JsonResponse
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue