ogboot/src/OgBootBundle/Controller/OgBootController.php

1523 lines
62 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)
{
$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
{
// Llamar al servicio para obtener las ISOs disponibles
$downloadsOutput = $this->curlRequestService->callOgLive("download");
// Verificar si hubo un error en la respuesta
if (is_array($downloadsOutput) && isset($downloadsOutput['error'])) {
return new JsonResponse(
['error' => 'FAILED_TO_RETRIEVE_ISOS', 'message' => $downloadsOutput['message']],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Formatear la respuesta según el nuevo formato
$response = [
'success' => 'ISOs retrieved successfully',
'message' => $downloadsOutput['output']['downloads'] // Aquí la estructura ya está en el formato correcto de la salida del shell script
];
return new JsonResponse($response, 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
{
// Llama al servicio que ejecuta el comando oglivecli y obtiene tanto el output como el código de salida
$response = $this->curlRequestService->callOgLive("list_installed_oglives");
$ogLiveConfigResult = $response['output'];
$exitCode = $response['exitCode'];
// Manejo de errores basado en el código de salida
if ($exitCode === 404) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => 'No ogLive clients found.'],
Response::HTTP_NOT_FOUND
);
} elseif ($exitCode === 500) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve ogLive clients due to server error.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
} elseif ($exitCode !== 0) {
// Manejar otros posibles códigos de error no esperados
return new JsonResponse(
['error' => 'UNKNOWN_ERROR', 'message' => 'An unknown error occurred.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Verificar si la salida es válida
if (empty($ogLiveConfigResult) || !isset($ogLiveConfigResult['installed_ogLives'])) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => 'No ogLive clients found.'],
Response::HTTP_NOT_FOUND
);
}
// Formatear la respuesta final en caso de éxito
$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
{
$response = $this->curlRequestService->callOgLive("get_default");
$result = $response['output'];
$exitCode = $response['exitCode'];
// Verificar si hay un error basado en el código de salida
if ($exitCode !== 0) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => $result['error'] ?? 'Failed to retrieve default ogLive.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// 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
{
// Llamar al servicio ogLive para obtener la información del ogLive correspondiente al checksum proporcionado
$response = $this->curlRequestService->callOgLive("get_info " . escapeshellarg($checksum));
$result = $response['output'];
$exitCode = $response['exitCode'];
// Verificar si hay un error basado en el código de salida
if ($exitCode === 404) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => "ogLive client with checksum $checksum not found."],
Response::HTTP_NOT_FOUND
);
} elseif ($exitCode !== 0) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve ogLive client.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// 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
{
$data = json_decode($request->getContent(), true);
// Validar que el checksum está presente en los datos de entrada
if (!isset($data['checksum'])) {
return new JsonResponse(
['error' => 'INVALID_INPUT', 'message' => 'Invalid input data: checksum is required.'],
Response::HTTP_BAD_REQUEST
);
}
$checksum = $data['checksum'];
// Llamar al servicio para establecer el ogLive como predeterminado utilizando el checksum proporcionado
$response = $this->curlRequestService->callOgLive("set_default " . escapeshellarg($checksum));
$result = $response['output'];
$exitCode = $response['exitCode'];
// Verificar si hay un error basado en el código de salida
if ($exitCode !== 0) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => $result['error'] ?? 'Failed to set ogLive as default.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Devolver la respuesta en el formato solicitado
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
{
// Obtener los datos del cuerpo de la petición
$data = json_decode($request->getContent(), true);
if (!isset($data['url']) || !isset($data['id'])) {
return new JsonResponse(['error' => 'Invalid input data'], JsonResponse::HTTP_BAD_REQUEST);
}
// Obtener la URL del ISO y el ID de la transacción
$isoUrl = $data['url'];
$transactionId = $data['id'];
try {
// Ejecutar el comando Symfony en segundo plano
$consolePath = $this->params->get('kernel.project_dir') . '/bin/console';
$this->logger->info($consolePath);
$process = new Process([
$consolePath,
'oglive:install',
$isoUrl, // Sin escapeshellarg
$transactionId // Sin escapeshellarg,
]);
$command = sprintf(
'php %s oglive:install %s %s > /dev/null 2>&1 ',
escapeshellarg($consolePath),
escapeshellarg($isoUrl),
escapeshellarg($transactionId)
);
$commandLine = $process->getCommandLine();
$this->logger->info('Command to be executed: ' . $commandLine);
$process = Process::fromShellCommandline($command);
#$process->start(); // Ejecuta en segundo plano
$process->setTimeout(null);
$process->disableOutput();
try {
$process->start();
} catch (\Exception $e) {
$this->logger->error('Error starting process: ' . $e->getMessage());
}
return new JsonResponse([
'success' => 'ogLive client installation started',
'transaction_id' => $transactionId
], JsonResponse::HTTP_ACCEPTED);
} catch (Exception $e) {
// Si ocurre algún error durante el proceso de inicio
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
{
// Llamada al servicio para desinstalar el cliente ogLive
error_log("Calling curlRequestService with checksum: $checksum");
// Ejecutar el comando y capturar tanto el resultado como el código de salida
$response = $this->curlRequestService->callOgLive("uninstall " . escapeshellarg($checksum));
$result = $response['output'];
$exitCode = $response['exitCode'];
// Verificar la respuesta del servicio según el código de salida
$this->logger->info("Service call result: " . print_r($result, true));
$this->logger->info("Exit code: " . $exitCode);
if ($exitCode === 404) {
// ogLive client no encontrado
return new JsonResponse([
'error' => 'NOT_FOUND',
'message' => $result['message'] ?? 'ogLive client not found.'
], Response::HTTP_NOT_FOUND);
} elseif ($exitCode === 403) {
// Intento de desinstalar el ogLive por defecto
return new JsonResponse([
'error' => 'FORBIDDEN',
'message' => $result['message'] ?? 'Cannot uninstall the default ogLive client.'
], Response::HTTP_FORBIDDEN);
} elseif ($exitCode === 500) {
// Error interno del servidor
return new JsonResponse([
'error' => 'SERVER_ERROR',
'message' => $result['message'] ?? 'Failed to uninstall ogLive client.'
], Response::HTTP_INTERNAL_SERVER_ERROR);
} elseif ($exitCode === 200) {
// Desinstalación exitosa
return new JsonResponse([
'message' => $result['message'],
'details' => $result['details'] ?? ''
], Response::HTTP_OK);
} else {
// Manejar otros códigos de error no previstos
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
{
#$directory = '/opt/ogboot/tftpboot/ipxe_scripts';
$directory = $this->tftpbootDir . '/ipxe_scripts';
// Verificar si el directorio existe
if (!is_dir($directory)) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => 'Failed to retrieve boot files: directory not found.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Obtener la lista de archivos
$files = scandir($directory);
// Filtrar los archivos que comiencen con '01-' y excluir directorios
$bootFiles = array_filter($files, function ($file) use ($directory) {
return !is_dir($directory . '/' . $file) && strpos($file, '01-') === 0;
});
// Si no se encuentran archivos
if (empty($bootFiles)) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => 'No boot files found.'],
Response::HTTP_NOT_FOUND
);
}
// Formatear la respuesta de éxito
$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="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
{
// Ruta donde están alojados los archivos de arranque
#$directory = '/opt/ogboot/tftpboot/ipxe_scripts';
$directory = $this->tftpbootDir . '/ipxe_scripts';
// Generar el nombre del archivo basado en la dirección MAC
$mac = $this->validateAndFormatMac($mac ?? null);
$fileName = "01-" . $mac;
$filePath = "$directory/$fileName";
$this->logger->info('FilePath: ' . $filePath);
// Verificar si el archivo existe
if (!file_exists($filePath)) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => 'No boot file found for the specified MAC address.'],
Response::HTTP_NOT_FOUND
);
}
$content = file_get_contents($filePath);
$templateName = 'unknown'; // Valor por defecto si no se encuentra la plantilla
$contentLines = explode("\n", $content);
// Buscar la plantilla utilizada
foreach ($contentLines as $line) {
if (strpos($line, '#Template:') !== false) {
$templateName = trim(str_replace('#Template:', '', $line));
break;
}
}
// Extraer los parámetros del contenido del archivo iPXE
preg_match('/set kernelargs (.*)/', $content, $matches);
// Si no se encuentran 'kernelargs', podría ser un archivo de arranque por disco
if (!isset($matches[1])) {
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
);
}
// Parsear los argumentos del kernel
$kernelargs = $matches[1];
parse_str(str_replace(' ', '&', $kernelargs), $params);
// Crear la estructura del resultado
$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'] ?? '',
'oglog' => $params['oglog'] ?? '',
'ogshare' => $params['ogshare'] ?? '',
'oglivedir' => $params['oglivedir'] ?? '',
'ogprof' => $params['ogprof'] ?? '',
'hardprofile' => $params['hardprofile'] ?? '',
'ogntp' => $params['ogntp'] ?? '',
'ogdns' => $params['ogdns'] ?? '',
'ogproxy' => $params['ogproxy'] ?? '',
'ogunit' => $params['ogunit'] ?? '',
'resolution' => $params['vga'] ?? '',
];
// Formatear la respuesta de éxito
return new JsonResponse(
['success' => 'Boot file retrieved successfully', 'message' => $result],
Response::HTTP_OK
);
}
/**
* @Route("/ogboot/v1/pxes", name="create_boot_file", methods={"POST"})
* @OA\Post(
* path="/ogboot/v1/pxes",
* summary="Create a new PXE boot file",
* description="Creates a PXE boot file based on the provided template and parameters. All parameters except 'template_name' and 'mac' are optional.",
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(
* 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="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=200,
* description="PXE boot file created successfully",
* @OA\JsonContent(
* type="object",
* @OA\Property(property="message", type="string")
* )
* ),
* @OA\Response(
* response=400,
* description="Invalid input",
* @OA\JsonContent(
* oneOf={
* @OA\Schema(
* @OA\Property(property="error", type="string", example="Missing required fields"),
* @OA\Property(property="details", type="string", example="MAC and template_name are required")
* ),
* @OA\Schema(
* @OA\Property(property="error", type="string", example="Invalid MAC address"),
* @OA\Property(property="details", type="string", example="MAC address contains invalid characters")
* ),
* @OA\Schema(
* @OA\Property(property="error", type="string", example="Template not found"),
* @OA\Property(property="details", type="string", example="The specified template does not exist")
* )
* }
* )
* ),
* @OA\Response(
* response=404,
* description="Template not found",
* @OA\JsonContent(
* @OA\Property(property="error", type="string", example="Template not found")
* )
* ),
* @OA\Response(
* response=500,
* description="Internal server error",
* @OA\JsonContent(
* oneOf={
* @OA\Schema(
* @OA\Property(property="error", type="string", example="Failed to create PXE boot file"),
* @OA\Property(property="details", type="string", example="Error writing to file system")
* ),
* @OA\Schema(
* @OA\Property(property="error", type="string", example="Failed to read template"),
* @OA\Property(property="details", type="string", example="Could not access the template file")
* )
* }
* )
* )
* )
*/
public function createBootFile(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
$templateName = $data['template_name'] ?? null;
$mac = $this->validateAndFormatMac($data['mac'] ?? null);
$serverIp = $data['server_ip'] ?? null;
$ogLiveDir = $data['oglivedir'] ?? 'ogLive';
// Verificación de los campos obligatorios
if (!$templateName || !$mac) {
return new JsonResponse(['error' => 'Missing required fields: mac and template_name'], Response::HTTP_BAD_REQUEST);
}
// Parámetros opcionales
$parameters = [
'LANG' => $data['lang'] ?? 'es_ES.UTF-8',
'ip' => $data['ip'] ?? '',
'router' => $data['router'] ?? '',
'netmask' => $data['netmask'] ?? '',
'computer_name' => $data['computer_name'] ?? '',
'netiface' => $data['netiface'] ?? '',
'group' => $data['group'] ?? '',
'ogrepo' => $data['ogrepo'] ?? '',
'oglive' => $data['oglive'] ?? $serverIp,
'oglog' => $data['oglog'] ?? $serverIp,
'ogshare' => $data['ogshare'] ?? $serverIp,
'oglivedir' => $data['oglivedir'] ?? '',
'ogprof' => $data['ogprof'] ?? 'false',
'hardprofile' => $data['hardprofile'] ?? '',
'ogntp' => $data['ogntp'] ?? '',
'ogdns' => $data['ogdns'] ?? '',
'ogproxy' => $data['ogproxy'] ?? '',
'ogunit' => $data['ogunit'] ?? '',
'resolution' => $data['resolution'] ?? '788'
];
#$templateDir = '/opt/ogboot/tftpboot/ipxe_scripts/templates';
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
$templatePath = $templateDir . '/' . $templateName;
// Verificar si la plantilla existe
if (!file_exists($templatePath)) {
return new JsonResponse(['error' => 'Template not found'], Response::HTTP_NOT_FOUND);
}
$templateContent = file_get_contents($templatePath);
if ($templateContent === false) {
return new JsonResponse(['error' => 'Failed to read template'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Construcción de los argumentos del kernel
$kernelArgs = 'ro boot=oginit quiet splash irqpoll acpi=on og2nd=sqfs ogprotocol=smb ogactiveadmin=true ogdebug=true ogtmpfs=15 ' .
'oglivedir=' . $parameters['oglivedir'] . ' ' .
'LANG=' . $parameters['LANG'] . ' ' .
'ip=' . $parameters['ip'] . ':' . $serverIp . ':' . $parameters['router'] . ':' . $parameters['netmask'] . ':' . $parameters['computer_name'] . ':' . $parameters['netiface'] . ':none ' .
'group=' . str_replace(' ', '_', trim($parameters['group'])) . ' ' .
'ogrepo=' . $parameters['ogrepo'] . ' ' .
'oglive=' . $serverIp . ' ' .
'oglog=' . $serverIp . ' ' .
'ogshare=' . $serverIp . ' ' .
'ogprof=' . ($parameters['ogprof'] === 'true' ? 'true' : 'false') . ' ' .
(!empty($parameters['hardprofile']) ? 'hardprofile=' . str_replace(' ', '_', trim($parameters['hardprofile'])) . ' ' : '') .
(!empty($parameters['ogntp']) ? 'ogntp=' . $parameters['ogntp'] . ' ' : '') .
(!empty($parameters['ogdns']) ? 'ogdns=' . $parameters['ogdns'] . ' ' : '') .
(!empty($parameters['ogproxy']) ? 'ogproxy=' . $parameters['ogproxy'] . ' ' : '') .
(!empty($parameters['ogunit']) ? 'ogunit=' . $parameters['ogunit'] . ' ' : '') .
(is_numeric($parameters['resolution']) && $parameters['resolution'] <= 999 ? 'vga=' . $parameters['resolution'] :
(strpos($parameters['resolution'], ':') !== false ? 'video=' . $parameters['resolution'] : ' ' . $parameters['resolution']));
// Insertar un comentario al principio del archivo con el nombre de la plantilla usada
$pxeContent = "#Template: $templateName\n" .
str_replace(['__INFOHOST__', '__SERVERIP__', '__OGLIVE__'], [$kernelArgs, $serverIp, $ogLiveDir], $templateContent);
// Nombre del archivo PXE basado en la MAC
$pxeFileName = '01-' . $mac;
// Ruta para guardar el archivo PXE
#$pxeFilePath = '/opt/ogboot/tftpboot/ipxe_scripts/' . $pxeFileName;
$pxeFilePath = $this->tftpbootDir . '/ipxe_scripts' . $pxeFileName;
// Crear el archivo PXE
if (file_put_contents($pxeFilePath, $pxeContent) === false) {
return new JsonResponse(['error' => 'Failed to create PXE boot file'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Retornar la plantilla creada en el formato solicitado
return new JsonResponse([
'success' => 'Plantilla creada con exito',
'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
{
#$directory = '/opt/ogboot/tftpboot/ipxe_scripts';
$directory = $this->tftpbootDir . '/ipxe_scripts';
// Validar y formatear la dirección MAC
$mac = $this->validateAndFormatMac($mac ?? null);
$fileName = "01-" . $mac;
$filePath = "$directory/$fileName";
// Verificar si el archivo de arranque existe
if (!file_exists($filePath)) {
return new JsonResponse(
['error' => 'NOT_FOUND', 'message' => 'No boot file found for the specified MAC address.'],
Response::HTTP_NOT_FOUND
);
}
// Intentar eliminar el archivo de arranque
if (!unlink($filePath)) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => 'Failed to delete the boot file due to server error.'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Respuesta exitosa con formato estándar
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
{
#$templateDir = '/opt/ogboot/tftpboot/ipxe_scripts/templates';
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
// Verificar si el directorio existe
if (!is_dir($templateDir)) {
return new JsonResponse(
['error' => 'SERVER_ERROR', 'message' => 'Directorio de plantillas no encontrado'],
Response::HTTP_INTERNAL_SERVER_ERROR
);
}
// Obtener la lista de archivos en el directorio
$files = scandir($templateDir);
// Filtrar los archivos válidos (excluir directorios y archivos ocultos)
$templates = array_filter($files, function ($file) use ($templateDir) {
return !in_array($file, ['.', '..']) && !is_dir($templateDir . '/' . $file);
});
// Formatear la respuesta siguiendo el estándar
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
{
#$templateDir = '/opt/ogboot/tftpboot/ipxe_scripts/templates';
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
$filePath = "$templateDir/$templateName";
// Comprobar si el archivo de plantilla existe
if (!file_exists($filePath)) {
return new Response(json_encode([
'error' => 'TEMPLATE_NOT_FOUND',
'message' => 'No se encontró la plantilla especificada'
]), Response::HTTP_NOT_FOUND, ['Content-Type' => 'application/json']);
}
// Intentar leer el contenido de la plantilla
$content = file_get_contents($filePath);
if ($content === false) {
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']);
}
// Devolver la respuesta con el nombre y contenido de la plantilla
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="message", type="string", example="Plantilla creada exitosamente"),
* @OA\Property(property="template", type="string", example="mi_plantilla.ipxe")
* )
* ),
* @OA\Response(
* response=400,
* description="La solicitud no pudo ser procesada debido a un error en los datos proporcionados en el cuerpo de la solicitud."
* ),
* @OA\Response(
* response=500,
* description="Ocurrió un error al crear la plantilla de arranque."
* )
* )
*/
public function createTemplate(Request $request)
{
$data = json_decode($request->getContent(), true);
if (!isset($data['name_template']) || !isset($data['content_template'])) {
return new Response('La solicitud no pudo ser procesada debido a un error en los datos proporcionados en el cuerpo de la solicitud.', 400);
}
$nameTemplate = $data['name_template'];
$contentTemplate = $data['content_template'];
#$templateDir = '/opt/ogboot/tftpboot/ipxe_scripts/templates';
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
// Validar el nombre de la plantilla
if (!preg_match('/^[a-zA-Z0-9._-]+$/', $nameTemplate)) {
return new Response('Nombre de la plantilla no válido.', 400);
}
$filePath = $templateDir . '/' . $nameTemplate;
$contentTemplate = str_replace("\\n", "\n", $contentTemplate);
try {
// Intentar crear la plantilla
file_put_contents($filePath, $contentTemplate);
// Comprobar si el archivo se ha creado correctamente
if (!file_exists($filePath)) {
throw new \Exception('El archivo no se pudo crear.');
}
// Verificar si el contenido escrito coincide con el contenido esperado
$writtenContent = file_get_contents($filePath);
if ($writtenContent !== $contentTemplate) {
throw new \Exception('El contenido del archivo no coincide con el contenido esperado.');
}
} catch (\Exception $e) {
return new Response('Ocurrió un error al crear la plantilla de arranque. ' . $e->getMessage(), 500);
}
// Retornar el nombre de la plantilla y su contenido en el formato solicitado
return new Response(json_encode([
'success' => 'Plantilla creada con éxito',
'template_name' => $nameTemplate,
'template_content' => $contentTemplate
]), 200, ['Content-Type' => 'application/json']);
}
/**
* @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($name): Response
{
#$templateDir = '/opt/ogboot/tftpboot/ipxe_scripts/templates';
$templateDir = $this->tftpbootDir . '/ipxe_scripts/templates';
$filePath = $templateDir . '/' . $name;
// Comprobar si la plantilla existe
if (!file_exists($filePath)) {
return new Response(json_encode([
'error' => 'TEMPLATE_NOT_FOUND',
'message' => 'No se encontró la plantilla especificada'
]), Response::HTTP_NOT_FOUND, ['Content-Type' => 'application/json']);
}
// Intentar eliminar la plantilla
try {
unlink($filePath);
} catch (\Exception $e) {
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']);
}
// Devolver respuesta exitosa
return new Response(json_encode([
'success' => 'Plantilla eliminada',
'message' => "La plantilla $name se ha borrado correctamente"
]), Response::HTTP_OK, ['Content-Type' => 'application/json']);
}
}