Compare commits

...

43 Commits

Author SHA1 Message Date
Nicolas Arenas 271bcbb05d Publish in aptly nightlies
ogdhcp/pipeline/head This commit looks good Details
2025-04-10 16:39:21 +02:00
Nicolas Arenas 09de586931 Update Jenkinsfile
ogdhcp/pipeline/tag This commit looks good Details
2025-03-27 09:01:20 +01:00
Nicolas Arenas f10aa88804 Updated jenksfile
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-27 08:54:57 +01:00
Nicolas Arenas 04049a8fc0 Fix public dir for nginx
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 16:45:02 +01:00
Luis Gerardo Romero Garcia 6d952b7246 Adds public directory and index.php
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 16:29:10 +01:00
Nicolas Arenas f07f27bbb8 Clean tmp directory for packages 2025-03-26 16:09:32 +01:00
Nicolas Arenas d1f61c3936 Change compilation params
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 16:08:34 +01:00
Nicolas Arenas a8242d5f8a Fixing rules
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 15:45:44 +01:00
Nicolas Arenas 182fab4d87 Fixing rules
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 15:41:59 +01:00
Luis Gerardo Romero Garcia 5f07a03986 Removes a lot of innecesaries directories generated by composer install
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 15:09:56 +01:00
Nicolas Arenas 44a73d0bbf Delete uploaded files in tmp file 2025-03-26 11:58:34 +01:00
Nicolas Arenas 83c3ac8bef Merge branch 'new_files_placement' - Resolved rename/delete conflicts
ogdhcp/pipeline/head This commit looks good Details
ogdhcp/pipeline/tag There was a failure building this commit Details
2025-03-26 11:01:10 +01:00
Nicolas Arenas da7269c64c add console
ogdhcp/pipeline/head This commit looks good Details
2025-03-26 10:53:44 +01:00
Nicolas Arenas ec97f1b7bd Add debian rules
ogdhcp/pipeline/head There was a failure building this commit Details
2025-03-25 08:43:28 +01:00
Luis Gerardo Romero Garcia 1b21fdfd24 removes composer.lock
ogdhcp/pipeline/head There was a failure building this commit Details
2025-03-25 08:30:01 +01:00
Nicolas Arenas 00cb244286 Updated debian files 2025-03-25 08:29:44 +01:00
Luis Gerardo Romero Garcia 475258bde9 removes composer.lock 2025-03-25 08:18:24 +01:00
Luis Gerardo Romero Garcia 56c61d07c3 moves /bin to api/bin 2025-03-25 08:06:05 +01:00
Luis Gerardo Romero Garcia bd44f6c658 adds bin directory 2025-03-24 16:09:11 +01:00
Luis Gerardo Romero Garcia ed010de9cb move symfony directories to api directory in repo 2025-03-24 15:11:26 +01:00
Luis Gerardo Romero Garcia 85380a3b4a Changes log installation in symfony directory
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-03-24 14:24:35 +01:00
Luis Gerardo Romero Garcia d1e8675236 Updates CHANGELOG 2025-03-24 09:31:28 +01:00
Luis Gerardo Romero Garcia 453dfd2b5a Fix backup directory creation hotfix
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-03-24 09:28:40 +01:00
Luis Gerardo Romero Garcia 6eac73bc69 Merge pull request 'refs #1687 changes symfony files to api directoty' (#7) from change-directories into main
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
Reviewed-on: #7
2025-03-21 10:07:48 +01:00
Nicolas Arenas eb2c46fb46 jenkins_upload_packages (#6)
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
ogdhcp/pipeline/tag This commit looks good Details
Publicar paquetes en aptly repo

Reviewed-on: #6

refers #1313
2025-03-19 13:05:25 +01:00
Nicolas Arenas 5389eba18c Add Jenkinsfile (#5)
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
ogdhcp/pipeline/head This commit looks good Details
Reviewed-on: #5
refs #1713
2025-03-18 11:08:17 +01:00
Nicolas Arenas 39a91ca9ab Add debian folder to create Debian packages for Ubuntu24 , refs #1709
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
Reviewed-on: #4
2025-03-13 16:56:19 +01:00
Luis Gerardo Romero Garcia c0c996903c refs #1687 changes symfony files to api directoty
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-03-13 09:46:17 +01:00
Luis Gerardo Romero Garcia c0ee3837c5 Updates changelog 0.6.0
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-03-03 08:36:59 +01:00
Luis Gerardo Romero Garcia 35b6e2df07 Merge pull request 'new-parameters-subnet' (#3) from new-parameters-subnet into main
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
Release:0.5.6
Añade nuevos parametros a la subred: dns y subnetname, añadiendolos a la configuración de kea
Resuelve error de permisos en el instalador
2025-03-03 08:35:01 +01:00
Luis Gerardo Romero Garcia 96783a972f refs #1543 fix swagger annotation
testing/og-dhcp-API/pipeline/pr-main There was a failure building this commit Details
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-03-03 08:30:42 +01:00
Luis Gerardo Romero Garcia 16eedd9546 refs #1568 adds new parameters subnetName and dns to kea dhcp
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-28 09:32:45 +01:00
Luis Gerardo Romero Garcia 82eddcc8e9 refs #1581 fix backup permissions in installer
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-27 16:10:18 +01:00
Luis Gerardo Romero Garcia 6b3d985834 refs #1468 update CHANGELOG
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-06 15:49:18 +01:00
Luis Gerardo Romero Garcia 642c1d8e3e refs #1468 fix bug and permissions in opt opengnsys
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-06 15:44:39 +01:00
Luis Gerardo Romero Garcia ebfecedcec refs #1468 updates CHANGELOG
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-06 13:25:51 +01:00
Luis Gerardo Romero Garcia 1dbccabe4e refs #1468 changes home of the opengnsys user
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-02-06 12:53:22 +01:00
Luis Gerardo Romero Garcia 05c050736e Adds changelog
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-01-13 11:40:36 +01:00
Luis Gerardo Romero Garcia 5ed78dec55 Merge pull request 'ogdhcp-log' (#2) from ogdhcp-log into main
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
Reviewed-on: #2
2025-01-13 11:33:17 +01:00
Luis Gerardo Romero Garcia 394a71134c refs #1204 Fix missing comprobations in update subnet
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-01-13 11:32:31 +01:00
Luis Gerardo Romero Garcia 24ddbead96 refs #1204 Fix logs formats in ogdhcp controller
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-01-13 11:18:20 +01:00
Luis Gerardo Romero Garcia 48a231ff7c refs #1204 Adds symfony logs with format in ogdhcp controller
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2025-01-13 10:39:21 +01:00
Luis Gerardo Romero Garcia 27f8babdf7 refs #1205 adds gateway paremeter in subnet
testing/og-dhcp-API/pipeline/head There was a failure building this commit Details
2024-12-05 11:53:05 +01:00
87 changed files with 1830 additions and 1916 deletions

11
.gitignore vendored
View File

@ -5,7 +5,6 @@
!app/cache/.gitkeep
!app/logs/.gitkeep
/app/phpunit.xml
/bin/
/build/
/composer.phar
/var/*
@ -38,3 +37,13 @@ output.xml
log.html
report.html
__pycache__
### Debian packaging
debian/ogdhcp
debian/*.substvars
debian/*.log
debian/.debhelper/
debian/files
debian/*.debhelper
debian/*.debhelper.log
debian/debhelper-build-stamp

43
CHANGELOG 100644
View File

@ -0,0 +1,43 @@
# CHANGELOG
# [0.6.3] - 24/03/2025
### **Cambios principales**
1. Mueve directorios de symfony al directorio api
## [0.6.2] - 03/03/2025
### **Cambios principales**
1. Añade publicacion de paquetes debian a jenkins
## [0.6.1] - 03/03/2025
### **Cambios principales**
1. Añade publicacion de paquetes debian a jenkins
## [0.6.0] - 03/03/2025
### **Cambios principales**
1. Añade nuevos parametros a la subred: dns y subnetname, añadiendolos a la configuración de kea
2. Resuelve error de permisos en el instalador
### **Cambios principales**
1. Arregla bugs en la creacion del home `/opt/opengnsys`del usuario opengnsys
## [0.5.5] - 06/02/2025
### **Cambios principales**
1. Arregla bugs en la creacion del home `/opt/opengnsys`del usuario opengnsys
## [0.5.4] - 06/02/2025
### **Cambios principales**
1. Cambia el home del usuario opengnsys como `/opt/opengnsys`
## [0.5.3] - 13/01/2025
### **Cambios principales**
1. Añade logs para todos los endpoints siguiendo un formato json preestablecido.
2. Actualiza monolog.yaml para devolver logs al journal de la maquina.

32
CHANGELOG.md 100644
View File

@ -0,0 +1,32 @@
# Changelog
## [0.7.0] - 2025-03-24
### Changed
- Mueve directorios de symfony al directorio api
## [0.6.1] - 2025-03-19
### Changed
- Modified Jenkinsfile to publish packages
## [0.6.0] - 2025-03-03
### Added
- Nuevos parámetros a la subred: `dns` y `subnetname`, añadiéndolos a la configuración de Kea.
### Fixed
- Error de permisos en el instalador.
- Bugs en la creación del home `/opt/opengnsys` del usuario `opengnsys`.
## [0.5.5] - 2025-02-06
### Fixed
- Bugs en la creación del home `/opt/opengnsys` del usuario `opengnsys`.
## [0.5.4] - 2025-02-06
### Changed
- Se cambia el home del usuario `opengnsys` a `/opt/opengnsys`.
## [0.5.3] - 2025-01-13
### Added
- Logs para todos los endpoints siguiendo un formato JSON preestablecido.
### Changed
- Se actualiza `monolog.yaml` para devolver logs al journal de la máquina.

View File

@ -0,0 +1,112 @@
@Library('jenkins-shared-library') _
pipeline {
agent {
label 'jenkins-slave'
}
environment {
DEBIAN_FRONTEND = 'noninteractive'
DEFAULT_DEV_NAME = 'Opengnsys Team'
DEFAULT_DEV_EMAIL = 'opengnsys@qindel.com'
}
options {
skipDefaultCheckout()
}
parameters {
string(name: 'DEV_NAME', defaultValue: '', description: 'Nombre del desarrollador')
string(name: 'DEV_EMAIL', defaultValue: '', description: 'Email del desarrollador')
}
stages {
stage('Prepare Workspace') {
steps {
script {
env.BUILD_DIR = "${WORKSPACE}/ogdhcp"
sh "mkdir -p ${env.BUILD_DIR}"
}
}
}
stage('Checkout') {
steps {
dir("${env.BUILD_DIR}") {
checkout scm
}
}
}
stage('Generate Changelog') {
when {
expression {
return env.TAG_NAME != null
}
}
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)
}
}
}
stage('Generate Changelog (Nightly)'){
when {
branch 'main'
}
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,"nightly")
}
}
}
stage('Build') {
steps {
script {
construirPaquete(env.BUILD_DIR, "../artifacts", "172.17.8.68", "/var/tmp/opengnsys/debian-repo/ogdhcp")
}
}
}
stage ('Publish to Debian Repository') {
when {
expression {
return env.TAG_NAME != null
}
}
agent { label 'debian-repo' }
steps {
script {
// Construir el patrón de versión esperado en el nombre del paquete
def versionPattern = "${env.TAG_NAME}-${env.BUILD_NUMBER}"
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogdhcp', 'opengnsys-devel', versionPattern)
}
}
}
stage ('Publish to Debian Repository (Nightly)') {
when {
branch 'main'
}
agent { label 'debian-repo' }
steps {
script {
// Construir el patrón de versión esperado en el nombre del paquete
def versionPattern = "-${env.BUILD_NUMBER}~nightly"
publicarEnAptly('/var/tmp/opengnsys/debian-repo/ogdhcp', 'nightly', versionPattern)
}
}
}
}
post {
always {
notifyBuildStatus('narenas@qindel.com')
}
}
}
// stage ('Publish to Debian Repository') {
// agent { label 'debian-repo' }
// steps {
// sh "aptly repo add opengnsys-devel /var/tmp/opengnsys/debian-repo/*.deb"
// }
// }

View File

17
api/bin/console 100755
View File

@ -0,0 +1,17 @@
#!/usr/bin/env php
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
return new Application($kernel);
};

View File

@ -22,6 +22,11 @@ when@dev:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
syslog:
type: syslog
ident: "ogdhcp"
level: info
channels: ["!event"]
when@test:
monolog:

View File

@ -4,7 +4,7 @@
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
backup_dir: '%kernel.project_dir%/etc/kea/backup'
backup_dir: '%kernel.project_dir%/../etc/kea/backup'
services:
# default configuration for services in *this* file
_defaults:

View File

@ -82,7 +82,7 @@ class CurlKeaService
$config_text = json_encode($get_output[0]['arguments']);
$configurationParsed = str_replace('\\', '', $config_text);
$backup_dir = __DIR__ . '/../../../etc/kea/backup';
$backup_dir = __DIR__ . '/../../../../etc/kea/backup';
if (!is_dir($backup_dir)) {
throw new Exception('El directorio de backup no existe');
}

261
api/symfony.lock 100644
View File

@ -0,0 +1,261 @@
{
"doctrine/annotations": {
"version": "1.14",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "a2759dd6123694c8d901d0ec80006e044c2e6457"
},
"files": [
"config/routes/annotations.yaml"
]
},
"doctrine/doctrine-bundle": {
"version": "2.11",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.4",
"ref": "191046a1fdd1a58fcca48d8bf2f58c45a93b1d00"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"phpunit/phpunit": {
"version": "8.5",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.7",
"ref": "db276258424d15e572d35a4eb834b8f815662b25"
},
"files": [
".env.test",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/console": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047"
},
"files": [
"bin/console"
]
},
"symfony/debug-bundle": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
},
"files": [
"config/packages/debug.yaml"
]
},
"symfony/flex": {
"version": "1.21",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
},
"files": [
".env"
]
},
"symfony/framework-bundle": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.4",
"ref": "3cd216a4d007b78d8554d44a5b1c0a446dab24fb"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/preload.php",
"config/routes/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php"
]
},
"symfony/mailer": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.3",
"ref": "df66ee1f226c46f01e85c29c2f7acce0596ba35a"
},
"files": [
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {
"version": "1.50",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/messenger": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.4",
"ref": "8bd5f27013fb1d7217191c548e340f0bdb11912c"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/monolog-bundle": {
"version": "3.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.7",
"ref": "aff23899c4440dd995907613c1dd709b6f59503f"
},
"files": [
"config/packages/monolog.yaml"
]
},
"symfony/notifier": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.0",
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/phpunit-bridge": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "07ce01a897311647520b43d4ddddad9537b99ba6"
},
"files": [
".env.test",
"bin/phpunit",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/routing": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "85de1d8ae45b284c3c84b668171d2615049e698f"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "98f1f2b0d635908c2b40f3675da2d23b1a069d30"
},
"files": [
"config/packages/security.yaml"
]
},
"symfony/translation": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
},
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.4",
"ref": "bb2178c57eee79e6be0b297aa96fc0c0def81387"
},
"files": [
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/validator": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "c32cfd98f714894c4f128bb99aa2530c1227603c"
},
"files": [
"config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "5.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "24bbc3d84ef2f427f82104f766014e799eefcc3e"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"twig/extra-bundle": {
"version": "v3.8.0"
}
}

6
debian/README vendored 100644
View File

@ -0,0 +1,6 @@
The Debian Package ogdhcp
----------------------------
<Comments regarding the Package.>
-- vagrant <vagrant@build> Wed, 05 Mar 2025 19:49:47 +0000

6
debian/README.Debian vendored 100644
View File

@ -0,0 +1,6 @@
ogdhcp for Debian
----------------
<Possible notes regarding this package - if none, delete this file.>
-- vagrant <vagrant@build> Wed, 05 Mar 2025 19:49:47 +0000

10
debian/README.source vendored 100644
View File

@ -0,0 +1,10 @@
ogdhcp for Debian
----------------
<This file describes information about the source package, see Debian policy
manual section 4.14. You WILL either need to modify or delete this file.>
-- vagrant <vagrant@build> Wed, 05 Mar 2025 19:49:47 +0000

14
debian/changelog vendored 100644
View File

@ -0,0 +1,14 @@
ogdhcp (1.0.2+pkg-deb20250310-1) unstable; urgency=medium
* Updates changelog 0.6.0
* Merge pull request 'new-parameters-subnet' (#3) from new-parameters-subnet into main
* refs #1543 fix swagger annotation
* refs #1568 adds new parameters subnetName and dns to kea dhcp
* refs #1581 fix backup permissions in installer
* refs #1468 update CHANGELOG
* refs #1468 fix bug and permissions in opt opengnsys
* refs #1468 updates CHANGELOG
* refs #1468 changes home of the opengnsys user
* Adds changelog
-- Tu Nombre <tuemail@example.com> Mon, 10 Mar 2025 19:58:42 +0000

38
debian/control vendored 100644
View File

@ -0,0 +1,38 @@
Source: ogdhcp
Section: unknown
Priority: optional
Maintainer: vagrant <vagrant@build>
Rules-Requires-Root: no
Build-Depends:
debhelper-compat (= 13)
Standards-Version: 4.6.2
Homepage: <insert the upstream URL, if relevant>
#Vcs-Browser: https://salsa.debian.org/debian/ogdhcp
#Vcs-Git: https://salsa.debian.org/debian/ogdhcp.git
Package: ogdhcp
Architecture: any
Multi-Arch: foreign
Recommends: kea-dhcp4-server, kea-common, kea-ctrl-agent
Depends: ${shlibs:Depends}, ${misc:Depends}, debconf (>= 1.5.0),
php,
php-cli,
php-fpm,
php-json,
php-pdo,
php-mysql,
php-zip,
php-gd,
php-mbstring,
php-curl,
php-xml,
php-pear,
php-bcmath,
composer,
unzip,
jq,
net-tools,
nginx
Conflicts: apache2
Description: <insert up to 60 chars description>
<Insert long description, indented with spaces.>

43
debian/copyright vendored 100644
View File

@ -0,0 +1,43 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: <url://example.com>
Upstream-Name: ogdhcp
Upstream-Contact: <preferred name and address to reach the upstream project>
Files:
*
Copyright:
<years> <put author's name and email here>
<years> <likewise for another author>
License: GPL-3.0+
Files:
debian/*
Copyright:
2025 vagrant <vagrant@build>
License: GPL-3.0+
License: GPL-3.0+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Comment:
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid picking licenses with terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.
#
# If you need, there are some extra license texts available in two places:
# /usr/share/debhelper/dh_make/licenses/
# /usr/share/common-licenses/

11
debian/ogdhcp.config vendored 100644
View File

@ -0,0 +1,11 @@
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
db_input high opengnsys/ogdhcp_interfaces || true
db_input high opengnsys/ogdhcp_ip|| true
db_input high opengnsys/ogdhcp_ogbootIP || true
db_go

16
debian/ogdhcp.dirs vendored 100644
View File

@ -0,0 +1,16 @@
/opt/opengnsys/ogdhcp/api
/opt/opengnsys/ogdhcp/api/bin
/opt/opengnsys/ogdhcp/api/config
/opt/opengnsys/ogdhcp/api/public
/opt/opengnsys/ogdhcp/api/src
/opt/opengnsys/ogdhcp/api/templates
/opt/opengnsys/ogdhcp/api/var/
/opt/opengnsys/ogdhcp/api/var/cache
/opt/opengnsys/ogdhcp/api/var/log
/opt/opengnsys/ogdhcp/api/vendor
/opt/opengnsys/ogdhcp/etc
/opt/opengnsys/ogdhcp/etc/kea/backup
/opt/opengnsys/ogdhcp/docs

4
debian/ogdhcp.install vendored 100644
View File

@ -0,0 +1,4 @@
api /opt/opengnsys/ogdhcp/
etc /opt/opengnsys/ogdhcp/
docs /opt/opengnsys/ogdhcp/
etc/systemd/system/kea-ctrl-agent.service.d/override.conf /etc/systemd/system/kea-ctrl-agent.service.d/

129
debian/ogdhcp.postinst vendored 100644
View File

@ -0,0 +1,129 @@
#!/bin/bash
set -e
. /usr/share/debconf/confmodule
KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf"
PUBLIC_DIR=/opt/opengnsys/ogdhcp/api/public
db_get opengnsys/ogdhcp_interfaces
OGDHCP_INTERFACES="$RET"
db_get opengnsys/ogdhcp_ip
OGDHCP_IP="$RET"
db_get opengnsys/ogdhcp_ogbootIP
OGBOOT_IP="$RET"
case "$1" in
configure)
echo "Configurando ogdhcp..."
# Configuración de kea-ctrl-agent
echo "Eliminando autenticación de kea-ctrl-agent..."
if [ -e "$KEA_CTRL_AGENT_CONF" ]; then
dpkg-divert --package ogdhcp --divert "$KEA_CTRL_AGENT_CONF.dpkg-dist" --rename "$KEA_CTRL_AGENT_CONF"
cp -a "$KEA_CTRL_AGENT_CONF.dpkg-dist" "$KEA_CTRL_AGENT_CONF"
if grep -q '^[^#]*"authentication": {' "$KEA_CTRL_AGENT_CONF"; then
sed -i '/"authentication": {/,/^[[:space:]]*},/ {
s/^\([[:space:]]*\)\([^#]\)/\1#\2/
}' "$KEA_CTRL_AGENT_CONF"
fi
fi
# Configuración de AppArmor
APPARMOR_LOCAL_PROFILE="/etc/apparmor.d/local/usr.sbin.kea-dhcp4"
echo "Añadiendo permisos personalizados a AppArmor para kea-dhcp4..."
mkdir -p "$(dirname "$APPARMOR_LOCAL_PROFILE")"
cat > "$APPARMOR_LOCAL_PROFILE" <<EOF
/etc/kea/ rw,
/etc/kea/** rw,
EOF
echo "Recargando perfiles de AppArmor..."
apparmor_parser -r /etc/apparmor.d/usr.sbin.kea-dhcp4
if [ $? -eq 0 ]; then
echo "El perfil de AppArmor se recargó correctamente."
else
echo "Error al recargar el perfil de AppArmor."
fi
# Configuración de nginx
echo "Configurando nginx..."
PHP_VERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
if [ ! -f /etc/nginx/sites-available/ogdhcp.conf ]; then
cp /opt/opengnsys/ogdhcp/etc/nginxServer.conf.tmpl /etc/nginx/sites-available/ogdhcp.conf
sed -i "s|__PHPVERSION__|$PHP_VERSION|g" /etc/nginx/sites-available/ogdhcp.conf
sed -i "s|__SERVERIP__|$OGDHCP_IP|g" /etc/nginx/sites-available/ogdhcp.conf
sed -i "s|__PUBLICDIR__|$PUBLIC_DIR|g" /etc/nginx/sites-available/ogdhcp.conf
ln -s /etc/nginx/sites-available/ogdhcp.conf /etc/nginx/sites-enabled/ogdhcp.conf
else
echo "El archivo /etc/nginx/sites-available/ogdhcp.conf ya existe."
fi
# Configuración de php-fpm
echo "Configurando php-fpm..."
if [ ! -f /etc/php/$PHP_VERSION/fpm/pool.d/ogdhcp.conf ]; then
cp /opt/opengnsys/ogdhcp/etc/php/fpm/ogdhcp-fpm.conf /etc/php/$PHP_VERSION/fpm/pool.d/ogdhcp.conf
fi
# Configuración de kea-dhcp4
echo "Configurando kea-dhcp4..."
IFS=',' read -r -a INTERFACES <<< "$OGDHCP_INTERFACES"
KEA_CONFIG="/etc/kea/kea-dhcp4.conf"
if [ -e "$KEA_CONFIG" ]; then
dpkg-divert --package ogdhcp --divert "$KEA_CONFIG.dpkg-dist" --rename "$KEA_CONFIG"
cat > "$KEA_CONFIG" <<EOF
{
"Dhcp4": {
"interfaces-config": {
"interfaces": [ $(
for interface in "${INTERFACES[@]}"; do
echo "\"$interface\""
done | paste -sd "," -
) ]
},
"client-classes": [
{
"name": "UEFI-64",
"test": "not substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'",
"boot-file-name": "ipxe.efi",
"next-server": "$OGBOOT_IP"
},
{
"name": "Legacy",
"test": "substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'",
"boot-file-name": "undionly.kpxe",
"next-server": "$OGBOOT_IP"
}
],
"control-socket": {
"socket-name": "/run/kea/kea4-ctrl-socket",
"socket-type": "unix"
}
}
}
EOF
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument '$1'" >&2
exit 1
;;
esac
chown opengnsys:www-data /opt/opengnsys/
chown -R opengnsys:www-data /opt/opengnsys/ogdhcp
chown -R _kea:_kea /etc/kea
# Reiniciar servicios
systemctl daemon-reload
systemctl restart nginx
systemctl restart kea-dhcp4-server
systemctl restart kea-ctrl-agent
systemctl restart php$PHP_VERSION-fpm
exit 0

15
debian/ogdhcp.preinst vendored 100755
View File

@ -0,0 +1,15 @@
#!/bin/bash
set -e
# Asegurarse de que el usuario exista
USER="opengnsys"
HOME_DIR="/opt/opengnsys"
if id "$USER" &>/dev/null; then
echo "El usuario $USER ya existe."
else
echo "Creando el usuario $USER con home en $HOME_DIR."
useradd -m -d "$HOME_DIR" -s /bin/bash "$USER"
fi
exit 0

69
debian/ogdhcp.prerm vendored 100644
View File

@ -0,0 +1,69 @@
#!/bin/bash
set -e
KEA_CTRL_AGENT_CONF="/etc/kea/kea-ctrl-agent.conf"
KEA_CONFIG="/etc/kea/kea-dhcp4.conf"
APPARMOR_LOCAL_PROFILE="/etc/apparmor.d/local/usr.sbin.kea-dhcp4"
NGINX_CONF="/etc/nginx/sites-available/ogdhcp.conf"
PHP_FPM_CONF="/etc/php/*/fpm/pool.d/ogdhcp.conf"
case "$1" in
remove)
echo "Preparando eliminación de ogdhcp..."
# Restaurar el archivo kea-ctrl-agent.conf original si se modificó
if [ -e "$KEA_CTRL_AGENT_CONF.dpkg-dist" ]; then
echo "Restaurando configuración original de kea-ctrl-agent..."
mv -f "$KEA_CTRL_AGENT_CONF.dpkg-dist" "$KEA_CTRL_AGENT_CONF"
dpkg-divert --package ogdhcp --remove --divert "$KEA_CTRL_AGENT_CONF.dpkg-dist" --rename "$KEA_CTRL_AGENT_CONF"
fi
# Restaurar el archivo kea-dhcp4.conf original si se modificó
if [ -e "$KEA_CONFIG.dpkg-dist" ]; then
echo "Restaurando configuración original de kea-dhcp4..."
mv -f "$KEA_CONFIG.dpkg-dist" "$KEA_CONFIG"
dpkg-divert --package ogdhcp --remove --divert "$KEA_CONFIG.dpkg-dist" --rename "$KEA_CONFIG"
fi
# Eliminar perfil personalizado de AppArmor
if [ -f "$APPARMOR_LOCAL_PROFILE" ]; then
echo "Eliminando perfil de AppArmor personalizado..."
rm -f "$APPARMOR_LOCAL_PROFILE"
apparmor_parser -r /etc/apparmor.d/usr.sbin.kea-dhcp4 || true
fi
# Eliminar configuración de nginx
if [ -f "$NGINX_CONF" ]; then
echo "Eliminando configuración de nginx..."
rm -f "$NGINX_CONF"
rm -f "/etc/nginx/sites-enabled/ogdhcp.conf"
fi
# Eliminar configuración de php-fpm
echo "Eliminando configuración de php-fpm..."
rm -f $PHP_FPM_CONF
# Restaurar permisos de directorios
echo "Restaurando permisos en /opt/opengnsys..."
chown root:root /opt/opengnsys/
chown -R root:root /opt/opengnsys/ogdhcp
# Detener servicios antes de eliminar el paquete
echo "Deteniendo servicios..."
systemctl stop nginx || true
systemctl stop kea-dhcp4-server || true
systemctl stop kea-ctrl-agent || true
systemctl stop php*-fpm || true
;;
upgrade|deconfigure)
echo "Preparando actualización o desconfiguración de ogdhcp..."
;;
*)
echo "prerm llamado con un argumento desconocido '$1'" >&2
exit 1
;;
esac
exit 0

19
debian/ogdhcp.templates vendored 100644
View File

@ -0,0 +1,19 @@
Template: opengnsys/ogdhcp_interfaces
Type: string
Default: eth0
Description: Interfaces para DHCP
Template: opengnsys/ogdhcp_ip
Type: string
Default: 127.0.0.1
Description: IP para el servicio de ogdhcp
Template: opengnsys/ogboot_ogliveUrl
Type: string
Default: 127.0.0.1
Description: URL del OgLive a instalar
Template: opengnsys/ogdhcp_ogbootIP
Type: string
Default: 127.0.0.1
Description: Ip para el servicio de ogBoot

28
debian/rules vendored 100755
View File

@ -0,0 +1,28 @@
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable).
# Output every command that modifies files on the build system.
#export DH_VERBOSE = 1
# See FEATURE AREAS in dpkg-buildflags(1).
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# See ENVIRONMENT in dpkg-buildflags(1).
# Package maintainers to append CFLAGS.
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
# Package maintainers to append LDFLAGS.
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
dh $@
override_dh_auto_build:
cd api; \
rm -rf var/cache/*; \
mkdir -p bin/; \
mkdir -p public; \
COMPOSER_ALLOW_SUPERUSER=1 APP_ENV=prod composer install --no-interaction --no-progress --optimize-autoloader; \
COMPOSER_ALLOW_SUPERUSER=1 APP_ENV=prod composer update doctrine/dbal;

1
debian/source/format vendored 100644
View File

@ -0,0 +1 @@
3.0 (native)

View File

@ -0,0 +1,12 @@
[ogdhcp]
user = opengnsys
group = www-data
listen = /var/run/php/php8.3-fpm-ogdhcp.sock
listen.owner = opengnsys
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

View File

@ -0,0 +1,4 @@
[Unit]
# Eliminamos la condición de existencia del archivo de contraseña
ConditionFileNotEmpty=

View File

@ -34,6 +34,7 @@ function globalSetup() {
# Directorios de instalación y destino de OpenGnsys.
WORKDIR=/tmp/ogdhcp_installer
INSTALL_TARGET=$(jq -r '.ogDhcp_Dir' "$CONFIG_FILE")
SYMFONY_TARGET=$INSTALL_TARGET/api
PATH=$PATH:$INSTALL_TARGET/bin
if command -v service &>/dev/null; then
@ -57,7 +58,7 @@ function globalSetup() {
SOCKET_PATH="/run/php/php__PHPVERSION__-fpm-ogdhcp.sock"
# Registro de incidencias.
OGLOGFILE="$INSTALL_TARGET/var/log/${PROGRAMNAME%.sh}.log"
OGLOGFILE="$SYMFONY_TARGET/var/log/${PROGRAMNAME%.sh}.log"
LOG_FILE="/tmp/$(basename "$OGLOGFILE")"
}
@ -138,37 +139,26 @@ function createDirs() {
fi
local path_opengnsys_base="$1"
local symfony_target="$path_opengnsys_base/api"
# Crear estructura de directorios.
echoAndLog "${FUNCNAME}(): creating directory paths in $path_opengnsys_base"
mkdir -p "$path_opengnsys_base"/{bin,config,docs,public,src,etc/kea/backup,templates,var/{cache,log},vendor}
mkdir -p "$symfony_target"/{bin,config,docs,public,src,templates,var/{cache,log},vendor}
mkdir -p "$path_opengnsys_base"/etc/kea/backup
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error while creating dirs. Do you have write permissions?"
return 1
fi
# Crear usuario ficticio.
if id -u "$OPENGNSYS_CLIENT_USER" &>/dev/null; then
echoAndLog "${FUNCNAME}(): user \"$OPENGNSYS_CLIENT_USER\" is already created"
else
echoAndLog "${FUNCNAME}(): creating OpenGnsys user"
useradd "$OPENGNSYS_CLIENT_USER" 2>/dev/null
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error creating OpenGnsys user"
return 1
fi
fi
# Mover el fichero de registro de instalación al directorio de logs.
echoAndLog "${FUNCNAME}(): moving installation log file"
mv "$LOG_FILE" "$symfony_target/var/log" && LOG_FILE="$OGLOGFILE"
usermod -aG $OPENGNSYS_CLIENT_USER _kea
# Mover el fichero de registro de instalación al directorio de logs.
echoAndLog "${FUNCNAME}(): moving installation log file"
mv "$LOG_FILE" "$path_opengnsys_base/var/log" && LOG_FILE="$OGLOGFILE"
chmod 777 "$LOG_FILE"
sudo chmod -R 777 "$path_opengnsys_base/etc"
# Mover el fichero de registro de instalación al directorio de logs.
echoAndLog "${FUNCNAME}(): moving installation log file"
touch "$path_opengnsys_base/var/log/dev.log"
chmod 777 "$path_opengnsys_base/var/log/dev.log"
touch "$symfony_target/var/log/dev.log"
echoAndLog "${FUNCNAME}(): directory paths created"
return 0
@ -181,16 +171,39 @@ function createDirs() {
function create_ogdhcp_project {
# Crea el usuario ogdhcp si no existe
echo "Creating ogdhcp user..."
local path_opengnsys_base="$1"
if ! id -u opengnsys &>/dev/null; then
echoAndLog "${FUNCNAME}(): creating opengnsys user"
useradd opengnsys 2>/dev/null
local symfony_target="$path_opengnsys_base/api"
echo $symfony_target
# Verificar si el usuario OPENGNSYS_CLIENT_USER existe
if id -u "$OPENGNSYS_CLIENT_USER" &>/dev/null; then
# Salida de getent passwd -> opengnsys:x:1001:1001::/opt/opengnsys:/bin/sh
CURRENT_HOME=$(getent passwd "$OPENGNSYS_CLIENT_USER" | cut -d: -f6)
echoAndLog "${FUNCNAME[0]}(): user \"$OPENGNSYS_CLIENT_USER\" already exists with home \"$CURRENT_HOME\""
# Si el home no es correcto, cambiarlo
if [ "$CURRENT_HOME" != "/opt/opengnsys" ]; then
echoAndLog "${FUNCNAME[0]}(): updating home directory for \"$OPENGNSYS_CLIENT_USER\" to \"/opt/opengnsys\""
usermod -d "/opt/opengnsys" -m "$OPENGNSYS_CLIENT_USER"
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME[0]}(): error updating home for \"$OPENGNSYS_CLIENT_USER\""
return 1
fi
fi
else
# Crear usuario si no existe
echoAndLog "${FUNCNAME[0]}(): creating OpenGnsys user \"$OPENGNSYS_CLIENT_USER\""
useradd --create-home -d "/opt/opengnsys" --shell "/bin/bash" "$OPENGNSYS_CLIENT_USER"
if [ $? -ne 0 ]; then
errorAndLog "${FUNCNAME}(): error creating opengnsys user"
errorAndLog "${FUNCNAME[0]}(): error creating user \"$OPENGNSYS_CLIENT_USER\""
return 1
fi
fi
# Asegurar que todos los usuarios puedan entrar y leer /opt/opengnsys
echoAndLog "${FUNCNAME[0]}(): setting permissions for /opt/opengnsys"
# sudo chmod 755 /opt/opengnsys
# Crea el directorio path_opengnsys_base con el usuario opengnsys
echoAndLog "${FUNCNAME}(): creating directory $path_opengnsys_base with opengnsys user"
sudo mkdir -p "$path_opengnsys_base"
@ -210,16 +223,17 @@ function copyServerFiles() {
fi
local path_opengnsys_base="$1"
local symfony_target="$path_opengnsys_base/api"
local etc_target="$path_opengnsys_base/etc"
# Lista de ficheros y directorios origen y de directorios destino.
local SOURCES=(
config
#public
src
etc
.env
bin
composer.json
composer.lock
phpunit.xml.dist
symfony.lock
)
@ -227,10 +241,9 @@ function copyServerFiles() {
config
#public
src
etc
.env
bin
composer.json
composer.lock
phpunit.xml.dist
symfony.lock
)
@ -243,19 +256,27 @@ function copyServerFiles() {
# Copiar ficheros.
echoAndLog "${FUNCNAME}(): copying files to server directories"
pushd "$WORKDIR/ogdhcp" || return
pushd "$WORKDIR/ogdhcp/api" || return
local i
for (( i = 0; i < ${#SOURCES[@]}; i++ )); do
if [ -f "${SOURCES[$i]}" ]; then
echoAndLog "Copying ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}" "$path_opengnsys_base/${TARGETS[$i]}"
echoAndLog "Copying ${SOURCES[$i]} to $symfony_target/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}" "$symfony_target/${TARGETS[$i]}"
elif [ -d "${SOURCES[$i]}" ]; then
echoAndLog "Copying content of ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}"/* "$path_opengnsys_base/${TARGETS[$i]}"
echoAndLog "Copying content of ${SOURCES[$i]} to $symfony_target/${TARGETS[$i]}"
cp -a "${SOURCES[$i]}"/* "$symfony_target/${TARGETS[$i]}"
else
warningAndLog "Unable to copy ${SOURCES[$i]} to $path_opengnsys_base/${TARGETS[$i]}"
warningAndLog "Unable to copy ${SOURCES[$i]} to $symfony_target/${TARGETS[$i]}"
fi
done
pushd "$WORKDIR/ogdhcp" || return
# Copiar el directorio etc
echoAndLog "Copying etc directory to $path_opengnsys_base"
cp -a etc "$path_opengnsys_base"
if [ $? -ne 0 ]; then
errorAndLog "Error while copying etc directory to $path_opengnsys_base"
return 1
fi
echoAndLog "Changing user permission"
chown -R "$OPENGNSYS_CLIENT_USER:$OPENGNSYS_CLIENT_USER" "$INSTALL_TARGET"
@ -266,7 +287,8 @@ function copyServerFiles() {
function runComposer() {
echoAndLog "Running composer.phar to install dependencies..."
local path_opengnsys_base="$1"
pushd $path_opengnsys_base
local symfony_target="$path_opengnsys_base/api"
pushd $symfony_target
pwd
# Ejecutar composer.phar
sudo -u "$OPENGNSYS_CLIENT_USER" composer --no-interaction install
@ -374,7 +396,8 @@ add_write_permission_apparmor() {
# Función para configurar Nginx
setup_nginx() {
local path_opengnsys_base="$1"
local public_dir="$path_opengnsys_base/public"
local symfony_target="$path_opengnsys_base/api"
local public_dir="$symfony_target/public"
#ip_address_server=$(get_ip_address "$DEFAULTDEV")
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "Error: El archivo de configuración no se encontró."
@ -581,6 +604,18 @@ if [ "$(whoami)" != 'root' ]; then
exit 1
fi
# Verificar si jq está instalado, si no, instalarlo
if ! command -v jq &> /dev/null; then
echo "jq no está instalado. Instalando jq..."
apt-get update -y
apt-get install -y jq
if [ $? -ne 0 ]; then
echo "Error al instalar jq. Por favor, instala jq manualmente y vuelve a intentarlo."
exit 1
fi
echo "jq instalado correctamente."
fi
globalSetup
echoAndLog "OpenGnsys installation begins at $(date)"
@ -590,6 +625,7 @@ pushd $WORKDIR
checkDependencies
# Si es necesario, descarga el repositorio de código en directorio temporal
if [ $REMOTE -eq 1 ]; then
downloadCode $GIT_REPO
if [ $? -ne 0 ]; then
@ -600,6 +636,7 @@ else
ln -fs "$(dirname $PROGRAMDIR)" ogdhcp
fi
create_ogdhcp_project ${INSTALL_TARGET}
if [ $? -ne 0 ]; then
errorAndLog "Error while creating skeleton directory!"

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,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

@ -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 %}

View File

@ -1,118 +0,0 @@
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'
echo 'Create Python venv to work with robotframework'
sh '''
python3 -m venv robotframework
. robotframework/bin/activate
pip install -r requirements.txt
'''
}
}
}
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\n' | sed 's/^[^0-9]*//' | sed 's/[[:space:]]*$//')
echo $new_ip > ip.txt
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: /'
'''
script {
def new_ip = readFile('ip.txt').trim()
env.NEW_IP = new_ip
}
}
}
}
stage('Run API tests') {
steps {
dir ('tests/API-dhcp') {
echo 'Running API tests'
sh '''
. robotframework/bin/activate
robot --variable BASE_URL:http://${NEW_IP}/ogdhcp/v1 -d results/ robot/
'''
}
// 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 {
// Recoger los resultados de los tests
dir ('tests/API-dhcp') {
robot outputPath: 'results',
outputFileName: 'output.xml',
logFileName: 'log.html',
reportFileName: 'report.html',
passThreshold: 100.0,
unstableThreshold: 75.0
}
// Siempre se ejecutará, independientemente del resultado
script {
// Elimina la entrada del /etc/hosts
sh "echo '$QINDEL_PASS' | sudo -S sed -i '/api-test/d' /etc/hosts"
def recipientEmail = env.BUILD_USER_EMAIL ?: getCommitterEmail()
mail to: recipientEmail,
subject: "Jenkins Job Completed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
El job '${env.JOB_NAME}' con número de build ${env.BUILD_NUMBER} ha finalizado.
Estado: ${currentBuild.currentResult}
Revisa los detalles del build en: ${env.BUILD_URL}
"""
}
}
}
}
def getCommitterEmail() {
return sh(
script: 'git log -1 --pretty=format:"%ae"',
returnStdout: true
).trim()
}

View File

@ -1,163 +0,0 @@
#
# 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

@ -1,374 +0,0 @@
#!/usr/bin/env python
from flask import Flask, jsonify, request
import ipaddress
import json
app = Flask(__name__)
def convert_to_cidr(address, mask):
"""
Convert an IP address and subnet mask to CIDR notation.
Args:
address (str): The IP address in dotted decimal format (e.g., '192.168.1.1').
mask (str): The subnet mask in dotted decimal format (e.g., '255.255.255.0').
Returns:
str: The CIDR notation of the network (e.g., '192.168.1.1/24').
None: If there is an error in conversion, returns None and prints an error message.
Raises:
ValueError: If the provided address or mask is invalid.
"""
# Convertir dirección y máscara a formato CIDR
try:
# Convertir la máscara de red de formato largo a formato corto
# Cada octeto se convierte a su representación binaria y se cuenta el número de bits '1'
cidr_mask = ipaddress.IPv4Network(f"0.0.0.0/{mask}").prefixlen
red_objeto = f"{address}/{cidr_mask}"
return red_objeto
except ValueError as e:
print(f"Error al convertir a CIDR: {e}")
return None
subnets_collection = [{"id": 1,"subnet": "192.168.1.0/24", "next-server": "192.168.1.1", "boot-file-name": "pxelinux.0", "reservations": [] }]
# Endpoint GET /ogdhcp/v1/status
"""
Endpoint to get the status of the DHCP service.
This endpoint returns a JSON response with the current status of the DHCP service,
including disk usage, subnets configuration, and the status of various services.
Returns:
Response: A JSON response with the following structure:
"total": str, # Total disk space
"used": str, # Used disk space
"available": str, # Available disk space
"percentage": str # Percentage of disk space used
"id": int, # Subnet ID
"subnet": str, # Subnet address
"pools": [
"pool": str # IP address pool range
"reservations": [
"ip-address": str, # Reserved IP address
"hw-address": str # Hardware address associated with the reservation
]
...
"kea-ctrl-agent": str, # Status of kea-ctrl-agent service
"kea-dhcp4": str, # Status of kea-dhcp4 service
"nginx": str # Status of nginx service
HTTP Status Code:
200: If the request was successful.
"""
@app.route('/ogdhcp/v1/status', methods=['GET'])
def get_status():
# Simular respuesta de éxito
return jsonify({
"success": "Mensaje éxito",
"message": {
"disk_usage": {
"total": "20G",
"used": "15G",
"available": "5G",
"percentage": "75%"
},
"subnets": [
{
"id": 1,
"subnet": "192.168.1.0/24",
"pools": [{"pool": "192.168.1.10-192.168.1.100"}],
"reservations": [{"ip-address": "192.168.1.20", "hw-address": "00:0c:29:6b:5e:71"}]
},
{
"id": 2,
"subnet": "10.0.0.0/24",
"pools": [{"pool": "10.0.0.10-10.0.0.100"}],
"reservations": []
}
],
"services_status": {
"kea-ctrl-agent": "active",
"kea-dhcp4": "active",
"nginx": "active"
}
}
}), 200
# Endpoint GET /ogdhcp/v1/subnets
@app.route('/ogdhcp/v1/subnets', methods=['GET'])
def get_subnets():
# Simular respuesta de éxito
return jsonify({
"success": "Subredes obtenidas correctamente",
"message": subnets_collection
}), 200
# Endpoint POST /ogdhcp/v1/subnets
"""
Create a new subnet.
Endpoint: /ogdhcp/v1/subnets
Method: POST
Request Body (JSON):
{
"id": <str>, # Unique identifier for the subnet
"address": <str>, # IP address of the subnet
"mask": <str>, # Subnet mask
"nextServer": <str>, # (Optional) Next server IP address
"bootFileName": <str> # (Optional) Boot file name
}
Responses:
200 OK:
{
"message": <new_subnet>
}
400 Bad Request:
- "Invalid JSON"
- "Missing 'id', 'address' or 'mask' key"
- {
"error": "Error: La subred con el id '<id>' ya existe."
}
- {
"error": "Error: La subred con la dirección '<subnet>' ya existe."
}
- "Invalid data format"
Description:
This endpoint allows the creation of a new subnet. It expects a JSON payload with the subnet details.
The function checks if the provided JSON is valid and contains the required keys ('id', 'address', 'mask').
It also ensures that the subnet ID and subnet address do not already exist in the collection.
If the validation passes, the new subnet is added to the collection and a success response is returned.
"""
@app.route('/ogdhcp/v1/subnets', methods=['POST'])
def create_subnet():
try:
new_subnet = json.loads(request.data)
new_subnet["next-server"] = new_subnet.get("nextServer")
new_subnet["boot-file-name"] = new_subnet.get("bootFileName")
except json.JSONDecodeError:
return "Invalid JSON", 400
if isinstance(new_subnet, dict):
if "id" in new_subnet and "address" in new_subnet and "mask" in new_subnet:
new_subnet_cidr = convert_to_cidr(new_subnet["address"], new_subnet["mask"])
# Comprobar si el id ya existe en la colección
for subnet in subnets_collection:
if subnet.get("id") == new_subnet["id"]:
return jsonify({
"error": f"Error: La subred con el id '{new_subnet['id']}' ya existe."
}), 400
if subnet.get("subnet") == new_subnet_cidr:
return jsonify({
"error": f"Error: La subred con la dirección '{new_subnet_cidr}' ya existe."
}), 400
# Si el id no existe, continuar con la creación de la subred
new_subnet["subnet"] = convert_to_cidr(new_subnet["address"], new_subnet["mask"])
subnets_collection.append(new_subnet)
return jsonify({
"success": "Subred agregada correctamente",
"message": new_subnet
}), 200
else:
return "Missing 'id', 'address' or 'mask' key", 400
else:
return "Invalid data format", 400
# Endpoint DELETE /ogdhcp/v1/subnets/<subnetId>
"""
Deletes a subnet from the subnets_collection based on the provided subnetId.
Args:
subnetId (int): The ID of the subnet to be deleted.
Returns:
Response: A JSON response indicating the success or failure of the deletion.
- If the subnet is successfully deleted, returns a JSON response with a success message and HTTP status 200.
- If the subnet with the given ID does not exist, returns a JSON response with an error message and HTTP status 404.
"""
@app.route('/ogdhcp/v1/subnets/<int:subnetId>', methods=['DELETE'])
def delete_subnet(subnetId):
subnet_to_delete = None
for subnet in subnets_collection:
if int(subnet["id"]) == subnetId:
subnet_to_delete = subnet
break
if subnet_to_delete:
print (f"Subnet Collection {subnets_collection}")
print (f"Subnet to delete {subnet_to_delete}")
subnets_collection.remove(subnet_to_delete)
print (f"Subnet Collection {subnets_collection}")
return jsonify({
"success": "Subred eliminada correctamente"
}), 200
else:
return jsonify({
"error": f"Error: La subred con el id '{subnetId}' no existe"
}), 404
# Endpoint PUT /ogdhcp/v1/subnets/<subnetId>
"""
Updates a subnet with the given subnetId based on the provided JSON data in the request.
Args:
subnetId (str): The ID of the subnet to be updated.
Returns:
Response: A JSON response indicating the success or failure of the update operation.
- On success: Returns a JSON response with a success message and the updated subnet data, with a status code of 200.
- On failure: Returns a JSON response with an error message and a status code of 400.
Raises:
json.JSONDecodeError: If the request data is not valid JSON.
The function performs the following steps:
1. Parses the JSON data from the request.
2. Validates the presence of required fields ('address' and 'mask') in the JSON data.
3. Converts the 'address' and 'mask' fields to a 'subnet' field in CIDR notation.
4. Searches for the subnet with the given subnetId in the subnets_collection.
5. Updates the subnet fields ('subnet', 'nextServer', 'bootFileName') if they are present in the JSON data.
6. Returns a success response if the subnet is found and updated.
7. Returns an error response if the subnet is not found.
"""
@app.route('/ogdhcp/v1/subnets/<int:subnetId>', methods=['PUT'])
def update_subnet(subnetId):
if subnetId == 0:
return jsonify({
"error": "Error al guardar la configuración en Kea DHCP: Unable to save configuration"
}), 400
try:
modify_data = json.loads(request.data)
except json.JSONDecodeError:
return "Invalid JSON", 400
print ("Modify data", modify_data)
print ("Modify data type", type(modify_data))
if modify_data.get("address") != None and modify_data.get("mask") == None:
print ("Address", modify_data.get("address"))
return jsonify({
"error": f"Error: La máscara de red es requerida con el parametro 'address'"
}), 400
if modify_data.get("mask") != None and modify_data.get("address") == None:
return jsonify({
"error": f"Error: La dirección de red es requerida con el parametro 'mask'"
}), 400
subnet_to_update = None
for subnet in subnets_collection:
# Casting subnet["id"] to int to avoid type mismatch
if str(subnet["id"]) == str(subnetId):
# subnet_to_update = subnet
if modify_data.get("subnet"):
subnet["subnet"] = modify_data["subnet"]
if modify_data.get("nextServer"):
subnet["next-server"] = modify_data["nextServer"]
if modify_data.get("bootFileName"):
subnet["boot-file-name"] = modify_data["bootFileName"]
subnet_to_update = subnet
break
if subnet_to_update:
# subnet_to_update.update(modify_data)
print ("Subnet to update", subnet_to_update)
return jsonify({
"success": "Subred modificada correctamente",
"message": subnet_to_update
}), 200
else:
# Si no se encuentra la subred, devolver un error
print (f"Subnet Collection {subnets_collection}")
response = jsonify({
"error": f"Error: La subred con el id '{subnetId}' no existe"
})
response.status_code = 404
response.headers["Content-Type"] = "application/json"
return response
# Endpoint GET /ogdhcp/v1/subnets/<subnetId>/hosts
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['GET'])
def get_hosts(subnetId):
# Simular respuesta de éxito
return jsonify({
"success": "Hosts retrieved successfully",
"message": [
{"ip-address": "192.168.1.10", "hw-address": "00:0c:29:6b:5e:71", "hostname": "host1"},
{"ip-address": "192.168.1.20", "hw-address": "00:0c:29:6b:5e:72", "hostname": "host2"}
]
}), 200
# Endpoint POST /ogdhcp/v1/subnets/<subnetId>/hosts
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['POST'])
def create_host(subnetId):
# Simular respuesta de éxito
return jsonify({
"success": "Host agregado correctamente",
"message": {
"id": 1,
"subnet": "192.168.1.0/24",
"next-server": "192.168.1.1",
"boot-file-name": "pxelinux.0",
"reservations": [
{"hostname": "pc11", "hw-address": "56:6f:c7:4f:00:4f", "ip-address": "172.30.4.11"}
]
}
}), 200
# Endpoint DELETE /ogdhcp/v1/subnets/<subnetId>/hosts
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['DELETE'])
def delete_host(subnetId):
# Simular respuesta de éxito
return jsonify({
"success": "Host eliminado correctamente",
"message": {
"id": 1,
"subnet": "192.168.1.0/24",
"next-server": "192.168.1.1",
"boot-file-name": "pxelinux.0",
"reservations": [
{"hostname": "host2", "hw-address": "00:0c:29:6b:5e:72", "ip-address": "172.30.4.12"}
]
}
}), 200
# Endpoint PUT /ogdhcp/v1/subnets/<subnetId>/hosts
@app.route('/ogdhcp/v1/subnets/<int:subnetId>/hosts', methods=['PUT'])
def update_host(subnetId):
# Simular respuesta de éxito
return jsonify({
"success": "Host actualizado correctamente",
"message": {
"id": 1,
"subnet": "192.168.1.0/24",
"next-server": "192.168.1.1",
"boot-file-name": "pxelinux.0",
"reservations": [
{"hostname": "pc11", "hw-address": "56:6f:c7:4f:01:01", "ip-address": "192.168.1.11"},
{"hostname": "host2", "hw-address": "00:0c:29:6b:5e:72", "ip-address": "192.168.1.12"}
]
}
}), 200
# Endpoint POST /ogdhcp/v1/backup
@app.route('/ogdhcp/v1/backup', methods=['POST'])
def backup_config():
# Simular respuesta de éxito
return jsonify({
"success": "Configuración cargada correctamente"
}), 200
if __name__ == '__main__':
app.run(debug=True, port=8006)

View File

@ -1,2 +0,0 @@
robotframework
robotframework-requests

View File

@ -1,215 +0,0 @@
*** Settings ***
Documentation This is a basic skeleton for a Robot Framework test suite.
Library Collections
Library RequestsLibrary
*** Variables ***
${BASE_URL} http://localhost:8006/ogdhcp/v1
${headers} Create Dictionary Content-Type application/json
${modified_subnet} Create Dictionary mask=255.255.192.0 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
${wrong_subnet_data_netmask} Create Dictionary mask=333.333.333.333 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
${wrong_subnet_data_address} Create Dictionary mask=255.255.255.0 address=444.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
${wrong_subnet_data_server} Create Dictionary mask=255.255.255.0 address=192.168.1.0 nextServer=555.168.1.1 bootFileName=pxelinux.0
${invalid_net_id} 999
${valid_net_id} 2
${subnet_error} 0
*** Test Cases ***
Get Status of the DHCP server
[Documentation] Get status of the dhcp server and check services status
[Tags] status
${response}= GET ${BASE_URL}/status
Status Should Be 200 ${response}
Log ${response.json()}
# Convertir la respuesta a JSON usando ${response.json()}
${json}= Convert to Dictionary ${response.json()}
Dictionary Should Contain Key ${json} success
Dictionary Should Contain Key ${json} message
Should Contain ${response.json()['message']} disk_usage
Should Contain ${response.json()['message']} subnets
Should Contain ${response.json()['message']['disk_usage']} total
Get All Subnets
[Documentation] Este test verifica que la API retorna las subredes correctamente con el código 200.
[Tags] subnets
${response}= GET ${BASE_URL}/subnets
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 200
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene las claves 'success' y 'message'
Dictionary Should Contain Key ${json} success
Dictionary Should Contain Key ${json} message
# Validar el mensaje de éxito
Should Be Equal ${json['success']} Subredes obtenidas correctamente
# Verificar que 'message' es una lista
# Should Be True ${json['message']} is list
# Verificar que cada subred en 'message' tiene los campos esperados
FOR ${subred} IN @{json['message']}
Dictionary Should Contain Key ${subred} id
Dictionary Should Contain Key ${subred} subnet
END
Post a new subnet
[Documentation] Post a new subnet
[Tags] subnets
${new_subnet} Create Dictionary
... subnetId=${valid_net_id}
... mask=255.255.255.0
... address=192.168.2.0
... nextServer=192.168.2.1
... bootFileName=pxelinux.0
${headers}= Create Dictionary Content-Type=application/json
${response}= POST ${BASE_URL}/subnets json=${new_subnet} headers=${headers}
Status Should Be 200 ${response}
${json}= Convert to Dictionary ${response.json()}
Dictionary Should Contain Key ${json} success
Dictionary Should Contain Key ${json} message
Should Contain ${json["success"]} Subred agregada correctamente
Should Be Equal As Numbers ${json["message"]["id"]} ${valid_net_id}
Post a new subnet with existing id
[Documentation] Post a new subnet with invalid data
[Tags] subnets
${new_subnet} Create Dictionary
... subnetId=2
... mask=255.255.255.0
... address=192.168.3.0
... nextServer=192.168.3.1
... bootFileName=pxelinux.0
${headers}= Create Dictionary Content-Type=application/json
${response}= POST ${BASE_URL}/subnets json=${new_subnet} headers=${headers} expected_status=400
Status Should Be 400 ${response}
${json}= Convert to Dictionary ${response.json()}
Dictionary Should Contain Key ${json} error
Should Contain ${response.json()["error"]} La subred con el id '${valid_net_id}' ya existe.
Post a new subnet with existing address
[Documentation] Post a new subnet with invalid data
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${new_subnet_invalid} Create Dictionary
... subnetId=3
... mask=255.255.255.0
... address=192.168.1.0
... nextServer=192.168.1.1
... bootFileName=pxelinux.0
${response}= POST ${BASE_URL}/subnets json=${new_subnet_invalid} headers=${headers} expected_status=400
Status Should Be 400 ${response}
${json}= Convert to Dictionary ${response.json()}
Dictionary Should Contain Key ${json} error
Should Contain ${response.json()['error']} La subred con la dirección '192.168.1.0/24' ya existe
Modify an existing subnet by id
[Documentation] Modify a subnet by id
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${modified_subnet}= Create Dictionary
... mask=255.255.192.0
... address=192.168.1.0
... nextServer=192.168.1.1
... bootFileName=pxelinux.0
# Modificar la subred con id=2
${response}= PUT ${BASE_URL}/subnets/2 json=${modified_subnet} headers=${headers} expected_status=200
Status Should Be 200 ${response}
${json}= Convert to Dictionary ${response.json()}
# Verificar que la respuesta contiene clave 'success'
Dictionary Should Contain Key ${json} success
# Validar el contenido del mensaje de éxito
Should Be Equal ${json['success']} Subred modificada correctamente
Should Be Equal ${json['message']['id']} 2
Modify a subnet with invalid id
[Documentation] Este test verifica que la modificación de una subred falla cuando el ID no existe.
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${modificar_subred}= Create Dictionary mask=255.255.192.0 address=192.168.1.0 nextServer=192.168.1.1 bootFileName=pxelinux.0
${response}= PUT ${BASE_URL}/ogdhcp/v1/subnets/${invalid_net_id} json=${modificar_subred} headers=${headers} expected_status=404
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 404
Modify subnet with error to save configuration
[Documentation] Este test verifica que la modificación falla cuando hay un error al guardar la configuración en Kea DHCP.
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${modificar_subred}= Create Dictionary subnet="192.168.1.0" mask="255.255.255.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
${response}= PUT ${BASE_URL}/subnets/${subnet_error} json=${modificar_subred} headers=${headers} expected_status=400
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 400
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene el error esperado
Should Be Equal ${json['error']} Error al guardar la configuración en Kea DHCP: Unable to save configuration
Modify subnet with invalid configuration address without netmask
[Documentation] Este test verifica que la modificación falla cuando hay un error en la configuración de Kea DHCP.
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${modificar_subred}= Create Dictionary address="192.168.1.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
${response}= PUT ${BASE_URL}/subnets/2 json=${modificar_subred} headers=${headers} expected_status=400
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 400
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene el error esperado
Should Be Equal ${json['error']} Falta un parámetro requerido: mask
Modify subnet with invalid configuration netmask without address
[Documentation] Este test verifica que la modificación falla cuando hay un error en la configuración de Kea DHCP.
[Tags] subnets
${headers}= Create Dictionary Content-Type=application/json
${modificar_subred}= Create Dictionary mask="255.255.255.0" nextServer="192.168.1.1" bootFileName="pxelinux.0"
${response}= PUT ${BASE_URL}/subnets/2 json=${modificar_subred} headers=${headers} expected_status=400
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 400
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene el error esperado
Should Be Equal ${json['error']} Falta un parámetro requerido: address
Delete subnet by id
[Documentation] Este test verifica que la subred se elimina correctamente con el código 200.
[Tags] subnets
${response}= DELETE ${BASE_URL}/subnets/${valid_net_id}
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 200
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene la clave 'success'
Dictionary Should Contain Key ${json} success
# Validar el mensaje de éxito
Should Be Equal ${json['success']} Subred eliminada correctamente
Delete subnet - Error: wrong subnet Id
[Documentation] Este test verifica que la eliminación falla si la subred con el ID no existe.
[Tags] subnets
${response}= DELETE ${BASE_URL}/subnets/${invalid_net_id} expected_status=404
# Verificar código de estado HTTP
Should Be Equal As Numbers ${response.status_code} 404
${json}= Convert To Dictionary ${response.json()}
# Verificar que la respuesta contiene la clave 'error'
Dictionary Should Contain Key ${json} error
# Validar el mensaje de error
Should Be Equal ${json['error']} La subred con el id '999' no existe

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