2373 lines
90 KiB
PHP
2373 lines
90 KiB
PHP
<?php
|
|
// src/OgBootBundle/Controller/OgBootController.php
|
|
|
|
namespace App\OgBootBundle\Controller;
|
|
use OpenApi\Annotations as OA;
|
|
use Psr\Log\LoggerInterface;
|
|
use App\OgBootBundle\Service\CurlRequestService;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\Routing\Annotation\Route;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use App\OgBootBundle\Message\InstallOgliveMessage;
|
|
use Symfony\Component\Messenger\MessageBusInterface;
|
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
|
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|
use Symfony\Component\Process\Process;
|
|
use Exception;
|
|
|
|
|
|
class OgBootController
|
|
{
|
|
private $logger;
|
|
/**
|
|
* @OA\Info(title="Ogboot API", version="1.0")
|
|
*/
|
|
|
|
private $curlRequestService;
|
|
private $httpClient;
|
|
private $params;
|
|
private $tftpbootDir;
|
|
public function __construct(CurlRequestService $curlRequestService, LoggerInterface $logger, HttpClientInterface $httpClient, ParameterBagInterface $params, protected readonly string $ogBootIP, protected readonly string $ogBootPort)
|
|
{
|
|
$this->curlRequestService = $curlRequestService;
|
|
$this->logger = $logger;
|
|
$this->httpClient = $httpClient;
|
|
$this->params = $params; // Accedemos a las variables de entorno a través de ParameterBagInterface
|
|
$this->tftpbootDir = $params->get('tftpboot_dir');
|
|
}
|
|
|
|
/*Tabla de Contenido
|
|
Obtener configuración de ogboot - GET /ogboot/config x
|
|
Obtener datos de rendimiento - GET /ogboot/status x
|
|
Mostrar información de todos los clientes ogLive instalados - GET /ogboot/oglives x
|
|
Mostrar información de un cliente ogLive instalado - GET /ogboot/oglives/{Index|Dir} x
|
|
Mostrar información del cliente ogLive predeterminado - GET /ogboot/oglives/default x
|
|
Cambiar ogLive predeterminado - POST /ogboot/oglives/default/{Index} x
|
|
Instalar nuevo cliente ogLive desde imagen descargada - POST /ogboot/oglive/{Index/iso} ----
|
|
Desinstalar cliente ogLive y eliminar imagen - DELETE /ogboot/oglives/{Index/iso} -------
|
|
Regenerar archivo de información de los ogLive - PUT /ogboot/oglives
|
|
Mostrar menú de descarga de imagen de ogLive - GET /ogboot/images/download X
|
|
|
|
/////////////////////////////////////////////
|
|
|
|
Obtener todos los archivos de arranque - GET /ogboot/pxes
|
|
Obtener archivo de arranque - GET /ogboot/clients/pxes/{mac}
|
|
Crear archivo de arranque - POST /ogboot/pxes
|
|
Eliminar archivo de arranque - DELETE /ogboot/clients/pxes
|
|
Obtener todas las plantillas - GET /ogboot/pxe-templates
|
|
Obtener contenido de la plantilla - GET /ogboot/pxe-templates/{nombre}
|
|
Crear plantilla - POST /ogboot/pxe-templates
|
|
Regenerar plantilla - PUT /ogboot/pxe-templates
|
|
*/
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/status", name="getStatus", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/status",
|
|
* summary="Get ogboot status",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Status retrieved successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="disk_usage", type="object",
|
|
* @OA\Property(property="total", type="string", example="20G"),
|
|
* @OA\Property(property="used", type="string", example="15G"),
|
|
* @OA\Property(property="available", type="string", example="5G"),
|
|
* @OA\Property(property="percentage", type="string", example="75%")
|
|
* ),
|
|
* @OA\Property(property="default_oglive", type="string", example="ogLive-5.11.0-r20210413"),
|
|
* @OA\Property(
|
|
* property="installed_oglives",
|
|
* type="array",
|
|
* @OA\Items(ref="#/components/schemas/OgLive")
|
|
* ),
|
|
* @OA\Property(property="services_status", type="object",
|
|
* @OA\Property(property="service_name", type="string", example="nginx"),
|
|
* @OA\Property(property="status", type="string", example="running")
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="No ogLive clients found or no default ogLive client available",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="No default or installed ogLives found.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Server error occurred while retrieving the status",
|
|
* @OA\JsonContent(
|
|
* oneOf={
|
|
* @OA\Schema(
|
|
* @OA\Property(property="error", type="string", example="FAILED_TO_RETRIEVE_DISK_USAGE"),
|
|
* @OA\Property(property="details", type="string", example="Unknown error")
|
|
* ),
|
|
* @OA\Schema(
|
|
* @OA\Property(property="error", type="string", example="FAILED_TO_RETRIEVE_OGLIVE_CONFIGURATION"),
|
|
* @OA\Property(property="details", type="string", example="Unknown error")
|
|
* ),
|
|
* @OA\Schema(
|
|
* @OA\Property(property="error", type="string", example="FAILED_TO_RETRIEVE_SERVICES_STATUS"),
|
|
* @OA\Property(property="details", type="string", example="Unknown error")
|
|
* )
|
|
* }
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
public function getStatus(): Response
|
|
{
|
|
// Llamar a oglivecli para obtener el uso del disco
|
|
$diskUsageResponse = $this->curlRequestService->callOgLive("disk_usage");
|
|
$diskUsageResult = $diskUsageResponse['output'];
|
|
$diskUsageExitCode = $diskUsageResponse['exitCode'];
|
|
|
|
if ($diskUsageExitCode !== 0) {
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_RETRIEVE_DISK_USAGE', 'details' => $diskUsageResult['error'] ?? 'Unknown error'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Llamar a oglivecli para obtener la configuración de los oglives instalados y el oglive por defecto
|
|
$ogLiveResponse = $this->curlRequestService->callOgLive("list_installed_oglives");
|
|
$ogLiveConfigResult = $ogLiveResponse['output'];
|
|
$ogLiveExitCode = $ogLiveResponse['exitCode'];
|
|
|
|
if ($ogLiveExitCode !== 0) {
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_RETRIEVE_OGLIVE_CONFIGURATION', 'details' => $ogLiveConfigResult['error'] ?? 'Unknown error'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Llamar a oglivecli para obtener el estado de los servicios
|
|
$servicesStatusResponse = $this->curlRequestService->callOgLive("check_services_status");
|
|
$servicesStatusResult = $servicesStatusResponse['output'];
|
|
$servicesStatusExitCode = $servicesStatusResponse['exitCode'];
|
|
|
|
if ($servicesStatusExitCode !== 0) {
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_RETRIEVE_SERVICES_STATUS', 'details' => $servicesStatusResult['error'] ?? 'Unknown error'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Verificar si las claves 'default_oglive' e 'installed_ogLives' existen en la respuesta de oglivecli
|
|
$defaultOglive = $ogLiveConfigResult['default_oglive'] ?? null;
|
|
$installedOglives = $ogLiveConfigResult['installed_ogLives'] ?? [];
|
|
|
|
if ($defaultOglive === null || empty($installedOglives)) {
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No default or installed ogLives found.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$response = [
|
|
'success' => 'Status retrieved successfully',
|
|
'message' => [
|
|
'disk_usage' => $diskUsageResult,
|
|
'default_oglive' => $defaultOglive,
|
|
'installed_oglives' => $installedOglives,
|
|
'services_status' => $servicesStatusResult
|
|
]
|
|
]; // Formatear la respuesta final con todos los datos
|
|
|
|
return new JsonResponse($response, Response::HTTP_OK);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/isos", name="getDownloadMenu", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/oglives/isos",
|
|
* summary="Get ogLive downloads menu",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Isos retrieved successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string"),
|
|
* @OA\Property(property="message", type="array",
|
|
* @OA\Items(ref="#/components/schemas/DownloadOgLive")
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to retrieve isos",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string"),
|
|
* @OA\Property(property="message", type="string")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function getDownloadMenu(): Response
|
|
{
|
|
$operation = 'ogboot.getDownloadMenu';
|
|
$component = 'ogboot';
|
|
|
|
// Log de inicio
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Attempting to retrieve ISO download menu.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Obtener datos
|
|
$downloadsOutput = $this->curlRequestService->callOgLive("download");
|
|
|
|
// Error en la llamada
|
|
if (is_array($downloadsOutput) && isset($downloadsOutput['error'])) {
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['error' => $downloadsOutput['error']],
|
|
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
|
'desc' => 'Failed to retrieve ISOs.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_RETRIEVE_ISOS', 'message' => $downloadsOutput['message']],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Log de salida exitosa
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => [],
|
|
'http_code' => Response::HTTP_OK,
|
|
'desc' => 'ISOs retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Respuesta
|
|
return new JsonResponse([
|
|
'success' => 'ISOs retrieved successfully',
|
|
'message' => $downloadsOutput['output']['downloads'] ?? []
|
|
], Response::HTTP_OK);
|
|
}
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives", name="getOglives", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/oglives",
|
|
* summary="Get list of all installed ogLive clients",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="List of installed ogLive clients retrieved successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="ogLive clients retrieved successfully"),
|
|
* @OA\Property(property="message", type="object",
|
|
* @OA\Property(property="default_oglive", type="string", description="The default ogLive client"),
|
|
* @OA\Property(property="installed_ogLives", type="array",
|
|
* @OA\Items(ref="#/components/schemas/OgLive")
|
|
* )
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="No ogLive clients found",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="No ogLive clients found.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Server or unknown error occurred",
|
|
* @OA\JsonContent(
|
|
* oneOf={
|
|
* @OA\Schema(
|
|
* @OA\Property(property="error", type="string", example="SERVER_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Failed to retrieve ogLive clients due to server error.")
|
|
* ),
|
|
* @OA\Schema(
|
|
* @OA\Property(property="error", type="string", example="UNKNOWN_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="An unknown error occurred.")
|
|
* )
|
|
* }
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
public function getOglives(): Response
|
|
{
|
|
$operation = 'ogboot.getOglives'; // Nombre de la operación
|
|
$component = 'ogboot'; // Componente responsable
|
|
|
|
// Log inicial: Inicio del endpoint
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Fetching list of installed ogLive clients.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$response = $this->curlRequestService->callOgLive('list_installed_oglives');
|
|
$ogLiveConfigResult = $response['output'];
|
|
$exitCode = $response['exitCode'];
|
|
|
|
// Log de depuración: Respuesta completa del servicio
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['response' => $response],
|
|
'desc' => 'Service response for list_installed_oglives.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if ($exitCode === 404) {
|
|
$httpCode = (string) Response::HTTP_NOT_FOUND;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'No ogLive clients found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No ogLive clients found.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
} elseif ($exitCode === 500) {
|
|
$httpCode = (string) Response::HTTP_INTERNAL_SERVER_ERROR;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Failed to retrieve ogLive clients due to server error.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve ogLive clients due to server error.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
} elseif ($exitCode !== 0) {
|
|
$httpCode = (string) Response::HTTP_INTERNAL_SERVER_ERROR;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Unknown error occurred while retrieving ogLive clients.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'UNKNOWN_ERROR', 'message' => 'An unknown error occurred.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
if (empty($ogLiveConfigResult) || !isset($ogLiveConfigResult['installed_ogLives'])) {
|
|
$httpCode = (string) Response::HTTP_NOT_FOUND;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'No installed ogLive clients found in the service response.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No ogLive clients found.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$httpCode = (string) Response::HTTP_OK;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'ogLive clients retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$response = [
|
|
'success' => 'ogLive clients retrieved successfully',
|
|
'message' => $ogLiveConfigResult // Incluye la estructura completa con default_oglive e installed_ogLives
|
|
];
|
|
|
|
return new JsonResponse($response, Response::HTTP_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/default", name="getOgliveDefault", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/oglives/default",
|
|
* summary="Get information of the default ogLive client",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Successful operation",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="se ha obtenido el oglive por defecto"),
|
|
* @OA\Property(property="message", ref="#/components/schemas/OgLive")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to retrieve information of the default ogLive client",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="SERVER_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Failed to retrieve default ogLive.")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function getOgliveDefault(Request $request): Response
|
|
{
|
|
$operation = 'ogboot.getOgliveDefault'; // Nombre de la operación
|
|
$component = 'ogboot'; // Componente responsable
|
|
|
|
// Log inicial: Inicio del endpoint
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Fetching default ogLive configuration.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Llamar al servicio que obtiene la configuración por defecto
|
|
$response = $this->curlRequestService->callOgLive('get_default');
|
|
$result = $response['output'];
|
|
$exitCode = $response['exitCode'];
|
|
|
|
// Log de depuración: Respuesta completa del servicio
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['response' => $response],
|
|
'desc' => 'Service response for get_default.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Manejo de errores basado en el código de salida
|
|
if ($exitCode !== 0) {
|
|
$httpCode = (string) Response::HTTP_INTERNAL_SERVER_ERROR;
|
|
$errorMessage = $result['error'] ?? 'Failed to retrieve default ogLive.';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => $errorMessage
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => $errorMessage],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Log de éxito: Respuesta válida obtenida
|
|
$httpCode = (string) Response::HTTP_OK;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Default ogLive configuration retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Devolver la respuesta en el formato solicitado
|
|
return new JsonResponse(
|
|
['success' => 'se ha obtenido el oglive por defecto', 'message' => $result],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/{checksum}", name="getOglive", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/oglives/{checksum}",
|
|
* summary="Get information of an installed ogLive client",
|
|
* @OA\Parameter(
|
|
* name="checksum",
|
|
* in="path",
|
|
* description="Checksum of the installed ogLive client",
|
|
* required=true,
|
|
* @OA\Schema(
|
|
* type="string",
|
|
* example="9e49a085ba74f97a81bdf9b3d0785094"
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="ogLive client retrieved successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="ogLive client retrieved successfully"),
|
|
* @OA\Property(property="message", ref="#/components/schemas/OgLive")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="ogLive client not found",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="ogLive client with checksum 9e49a085ba74f97a81bdf9b3d0785094 not found.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to retrieve ogLive client",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="SERVER_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Failed to retrieve ogLive client.")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function getOglive(string $checksum): Response
|
|
{
|
|
$operation = 'ogboot.getOglive'; // Nombre de la operación
|
|
$component = 'ogboot'; // Componente responsable
|
|
|
|
// Log inicial: Inicio del endpoint con el checksum proporcionado
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Fetching ogLive client.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Llamar al servicio ogLive para obtener la información del ogLive correspondiente
|
|
$response = $this->curlRequestService->callOgLive("get_info " . escapeshellarg($checksum));
|
|
$result = $response['output'];
|
|
$exitCode = $response['exitCode'];
|
|
|
|
// Log de depuración: Respuesta completa del servicio
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['response' => $response],
|
|
'desc' => 'Service response for get_info.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Manejo de errores basado en el código de salida
|
|
if ($exitCode === 404) {
|
|
$httpCode = (string) Response::HTTP_NOT_FOUND;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'ogLive client not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => "ogLive client with checksum $checksum not found."],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
} elseif ($exitCode !== 0) {
|
|
$httpCode = (string) Response::HTTP_INTERNAL_SERVER_ERROR;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Failed to retrieve ogLive client.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve ogLive client.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
// Log de éxito: Respuesta válida obtenida
|
|
$httpCode = (string) Response::HTTP_OK;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'ogLive client retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
// Formatear la respuesta de éxito con el ogLive encontrado
|
|
return new JsonResponse(
|
|
['success' => 'ogLive client retrieved successfully', 'message' => $result],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/default", name="setOgliveDefault", methods={"PUT"})
|
|
* @OA\Put(
|
|
* path="/ogboot/v1/oglives/default",
|
|
* summary="Set default ogLive client",
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(
|
|
* property="checksum",
|
|
* type="string",
|
|
* example="9e49a085ba74f97a81bdf9b3d0785094",
|
|
* description="Checksum of the ogLive client to set as default"
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="ogLive client set as default successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="ogLive client set as default successfully"),
|
|
* @OA\Property(property="message", ref="#/components/schemas/OgLive")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=400,
|
|
* description="Invalid input data",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="INVALID_INPUT"),
|
|
* @OA\Property(property="message", type="string", example="Invalid input data: checksum is required.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to set default ogLive client",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="SERVER_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Failed to set ogLive as default.")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function setOgliveDefault(Request $request): Response
|
|
{
|
|
$operation = 'ogboot.setOgliveDefault';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Setting ogLive client as default.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$data = json_decode($request->getContent(), true);
|
|
|
|
if (!isset($data['checksum'])) {
|
|
$httpCode = (string) Response::HTTP_BAD_REQUEST;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Invalid input data: checksum is required.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'INVALID_INPUT', 'message' => 'Invalid input data: checksum is required.'],
|
|
Response::HTTP_BAD_REQUEST
|
|
);
|
|
}
|
|
|
|
$checksum = $data['checksum'];
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Checksum received for setting default.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$response = $this->curlRequestService->callOgLive("set_default " . escapeshellarg($checksum));
|
|
$result = $response['output'];
|
|
$exitCode = $response['exitCode'];
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['response' => $response],
|
|
'desc' => 'Service response for set_default.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if ($exitCode !== 0) {
|
|
$httpCode = (string) Response::HTTP_INTERNAL_SERVER_ERROR;
|
|
$errorMessage = $result['error'] ?? 'Failed to set ogLive as default.';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => $errorMessage
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => $errorMessage],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$httpCode = (string) Response::HTTP_OK;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'ogLive client set as default successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['success' => 'ogLive client set as default successfully', 'message' => $result],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/install", name="installOglive", methods={"POST"})
|
|
* @OA\Post(
|
|
* path="/ogboot/v1/oglives/install",
|
|
* summary="Install an ogLive client",
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(
|
|
* property="url",
|
|
* type="string",
|
|
* example="https://ognproject.evlt.uma.es/trac/downloads/ogLive-focal-5.11.0-22-generic-amd64-r20210413.992ebb9.iso",
|
|
* description="URL of the ogLive ISO to download and install"
|
|
* ),
|
|
* @OA\Property(
|
|
* property="id",
|
|
* type="string",
|
|
* example="12345",
|
|
* description="Unique transaction ID to track the ogLive installation process"
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="ogLive client installation initiated",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="message", type="string"),
|
|
* @OA\Property(property="details", type="object")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=400,
|
|
* description="Invalid input data",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string"),
|
|
* @OA\Property(property="details", type="string")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to initiate ogLive installation",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string"),
|
|
* @OA\Property(property="details", type="string")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
public function installOglive(Request $request): JsonResponse
|
|
{
|
|
$operation = 'ogboot.installOglive';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Initiating ogLive client installation process.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$data = json_decode($request->getContent(), true);
|
|
|
|
if (!isset($data['url']) || !isset($data['id'])) {
|
|
$httpCode = (string) JsonResponse::HTTP_BAD_REQUEST;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Invalid input data. URL or Transaction ID missing.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(['error' => 'Invalid input data'], JsonResponse::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$isoUrl = $data['url'];
|
|
$transactionId = $data['id'];
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['url' => $isoUrl, 'transaction_id' => $transactionId],
|
|
'desc' => 'Received ISO URL and Transaction ID.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
try {
|
|
$consolePath = $this->params->get('kernel.project_dir') . '/bin/console';
|
|
$command = sprintf(
|
|
'php %s oglive:install %s %s > /dev/null 2>&1',
|
|
escapeshellarg($consolePath),
|
|
escapeshellarg($isoUrl),
|
|
escapeshellarg($transactionId)
|
|
);
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['command' => $command],
|
|
'desc' => 'Command constructed for execution.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$process = Process::fromShellCommandline($command);
|
|
$process->setTimeout(null);
|
|
$process->disableOutput();
|
|
|
|
try {
|
|
$process->start();
|
|
|
|
$httpCode = (string) JsonResponse::HTTP_ACCEPTED;
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['transaction_id' => $transactionId],
|
|
'desc' => 'ogLive client installation process started successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'success' => 'ogLive client installation started',
|
|
'transaction_id' => $transactionId
|
|
], JsonResponse::HTTP_ACCEPTED);
|
|
|
|
} catch (\Exception $e) {
|
|
$httpCode = (string) JsonResponse::HTTP_INTERNAL_SERVER_ERROR;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Error starting ogLive client installation process.',
|
|
'params' => ['message' => $e->getMessage()]
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
throw $e;
|
|
}
|
|
} catch (\Exception $e) {
|
|
$httpCode = (string) JsonResponse::HTTP_INTERNAL_SERVER_ERROR;
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Failed to initiate ogLive installation.',
|
|
'params' => ['message' => $e->getMessage()]
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'Failed to initiate ogLive installation',
|
|
'details' => $e->getMessage()
|
|
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Enviar el resultado al webhook
|
|
*
|
|
* @param string $webhookUrl
|
|
* @param array $data Datos para enviar al webhook
|
|
*/
|
|
private function notifyWebhook(string $webhookUrl, array $data): void
|
|
{
|
|
try {
|
|
error_log('Webhook URL: ' . $webhookUrl);
|
|
$this->logger->info('Webhook URL: ' . $webhookUrl);
|
|
error_log('Data being sent to webhook: ' . json_encode($data));
|
|
$this->logger->info('Data being sent to webhook: ' . json_encode($data));
|
|
$this->httpClient->request('POST', $webhookUrl, [
|
|
'headers' => [
|
|
'accept' => 'application/json',
|
|
'Content-Type' => 'application/json',
|
|
],
|
|
'body' => json_encode($data),
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
// Manejo de errores en la notificación del webhook
|
|
error_log('Error sending webhook notification: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/oglives/{checksum}", name="uninstallOglive", methods={"DELETE"})
|
|
* @OA\Delete(
|
|
* path="/ogboot/v1/oglives/{checksum}",
|
|
* summary="Uninstall an ogLive client",
|
|
* @OA\Parameter(
|
|
* name="checksum",
|
|
* in="path",
|
|
* description="Checksum of the ogLive client to uninstall",
|
|
* required=true,
|
|
* @OA\Schema(type="string", example="9e49a085ba74f97a81bdf9b3d0785094")
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="ogLive client uninstalled successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="message", type="string"),
|
|
* @OA\Property(property="details", type="string")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="ogLive client not found"
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to uninstall ogLive client",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function uninstallOglive(string $checksum): Response
|
|
{
|
|
$operation = 'ogboot.uninstallOglive';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Initiating ogLive client uninstallation.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$response = $this->curlRequestService->callOgLive("uninstall " . escapeshellarg($checksum));
|
|
$result = $response['output'];
|
|
$exitCode = $response['exitCode'];
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['response' => $result, 'exitCode' => $exitCode],
|
|
'desc' => 'Service response for ogLive uninstallation.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if ($exitCode === 404) {
|
|
$httpCode = '404';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'ogLive client not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'NOT_FOUND',
|
|
'message' => $result['message'] ?? 'ogLive client not found.'
|
|
], Response::HTTP_NOT_FOUND);
|
|
}
|
|
|
|
if ($exitCode === 403) {
|
|
$httpCode = '403';
|
|
$this->logger->warning(json_encode([
|
|
'severity' => 'WARNING',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Attempt to uninstall the default ogLive client.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'FORBIDDEN',
|
|
'message' => $result['message'] ?? 'Cannot uninstall the default ogLive client.'
|
|
], Response::HTTP_FORBIDDEN);
|
|
}
|
|
|
|
if ($exitCode === 500) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Server error during ogLive uninstallation.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'SERVER_ERROR',
|
|
'message' => $result['message'] ?? 'Failed to uninstall ogLive client.'
|
|
], Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
if ($exitCode === 200) {
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'ogLive client uninstalled successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'message' => $result['message'],
|
|
'details' => $result['details'] ?? ''
|
|
], Response::HTTP_OK);
|
|
}
|
|
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['checksum' => $checksum],
|
|
'desc' => 'Unknown error during ogLive uninstallation.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'UNKNOWN_ERROR',
|
|
'message' => 'An unknown error occurred.'
|
|
], Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxes", name="get_boot_files", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/pxes",
|
|
* summary="Get all PXE boot files",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Successful operation",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(
|
|
* property="success",
|
|
* type="string",
|
|
* example="Boot files retrieved successfully"
|
|
* ),
|
|
* @OA\Property(
|
|
* property="message",
|
|
* type="array",
|
|
* @OA\Items(
|
|
* type="string",
|
|
* description="Boot file"
|
|
* )
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to retrieve boot files"
|
|
* )
|
|
* )
|
|
*/
|
|
public function getBootFiles(): JsonResponse
|
|
{
|
|
$operation = 'ogboot.getBootFiles';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Attempting to retrieve boot files.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$directory = $this->tftpbootDir . '/ipxe_scripts';
|
|
|
|
if (!is_dir($directory)) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['directory' => $directory],
|
|
'desc' => 'Failed to retrieve boot files: directory not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve boot files: directory not found.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$files = scandir($directory);
|
|
|
|
$bootFiles = array_filter($files, function ($file) use ($directory) {
|
|
return !is_dir($directory . '/' . $file) && strpos($file, '01-') === 0;
|
|
});
|
|
|
|
if (empty($bootFiles)) {
|
|
$httpCode = '404';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['directory' => $directory],
|
|
'desc' => 'No boot files found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No boot files found.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['boot_files' => array_values($bootFiles)],
|
|
'desc' => 'Boot files retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$response = [
|
|
'success' => 'Boot files retrieved successfully',
|
|
'message' => array_values($bootFiles)
|
|
];
|
|
|
|
return new JsonResponse($response, Response::HTTP_OK);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxes/{mac}", name="ogboot_get_boot_file_with_params", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/pxes/{mac}",
|
|
* summary="Get boot file with parameters",
|
|
* @OA\Parameter(
|
|
* name="mac",
|
|
* in="path",
|
|
* description="MAC address",
|
|
* required=true,
|
|
* @OA\Schema(type="string", example="00:50:56:22:11:12")
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Successful operation",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="Boot file retrieved successfully"),
|
|
* @OA\Property(
|
|
* property="message",
|
|
* type="object",
|
|
* @OA\Property(property="template_name", type="string", description="Template name (required)", example="pxe"),
|
|
* @OA\Property(property="mac", type="string", description="MAC address (required)", example="00:50:56:22:11:12"),
|
|
* @OA\Property(property="lang", type="string", description="Language (optional)", example="es_ES.UTF-8"),
|
|
* @OA\Property(property="ip", type="string", description="IP address (optional)", example="192.168.2.11"),
|
|
* @OA\Property(property="server_ip", type="string", description="Server IP address (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="router", type="string", description="Router (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="netmask", type="string", description="Netmask (optional)", example="255.255.255.0"),
|
|
* @OA\Property(property="computer_name", type="string", description="Computer name (optional)", example="pc11"),
|
|
* @OA\Property(property="netiface", type="string", description="Network interface (optional)", example="eth0"),
|
|
* @OA\Property(property="group", type="string", description="Group (optional)", example="Aula_virtual"),
|
|
* @OA\Property(property="ogrepo", type="string", description="Repository IP (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="oglive", type="string", description="Live server IP (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="ogcore", type="string", description="Ogcore IP(optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="oglog", type="string", description="Log server IP (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="ogshare", type="string", description="Share server IP (optional)", example="192.168.2.1"),
|
|
* @OA\Property(property="oglivedir", type="string", description="Live directory (optional)", example="ogLive"),
|
|
* @OA\Property(property="ogprof", type="string", description="Is professor (optional)", example="false"),
|
|
* @OA\Property(property="hardprofile", type="string", description="Hardware profile (optional)", example=""),
|
|
* @OA\Property(property="ogntp", type="string", description="NTP server (optional)", example=""),
|
|
* @OA\Property(property="ogdns", type="string", description="DNS server (optional)", example=""),
|
|
* @OA\Property(property="ogproxy", type="string", description="Proxy server (optional)", example=""),
|
|
* @OA\Property(property="ogunit", type="string", description="Unit directory (optional)", example=""),
|
|
* @OA\Property(property="resolution", type="string", description="Screen resolution (optional)", example="788")
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="No boot file found for the specified MAC address",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="No boot file found for the specified MAC address.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Internal server error"
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
|
|
public function getBootFile(string $mac): Response
|
|
{
|
|
$operation = 'ogboot.getBootFile';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['mac' => $mac],
|
|
'desc' => 'Retrieving boot file for MAC address.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$directory = $this->tftpbootDir . '/ipxe_scripts';
|
|
$mac = $this->validateAndFormatMac($mac ?? null);
|
|
$fileName = "01-" . $mac;
|
|
$filePath = "$directory/$fileName";
|
|
$realFilePath = realpath($directory) . '/' . $fileName;
|
|
|
|
if (strpos($realFilePath, realpath($directory)) !== 0) {
|
|
$httpCode = '403';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['mac' => $mac, 'attemptedPath' => $realFilePath],
|
|
'desc' => 'Unauthorized access attempt outside the boot directory.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'UNAUTHORIZED_ACCESS', 'message' => 'Attempted unauthorized access outside the boot directory.'],
|
|
Response::HTTP_FORBIDDEN
|
|
);
|
|
}
|
|
|
|
if (!file_exists($realFilePath)) {
|
|
$httpCode = '404';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['mac' => $mac],
|
|
'desc' => 'Boot file not found for specified MAC address.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No boot file found for the specified MAC address.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$content = file_get_contents($realFilePath);
|
|
if ($content === false) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['filePath' => $realFilePath],
|
|
'desc' => 'Failed to read the boot file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_READ_BOOT_FILE', 'message' => 'Error reading the boot file.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$templateName = 'unknown';
|
|
$oglivedir = '';
|
|
$kernelArgs = '';
|
|
|
|
if (preg_match('/#Template:\s*(.*)/', $content, $matches)) {
|
|
$templateName = trim($matches[1]);
|
|
}
|
|
|
|
if (preg_match('/set ISODIR\s+(.*)/', $content, $matches)) {
|
|
$oglivedir = trim($matches[1]);
|
|
}
|
|
|
|
if (preg_match('/set kernelargs\s+(.*)/', $content, $matches)) {
|
|
$kernelArgs = trim($matches[1]);
|
|
}
|
|
|
|
if (empty($kernelArgs)) {
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['mac' => $mac, 'templateName' => $templateName],
|
|
'desc' => 'Boot file retrieved without kernel parameters.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
[
|
|
'success' => 'Boot file retrieved successfully',
|
|
'message' => [
|
|
'template_name' => $templateName,
|
|
'mac' => $mac,
|
|
'message' => 'Boot file without parameters, possibly a disk boot template.'
|
|
]
|
|
],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
parse_str(str_replace(' ', '&', $kernelArgs), $params);
|
|
|
|
$result = [
|
|
'template_name' => $templateName,
|
|
'mac' => $mac,
|
|
'lang' => $params['LANG'] ?? '',
|
|
'ip' => explode(':', $params['ip'])[0] ?? '',
|
|
'server_ip' => explode(':', $params['ip'])[1] ?? '',
|
|
'router' => explode(':', $params['ip'])[2] ?? '',
|
|
'netmask' => explode(':', $params['ip'])[3] ?? '',
|
|
'computer_name' => explode(':', $params['ip'])[4] ?? '',
|
|
'netiface' => explode(':', $params['ip'])[5] ?? '',
|
|
'group' => $params['group'] ?? '',
|
|
'ogrepo' => $params['ogrepo'] ?? '',
|
|
'oglive' => $params['oglive'] ?? '',
|
|
'ogcore' => $params['ogcore'] ?? '',
|
|
'oglog' => $params['oglog'] ?? '',
|
|
'ogshare' => $params['ogshare'] ?? '',
|
|
'oglivedir' => $oglivedir,
|
|
'ogprof' => $params['ogprof'] ?? '',
|
|
'hardprofile' => $params['hardprofile'] ?? '',
|
|
'ogntp' => $params['ogntp'] ?? '',
|
|
'ogdns' => $params['ogdns'] ?? '',
|
|
'ogproxy' => $params['ogproxy'] ?? '',
|
|
'ogunit' => $params['ogunit'] ?? '',
|
|
'resolution' => $params['vga'] ?? '',
|
|
];
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['mac' => $mac, 'templateName' => $templateName],
|
|
'desc' => 'Boot file retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['success' => 'Boot file retrieved successfully', 'message' => $result],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxes", methods={"POST"})
|
|
* @OA\Post(
|
|
* path="/ogboot/v1/pxes",
|
|
* summary="Crear archivo PXE",
|
|
* description="Crea un archivo de arranque PXE con la MAC y plantilla proporcionadas.",
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="mac", type="string", example="00:50:56:22:11:12"),
|
|
* @OA\Property(property="template_name", type="string", example="mi_plantilla.ipxe"),
|
|
* @OA\Property(property="server_ip", type="string", example="192.168.2.1"),
|
|
* @OA\Property(property="oglivedir", type="string", example="ogLive")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Plantilla creada exitosamente",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="Plantilla creada con éxito"),
|
|
* @OA\Property(property="message", type="string")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=400,
|
|
* description="Entrada inválida o datos requeridos faltantes"
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Error interno del servidor al crear el archivo PXE"
|
|
* )
|
|
* )
|
|
*/
|
|
public function createBootFile(Request $request): JsonResponse
|
|
{
|
|
$operation = 'ogboot.createBootFile';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Starting PXE file creation process.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$data = json_decode($request->getContent(), true);
|
|
$templateName = $data['template_name'] ?? null;
|
|
$mac = $this->validateAndFormatMac($data['mac'] ?? null);
|
|
$serverIp = $data['server_ip'] ?? null;
|
|
|
|
if ($serverIp && strpos($serverIp, ':') !== false) {
|
|
$serverIp = explode(':', $serverIp)[0];
|
|
}
|
|
|
|
$ogLiveDir = $data['oglivedir'] ?? 'ogLive';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => [
|
|
'template_name' => $templateName,
|
|
'mac' => $mac,
|
|
'server_ip' => $serverIp,
|
|
'oglivedir' => $ogLiveDir
|
|
],
|
|
'desc' => 'Input data for PXE file creation.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!$templateName || !$mac) {
|
|
$httpCode = '400';
|
|
$this->logger->warning(json_encode([
|
|
'severity' => 'WARNING',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Missing required fields: mac and/or template_name.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'Missing required fields: mac and template_name'],
|
|
Response::HTTP_BAD_REQUEST
|
|
);
|
|
}
|
|
|
|
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $templateName) || strpos($templateName, '..') !== false) {
|
|
$httpCode = '400';
|
|
$this->logger->warning(json_encode([
|
|
'severity' => 'WARNING',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['template_name' => $templateName],
|
|
'desc' => 'Invalid template name or unauthorized access attempt.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'INVALID_TEMPLATE_NAME', 'message' => 'Invalid template name or unauthorized access attempt.'],
|
|
Response::HTTP_BAD_REQUEST
|
|
);
|
|
}
|
|
|
|
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
|
|
$templatePath = $templateDir . '/' . $templateName;
|
|
|
|
if (!file_exists($templatePath)) {
|
|
$httpCode = '404';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['template_path' => $templatePath],
|
|
'desc' => 'Template not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'TEMPLATE_NOT_FOUND', 'message' => 'Template not found.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$templateContent = file_get_contents($templatePath);
|
|
if ($templateContent === false) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['template_path' => $templatePath],
|
|
'desc' => 'Failed to read the template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_READ_TEMPLATE', 'message' => 'Failed to read template.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Template content loaded.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$kernelArgs = 'ro boot=oginit quiet splash irqpoll acpi=on og2nd=sqfs ogprotocol=smb ogactiveadmin=true ogdebug=true ogtmpfs=15 ' .
|
|
'oglivedir=${ISODIR} ' .
|
|
'LANG=' . ($data['lang'] ?? 'es_ES.UTF-8') . ' ' .
|
|
'ip=' . ($data['ip'] ?? '') . ':' . $serverIp . ':' . ($data['router'] ?? '') . ':' . ($data['netmask'] ?? '') . ':' . ($data['computer_name'] ?? '') . ':' . ($data['netiface'] ?? '') . ':none ';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['kernelArgs' => $kernelArgs],
|
|
'desc' => 'Kernel arguments constructed.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$serverIpPort = $this->ogBootIP;
|
|
if (!empty($this->ogBootPort)) {
|
|
$serverIpPort .= ':' . $this->ogBootPort;
|
|
}
|
|
|
|
$pxeContent = str_replace(
|
|
['__INFOHOST__', '__SERVERIP__', '__OGLIVE__'],
|
|
[$kernelArgs, $serverIpPort, basename($ogLiveDir)],
|
|
$templateContent
|
|
);
|
|
|
|
if (file_put_contents($this->tftpbootDir . '/ipxe_scripts/01-' . $mac, $pxeContent) === false) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'Failed to create PXE file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'FAILED_TO_CREATE_PXE_FILE', 'message' => 'Failed to create PXE file.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'desc' => 'PXE file created successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'success' => 'PXE file created successfully',
|
|
'message' => $pxeContent
|
|
], Response::HTTP_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateAndFormatMac($mac)
|
|
{
|
|
// Convertir a minúsculas para un formato uniforme
|
|
$mac = strtolower($mac);
|
|
|
|
// Comprobar si la MAC tiene el formato correcto con dos puntos (ej. fc:aa:14:21:55:b9)
|
|
if (preg_match('/^([0-9a-f]{2}:){5}[0-9a-f]{2}$/', $mac)) {
|
|
return $mac; // MAC ya está en el formato correcto
|
|
}
|
|
|
|
// Comprobar si la MAC tiene el formato sin los dos puntos (ej. fcaa142155b9)
|
|
if (preg_match('/^[0-9a-f]{12}$/', $mac)) {
|
|
// Insertar los dos puntos en la MAC y devolverla en el formato correcto
|
|
return strtolower(implode(':', str_split($mac, 2)));
|
|
}
|
|
|
|
// Si no cumple con ninguno de los formatos, devolver un error
|
|
return false; // MAC no válida
|
|
}
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxes/{mac}", name="ogboot_delete_boot_file", methods={"DELETE"})
|
|
* @OA\Delete(
|
|
* path="/ogboot/v1/pxes/{mac}",
|
|
* summary="Delete PXE boot file",
|
|
* description="Delete a specific PXE boot file using its MAC address.",
|
|
* @OA\Parameter(
|
|
* name="mac",
|
|
* in="path",
|
|
* description="MAC address of the client whose boot file is to be deleted",
|
|
* required=true,
|
|
* @OA\Schema(type="string", example="00:11:22:33:44:55")
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Boot file deleted successfully",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="Boot file deleted successfully"),
|
|
* @OA\Property(property="message", type="string", example="The boot file for MAC 00:11:22:33:44:55 has been deleted.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="No boot file found for the specified MAC address",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="No boot file found for the specified MAC address.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Failed to delete the boot file",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="Failed to delete the boot file due to server error.")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function deleteBootFile(string $mac): Response
|
|
{
|
|
$operation = 'ogboot.deleteBootFile';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['mac' => $mac],
|
|
'desc' => 'Attempting to delete boot file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$directory = $this->tftpbootDir . '/ipxe_scripts';
|
|
$mac = $this->validateAndFormatMac($mac ?? null);
|
|
$fileName = "01-" . $mac;
|
|
$filePath = "$directory/$fileName";
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Computed file path for boot file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!file_exists($filePath)) {
|
|
$httpCode = '404';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => [
|
|
'mac' => $mac,
|
|
'filePath' => $filePath
|
|
],
|
|
'desc' => 'Boot file not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'NOT_FOUND', 'message' => 'No boot file found for the specified MAC address.'],
|
|
Response::HTTP_NOT_FOUND
|
|
);
|
|
}
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Boot file exists, proceeding to delete.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!unlink($filePath)) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => [
|
|
'mac' => $mac,
|
|
'filePath' => $filePath
|
|
],
|
|
'desc' => 'Failed to delete boot file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => 'Failed to delete the boot file due to server error.'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => [
|
|
'mac' => $mac,
|
|
'filePath' => $filePath
|
|
],
|
|
'desc' => 'Boot file deleted successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['success' => 'Boot file deleted successfully', 'message' => "The boot file for MAC $mac has been deleted."],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxe-templates", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/pxe-templates",
|
|
* summary="Obtener todas las plantillas PXE",
|
|
* description="Obtiene una lista de todas las plantillas de arranque PXE disponibles.",
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Lista de plantillas de arranque PXE",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="Lista de plantillas obtenida con éxito"),
|
|
* @OA\Property(
|
|
* property="message",
|
|
* type="array",
|
|
* @OA\Items(type="string", example="mi_plantilla.ipxe")
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Error interno del servidor",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="SERVER_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Directorio de plantillas no encontrado")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function getAllTemplates(): JsonResponse
|
|
{
|
|
$operation = 'ogboot.getAllTemplates';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Attempting to retrieve all templates.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
|
|
|
|
if (!is_dir($templateDir)) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateDir' => $templateDir],
|
|
'desc' => 'Template directory not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['error' => 'SERVER_ERROR', 'message' => 'Directorio de plantillas no encontrado'],
|
|
Response::HTTP_INTERNAL_SERVER_ERROR
|
|
);
|
|
}
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['templateDir' => $templateDir],
|
|
'desc' => 'Template directory exists.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$files = scandir($templateDir);
|
|
|
|
$templates = array_filter($files, function ($file) use ($templateDir) {
|
|
return !in_array($file, ['.', '..']) && !is_dir($templateDir . '/' . $file);
|
|
});
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => [
|
|
'templateDir' => $templateDir,
|
|
'templateCount' => count($templates)
|
|
],
|
|
'desc' => 'Templates retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['templates' => array_values($templates)],
|
|
'desc' => 'Template list retrieved.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse(
|
|
['success' => 'Lista de plantillas obtenida con éxito', 'message' => array_values($templates)],
|
|
Response::HTTP_OK
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxe-templates/{templateName}", name="get_template", methods={"GET"})
|
|
* @OA\Get(
|
|
* path="/ogboot/v1/pxe-templates/{templateName}",
|
|
* summary="Obtener contenido de una plantilla PXE",
|
|
* description="Obtiene el contenido de una plantilla de arranque PXE específica por su nombre.",
|
|
* @OA\Parameter(
|
|
* name="templateName",
|
|
* in="path",
|
|
* required=true,
|
|
* description="Nombre de la plantilla PXE",
|
|
* @OA\Schema(type="string", example="mi_plantilla.ipxe")
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="Contenido de la plantilla de arranque PXE",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="success", type="string", example="Plantilla obtenida con éxito"),
|
|
* @OA\Property(property="template_name", type="string", example="mi_plantilla.ipxe"),
|
|
* @OA\Property(property="template_content", type="string", example="#!ipxe\nset timeout 0\nset timeout-style hidden\n\nset ISODIR ogLive\nset default 0\nset kernelargs INFOHOST\nkernel tftp://SERVERIP/ogLive/ogvmlinuz ${kernelargs}\ninitrd tftp://SERVERIP/ogLive/oginitrd.img\nboot")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="Plantilla no encontrada",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="error", type="string", example="TEMPLATE_NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="No se encontró la plantilla especificada")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Error interno del servidor",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="error", type="string", example="FAILED_TO_READ_TEMPLATE"),
|
|
* @OA\Property(property="message", type="string", example="Error al leer la plantilla")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
public function getTemplate(string $templateName): Response
|
|
{
|
|
$operation = 'ogboot.getTemplate';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['templateName' => $templateName],
|
|
'desc' => 'Attempting to retrieve template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
|
|
$filePath = "$templateDir/$templateName";
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Computed file path for template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!file_exists($filePath)) {
|
|
$httpCode = '404';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $templateName, 'filePath' => $filePath],
|
|
'desc' => 'Template not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new Response(json_encode([
|
|
'error' => 'TEMPLATE_NOT_FOUND',
|
|
'message' => 'No se encontró la plantilla especificada'
|
|
]), Response::HTTP_NOT_FOUND, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Template found, attempting to read content.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$content = file_get_contents($filePath);
|
|
if ($content === false) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $templateName, 'filePath' => $filePath],
|
|
'desc' => 'Failed to read template content.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new Response(json_encode([
|
|
'error' => 'FAILED_TO_READ_TEMPLATE',
|
|
'message' => 'Error al leer la plantilla'
|
|
]), Response::HTTP_INTERNAL_SERVER_ERROR, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $templateName],
|
|
'desc' => 'Template retrieved successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['templateContent' => $content],
|
|
'desc' => 'Template content retrieved.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new Response(json_encode([
|
|
'success' => 'Plantilla obtenida con éxito',
|
|
'template_name' => $templateName,
|
|
'template_content' => $content
|
|
]), Response::HTTP_OK, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxe-templates", methods={"POST"})
|
|
*
|
|
* @OA\Post(
|
|
* path="/ogboot/v1/pxe-templates",
|
|
* summary="Crear Plantilla",
|
|
* description="Crea una nueva plantilla de arranque utilizando los datos proporcionados.",
|
|
* @OA\RequestBody(
|
|
* required=true,
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="name_template", type="string", example="mi_plantilla.ipxe"),
|
|
* @OA\Property(property="content_template", type="string", example="#!ipxe\nset timeout 0\nset timeout-style hidden\nset ISODIR __OGLIVE__\nset default 0\nset kernelargs __INFOHOST__\n:try_iso\nkernel http://__SERVERIP__/tftpboot/${ISODIR}/ogvmlinuz ${kernelargs} || goto fallback\ninitrd http://__SERVERIP__/tftpboot/${ISODIR}/oginitrd.img\nboot\n\n:fallback\nset ISODIR ogLive\nkernel http://__SERVERIP__/tftpboot/${ISODIR}/ogvmlinuz ${kernelargs}\ninitrd http://__SERVERIP__/tftpboot/${ISODIR}/oginitrd.img\nboot\n")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="La plantilla de arranque se creó exitosamente.",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="success", type="string", example="Plantilla creada con éxito"),
|
|
* @OA\Property(
|
|
* property="message",
|
|
* type="object",
|
|
* @OA\Property(property="template_name", type="string", example="mi_plantilla.ipxe"),
|
|
* @OA\Property(property="template_content", type="string", example="#!ipxe\nset timeout 0\nset timeout-style hidden\nset ISODIR __OGLIVE__\nset default 0\nset kernelargs __INFOHOST__\n:try_iso\nkernel http://__SERVERIP__/tftpboot/${ISODIR}/ogvmlinuz ${kernelargs} || goto fallback\ninitrd http://__SERVERIP__/tftpboot/${ISODIR}/oginitrd.img\nboot\n\n:fallback\nset ISODIR ogLive\nkernel http://__SERVERIP__/tftpboot/${ISODIR}/ogvmlinuz ${kernelargs}\ninitrd http://__SERVERIP__/tftpboot/${ISODIR}/oginitrd.img\nboot\n")
|
|
* )
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=400,
|
|
* description="Datos no válidos. Faltan los parámetros 'name_template' o 'content_template'.",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="INVALID_INPUT"),
|
|
* @OA\Property(property="message", type="string", example="Faltan datos requeridos: name_template y content_template son necesarios.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=403,
|
|
* description="Intento de acceso no autorizado fuera del directorio de plantillas.",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="UNAUTHORIZED_ACCESS"),
|
|
* @OA\Property(property="message", type="string", example="Intento de acceso no autorizado fuera del directorio de plantillas.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Ocurrió un error al crear la plantilla de arranque.",
|
|
* @OA\JsonContent(
|
|
* type="object",
|
|
* @OA\Property(property="error", type="string", example="FILE_CREATION_ERROR"),
|
|
* @OA\Property(property="message", type="string", example="Ocurrió un error al crear la plantilla de arranque.")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
|
|
public function createTemplate(Request $request): JsonResponse
|
|
{
|
|
$operation = 'ogboot.createTemplate';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'desc' => 'Attempting to create a new template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$data = json_decode($request->getContent(), true);
|
|
|
|
if (!isset($data['name_template']) || !isset($data['content_template'])) {
|
|
$httpCode = '400';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['requestData' => $data],
|
|
'desc' => 'Missing required fields: name_template or content_template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'INVALID_INPUT',
|
|
'message' => 'Faltan datos requeridos: name_template y content_template son necesarios.'
|
|
], JsonResponse::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$nameTemplate = $data['name_template'];
|
|
$contentTemplate = $data['content_template'];
|
|
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['nameTemplate' => $nameTemplate],
|
|
'desc' => 'Received template data.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $nameTemplate)) {
|
|
$httpCode = '400';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['nameTemplate' => $nameTemplate],
|
|
'desc' => 'Invalid template name. Contains invalid characters.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'INVALID_TEMPLATE_NAME',
|
|
'message' => 'El nombre de la plantilla contiene caracteres no válidos.'
|
|
], JsonResponse::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$filePath = $templateDir . '/' . $nameTemplate;
|
|
$realFilePath = realpath($templateDir) . '/' . $nameTemplate;
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath, 'realFilePath' => $realFilePath],
|
|
'desc' => 'Computed file paths for template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (strpos($realFilePath, realpath($templateDir)) !== 0) {
|
|
$httpCode = '403';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['nameTemplate' => $nameTemplate, 'filePath' => $filePath],
|
|
'desc' => 'Unauthorized access attempt outside the template directory.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'UNAUTHORIZED_ACCESS',
|
|
'message' => 'Intento de acceso no autorizado fuera del directorio de plantillas.'
|
|
], JsonResponse::HTTP_FORBIDDEN);
|
|
}
|
|
|
|
$contentTemplate = str_replace("\\n", "\n", $contentTemplate);
|
|
|
|
try {
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $realFilePath],
|
|
'desc' => 'Attempting to create the template file.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
file_put_contents($realFilePath, $contentTemplate);
|
|
|
|
if (!file_exists($realFilePath)) {
|
|
throw new \Exception('El archivo no se pudo crear.');
|
|
}
|
|
|
|
$writtenContent = file_get_contents($realFilePath);
|
|
if ($writtenContent !== $contentTemplate) {
|
|
throw new \Exception('El contenido del archivo no coincide con el contenido esperado.');
|
|
}
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['filePath' => $realFilePath],
|
|
'desc' => 'Template created successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
} catch (\Exception $e) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['nameTemplate' => $nameTemplate, 'filePath' => $realFilePath, 'exception' => $e->getMessage()],
|
|
'desc' => 'Failed to create template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new JsonResponse([
|
|
'error' => 'FILE_CREATION_ERROR',
|
|
'message' => 'Ocurrió un error al crear la plantilla de arranque: ' . $e->getMessage()
|
|
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
return new JsonResponse([
|
|
'success' => 'Plantilla creada con éxito',
|
|
'message' => [
|
|
'template_name' => $nameTemplate,
|
|
'template_content' => $contentTemplate
|
|
]
|
|
], JsonResponse::HTTP_OK);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* @Route("/ogboot/v1/pxe-templates/{name}", methods={"DELETE"})
|
|
*
|
|
* @OA\Delete(
|
|
* path="/ogboot/v1/pxe-templates/{name}",
|
|
* summary="Eliminar Plantilla",
|
|
* description="Elimina una plantilla de arranque específica utilizando su nombre.",
|
|
* @OA\Parameter(
|
|
* name="name",
|
|
* in="path",
|
|
* required=true,
|
|
* description="El nombre de la plantilla de arranque que se desea eliminar.",
|
|
* @OA\Schema(type="string")
|
|
* ),
|
|
* @OA\Response(
|
|
* response=200,
|
|
* description="La plantilla de arranque se eliminó correctamente.",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="success", type="string", example="Plantilla eliminada"),
|
|
* @OA\Property(property="message", type="string", example="La plantilla mi_plantilla se ha borrado correctamente.")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=404,
|
|
* description="No se encontró ninguna plantilla de arranque con el nombre especificado.",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="error", type="string", example="TEMPLATE_NOT_FOUND"),
|
|
* @OA\Property(property="message", type="string", example="No se encontró la plantilla especificada")
|
|
* )
|
|
* ),
|
|
* @OA\Response(
|
|
* response=500,
|
|
* description="Ocurrió un error al eliminar la plantilla de arranque.",
|
|
* @OA\JsonContent(
|
|
* @OA\Property(property="error", type="string", example="FAILED_TO_DELETE_TEMPLATE"),
|
|
* @OA\Property(property="message", type="string", example="Ocurrió un error al intentar eliminar la plantilla")
|
|
* )
|
|
* )
|
|
* )
|
|
*/
|
|
public function deleteTemplate(string $name): Response
|
|
{
|
|
$operation = 'ogboot.deleteTemplate';
|
|
$component = 'ogboot';
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['templateName' => $name],
|
|
'desc' => 'Attempting to delete template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
|
|
$filePath = $templateDir . '/' . $name;
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Computed file path for template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
if (!file_exists($filePath)) {
|
|
$httpCode = '404';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $name, 'filePath' => $filePath],
|
|
'desc' => 'Template not found.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new Response(json_encode([
|
|
'error' => 'TEMPLATE_NOT_FOUND',
|
|
'message' => 'No se encontró la plantilla especificada'
|
|
]), Response::HTTP_NOT_FOUND, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
$this->logger->debug(json_encode([
|
|
'severity' => 'DEBUG',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'params' => ['filePath' => $filePath],
|
|
'desc' => 'Template exists. Proceeding to delete.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
try {
|
|
unlink($filePath);
|
|
|
|
$httpCode = '200';
|
|
$this->logger->info(json_encode([
|
|
'severity' => 'INFO',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $name, 'filePath' => $filePath],
|
|
'desc' => 'Template deleted successfully.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
} catch (\Exception $e) {
|
|
$httpCode = '500';
|
|
$this->logger->error(json_encode([
|
|
'severity' => 'ERROR',
|
|
'operation' => $operation,
|
|
'component' => $component,
|
|
'http_code' => $httpCode,
|
|
'params' => ['templateName' => $name, 'filePath' => $filePath, 'exception' => $e->getMessage()],
|
|
'desc' => 'Failed to delete template.'
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
|
|
return new Response(json_encode([
|
|
'error' => 'FAILED_TO_DELETE_TEMPLATE',
|
|
'message' => 'Ocurrió un error al intentar eliminar la plantilla'
|
|
]), Response::HTTP_INTERNAL_SERVER_ERROR, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
return new Response(json_encode([
|
|
'success' => 'Plantilla eliminada',
|
|
'message' => "La plantilla $name se ha borrado correctamente"
|
|
]), Response::HTTP_OK, ['Content-Type' => 'application/json']);
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|