Compare commits

...

47 Commits

Author SHA1 Message Date
Nicolas Arenas c172ba0682 Remove extra chareacters at the beginning of the line
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 17:42:40 +02:00
Nicolas Arenas 088b33a235 Fix problem with ip space at the end
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 17:39:16 +02:00
Luis Gerardo Romero Garcia 3496a993c9 refs #799 adds daemon reload
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 17:26:35 +02:00
Nicolas Arenas 36a1a8cc33 Fix env var
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 17:25:01 +02:00
Luis Gerardo Romero Garcia d53fddf3a9 refs #799 removes kea password comprobation in kea agent service
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 17:15:18 +02:00
Nicolas Arenas bd88f58303 Update url to check api up
testing/og-dhcp-API/pipeline/head Build queued... Details
2024-10-01 17:08:21 +02:00
Luis Gerardo Romero Garcia 78639f92a3 refs #799 fix a error in adding apparmor write permissions to kea conf
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 16:41:49 +02:00
Luis Gerardo Romero Garcia aa1b85a785 refs #799 fix a error in the comment kea ctrl authentication and a typo in the swagger doc 2024-10-01 16:41:49 +02:00
Nicolas Arenas dbf5c9ebc0 Fix get email
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 16:21:30 +02:00
Luis Gerardo Romero Garcia c136f004e9 refs #799 adds apparmor exception to write in kea conf and delete hash in controller
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 16:04:40 +02:00
Luis Gerardo Romero Garcia 4266bdffb4 refs #799 adds apparmor exception to write in kea conf 2024-10-01 16:04:40 +02:00
Nicolas Arenas 35c44c163f Improve plugin installation
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 14:12:34 +02:00
Nicolas Arenas 231cbe92d8 Change script to get user email
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 13:58:58 +02:00
Nicolas Arenas c9764a99d3 Revert commit as it was working fine 2024-10-01 13:37:53 +02:00
Nicolas Arenas 529f4a3653 Test api in proper stage
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 13:34:17 +02:00
Nicolas Arenas a6968ca83a Move vagrant destroy server to post action 2024-10-01 13:32:31 +02:00
Nicolas Arenas 139102eec8 Update Jenkinsfile with copilot help
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 13:27:31 +02:00
Luis Gerardo Romero Garcia 14a2ae7d4f refs #799 fix conflict
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 13:07:13 +02:00
Qindel e1f498c3df refs #799 fix problems with composer routes 2024-10-01 13:07:13 +02:00
Nicolas Arenas 9a3c5bd80f Fix typo
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 12:37:11 +02:00
Nicolas Arenas 57e01f880b Using mailer plugin
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 12:24:35 +02:00
Nicolas Arenas 5617453e0e Deshabilita las ejecuciones concurrentes
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 12:11:17 +02:00
Nicolas Arenas 110f7e3370 Add mail notification to Jenkinsfile
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 12:08:05 +02:00
Nicolas Arenas 458930c7cb Update vagrant and Jenkins for new installer
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 11:17:01 +02:00
Luis Gerardo Romero Garcia 2c4160e629 refs #799 fix composer error and deletes download composer.phar function
testing/og-dhcp-API/pipeline/head This commit looks good Details
2024-10-01 11:05:42 +02:00
Luis Gerardo Romero Garcia d844185d89 refs #799 adds nginx installation function, configure php-fpm based on php version installed, adds comments in kea agent and adds nginx template 2024-10-01 11:05:42 +02:00
Luis Gerardo Romero Garcia 6b79e04805 refs #799 deletes a lot of innecesaries files 2024-10-01 11:05:35 +02:00
Qindel bfb040fbaf refs #797 removes schema swagger for errors with nelmio, adds nelmio to composer.json 2024-10-01 11:02:27 +02:00
Nicolas Arenas 8f633961bb Update some typos
testing/og-dhcp-API/pipeline/head This commit looks good Details
2024-10-01 09:46:56 +02:00
Nicolas Arenas 62134cd7fd Update provision and swagger init file
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 09:28:16 +02:00
Nicolas Arenas 8e2f093da1 Replace echo command and get the ip
testing/og-dhcp-API/pipeline/head This commit looks good Details
2024-10-01 08:51:22 +02:00
Nicolas Arenas 6973eb7d67 Update password for user qindel
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 08:14:15 +02:00
Nicolas Arenas 1f0561666c Fix wrong directory in vagrantfile
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 00:58:06 +02:00
Nicolas Arenas 90e3a9ef32 Updating scripts to get environment ready
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 00:49:47 +02:00
Nicolas Arenas 35c2ec682e Update apache config
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-10-01 00:13:37 +02:00
Nicolas Arenas 58a670d3f2 Not destroying server to check installation
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 19:47:19 +02:00
Nicolas Arenas e419c3bc18 Force vagrant provision
testing/og-dhcp-API/pipeline/head This commit looks good Details
2024-09-30 19:38:14 +02:00
Nicolas Arenas 8eba47c2e0 Fix typo
testing/og-dhcp-API/pipeline/head This commit looks good Details
2024-09-30 19:33:10 +02:00
Nicolas Arenas d6587e5209 Updated sync method for deployment
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 19:29:58 +02:00
Nicolas Arenas 215da35234 Launch provision in installer
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 19:26:45 +02:00
Nicolas Arenas 9c106f04c0 Update PATH
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 19:09:25 +02:00
Nicolas Arenas 9935af4f48 Update PATH environment var
testing/og-dhcp-API/pipeline/head Something is wrong with the build of this commit Details
2024-09-30 19:04:54 +02:00
Nicolas Arenas 1fb3b305e6 Install plugin for esxi and specify provider
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 18:35:11 +02:00
Nicolas Arenas 1659275b19 Updated Jenkinsfile
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 18:32:05 +02:00
Nicolas Arenas 17f0768f6f Update Jenkinsfile and Vagrantfile to create environment
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-09-30 18:29:18 +02:00
Nicolas Arenas 31c0976e42 Test Jenkins agent
testing/og-dhcp-API/pipeline/head Something is wrong with the build of this commit Details
2024-09-30 14:16:19 +02:00
Nicolas Arenas 114a1de095 skelton pipeline 2024-09-30 13:26:49 +02:00
36 changed files with 841 additions and 999 deletions

View File

@ -4,17 +4,16 @@
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=7.2.0",
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"doctrine/annotations": "^1.6",
"doctrine/doctrine-bundle": "^2.0",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.7",
"nelmio/api-doc-bundle": "^4.9",
"phpdocumentor/reflection-docblock": "^5.0",
"phpstan/phpdoc-parser": "^0.4",
"zircote/swagger-php": "3.*",
"symfony/runtime": "5.*",
"symfony/asset": "5.*",
"symfony/console": "5.*",
"symfony/doctrine-messenger": "5.*",
@ -32,6 +31,7 @@
"symfony/process": "5.*",
"symfony/property-access": "5.*",
"symfony/property-info": "5.*",
"symfony/runtime": "5.*",
"symfony/security-bundle": "5.*",
"symfony/serializer": "5.*",
"symfony/string": "5.*",
@ -41,7 +41,8 @@
"symfony/web-link": "5.*",
"symfony/yaml": "5.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0"
"twig/twig": "^2.12|^3.0",
"zircote/swagger-php": "3.*"
},
"require-dev": {
"phpunit/phpunit": "^8.5",

View File

@ -12,4 +12,6 @@ return [
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
App\DhcpBundle\DhcpBundle::class => ['all' => true],
Nelmio\ApiDocBundle\NelmioApiDocBundle::class => ['all' => true],
];

View File

@ -0,0 +1,9 @@
nelmio_api_doc:
documentation:
info:
title: My App
description: This is an awesome app!
version: 1.0.0
areas: # to filter documented areas
path_patterns:
- ^/ogdhcp/ # Accepts routes under /api except /api/doc

View File

@ -1,3 +1,7 @@
#index:
# path: /
# controller: App\Controller\DefaultController::index
app.swagger_ui:
path: /ogdhcp/api/doc
methods: GET
defaults: { _controller: nelmio_api_doc.controller.swagger_ui }

View File

@ -2,6 +2,7 @@
<VirtualHost *:80>
ServerName localhost
ServerAlias api-test
DocumentRoot /opt/ogdhcp/public
<Directory /opt/ogdhcp/public>
@ -21,7 +22,7 @@
</IfModule>
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost/"
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
</FilesMatch>
ErrorLog ${APACHE_LOG_DIR}/ogdhcp_error.log

View File

@ -0,0 +1,42 @@
server {
listen 80;
server_name __SERVERIP__ localhost; # IP del servidor
# Raíz del documento para el proyecto Symfony
root /opt/ogdhcp/public;
# Bloque para manejar las solicitudes a /ogdhcp
location /ogdhcp {
try_files $uri $uri/ /index.php?$query_string;
# Aumentar el tiempo de espera por el install ogdhcp (si es necesario)
proxy_read_timeout 600;
proxy_connect_timeout 600;
proxy_send_timeout 600;
send_timeout 600;
}
# Bloque para manejar las solicitudes a index.php
location ~ ^/index.php(/|$) {
include fastcgi_params;
fastcgi_pass unix:/run/php/php__PHPVERSION__-fpm-ogdhcp.sock; # Asegúrate de que esto sea correcto
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param DOCUMENT_ROOT $document_root;
internal;
}
# Bloque para devolver 404 en cualquier solicitud a archivos PHP que no sean index.php
location ~ \.php$ {
return 404;
}
# Logs de error y acceso para el proyecto Symfony
error_log /var/log/nginx/ogdhcp_error.log;
access_log /var/log/nginx/ogdhcp_access.log;
# Manejo de la ruta para la documentación de la API (Swagger)
location /ogdhcp/api/doc {
try_files $uri /index.php?$query_string;
}
}

View File

@ -41,18 +41,14 @@ function globalSetup() {
ENABLESERVICE="eval update-rc.d \$service defaults"
DISABLESERVICE="eval update-rc.d \$service disable"
APACHESERV=apache2
APACHECFGDIR=/etc/apache2
APACHESITESDIR=sites-available
APACHEOGSITE=ogdhcp
APACHEUSER="www-data"
APACHEGROUP="www-data"
APACHEENABLEMODS="a2enmod headers ssl rewrite proxy_fcgi fastcgi actions alias"
APACHEENABLESSL="a2ensite default-ssl"
APACHEENABLEOG="a2ensite $APACHEENABLEOG"
APACHEMAKECERT="make-ssl-cert generate-default-snakeoil --force-overwrite"
PHPFPMSERV=php7.2-fpm
# Variables globales
DEFAULTDEV=""
NGINX_TEMPLATE="$INSTALL_TARGET/etc/nginxServer.conf.tmpl"
NGINX_OUTPUT="/etc/nginx/sites-available/ogdhcp.conf"
NGINX_CONF_PATH="/etc/nginx/nginx.conf"
PHP_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/www.conf"
NEW_FPM_CONF_PATH="/etc/php/__PHPVERSION__/fpm/pool.d/ogdhcp.conf"
SOCKET_PATH="/run/php/php__PHPVERSION__-fpm-ogdhcp.sock"
# Registro de incidencias.
OGLOGFILE="$INSTALL_TARGET/var/log/${PROGRAMNAME%.sh}.log"
@ -80,47 +76,31 @@ function checkDependencies() {
php-bcmath
composer
unzip
apache2
libapache2-mod-php
kea-dhcp4-server
kea-common
kea-ctrl-agent
jq
net-tools
nginx
)
export DEBIAN_FRONTEND=noninteractive
# Comprobar cada dependencia
for dep in "${DEPENDENCIES[@]}"; do
if ! dpkg -s "$dep" >/dev/null 2>&1; then
echoAndLog "$dep is not installed. Installing..."
sudo apt-get install -y "$dep"
sudo apt-get install -y --no-install-recommends "$dep"
else
echoAndLog "$dep is already installed."
fi
done
sed -i '/ConditionFileNotEmpty=\/etc\/kea\/kea-api-password/d' /usr/lib/systemd/system/kea-ctrl-agent.service
systemctl daemon-reload
systemctl restart kea-ctrl-agent.service
echoAndLog "Dependencies checked."
}
# Función para instalar los paquetes necesarios para KEA-DHCP
install_kea() {
sudo apt-get install -y isc-kea-common isc-kea-ctrl-agent isc-kea-dhcp4-server isc-kea-dhcp6-server isc-kea-admin
}
# Función para instalar Composer
install_composer() {
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
}
# Función para instalar Swagger UI
install_swagger() {
sudo apt-get install -y unzip
wget https://github.com/swagger-api/swagger-ui/archive/master.zip
unzip master.zip -d /var/www/html/
sudo mv /var/www/html/swagger-ui-master /var/www/html/swagger-ui
}
# Obtiene el código fuente del proyecto desde el repositorio de GitHub.
function downloadCode() {
@ -194,17 +174,30 @@ function createDirs() {
cp -a "$WORKDIR/ogdhcp/.env" "${path_opengnsys_base}/.env"
}
function create_ogdhcp_project {
# Cambia al usuario ogdhcp y crea el proyecto Symfony
local path_opengnsys_base="$1"
composer create-project symfony/website-skeleton "$path_opengnsys_base"
pushd "$path_opengnsys_base" || return
# Elimina el archivo composer.lock
rm composer.lock
popd || return
echoAndLog "Esqueleto de la aplicación creado y archivo composer.lock eliminado."
}
function create_ogdhcp_project {
# Crea el usuario ogdhcp si no existe
local path_opengnsys_base="$1"
if ! id -u ogdhcp &>/dev/null; then
echoAndLog "${FUNCNAME}(): creating ogdhcp user"
useradd ogdhcp 2>/dev/null
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error creating ogdhcp user"
return 1
fi
fi
# Crea el directorio path_opengnsys_base con el usuario ogdhcp
echoAndLog "${FUNCNAME}(): creating directory $path_opengnsys_base with ogdhcp user"
sudo mkdir -p "$path_opengnsys_base"
sudo chown ogdhcp:ogdhcp $path_opengnsys_base
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error while creating directory $path_opengnsys_base"
return 1
fi
echoAndLog "Directory $path_opengnsys_base created with ogdhcp user"
}
function copyServerFiles() {
if [ $# -ne 1 ]; then
@ -220,9 +213,6 @@ function copyServerFiles() {
#public
src
etc
templates
tests
vendor
.env
composer.json
composer.lock
@ -234,9 +224,6 @@ function copyServerFiles() {
#public
src
etc
templates
tests
vendor
.env
composer.json
composer.lock
@ -271,53 +258,14 @@ function copyServerFiles() {
popd || return
}
function downloadComposer() {
echoAndLog "Downloading composer.phar..."
# Crear el directorio de trabajo si no existe
mkdir -p "$WORKDIR/ogdhcp/bin" || return
# Cambiar al directorio de trabajo
pushd "$WORKDIR/ogdhcp/bin" || return
# Descargar composer.phar
curl -sS https://getcomposer.org/installer | php
# Comprobar si la descarga fue exitosa
if [ ! -f composer.phar ]; then
errorAndLog "Failed to download composer.phar"
popd
return 1
fi
# Crear el directorio de destino si no existe
mkdir -p "/opt/ogdhcp/bin" || return
# Mover composer.phar a /opt/ogdhcp/bin
mv composer.phar "/opt/ogdhcp/bin/"
# Comprobar si el movimiento fue exitoso
if [ ! -f "/opt/ogdhcp/bin/composer.phar" ]; then
errorAndLog "Failed to move composer.phar to /opt/ogdhcp/bin"
popd
return 1
fi
# Volver al directorio original
popd || return
echoAndLog "composer.phar downloaded and moved to /opt/ogdhcp/bin"
return 0
}
function runComposer() {
echoAndLog "Running composer.phar to install dependencies..."
# Cambiar al directorio donde está composer.phar
pushd /opt/ogdhcp/bin || return
local path_opengnsys_base="$1"
pushd $path_opengnsys_base
pwd
# Ejecutar composer.phar
sudo -u "$OPENGNSYS_CLIENT_USER" php composer.phar install
sudo -u "$OPENGNSYS_CLIENT_USER" composer --no-interaction install
# Comprobar si la ejecución fue exitosa
if [ $? -ne 0 ]; then
@ -326,92 +274,181 @@ function runComposer() {
return 1
fi
# Volver al directorio original
popd || return
echoAndLog "composer.phar ran successfully and dependencies were installed"
return 0
}
function install_swagger_ui {
# Define la URL del archivo de Swagger UI que quieres descargar
swagger_ui_url="https://github.com/swagger-api/swagger-ui/archive/refs/heads/master.zip"
# Define la ruta donde quieres descomprimir Swagger UI
swagger_ui_path="/tmp/swagger-ui"
get_first_network_interface_with_traffic() {
while read -r line; do
if [[ "$line" == *:* ]]; then
interface=$(echo "$line" | cut -d ':' -f 1 | xargs)
if [[ "$interface" != "lo" ]]; then
received_bytes=$(echo "$line" | awk '{print $2}')
transmitted_bytes=$(echo "$line" | awk '{print $10}')
if (( received_bytes > 0 || transmitted_bytes > 0 )); then
DEFAULTDEV="$interface"
break
fi
fi
fi
done < /proc/net/dev
}
comment_auth_kea() {
KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf"
# Verificar si el bloque de "authentication" ya está comentado
if grep -q '^[^#]*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then
echo "Comentando el bloque de autenticación en $KEA_CTRL_AGENT_CONF..."
# Define la ruta de destino para los archivos de Swagger UI
destination_path="/opt/ogdhcp/public"
# Comentar solo el bloque de authentication desde la apertura hasta la línea con '},'
sed -i '/"authentication": {/,/^[[:space:]]*},/ {
s/^\([[:space:]]*\)\([^#]\)/\1#\2/
}' "$KEA_CTRL_AGENT_CONF"
# Crea los directorios si no existen
mkdir -p "$swagger_ui_path"
mkdir -p "$destination_path"
echo "Bloque de autenticación comentado correctamente."
else
echo "El bloque de autenticación ya está comentado."
fi
# Descarga el archivo de Swagger UI
wget "$swagger_ui_url" -O /tmp/swagger-ui.zip
# Verificar si el bloque fue comentado correctamente
if grep -q '^#\s*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then
echo "Confirmación: Bloque de autenticación comentado correctamente."
# Descomprime el archivo de Swagger UI en la ruta especificada
unzip /tmp/swagger-ui.zip -d "$swagger_ui_path"
# Reiniciar el servicio de Kea Control Agent para aplicar los cambios
echo "Reiniciando el agente de Kea Control Agent..."
sudo systemctl restart kea-ctrl-agent.service
# Copia los archivos de Swagger UI al directorio de destino
cp -r "$swagger_ui_path"/swagger-ui-master/dist/* "$destination_path"
# Elimina el archivo descargado y el directorio temporal
rm /tmp/swagger-ui.zip
rm -r "$swagger_ui_path"
/opt/ogdhcp/vendor/bin/openapi /opt/ogdhcp/src/DhcpBundle/Controller/ -o "$destination_path/swagger.json"
echo "Swagger UI instalado en $destination_path."
if systemctl is-active --quiet kea-ctrl-agent.service; then
echo "El agente de Kea Control Agent se ha reiniciado correctamente."
else
echo "Error: No se pudo reiniciar el agente de Kea Control Agent."
fi
else
echo "Error: No se pudo comentar correctamente el bloque de autenticación."
fi
}
# Función para obtener la dirección IP de una interfaz
get_ip_address() {
local interface="$1"
ip -4 addr show "$interface" | grep -oP "(?<=inet\s)\d+(\.\d+){3}"
}
function installWebConsoleApacheConf() {
if [ $# -ne 2 ]; then
errorAndLog "${FUNCNAME}(): invalid number of parameters"
# Función para obtener la versión de PHP instalada
get_php_fpm_version() {
php -v | grep -oP "PHP \K\d+\.\d+"
}
add_write_permission_apparmor() {
APPARMOR_PROFILE="/etc/apparmor.d/usr.sbin.kea-dhcp4"
# Comprobar si las líneas existen
if grep -q "/etc/kea/ r," "$APPARMOR_PROFILE" && grep -q "/etc/kea/** r," "$APPARMOR_PROFILE"; then
echo "Modificando permisos en $APPARMOR_PROFILE..."
# Modificar las líneas /etc/kea/ r, y /etc/kea/** r, añadiendo w
sed -i 's#/etc/kea/ r,#/etc/kea/ rw,#g' "$APPARMOR_PROFILE"
sed -i 's#/etc/kea/\*\* r,#/etc/kea/** rw,#g' "$APPARMOR_PROFILE"
echo "Permisos de escritura añadidos correctamente a $APPARMOR_PROFILE."
else
echo "Las líneas no fueron encontradas o ya están modificadas."
fi
# Recargar el perfil de AppArmor para aplicar los cambios
echo "Recargando el perfil de AppArmor para kea-dhcp4..."
sudo apparmor_parser -r "$APPARMOR_PROFILE"
if [ $? -eq 0 ]; then
echo "El perfil de AppArmor se recargó correctamente."
else
echo "Error al recargar el perfil de AppArmor."
fi
}
# Función para configurar Nginx
setup_nginx() {
get_first_network_interface_with_traffic
if [[ -z "$DEFAULTDEV" ]]; then
echo "Error: No se encontró una interfaz de red activa."
exit 1
fi
local path_opengnsys_base="$1"
local path_apache2_confd="$2"
local OGHDPCDIR="${path_opengnsys_base}/public"
local sockfile
ip_address_server=$(get_ip_address "$DEFAULTDEV")
php_version=$(get_php_fpm_version)
if [ ! -d "$path_apache2_confd" ]; then
errorAndLog "${FUNCNAME}(): path to apache2 conf.d can not found, verify your server installation"
return 1
if [[ -z "$php_version" ]]; then
echo "Error: No se pudo obtener la versión de PHP."
exit 1
fi
mkdir -p "$path_apache2_confd/{sites-available,sites-enabled}"
echoAndLog "${FUNCNAME}(): creating apache2 config file.."
# Activar PHP-FPM.
echoAndLog "${FUNCNAME}(): configuring PHP-FPM"
service="$PHPFPMSERV"
$ENABLESERVICE; $STARTSERVICE
sockfile=$(find /run/php -name "php*.sock" -type s -print 2>/dev/null | tail -1)
# Activar módulos de Apache.
$APACHEENABLEMODS
# Generar configuración de consola web a partir del archivo de plantilla.
if [ -n "$sockfile" ]; then
sed -e "s,OGHDPCDIR,$OGHDPCDIR,g" \
-e "s,proxy:fcgi:.*,proxy:unix:${sockfile%% *}|fcgi://localhost\",g" \
"$WORKDIR/ogdhcp/etc/apache.conf.tmpl" > "$path_apache2_confd/$APACHESITESDIR/${APACHEOGSITE}.conf"
else
sed -e "s,OGHDPCDIR,$OGHDPCDIR,g" \
"$WORKDIR/ogdhcp/server/etc/apache.conf.tmpl" > "$path_apache2_confd/$APACHESITESDIR/${APACHEOGSITE}.conf"
# Leer y modificar la plantilla de configuración de nginx
if [[ ! -f "$NGINX_TEMPLATE" ]]; then
echo "Error: La plantilla de Nginx no se encontró."
exit 1
fi
$APACHEENABLEOG
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): config file can't be linked to apache conf, verify your server installation"
return 1
fi
echoAndLog "${FUNCNAME}(): config file created and linked, restarting apache daemon"
service="$APACHESERV"
$ENABLESERVICE; $STARTSERVICE
return 0
nginx_content=$(<"$NGINX_TEMPLATE")
nginx_content="${nginx_content//__SERVERIP__/$ip_address_server}"
nginx_content="${nginx_content//__PHPVERSION__/$php_version}"
# Crear el archivo de configuración de Nginx
echo "$nginx_content" > "$NGINX_OUTPUT"
echo "Archivo de configuración de Nginx creado en $NGINX_OUTPUT."
# Crear el enlace simbólico
ln -sf "$NGINX_OUTPUT" /etc/nginx/sites-enabled/ogdhcp.conf
echo "Enlace simbólico creado en /etc/nginx/sites-enabled/ogdhcp.conf."
# Modificar nginx.conf para ejecutar como ogdhcp
sed -i 's/user www-data;/user ogdhcp;/g' "$NGINX_CONF_PATH"
echo "Nginx configurado para ejecutarse como ogdhcp."
# Reiniciar Nginx
systemctl restart nginx.service
echo "Servicio Nginx reiniciado."
}
# Función para modificar el archivo de configuración PHP-FPM
modify_php_fpm_config() {
php_version=$(get_php_fpm_version)
if [[ -z "$php_version" ]]; then
echo "Error: No se pudo obtener la versión de PHP."
exit 1
fi
php_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/www.conf"
new_fpm_conf_path="/etc/php/$php_version/fpm/pool.d/ogdhcp.conf"
socket_path="/run/php/php$php_version-fpm-ogdhcp.sock"
# Copiar el archivo www.conf a ogdhcp.conf
cp "$php_fpm_conf_path" "$new_fpm_conf_path"
# Modificar el archivo ogdhcp.conf
sed -i 's/\[www\]/[ogdhcp]/g' "$new_fpm_conf_path"
sed -i 's/user = www-data/user = ogdhcp/g' "$new_fpm_conf_path"
sed -i 's/group = www-data/group = ogdhcp/g' "$new_fpm_conf_path"
sed -i "s|listen =.*|listen = $socket_path|g" "$new_fpm_conf_path"
sed -i 's/listen.owner = www-data/listen.owner = ogdhcp/g' "$new_fpm_conf_path"
sed -i 's/listen.group = www-data/listen.group = ogdhcp/g' "$new_fpm_conf_path"
# Reiniciar PHP-FPM
systemctl restart php"$php_version"-fpm.service
echo "PHP-FPM reiniciado."
# Verificar la creación del socket
if [[ -S "$socket_path" ]]; then
echo "Socket PHP-FPM $socket_path creado correctamente."
else
echo "Error: El socket PHP-FPM $socket_path no se ha creado."
exit 1
fi
}
#####################################################################
####### Algunas funciones útiles de propósito general:
#####################################################################
@ -459,7 +496,6 @@ mkdir -p $WORKDIR
pushd $WORKDIR
checkDependencies
install_kea
# Si es necesario, descarga el repositorio de código en directorio temporal
if [ $REMOTE -eq 1 ]; then
downloadCode $GIT_REPO
@ -492,18 +528,32 @@ if [ $? -ne 0 ]; then
exit 1
fi
downloadComposer
runComposer
install_swagger_ui
# Creando configuración de Apache.
installWebConsoleApacheConf $INSTALL_TARGET $APACHECFGDIR
comment_auth_kea
if [ $? -ne 0 ]; then
errorAndLog "Error configuring Apache for OpenGnsys Admin"
errorAndLog "Error while commenting auth block!"
exit 1
fi
sudo apt-get update
runComposer ${INSTALL_TARGET}
setup_nginx $INSTALL_TARGET
if [ $? -ne 0 ]; then
errorAndLog "Error configuring Nginx for OpenGnsys Admin"
exit 1
fi
modify_php_fpm_config
if [ $? -ne 0 ]; then
errorAndLog "Error configuring PHP-FPM for OpenGnsys Admin"
exit 1
fi
add_write_permission_apparmor
if [ $? -ne 0 ]; then
errorAndLog "Error adding write permission to AppArmor profile"
exit 1
fi
# install_kea
# install_php
# install_composer
@ -512,4 +562,4 @@ sudo apt-get update
# Ahora puedes clonar e instalar el componente ogDhcp
# git clone <URL del repositorio de ogDhcp>
# cd <directorio de ogDhcp>
# composer install
# composer install

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

View File

@ -1,16 +0,0 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}

View File

@ -1,19 +0,0 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>

View File

@ -1,9 +0,0 @@
<?php
use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

View File

@ -1,79 +0,0 @@
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState;
if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>

View File

@ -1,20 +0,0 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
url: "http://192.168.0.27:8080/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,549 +0,0 @@
{
"openapi": "3.0.0",
"info": {
"title": "Ogdhcp API",
"version": "1.0"
},
"paths": {
"/opengnsys3/rest/dhcp/subnets": {
"get": {
"operationId": "8f92a1cbcb8cd176bdc4ae272b3ad303",
"responses": {
"200": {
"description": "Devuelve todas las subredes",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Subnet"
}
}
}
}
},
"400": {
"description": "Error al obtener las subredes"
}
}
},
"post": {
"summary": "Add a new DHCP subnet",
"operationId": "88949bae5e7784ce2721ffafe7c88c0a",
"requestBody": {
"description": "JSON payload",
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"subnetId": {
"type": "integer",
"example": 2
},
"mask": {
"type": "string",
"example": "255.255.255.0"
},
"address": {
"type": "string",
"example": "192.168.1.0"
},
"nextServer": {
"type": "string",
"example": "192.168.1.1"
},
"bootFileName": {
"type": "string",
"example": "pxelinux.0"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Subnet added successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
}
},
"/opengnsys3/rest/dhcp/subnets/{subnetId}": {
"put": {
"summary": "Modify a DHCP subnet",
"operationId": "548b55fc0e1ad59ea5b5c909dfd07c71",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "ID of the subnet to modify",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"description": "Data to modify the subnet",
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"mask": {
"type": "string"
},
"address": {
"type": "string"
},
"nextServer": {
"type": "string"
},
"bootFileName": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Subnet modified successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
},
"delete": {
"summary": "Delete a DHCP subnet",
"operationId": "c1c1c34729bdd85857b22e6e2bdc41de",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "ID of the subnet to delete",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Subnet deleted successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
}
},
"/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts": {
"get": {
"summary": "Get all hosts in a subnet",
"operationId": "0989ca622a6a7e23f5af8e3bdd6f6b05",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "The ID of the subnet",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "List of hosts in the subnet",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Host"
}
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"500": {
"description": "Server error",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
},
"put": {
"summary": "Update a DHCP host",
"operationId": "1541441cd53685aaf6df45ab48befaa8",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "The ID of the subnet",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"description": "Data for the host to update",
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"host": {
"type": "string",
"example": "pc11"
},
"oldMacAddress": {
"type": "string",
"example": "56:6f:c7:4f:00:4f"
},
"oldAddress": {
"type": "string",
"example": "192.168.1.11"
},
"macAddress": {
"type": "string",
"example": "56:6f:c7:4f:01:01"
},
"address": {
"type": "string",
"example": "192.168.1.11"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Host updated successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
},
"post": {
"summary": "Add a DHCP host to a subnet",
"operationId": "3f897dcd7c04787ac9c42ddbb57cb800",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "ID of the subnet to add the host to",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"description": "Data for the new host",
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"host": {
"type": "string",
"example": "pc11"
},
"macAddress": {
"type": "string",
"example": "56:6f:c7:4f:00:4f"
},
"address": {
"type": "string",
"example": "172.30.4.11"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Host added successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
},
"delete": {
"summary": "Delete a DHCP host from a specific subnet",
"operationId": "f652c52b39d57d283401df66a7930b5f",
"parameters": [
{
"name": "subnetId",
"in": "path",
"description": "The ID of the subnet",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"description": "Data for the host to delete",
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"host": {
"type": "string",
"example": "pc11"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Host deleted successfully",
"content": {
"application/json": {
"schema": {
"properties": {
"success": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"400": {
"description": "Error occurred",
"content": {
"application/json": {
"schema": {
"properties": {
"error": {
"type": "string"
}
},
"type": "object"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Subnet": {
"properties": {
"id": {
"description": "The ID of the subnet",
"type": "integer"
},
"subnet": {
"description": "The name of the subnet",
"type": "string"
},
"next-server": {
"description": "The next server in the subnet",
"type": "string"
},
"boot-file-name": {
"description": "The boot file name for the subnet",
"type": "string"
},
"reservations": {
"type": "array",
"items": {
"description": "The reservations in the subnet",
"type": "object"
}
}
},
"type": "object"
},
"Host": {
"properties": {
"host": {
"type": "string",
"example": "pc11"
},
"macAddress": {
"type": "string",
"example": "56:6f:c7:4f:00:4f"
},
"address": {
"type": "string",
"example": "172.30.4.11"
}
},
"type": "object"
}
}
}
}

View File

@ -20,6 +20,21 @@ class DhcpController
* @OA\Info(title="Ogdhcp API", version="1.0")
*/
/**
* @OA\Schema(
* schema="Subnet",
* type="object",
* @OA\Property(property="id", type="integer", description="The ID of the subnet"),
* @OA\Property(property="subnet", type="string", description="The name of the subnet"),
* @OA\Property(property="next-server", type="string", description="The next server in the subnet"),
* @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"),
* @OA\Property(
* property="reservations",
* type="array",
* @OA\Items(type="object", description="The reservations in the subnet")
* )
* )
*/
private $curlKeaService;
public function __construct(CurlKeaService $curlKeaService, LoggerInterface $logger)
@ -27,39 +42,148 @@ class DhcpController
$this->curlKeaService = $curlKeaService;
$this->logger = $logger;
}
/**
*
* @OA\Schema(
* schema="Subnet",
* type="object",
* @OA\Property(property="id", type="integer", description="The ID of the subnet"),
* @OA\Property(property="subnet", type="string", description="The name of the subnet"),
* @OA\Property(property="next-server", type="string", description="The next server in the subnet"),
* @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"),
* @OA\Property(
* property="reservations",
* type="array",
* @OA\Items(type="object", description="The reservations in the subnet")
* )
* )
* @Route("/ogdhcp/v1/status", name="getDhcpStatus", methods={"GET"})
* @OA\Get(
* path="/opengnsys3/rest/dhcp/subnets",
* path="/ogdhcp/v1/status",
* summary="Get ogDHCP status",
* @OA\Response(
* response=200,
* description="Devuelve todas las subredes",
* description="Status retrieved successfully",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref="#/components/schemas/Subnet")
* type="object",
* @OA\Property(property="disk_usage", type="object",
* @OA\Property(property="total", type="string"),
* @OA\Property(property="used", type="string"),
* @OA\Property(property="available", type="string"),
* @OA\Property(property="percentage", type="string")
* ),
* @OA\Property(property="default_oglive", type="string"),
* @OA\Property(property="installed_oglives", type="array", @OA\Items(type="string")),
* @OA\Property(property="services_status", type="object",
* @OA\Property(property="dhcp_daemon", type="string"),
* @OA\Property(property="nginx", type="string"),
* @OA\Property(property="tftpboot", type="string")
* )
* )
* ),
* @OA\Response(
* response=400,
* description="Error al obtener las subredes",
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets", methods={"GET"})
*/
public function getDhcpStatus(): Response
{
// Obtener el uso de disco
$diskUsageResult = $this->getDiskUsage();
if (!$diskUsageResult) {
return new JsonResponse(['error' => 'Failed to retrieve disk usage'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Obtener el estado de los servicios de ogDHCP (similar a check_services_status en ogboot)
$servicesStatusResult = $this->getServicesStatus();
if (!$servicesStatusResult) {
return new JsonResponse(['error' => 'Failed to retrieve services status'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Obtener las subredes y las reservas asociadas
$subnetsResult = $this->getSubnetsService();
if (!$subnetsResult) {
return new JsonResponse(['error' => 'Failed to retrieve subnets'], Response::HTTP_INTERNAL_SERVER_ERROR);
}
// Componer la respuesta
$response = [
'disk_usage' => $diskUsageResult,
'subnets' => $subnetsResult,
'services_status' => $servicesStatusResult
];
return new JsonResponse($response, Response::HTTP_OK);
}
private function getDiskUsage(): array
{
// Simular la salida del comando df para obtener el uso del disco
$output = shell_exec("df -h /opt/ogdhcp | tail -1 | awk '{print $2, $3, $4, $5}'");
if (!$output) {
$this->logger->error("Failed to execute disk usage command");
return null;
}
list($total, $used, $available, $percentage) = explode(' ', $output);
return [
'total' => trim($total),
'used' => trim($used),
'available' => trim($available),
'percentage' => trim($percentage),
];
}
private function getServicesStatus(): array
{
$services = [
'tftpboot' => 'active',
'nginx' => 'active',
];
return $services;
}
private function getSubnetsService(): ?array
{
try {
$response = $this->curlKeaService->executeCurlCommand('config-get');
if (!$response) {
$this->logger->error('Error: No se pudo acceder al archivo de configuración Kea.');
return null;
}
$result_code = $response[0]["result"];
if ($result_code == 0) {
if (!isset($response[0]['arguments']['Dhcp4']['subnet4'])) {
$this->logger->error("El campo 'subnet4' no está inicializado");
return null;
} else {
return $response[0]['arguments']['Dhcp4']['subnet4']; // Subredes y sus reservas
}
} else {
$this->logger->error("Error en la configuración Kea: " . $response[0]["text"]);
return null;
}
} catch (\Exception $e) {
$this->logger->error("Error al obtener la configuración de Kea DHCP: " . $e->getMessage());
return null;
}
}
/**
* @OA\Schema(
* schema="Subnet",
* type="object",
* @OA\Property(property="id", type="integer", description="The ID of the subnet"),
* @OA\Property(property="subnet", type="string", description="The name of the subnet"),
* @OA\Property(property="next-server", type="string", description="The next server in the subnet"),
* @OA\Property(property="boot-file-name", type="string", description="The boot file name for the subnet"),
* @OA\Property(
* property="reservations",
* type="array",
* @OA\Items(type="object", description="The reservations in the subnet")
* )
* )
*/
/**
* @OA\Get(
* path="/ogdhcp/v1/subnets",
* @OA\Response(
* response=200,
* description="Devuelve todas las subredes",
* ),
* @OA\Response(
* response=400,
* description="Error al obtener las subredes",
* )
* )
* @Route("/ogdhcp/v1/subnets", methods={"GET"})
*/
public function getSubnets(): JsonResponse
{
try {
@ -91,7 +215,7 @@ class DhcpController
/**
* @OA\Post(
* path="/opengnsys3/rest/dhcp/subnets",
* path="/ogdhcp/v1/subnets",
* summary="Add a new DHCP subnet",
* @OA\RequestBody(
* description="JSON payload",
@ -122,7 +246,7 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets", methods={"POST"})
* @Route("/ogdhcp/v1/subnets", methods={"POST"})
*/
public function addDhcpSubnet(Request $request): JsonResponse
{
@ -160,11 +284,15 @@ class DhcpController
if ($exists) {
$responseError = "Error: La subred el subnet '$subnetName' ya existe en las subredes";
return new JsonResponse(['error' => $responseError], 400);
} else {
$response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;
$array_encoded = json_encode($response[0]['arguments']);
} else {
$response[0]['arguments']['Dhcp4']['subnet4'][] = $newSubnet;
// Eliminar el campo 'hash' si existe
if (isset($response[0]['arguments']['hash'])) {
unset($response[0]['arguments']['hash']);
}
$array_encoded = json_encode($response[0]['arguments']);
$configurationParsed = str_replace('\\', '', $array_encoded);
$configuration = json_decode($configurationParsed);
$configuration = json_decode($configurationParsed);
$responseTest = $this->curlKeaService->executeCurlCommand('config-test', $configuration);
if ($responseTest[0]["result"] == 0) {
@ -192,13 +320,11 @@ class DhcpController
return new JsonResponse(['error' => $responseError], 400);
}
}
/**
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"DELETE"})
* @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"DELETE"})
* @OA\Delete(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}",
* path="/ogdhcp/v1/subnets/{subnetId}",
* summary="Delete a DHCP subnet",
* @OA\Parameter(
* name="subnetId",
@ -226,8 +352,9 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"DELETE"})
*/
public function deleteDhcpSubnet(Request $request): JsonResponse
{
$subnetId = (int) $request->get('subnetId');
@ -281,9 +408,9 @@ class DhcpController
/**
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"PUT"})
* @Route("/ogdhcp/v1/subnets/{subnetId}", methods={"PUT"})
* @OA\Put(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}",
* path="/ogdhcp/v1/subnets/{subnetId}",
* summary="Modify a DHCP subnet",
* @OA\Parameter(
* name="subnetId",
@ -322,7 +449,6 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}", methods={"PUT"})
*/
public function modifyDhcpSubnet(Request $request): JsonResponse
{
@ -392,17 +518,9 @@ class DhcpController
}
}
/**
* @OA\Schema(
* schema="Host",
* type="object",
* @OA\Property(property="host", type="string", example="pc11"),
* @OA\Property(property="macAddress", type="string", example="56:6f:c7:4f:00:4f"),
* @OA\Property(property="address", type="string", example="172.30.4.11")
* )
* @OA\Get(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts",
* path="/ogdhcp/v1/subnets/{subnetId}/hosts",
* summary="Get all hosts in a subnet",
* @OA\Parameter(
* name="subnetId",
@ -414,10 +532,6 @@ class DhcpController
* @OA\Response(
* response=200,
* description="List of hosts in the subnet",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref="#/components/schemas/Host")
* )
* ),
* @OA\Response(
* response=400,
@ -436,7 +550,7 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"GET"})
* @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"GET"})
*/
public function getHosts($subnetId): JsonResponse
{
@ -475,9 +589,8 @@ class DhcpController
/**
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"POST"})
* @OA\Post(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts",
* path="/ogdhcp/v1/subnets/{subnetId}/hosts",
* summary="Add a DHCP host to a subnet",
* @OA\Parameter(
* name="subnetId",
@ -515,7 +628,7 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"POST"})
* @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"POST"})
*/
public function addDhcpHost(Request $request): JsonResponse
{
@ -597,7 +710,7 @@ class DhcpController
/**
* @OA\Delete(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts",
* path="/ogdhcp/v1/subnets/{subnetId}/hosts",
* summary="Delete a DHCP host from a specific subnet",
* @OA\Parameter(
* name="subnetId",
@ -631,7 +744,7 @@ class DhcpController
* )
* )
* )
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"DELETE"})
* @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"DELETE"})
*/
public function deleteDhcpHost(Request $request, $subnetId): JsonResponse
{
@ -702,7 +815,7 @@ class DhcpController
/**
* @OA\Put(
* path="/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts",
* path="/ogdhcp/v1/subnets/{subnetId}/hosts",
* summary="Update a DHCP host",
* @OA\Parameter(
* name="subnetId",
@ -741,7 +854,7 @@ class DhcpController
* )
* )
*
* @Route("/opengnsys3/rest/dhcp/subnets/{subnetId}/hosts", methods={"PUT"})
* @Route("/ogdhcp/v1/subnets/{subnetId}/hosts", methods={"PUT"})
*/
public function updateDhcpHost(Request $request, $subnetId): JsonResponse
{
@ -824,9 +937,6 @@ class DhcpController
}
}
/**
* @Route("/opengnsys3/rest/dhcp/backup", methods={"POST"})
*/
public function restoreDhcpConfiguration(): JsonResponse
{
$backup_dir = '/opt/opengnsys/etc/kea/backup';

View File

@ -1,19 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

View File

@ -1,20 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Hello DhcpController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code><a href="{{ '/home/luis/dhcp_symfony/src/Controller/DhcpController.php'|file_link(0) }}">src/Controller/DhcpController.php</a></code></li>
<li>Your template at <code><a href="{{ '/home/luis/dhcp_symfony/templates/dhcp/index.html.twig'|file_link(0) }}">templates/dhcp/index.html.twig</a></code></li>
</ul>
</div>
{% endblock %}

121
tests/API-dhcp/Jenkinsfile vendored 100644
View File

@ -0,0 +1,121 @@
pipeline {
agent {
node {
label 'jenkins-slave'
}
}
options {
// Deshabilita ejecuciones concurrentes
disableConcurrentBuilds()
}
environment {
ESXI_PASS = credentials('VI_PASSWORD')
QINDEL_PASS = credentials('jenkins-user-slave-password')
PATH = "/home/qindel/bin/ovftool:${env.PATH}"
}
stages {
stage('Prepare environment') {
steps {
dir ('tests/API-dhcp') {
echo "Install vagrant plugin"
sh '''
if ! vagrant plugin list | grep -q vagrant-vmware-esxi; then
echo "Vagrant plugin vagrant-vmware-esxi not found. Installing..."
vagrant plugin install vagrant-vmware-esxi
else
echo "Vagrant plugin vagrant-vmware-esxi is already installed."
fi
'''
echo "Deploy API server for DHCP with Vagrant"
sh 'vagrant up --provider=vmware_esxi --provision'
}
}
}
stage('Check Installation') {
steps {
dir ('tests/API-dhcp') {
echo "Get IP of API server for DHCP with Vagrant"
sh '''
set -e
new_ip=$(vagrant ssh -c "hostname -I" | tr -d '\r' | sed 's/^[^a-zA-Z]*//' | sed 's/[[:space:]]*$//')
echo "$QINDEL_PASS" | sudo -S bash -c "echo '$new_ip api-test' >> /etc/hosts"
echo "IP: $new_ip"
curl -X 'GET' "http://$new_ip/ogdhcp/v1/subnets" -H 'accept: /'
'''
}
}
}
stage('Run API tests') {
steps {
echo 'Running API tests'
// Aquí incluirías los comandos para ejecutar tus pruebas
}
}
}
post {
success {
// Si el trabajo ha sido exitoso, destruir la máquina de Vagrant
echo "El trabajo ha finalizado con éxito. Destruyendo máquina Vagrant..."
dir ('tests/API-dhcp') {
sh 'vagrant destroy -f'
}
}
always {
script {
def userCause = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)
if (userCause != null) {
// Si fue lanzado manualmente, obtener el usuario y su correo desde las propiedades de Jenkins
def userId = userCause.getUserId()
def userEmail = getUserEmail(userId)
if (userEmail) {
echo "El correo del usuario que lanzó el build manualmente es: ${userEmail}"
// Enviar correo al usuario que lanzó el build manualmente
mail to: "${userEmail}",
subject: "Jenkins Job Completed (Manual): ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
El job '${env.JOB_NAME}' con número de build ${env.BUILD_NUMBER} ha finalizado (ejecutado manualmente).
Estado: ${currentBuild.currentResult}
Revisa los detalles del build en: ${env.BUILD_URL}
"""
} else {
echo "No se pudo encontrar un correo electrónico para el usuario: ${userId}"
}
} else {
// Si fue lanzado automáticamente, obtener el correo del committer
def committerEmail = sh(
script: 'git log -1 --pretty=format:"%ae"',
returnStdout: true
).trim()
echo "El build fue lanzado automáticamente. Correo del committer: ${committerEmail}"
// Enviar correo al committer
mail to: "${committerEmail}",
subject: "Jenkins Job Completed (Automático): ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
El job '${env.JOB_NAME}' con número de build ${env.BUILD_NUMBER} ha finalizado (ejecutado automáticamente).
Estado: ${currentBuild.currentResult}
Revisa los detalles del build en: ${env.BUILD_URL}
"""
}
}
}
}
}
@NonCPS
def getUserEmail(userId) {
def jenkinsInstance = jenkins.model.Jenkins.getInstanceOrNull()
if (jenkinsInstance != null) {
def user = jenkinsInstance.getUser(userId)
return user.getProperty(jenkins.plugins.mailer.tasks.Mailer.UserProperty)?.getAddress()
}
return null
}

163
tests/API-dhcp/Vagrantfile vendored 100644
View File

@ -0,0 +1,163 @@
#
# Fully documented Vagrantfile available
# in the wiki: https://github.com/josenk/vagrant-vmware-esxi/wiki
$script = <<SCRIPT
SERVER_NAME=localhost
echo "Provisioning with shell script..."
cd /vagrant/installer
chmod +x ogdhcp_installer.sh && ./ogdhcp_installer.sh
SCRIPT
Vagrant.configure('2') do |config|
config.vm.box = 'dummy'
VM_TEMPLATE = 'template-ubuntu24'
# Use rsync and NFS synced folders. (or use the option to disable them)
# https://www.vagrantup.com/docs/synced-folders/
#config.vm.synced_folder('.', '/vagrant', type: 'rsync')
config.vm.synced_folder('../../', '/vagrant', type: 'rsync')
# Vagrant can configure additional network interfaces using a static IP or
# DHCP. Use public_network or private_network to manually set a static IP and
# optionally netmask. ESXi doesn't use the concept of public or private
# networks so both are valid here. The primary network interface is considered the
# "vagrant management" interface and cannot be changed and this plugin
# supports 10 NICS, so you can specify 9 entries here!
#
# https://www.vagrantup.com/docs/networking/public_network.html
# https://www.vagrantup.com/docs/networking/private_network.html
#
# *** Invalid settings could cause 'vagrant up' to fail ***
#config.vm.network 'private_network', ip: '192.168.10.170', netmask: '255.255.255.0'
#config.vm.network 'private_network', ip: '192.168.11.170'
#config.vm.network 'public_network', ip: '192.168.12.170'
#
# Provider (esxi) settings
#
config.vm.provision 'shell', inline: $script
config.vm.provider :vmware_esxi do |esxi|
# REQUIRED! ESXi hostname/IP
esxi.esxi_hostname = 'esxi-jenkins.evlt.uma.es'
# ESXi username
esxi.esxi_username = 'root'
# IMPORTANT! Set ESXi password.
# 1) 'prompt:'
# 2) 'file:' or 'file:my_secret_file'
# 3) 'env:' or 'env:my_secret_env_var'
# 4) 'key:' or key:~/.ssh/some_ssh_private_key'
# 5) or esxi.esxi_password = 'my_esxi_password'
#
esxi.esxi_password = 'env:ESXI_PASS'
# SSH port.
#esxi.esxi_hostport = 22
# HIGHLY RECOMMENDED! ESXi Virtual Network
# You should specify an ESXi Virtual Network! If it's not specified, the
# default is to use the first found. You can specify up to 10 virtual
# networks using an array format.
esxi.esxi_virtual_network = ['vLan_742']
# OPTIONAL. Specify a Disk Store
#esxi.esxi_disk_store = 'DS_001'
# OPTIONAL. Resource Pool
# Vagrant will NOT create a Resource pool it for you.
esxi.esxi_resource_pool = '/'
# Optional. Specify a VM to clone instead of uploading a box.
# Vagrant can use any stopped VM as the source 'box'. The VM must be
# registered, stopped and must have the vagrant insecure ssh key installed.
# If the VM is stored in a resource pool, it must be specified.
# See wiki: https://github.com/josenk/vagrant-vmware-esxi/wiki/How-to-clone_from_vm
esxi.clone_from_vm = VM_TEMPLATE
# OPTIONAL. Guest VM name to use.
# The Default will be automatically generated.
#esxi.guest_name = 'Custom-Guest-VM_Name'
# OPTIONAL. When automatically naming VMs, use this prefix.
#esxi.guest_name_prefix = 'V-'
# OPTIONAL. Set the guest username login. The default is 'vagrant'.
#esxi.guest_username = 'vagrant'
# OPTIONAL. Memory size override
#esxi.guest_memsize = '2048'
# OPTIONAL. Virtual CPUs override
#esxi.guest_numvcpus = '2'
# OPTIONAL & RISKY. Specify up to 10 MAC addresses
# The default is ovftool to automatically generate a MAC address.
# You can specify an array of MAC addresses using upper or lower case,
# separated by colons ':'.
#esxi.guest_mac_address = ['00:50:56:aa:bb:cc', '00:50:56:01:01:01','00:50:56:02:02:02','00:50:56:BE:AF:01' ]
# OPTIONAL & RISKY. Specify a guest_nic_type
# The validated list of guest_nic_types are 'e1000', 'e1000e', 'vmxnet',
# 'vmxnet2', 'vmxnet3', 'Vlance', and 'Flexible'.
#esxi.guest_nic_type = 'e1000'
# OPTIONAL. Specify a disk type.
# If unspecified, it will be set to 'thin'. Otherwise, you can set to
# 'thin', 'thick', or 'eagerzeroedthick'
#esxi.guest_disk_type = 'thick'
# OPTIONAL. Boot disk size.
# If unspecified, the boot disk size will be the same as the original
# box. You can specify a larger boot disk size in GB. The extra disk space
# will NOT automatically be available to your OS. You will need to
# create or modify partitions, LVM and/or filesystems.
#esxi.guest_boot_disk_size = 50
# OPTIONAL. Create additional storage for guests.
# You can specify an array of up to 13 virtual disk sizes (in GB) that you
# would like the provider to create once the guest has been created. You
# can optionally specify the size and datastore using a hash.
#esxi.guest_storage = [ 10, 20, { size: 30, datastore: 'datastore1' } ]
# OPTIONAL. specify snapshot options.
#esxi.guest_snapshot_includememory = 'true'
#esxi.guest_snapshot_quiesced = 'true'
# RISKY. guest_guestos
# https://github.com/josenk/vagrant-vmware-esxi/wiki/VMware-ESXi-6.5-guestOS-types
#esxi.guest_guestos = 'centos-64'
# OPTIONAL. guest_virtualhw_version
# ESXi 6.7 supports these versions. 4,7,8,9,10,11,12,13 & 14.
#esxi.guest_virtualhw_version = '9'
# OPTIONAL. Guest Autostart
# Guest VM will autostart when esxi host is booted. 'true' or 'false'(default)
#esxi.guest_autostart = 'false'
# RISKY. guest_custom_vmx_settings
#esxi.guest_custom_vmx_settings = [['vhv.enable','TRUE'], ['floppy0.present','TRUE']]
# OPTIONAL. local_lax
#esxi.local_lax = 'true'
# OPTIONAL. Guest IP Caching
#esxi.local_use_ip_cache = 'True'
# DANGEROUS! Allow Overwrite
# If unspecified, the default is to produce an error if overwriting
# VMs and packages.
#esxi.local_allow_overwrite = 'True'
# Advanced Users.
# If set to 'True', all WARNINGS will produce a FAILURE and Vagrant will stop.
#esxi.local_failonwarning = 'True'
# Plugin debug output.
# Please send any bug reports with this debug output...
#esxi.debug = 'true'
end
end

View File

@ -0,0 +1,104 @@
// This is a basic configuration for the Kea Control Agent.
//
// This is just a very basic configuration. Kea comes with large suite (over 30)
// of configuration examples and extensive Kea User's Guide. Please refer to
// those materials to get better understanding of what this software is able to
// do. Comments in this configuration file sometimes refer to sections for more
// details. These are section numbers in Kea User's Guide. The version matching
// your software should come with your Kea package, but it is also available
// in ISC's Knowledgebase (https://kea.readthedocs.io; the direct link for
// the stable version is https://kea.readthedocs.io/).
//
// This configuration file contains only Control Agent's configuration.
// If configurations for other Kea services are also included in this file they
// are ignored by the Control Agent.
{
// This is a basic configuration for the Kea Control Agent.
// RESTful interface to be available at http://127.0.0.1:8000/
"Control-agent": {
"http-host": "127.0.0.1",
// If enabling HA and multi-threading, the 8000 port is used by the HA
// hook library http listener. When using HA hook library with
// multi-threading to function, make sure the port used by dedicated
// listener is different (e.g. 8001) than the one used by CA. Note
// the commands should still be sent via CA. The dedicated listener
// is specifically for HA updates only.
"http-port": 8000,
// Specify location of the files to which the Control Agent
// should connect to forward commands to the DHCPv4, DHCPv6
// and D2 servers via unix domain sockets.
"control-sockets": {
"dhcp4": {
"socket-type": "unix",
"socket-name": "/run/kea/kea4-ctrl-socket"
},
"dhcp6": {
"socket-type": "unix",
"socket-name": "/run/kea/kea6-ctrl-socket"
},
"d2": {
"socket-type": "unix",
"socket-name": "/run/kea/kea-ddns-ctrl-socket"
}
},
// Specify hooks libraries that are attached to the Control Agent.
// Such hooks libraries should support 'control_command_receive'
// hook point. This is currently commented out because it has to
// point to the existing hooks library. Otherwise the Control
// Agent will fail to start.
"hooks-libraries": [
// {
// "library": "/usr/lib/x86_64-linux-gnu/kea/hooks/control-agent-commands.so",
// "parameters": {
// "param1": "foo"
// }
// }
],
// Logging configuration starts here. Kea uses different loggers to log various
// activities. For details (e.g. names of loggers), see Chapter 18.
"loggers": [
{
// This specifies the logging for Control Agent daemon.
"name": "kea-ctrl-agent",
"output_options": [
{
// Specifies the output file. There are several special values
// supported:
// - stdout (prints on standard output)
// - stderr (prints on standard error)
// - syslog (logs to syslog)
// - syslog:name (logs to syslog using specified name)
// Any other value is considered a name of the file
"output": "stdout",
// Shorter log pattern suitable for use with systemd,
// avoids redundant information
"pattern": "%-5p %m\n"
// This governs whether the log output is flushed to disk after
// every write.
// "flush": false,
// This specifies the maximum size of the file before it is
// rotated.
// "maxsize": 1048576,
// This specifies the maximum number of rotated files to keep.
// "maxver": 8
}
],
// This specifies the severity of log messages to keep. Supported values
// are: FATAL, ERROR, WARN, INFO, DEBUG
"severity": "INFO",
// If DEBUG level is specified, this value is used. 0 is least verbose,
// 99 is most verbose. Be cautious, Kea can generate lots and lots
// of logs if told to do so.
"debuglevel": 0
}
]
}
}

View File

@ -1,11 +0,0 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/vendor/autoload.php';
if (file_exists(dirname(__DIR__).'/config/bootstrap.php')) {
require dirname(__DIR__).'/config/bootstrap.php';
} elseif (method_exists(Dotenv::class, 'bootEnv')) {
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
}

View File