Compare commits
No commits in common. "main" and "opengnsys-3.1.0" have entirely different histories.
main
...
opengnsys-
|
|
@ -47,4 +47,3 @@ debian/files
|
|||
debian/*.debhelper
|
||||
debian/*.debhelper.log
|
||||
debian/debhelper-build-stamp
|
||||
.vscode/
|
||||
|
|
|
|||
|
|
@ -1,14 +1,5 @@
|
|||
# Changelog
|
||||
|
||||
## [0.7.4] - 2026-07-31
|
||||
### Added
|
||||
- Añadidos endpoints a la API para eliminar concesiones (leases) a nivel de host y de subred.
|
||||
- Añadido el hook de leases a la configuración de Kea.
|
||||
|
||||
## [0.7.3] - 2025-10-20
|
||||
### Fixed
|
||||
- Arregla el código de DNS en el kea cuando se actualiza la información de una subred existente.
|
||||
|
||||
## [0.7.2] - 2025-06-06
|
||||
### Changed
|
||||
- Corrige bug cuando no recibe parámetro boot-file-name.
|
||||
|
|
|
|||
|
|
@ -61,19 +61,6 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
stage('Generate Changelog (Devel)') {
|
||||
when {
|
||||
branch 'devel'
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def devName = params.DEV_NAME ? params.DEV_NAME : env.DEFAULT_DEV_NAME
|
||||
def devEmail = params.DEV_EMAIL ? params.DEV_EMAIL : env.DEFAULT_DEV_EMAIL
|
||||
generateDebianChangelog(env.BUILD_DIR, devName, devEmail, "devel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
script {
|
||||
|
|
@ -109,19 +96,6 @@ pipeline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage ('Publish to Debian Repository (Devel)') {
|
||||
when {
|
||||
branch 'devel'
|
||||
}
|
||||
agent { label 'debian-repo' }
|
||||
steps {
|
||||
script {
|
||||
def versionPattern = "-${env.BUILD_NUMBER}~devel"
|
||||
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogdhcp', 'devel', versionPattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
|
|
@ -134,13 +108,6 @@ pipeline {
|
|||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
}
|
||||
if (env.BRANCH_NAME == 'devel') {
|
||||
build job: 'Aptly publish develop repository',
|
||||
wait: false,
|
||||
parameters: [
|
||||
string(name: 'TRIGGERED_BY', value: "${env.JOB_NAME}-${env.BUILD_NUMBER}")
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
always {
|
||||
|
|
|
|||
|
|
@ -1032,7 +1032,7 @@ public function modifyDhcpSubnet(Request $request): JsonResponse
|
|||
if (!empty($DNS)) {
|
||||
$newSubnet["option-data"][] = [
|
||||
"name" => "domain-name-servers",
|
||||
"code" => 6,
|
||||
"code" => 23,
|
||||
"space" => "dhcp4",
|
||||
"csv-format" => true,
|
||||
"data" => $DNS
|
||||
|
|
@ -1111,7 +1111,7 @@ public function modifyDhcpSubnet(Request $request): JsonResponse
|
|||
'component' => $component,
|
||||
'http_code' => Response::HTTP_OK,
|
||||
'desc' => $responseSuccess,
|
||||
'params' => [$input]
|
||||
'params' => ['subnet_id' => $subnetId]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['success' => $responseSuccess], Response::HTTP_OK);
|
||||
}
|
||||
|
|
@ -2209,261 +2209,6 @@ public function restoreDhcpConfiguration(): JsonResponse
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* path="/ogdhcp/v1/subnets/{subnetId}/leases",
|
||||
* summary="Elimina todos los leases de una subred",
|
||||
* @OA\Parameter(
|
||||
* name="subnetId",
|
||||
* in="path",
|
||||
* description="ID de la subred cuyos leases se van a eliminar",
|
||||
* required=true,
|
||||
* @OA\Schema(type="integer")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Leases eliminados correctamente",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="success", type="string", example="Leases de la subred eliminados correctamente"),
|
||||
* @OA\Property(property="message", type="string", example="Leases deleted.")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="No se encontraron leases en la subred",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string", example="No se encontraron leases en la subred con id '44'")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=500,
|
||||
* description="Error al comunicarse con el agente de control de Kea",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string", example="Error al ejecutar lease4-wipe")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* @Route("/ogdhcp/v1/subnets/{subnetId}/leases", methods={"DELETE"})
|
||||
*/
|
||||
public function wipeSubnetLeases(Request $request): JsonResponse
|
||||
{
|
||||
$operation = 'wipeSubnetLeases';
|
||||
$component = 'ogdhcp';
|
||||
$subnetId = (int) $request->get('subnetId');
|
||||
|
||||
try {
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'params' => ['subnet_id' => $subnetId],
|
||||
'desc' => 'Iniciando eliminación de leases de la subred.'
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
$response = $this->curlKeaService->executeLeaseCommand('lease4-wipe', ['subnet-id' => $subnetId]);
|
||||
|
||||
if (!$response) {
|
||||
$errorText = "No se obtuvo respuesta del agente de control de Kea al ejecutar lease4-wipe.";
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['subnet_id' => $subnetId]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$result = $response[0]['result'];
|
||||
$text = $response[0]['text'] ?? '';
|
||||
|
||||
// result 3 = empty: el comando se ejecutó pero no había leases
|
||||
if ($result === 3) {
|
||||
$errorText = "No se encontraron leases en la subred con id '$subnetId'";
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_NOT_FOUND,
|
||||
'desc' => $errorText,
|
||||
'params' => ['subnet_id' => $subnetId]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($result !== 0) {
|
||||
$errorText = "Error al eliminar los leases de la subred '$subnetId': $text";
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['subnet_id' => $subnetId, 'kea_result' => $result]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_OK,
|
||||
'desc' => 'Leases de la subred eliminados correctamente.',
|
||||
'params' => ['subnet_id' => $subnetId]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
return new JsonResponse([
|
||||
'success' => "Leases de la subred eliminados correctamente",
|
||||
'message' => $text
|
||||
], Response::HTTP_OK);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$errorText = "Error al ejecutar lease4-wipe: " . $e->getMessage();
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['subnet_id' => $subnetId]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @OA\Delete(
|
||||
* path="/ogdhcp/v1/leases/{ipAddress}",
|
||||
* summary="Elimina el lease de una máquina por su dirección IP",
|
||||
* @OA\Parameter(
|
||||
* name="ipAddress",
|
||||
* in="path",
|
||||
* description="Dirección IP del lease a eliminar (ej: 192.168.1.11)",
|
||||
* required=true,
|
||||
* @OA\Schema(type="string")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Lease eliminado correctamente",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="success", type="string", example="Lease eliminado correctamente"),
|
||||
* @OA\Property(property="message", type="string", example="IPv4 lease deleted.")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="No se encontró un lease para la IP indicada",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string", example="No se encontró un lease para la IP '192.168.1.11'")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=500,
|
||||
* description="Error al comunicarse con el agente de control de Kea",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string", example="Error al ejecutar lease4-del")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* @Route("/ogdhcp/v1/leases/{ipAddress}", methods={"DELETE"}, requirements={"ipAddress"=".+"})
|
||||
*/
|
||||
public function deleteHostLease(Request $request): JsonResponse
|
||||
{
|
||||
$operation = 'deleteHostLease';
|
||||
$component = 'ogdhcp';
|
||||
$ipAddress = $request->get('ipAddress');
|
||||
|
||||
try {
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'params' => ['ip_address' => $ipAddress],
|
||||
'desc' => 'Iniciando eliminación del lease del host.'
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
$response = $this->curlKeaService->executeLeaseCommand('lease4-del', ['ip-address' => $ipAddress]);
|
||||
|
||||
if (!$response) {
|
||||
$errorText = "No se obtuvo respuesta del agente de control de Kea al ejecutar lease4-del.";
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['ip_address' => $ipAddress]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$result = $response[0]['result'];
|
||||
$text = $response[0]['text'] ?? '';
|
||||
|
||||
// result 3 = empty: no se encontró un lease para esa IP
|
||||
if ($result === 3) {
|
||||
$errorText = "No se encontró un lease para la IP '$ipAddress'";
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_NOT_FOUND,
|
||||
'desc' => $errorText,
|
||||
'params' => ['ip_address' => $ipAddress]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
if ($result !== 0) {
|
||||
$errorText = "Error al eliminar el lease de la IP '$ipAddress': $text";
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['ip_address' => $ipAddress, 'kea_result' => $result]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
$this->logger->info(json_encode([
|
||||
'severity' => 'INFO',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_OK,
|
||||
'desc' => 'Lease eliminado correctamente.',
|
||||
'params' => ['ip_address' => $ipAddress]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
|
||||
return new JsonResponse([
|
||||
'success' => "Lease eliminado correctamente",
|
||||
'message' => $text
|
||||
], Response::HTTP_OK);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$errorText = "Error al ejecutar lease4-del: " . $e->getMessage();
|
||||
$this->logger->error(json_encode([
|
||||
'severity' => 'ERROR',
|
||||
'operation' => $operation,
|
||||
'component' => $component,
|
||||
'http_code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'desc' => $errorText,
|
||||
'params' => ['ip_address' => $ipAddress]
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
return new JsonResponse(['error' => $errorText], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,45 +61,6 @@ class CurlKeaService
|
|||
}
|
||||
}
|
||||
|
||||
public function executeLeaseCommand($command, $arguments)
|
||||
{
|
||||
$apiUrl = getenv('DHCP_IP');
|
||||
if (!$apiUrl) {
|
||||
$apiUrl = 'http://localhost:8000/';
|
||||
}
|
||||
|
||||
$requestData = [
|
||||
'command' => $command,
|
||||
'service' => ['dhcp4'],
|
||||
'arguments' => $arguments,
|
||||
];
|
||||
|
||||
$jsonData = json_encode($requestData);
|
||||
try {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $apiUrl);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Expect:']);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$output = json_decode($response, true);
|
||||
|
||||
if ($httpCode >= 200 && $httpCode < 300) {
|
||||
return $output;
|
||||
} else {
|
||||
$error = curl_error($ch);
|
||||
throw new Exception($error);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function convertMaskToCIDR($mask)
|
||||
{
|
||||
$bits = 0;
|
||||
|
|
|
|||
|
|
@ -24,28 +24,6 @@ restore_config_if_modified() {
|
|||
}
|
||||
|
||||
|
||||
# Añade el hook lease-cmds a kea-dhcp4.conf solo si no está ya presente
|
||||
ensure_lease_cmds_hook() {
|
||||
local config="$1"
|
||||
local lib="$2"
|
||||
|
||||
[ -f "$config" ] || return 0
|
||||
[ -n "$lib" ] || return 0
|
||||
|
||||
if grep -q "libdhcp_lease_cmds" "$config"; then
|
||||
echo "El hook lease-cmds ya está presente en $config, no se añade de nuevo."
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Añadiendo hook lease-cmds a $config..."
|
||||
local tmp
|
||||
tmp=$(mktemp)
|
||||
jq --arg lib "$lib" \
|
||||
'.Dhcp4["hooks-libraries"] = (.Dhcp4["hooks-libraries"] // []) + [{"library": $lib}]' \
|
||||
"$config" > "$tmp" && mv "$tmp" "$config"
|
||||
chown _kea:_kea "$config"
|
||||
}
|
||||
|
||||
KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf"
|
||||
PUBLIC_DIR=/opt/opengnsys/ogdhcp/api/public
|
||||
db_get opengnsys/ogdhcp_interfaces
|
||||
|
|
@ -117,18 +95,8 @@ EOF
|
|||
echo "Configurando kea-dhcp4..."
|
||||
IFS=',' read -r -a INTERFACES <<< "$OGDHCP_INTERFACES"
|
||||
KEA_CONFIG="/etc/kea/kea-dhcp4.conf"
|
||||
|
||||
# Detectar la ruta de libdhcp_lease_cmds.so (varía según arquitectura)
|
||||
LEASE_CMDS_LIB=$(find /usr/lib -name "libdhcp_lease_cmds.so" 2>/dev/null | head -1)
|
||||
if [ -z "$LEASE_CMDS_LIB" ]; then
|
||||
echo "Advertencia: no se encontró libdhcp_lease_cmds.so. El hook lease-cmds no estará activo."
|
||||
else
|
||||
echo "Librería lease-cmds encontrada en: $LEASE_CMDS_LIB"
|
||||
fi
|
||||
|
||||
if [ -e "$KEA_CONFIG" ]; then
|
||||
dpkg-divert --package ogdhcp --divert "$KEA_CONFIG.dpkg-dist" --rename "$KEA_CONFIG"
|
||||
# El fichero se genera desde cero, no hay riesgo de duplicación
|
||||
cat > "$KEA_CONFIG" <<EOF
|
||||
{
|
||||
"Dhcp4": {
|
||||
|
|
@ -160,8 +128,6 @@ EOF
|
|||
}
|
||||
}
|
||||
EOF
|
||||
# Añadir el hook tras generar el fichero (la función verifica que no esté ya)
|
||||
ensure_lease_cmds_hook "$KEA_CONFIG" "$LEASE_CMDS_LIB"
|
||||
fi
|
||||
else
|
||||
|
||||
|
|
@ -171,10 +137,6 @@ EOF
|
|||
restore_config_if_modified "/opt/opengnsys/ogdhcp/api/.env"
|
||||
restore_config_if_modified "/etc/nginx/sites-available/ogdhcp.conf"
|
||||
restore_config_if_modified "/etc/php/$PHP_VERSION/fpm/pool.d/ogdhcp.conf"
|
||||
|
||||
# En upgrade: añadir el hook si se instaló kea-hook-lease-cmds y no estaba configurado
|
||||
LEASE_CMDS_LIB=$(find /usr/lib -name "libdhcp_lease_cmds.so" 2>/dev/null | head -1)
|
||||
ensure_lease_cmds_hook "/etc/kea/kea-dhcp4.conf" "$LEASE_CMDS_LIB"
|
||||
fi
|
||||
echo ">>> Configuración de ogdhcp completada."
|
||||
;;
|
||||
|
|
|
|||
Loading…
Reference in New Issue