Compare commits
80 Commits
deb-packag
...
main
Author | SHA1 | Date |
---|---|---|
|
2ad4848a5e | |
|
6e8d9d4132 | |
|
d048ee782c | |
|
73c0220ab3 | |
|
037ac63c97 | |
|
83b0fd7c03 | |
|
199ef8c5e1 | |
|
05b51de851 | |
|
228bd85aa8 | |
|
3992ff27f0 | |
|
8728682936 | |
|
a1f0561f5c | |
|
e355562714 | |
|
8dcd1faefd | |
|
05b963d611 | |
|
da5d6fd8c5 | |
|
3c2fc27e2e | |
|
b04bf3c5b1 | |
|
bff65cde01 | |
|
984b251615 | |
|
28f2537aed | |
|
c949cfb9a9 | |
|
9f87997722 | |
|
a387af27d0 | |
|
9a9cf17403 | |
|
ba5384ea77 | |
|
74efebf3c8 | |
|
88953696e7 | |
|
f972ae1ae9 | |
|
95524ac9cf | |
|
ccf04ba8fc | |
|
9f170c23c7 | |
|
6236be85d8 | |
|
0118ca53a5 | |
|
bada82e88a | |
|
a3b938e41e | |
|
dd60800c97 | |
|
ecbba3d45e | |
|
a58023f893 | |
|
c23b4ddddb | |
|
2507c035ae | |
|
d0149f40f8 | |
|
fba880c477 | |
|
29f653a527 | |
|
b9d3f5c4c7 | |
|
5406e67b95 | |
|
15769dde0f | |
|
f8cb868a2a | |
|
4316217faa | |
|
b77aa1fc4d | |
|
d7869c35b7 | |
|
8af857c9ef | |
|
48d10b7cd9 | |
|
90fd5b274f | |
|
311ecc7f3a | |
|
6ba0788bc0 | |
|
826625f66a | |
|
d585e992e6 | |
|
bf0f138bcd | |
|
7906c3e6aa | |
|
0762178aa4 | |
|
5c57137c4d | |
|
ee91db10df | |
|
8891150d79 | |
|
225d8eee0d | |
|
251ebf87b3 | |
|
14fe0af2f6 | |
|
997819aafe | |
|
84bbdac4d0 | |
|
ba0198694d | |
|
55b3304fea | |
|
8fb7a25c5e | |
|
20a1628dd3 | |
|
96fe86b681 | |
|
bafa4c78fa | |
|
d1501e7b02 | |
|
064a8f1fab | |
|
f5cf0ce0ec | |
|
48dfc3d190 | |
|
43bc2782e6 |
|
@ -0,0 +1,230 @@
|
|||
# Changelog
|
||||
|
||||
## [0.10.0] - 2025-07-07
|
||||
|
||||
### Added
|
||||
|
||||
- OgGit functionality (#2371, #2363, #2363, #2317)
|
||||
|
||||
## [0.9.0] - 2025-06-25
|
||||
|
||||
## Added
|
||||
|
||||
- Changed old tools for tools non dependant of Pyhton2 in repo
|
||||
- mktorrent to handle creation of torrent files
|
||||
- aria2c as torrent client for initial seeding
|
||||
- opentracker as torrent tracker tool
|
||||
|
||||
## [0.8.2] - 2025-06-01
|
||||
|
||||
### Changed
|
||||
|
||||
- Modified sudoersfile to start torrent
|
||||
|
||||
## [0.8.1] - 2025-04-01
|
||||
|
||||
### Changed
|
||||
|
||||
- Add sudo to cancel transfers endpoints (#1796)
|
||||
|
||||
## [0.8.0] - 2025-03-25
|
||||
|
||||
### Added
|
||||
|
||||
- Rename Image functionality (#1733)
|
||||
|
||||
## [0.7.3] - 2025-03-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix permissions problem and authorized_keys file in debian package
|
||||
|
||||
## [0.7.2] - 2025-03-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Update CHANGELOG.md
|
||||
|
||||
## [0.7.1] - 2025-03-19
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated Jenkinsfile for publishing packages (#1313)
|
||||
|
||||
## [0.7.0] - 2025-03-18
|
||||
|
||||
### Added
|
||||
|
||||
- Image to Virtual Disk conversion (#1689)
|
||||
|
||||
## [0.6.4] - 2025-03-13
|
||||
|
||||
### Changed
|
||||
|
||||
- Virtual Disk to Image conversion improvement (#1701)
|
||||
|
||||
## [0.6.3] - 2025-03-12
|
||||
|
||||
### Fixed
|
||||
|
||||
- Virtual Disk to Image conversion fix (#1701)
|
||||
|
||||
## [0.6.2] - 2025-03-10
|
||||
|
||||
### Added
|
||||
|
||||
- ogGit Install Status info (#1681)
|
||||
|
||||
## [0.6.1] - 2025-03-05
|
||||
|
||||
### Changed
|
||||
|
||||
- Cancel Transfers scripts improvement (#1642)
|
||||
|
||||
## [0.6.0] - 2025-03-03
|
||||
|
||||
### Added
|
||||
|
||||
- Virtual Disk to Image conversion (#1525)
|
||||
|
||||
## [0.5.23] - 2025-02-20
|
||||
|
||||
### Changed
|
||||
|
||||
- Backup Image improvement (#1530)
|
||||
|
||||
## [0.5.22] - 2025-02-20
|
||||
|
||||
### Added
|
||||
|
||||
- Backup Image (#1530)
|
||||
|
||||
## [0.5.20] - 2025-02-11
|
||||
|
||||
### Changed
|
||||
|
||||
- Paramiko SSH Client parameters improvement (#1482)
|
||||
|
||||
## [0.5.19] - 2025-02-06
|
||||
|
||||
### Fixed
|
||||
|
||||
- Script corrections (#1437)
|
||||
|
||||
## [0.5.18] - 2025-02-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Script corrections (#1437)
|
||||
|
||||
## [0.5.17] - 2025-02-03
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove unnecessary sudo calls (#1437)
|
||||
|
||||
## [0.5.16] - 2025-01-31
|
||||
|
||||
### Added
|
||||
|
||||
- API tests (#1378)
|
||||
|
||||
### Changed
|
||||
|
||||
- API improvement (#1378)
|
||||
|
||||
## [0.5.15] - 2025-01-28
|
||||
|
||||
### Fixed
|
||||
|
||||
- API tests errors fixes (#1378)
|
||||
|
||||
## [0.5.14] - 2025-01-24
|
||||
|
||||
### Added
|
||||
|
||||
- API tests (#1346)
|
||||
|
||||
## [0.5.13] - 2025-01-10
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove recursive image search (#1335)
|
||||
|
||||
## [0.5.12] - 2024-12-17
|
||||
|
||||
### Changed
|
||||
|
||||
- Modify logs format (#1294)
|
||||
|
||||
## [0.5.11] - 2024-12-12
|
||||
|
||||
### Changed
|
||||
|
||||
- API logs improvement (#1242)
|
||||
|
||||
## [0.5.10] - 2024-12-02
|
||||
|
||||
### Changed
|
||||
|
||||
- API and Script logs improvement (#631)
|
||||
|
||||
## [0.5.9] - 2024-11-29
|
||||
|
||||
### Added
|
||||
|
||||
- Script journalctl logs (#631)
|
||||
|
||||
## [0.5.8] - 2024-11-28
|
||||
|
||||
### Added
|
||||
|
||||
- API journalctl logs (#631)
|
||||
|
||||
## [0.5.7] - 2024-11-26
|
||||
|
||||
### Added
|
||||
|
||||
- 'python3-request' packet
|
||||
|
||||
## [0.5.6] - 2024-11-22
|
||||
|
||||
### Changed
|
||||
|
||||
- API improvements (#631)
|
||||
|
||||
## [0.5.5] - 2024-11-21
|
||||
|
||||
### Changed
|
||||
|
||||
- API improvements (#631)
|
||||
|
||||
## [0.5.4] - 2024-11-20
|
||||
|
||||
### Changed
|
||||
|
||||
- API and Script improvements (#631)
|
||||
|
||||
## [0.5.3] - 2024-11-18
|
||||
|
||||
### Changed
|
||||
|
||||
- Update Documentation (#631)
|
||||
|
||||
## [0.5.2] - 2024-11-18
|
||||
|
||||
### Changed
|
||||
|
||||
- API improvements (#631)
|
||||
|
||||
## [0.5.1] - 2024-11-15
|
||||
|
||||
### Changed
|
||||
|
||||
- API improvements (#610)
|
||||
|
||||
## [0.5.0] - 2024-11-15
|
||||
|
||||
### Changed
|
||||
|
||||
- Update Documentation (#1084)
|
|
@ -0,0 +1,113 @@
|
|||
@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}/ogrepository"
|
||||
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/ogrepository")
|
||||
}
|
||||
}
|
||||
}
|
||||
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/ogrepository', '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/ogrepository', '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"
|
||||
// }
|
||||
// }
|
||||
|
525
README.md
525
README.md
|
@ -20,6 +20,9 @@ Paquetes APT requeridos:
|
|||
- **bittorrent** (se puede instalar con "sudo apt install bittorrent", pero previamente hay que añadir un repositorio de Debian)
|
||||
- **bittornado** (se puede instalar con "sudo apt install bittornado", pero previamente hay que añadir un repositorio de Debian)
|
||||
- **wakeonlan** (se puede instalar con "sudo apt install wakeonlan")
|
||||
- **qemu** (se puede instalar con "sudo apt install qemu-utils")
|
||||
- **partclone** (se puede instalar con "sudo apt install partclone")
|
||||
- **lzop** (se puede instalar con "sudo apt install lzop")
|
||||
|
||||
Librerías Python requeridas:
|
||||
- **flask** (se puede instalar con "sudo apt install python3-flask")
|
||||
|
@ -31,6 +34,7 @@ Librerías Python requeridas:
|
|||
Para que todos los endpoints y scripts funcionen con la configuración actual deben existir los siguientes directorios:
|
||||
- **/opt/opengnsys/ogrepository/images/**
|
||||
- **/opt/opengnsys/ogrepository/images_trash/** (debe estar en la misma partición que el anterior, o tardarán mucho las eliminaciones y restauraciones)
|
||||
- **/opt/opengnsys/ogrepository/images_virtual/** (aquí deben copiarse las imágenes virtuales que se quiera convertir a "img")
|
||||
- **/opt/opengnsys/ogrepository/bin/** (aquí deben estar todos los scripts de Python, y el binario "udp-sender")
|
||||
- **/opt/opengnsys/ogrepository/api/** (aquí debe estar la API y el Swagger)
|
||||
- **/opt/opengnsys/ogrepository/etc/** (aquí se guardan los archivos "repoinfo.json" y "trashinfo.json")
|
||||
|
@ -58,23 +62,26 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará
|
|||
6. [Eliminar una Imagen](#eliminar-una-imagen) - `DELETE /ogrepository/v1/images/{ID_img}?method={method}`
|
||||
7. [Recuperar una Imagen](#recuperar-una-imagen) - `POST /ogrepository/v1/trash/images`
|
||||
8. [Eliminar una Imagen de la Papelera](#eliminar-una-imagen-de-la-papelera) - `DELETE /ogrepository/v1/trash/images/{ID_img}`
|
||||
9. [Transferir una Imagen entre Repositorios](#transferir-una-imagen-entre-repositorios) - `POST /ogrepository/v1/repo/images`
|
||||
10. [Hacer Backup de una Imagen](#hacer-backup-de-una-imagen) - `PUT /ogrepository/v1/repo/images`
|
||||
11. [Crear archivos auxiliares](#crear-archivos-auxiliares) - `POST /ogrepository/v1/images/torrentsum`
|
||||
12. [Enviar paquete Wake On Lan](#enviar-paquete-wake-on-lan) - `POST /ogrepository/v1/wol`
|
||||
13. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast`
|
||||
14. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp`
|
||||
9. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast`
|
||||
10. [Ver Estado de Transmisiones UDPcast](#ver-estado-de-transmisiones-udpcast) - `GET /ogrepository/v1/udpcast`
|
||||
11. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}`
|
||||
12. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp`
|
||||
13. [Ver Estado de Transmisiones UFTP](#ver-estado-de-transmisiones-uftp) - `GET /ogrepository/v1/uftp`
|
||||
14. [Cancelar Transmisión UFTP](#cancelar-transmisión-uftp) - `DELETE /ogrepository/v1/uftp/images/{ID_img}`
|
||||
15. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/p2p`
|
||||
16. [Ver Estado de Transmisiones UDPcast](#ver-estado-de-transmisiones-udpcast) - `GET /ogrepository/v1/udpcast`
|
||||
17. [Ver Estado de Transmisiones UFTP](#ver-estado-de-transmisiones-uftp) - `GET /ogrepository/v1/uftp`
|
||||
18. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}`
|
||||
19. [Cancelar Transmisión UFTP](#cancelar-transmisión-uftp) - `DELETE /ogrepository/v1/uftp/images/{ID_img}`
|
||||
20. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p`
|
||||
16. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p`
|
||||
17. [Transferir una Imagen entre Repositorios](#transferir-una-imagen-entre-repositorios) - `POST /ogrepository/v1/repo/images`
|
||||
18. [Hacer Backup de una Imagen](#hacer-backup-de-una-imagen) - `PUT /ogrepository/v1/repo/images`
|
||||
19. [Convertir Imagen Virtual a Imagen OpenGnsys](#convertir-imagen-virtual-a-imagen-opengnsys) - `POST /ogrepository/v1/images/virtual`
|
||||
20. [Convertir Imagen OpenGnsys a Imagen Virtual](#convertir-imagen-opengnsys-a-imagen-virtual) - `PUT /ogrepository/v1/images/virtual`
|
||||
21. [Renombrar una Imagen](#renombrar-una-imagen) - `POST /ogrepository/v1/images/rename`
|
||||
22. [Crear archivos auxiliares](#crear-archivos-auxiliares) - `POST /ogrepository/v1/images/torrentsum`
|
||||
23. [Enviar paquete Wake On Lan](#enviar-paquete-wake-on-lan) - `POST /ogrepository/v1/wol`
|
||||
|
||||
---
|
||||
### Obtener Información de Estado de ogRepository
|
||||
|
||||
Se devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato JSON.
|
||||
Se devolverá informacion de CPU, memoria RAM, disco duro, el estado de ciertos servicios y procesos de ogRepository, y el estado de instalación de ogGit, en formato JSON.
|
||||
Se puede utilizar el script "**getRepoStatus.py**, que debe ser llamado por el endpoint.
|
||||
**NOTA**: En los apartados "services" y "processes" he especificado los servicios y procesos que me han parecido interesantes, pero se puede añadir o eliminar los que se desee.
|
||||
|
||||
|
@ -93,6 +100,9 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
- **Contenido:** Información de estado en formato JSON.
|
||||
```json
|
||||
{
|
||||
"oggit": {
|
||||
"installed": "True"
|
||||
},
|
||||
"cpu": {
|
||||
"used_percentage": "35%"
|
||||
},
|
||||
|
@ -359,6 +369,210 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/t
|
|||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se eliminó exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UDPcast
|
||||
|
||||
Se enviará la imagen especificada por Multicast, mediante la aplicación UDPcast.
|
||||
Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binario "**udp-sender**", que es quien realmente realiza el envío.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **method**: Modalidad half-duplex o full-duplex ("half" o "full").
|
||||
- **ip**: IP Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (en Mbps).
|
||||
- **nclients**: Número mínimo de clientes.
|
||||
- **maxtime**: Tiempo máximo de espera.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UDPcast.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UDPcast
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UDPcast activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUDPcastInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UDPcast.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UDPcast activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UDPcast activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UDPcast activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"6720": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"6721": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UDPcast
|
||||
|
||||
Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUDPcast.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UDPcast.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UDPcast activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UDPcast se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UFTP
|
||||
|
||||
Se enviará la imagen especificada por Unicast o Multicast, mediante el protocolo "UFTP".
|
||||
Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente los clientes ogLive destino se pongan en escucha con un daemon "UFTPD" (ejecutando el script "**listenUFTPD.py**"). Esto funciona al revés que "UDPcast", ya que primero se debe ejecutar un comando en los clientes, y luego en el servidor.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **ip**: IP Unicast/Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (con "K" para Kbps, "M" para Mbps o "G" para Gbps).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UFTP.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UFTP
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UFTP activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUFTPInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UFTP.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UFTP activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UFTP activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UFTP activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"3427": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"4966": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UFTP
|
||||
|
||||
Se cancelará la transmisión por UFTP activa de la imagen especificada como parámetro, deteniendo el proceso "uftp" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUFTP.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UFTP.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UFTP activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UFTP se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante P2P
|
||||
|
||||
Se enviará la imagen especificada mediante "P2P", iniciando el tracker y el seeder (que harán tracking y seed de los torrents contenidos en el directorio de imágenes).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts no reciben parámetros, pero es necesario que el endpoint compruebe si la imagen a enviar existe antes de llamarlos, por lo que se le debe enviar el ID de la imagen (que corresponde al contenido del archivo "full.sum") desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d"}' http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al intentar enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante P2P.
|
||||
|
||||
---
|
||||
### Cancelar Transmisiones P2P
|
||||
|
||||
Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado".
|
||||
Se puede hacer con el script "**stopP2P.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado.
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones P2P.
|
||||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Transferir una Imagen entre Repositorios
|
||||
|
||||
|
@ -382,9 +596,9 @@ Se puede hacer con el script "**importImage.py**", que debe ser llamado por el e
|
|||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "repo_ip":"192.168.56.100", "user":"opengnsys"}' http://example.com/ogrepository/v1/repo/images
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al importar la imagen.
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al transferir la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se está importando.
|
||||
- **Código 200 OK:** La imagen se está transfiriendo.
|
||||
|
||||
---
|
||||
### Hacer Backup de una Imagen
|
||||
|
@ -410,9 +624,83 @@ Se puede hacer con el script "**backupImage.py**", que debe ser llamado por el e
|
|||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "repo_ip":"192.168.56.100", "user":"opengnsys", "remote_path":"/home/opengnsys"}' http://example.com/ogrepository/v1/repo/images
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al exportar la imagen.
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al hacer backup de la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se ha exportando exitosamente.
|
||||
- **Código 200 OK:** Se está haciendo backup de la imagen.
|
||||
|
||||
---
|
||||
### Convertir Imagen Virtual a Imagen OpenGnsys
|
||||
|
||||
Se convertirá la imagen virtual especificada (que debe haberse copiado previamente en la ruta "opt/opengnsys/ogrepository/images_virtual") en una imagen "img" como las que se generan desde OpenGnsys (con "partclone" y "lzop").
|
||||
Se puede hacer con el script "**convertVMtoIMG.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen virtual (con extensión) como primer parámetro, y el sistema de archivos de la partición a clonar como segundo parámetro (en formato "blkid"). Estos parámetros deben enviarse desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen virtual se está convirtiendo, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/virtual`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **virtual_image**: Nombre de la imagen virtual (con extensión).
|
||||
- **filesystem**: Sistema de archivos de la partición a clonar, en formato "blkid".
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"virtual_image":"UbuntuVM.vdi", "filesystem":"ext4"}' http://example.com/ogrepository/v1/images/virtual
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al convertir la imagen virtual.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen virtual especificada.
|
||||
- **Código 200 OK:** La imagen virtual se está convirtiendo.
|
||||
|
||||
---
|
||||
### Convertir Imagen OpenGnsys a Imagen Virtual
|
||||
|
||||
Se convertirá la imagen "img" especificada en una imagen virtual con la extensión especificada ("vdi", "vmdk", etc), guardándola en la ruta "opt/opengnsys/ogrepository/images_virtual/export".
|
||||
Se puede hacer con el script "**convertIMGtoVM.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y la extensión del disco virtual destino ("vdi", "vmdk", etc) como segundo parámetro. El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero la extensión del disco virtual debe enviarse en el JSON.
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está convirtiendo a virtual, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/virtual`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **vm_extension**: Extensión del disco virtual destino ("vdi", "vmdk", etc).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "vm_extension":"vdi"}' http://example.com/ogrepository/v1/images/virtual
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al convertir la imagen a virtual.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está convirtiendo a virtual.
|
||||
|
||||
---
|
||||
### Renombrar una Imagen
|
||||
|
||||
Se renombrará la imagen especificada como primer parámetro (y todos sus archivos asociados), asignando el nombre especificado como segundo parámetro.
|
||||
Se puede hacer con el script "**renameImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (sin extensión) como primer parámetro, y el nuevo nombre a asignar como segundo parámetro. El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero el nuevo nombre a asignar debe enviarse en el JSON.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/rename`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **image_new_name**: Nuevo nombre a asignar a la imagen.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "image_new_name":"Ubuntu_BKP"}' http://example.com/ogrepository/v1/images/rename
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al renombrar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se ha renombrado exitosamente.
|
||||
|
||||
---
|
||||
### Crear archivos auxiliares
|
||||
|
@ -461,209 +749,4 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar el paquete Wake On Lan.
|
||||
- **Código 200 OK:** El paquete Wake On Lan se ha enviado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UDPcast
|
||||
|
||||
Se enviará la imagen especificada por Multicast, mediante la aplicación UDPcast.
|
||||
Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binario "**udp-sender**", que es quien realmente realiza el envío.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **method**: Modalidad half-duplex o full-duplex ("half" o "full").
|
||||
- **ip**: IP Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (en Mbps).
|
||||
- **nclients**: Número mínimo de clientes.
|
||||
- **maxtime**: Tiempo máximo de espera.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UDPcast.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UFTP
|
||||
|
||||
Se enviará la imagen especificada por Unicast o Multicast, mediante el protocolo "UFTP".
|
||||
Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente los clientes ogLive destino se pongan en escucha con un daemon "UFTPD" (ejecutando el script "**listenUFTPD.py**"). Esto funciona al revés que "UDPcast", ya que primero se debe ejecutar un comando en los clientes, y luego en el servidor.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **ip**: IP Unicast/Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (con "K" para Kbps, "M" para Mbps o "G" para Gbps).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UFTP.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante P2P
|
||||
|
||||
Se enviará la imagen especificada mediante "P2P", iniciando el tracker y el seeder (que harán tracking y seed de los torrents contenidos en el directorio de imágenes).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts no reciben parámetros, pero es necesario que el endpoint compruebe si la imagen a enviar existe antes de llamarlos, por lo que se le debe enviar el ID de la imagen (que corresponde al contenido del archivo "full.sum") desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d"}' http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al intentar enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante P2P.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UDPcast
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UDPcast activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUDPcastInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UDPcast.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UDPcast activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UDPcast activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UDPcast activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"6720": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"6721": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Ver Estado de Transmisiones UFTP
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UFTP activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUFTPInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UFTP.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UFTP activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UFTP activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UFTP activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"3427": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"4966": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UDPcast
|
||||
|
||||
Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUDPcast.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UDPcast.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UDPcast activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UDPcast se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Cancelar Transmisión UFTP
|
||||
|
||||
Se cancelará la transmisión por UFTP activa de la imagen especificada como parámetro, deteniendo el proceso "uftp" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUFTP.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UFTP.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UFTP activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UFTP se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Cancelar Transmisiones P2P
|
||||
|
||||
Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado".
|
||||
Se puede hacer con el script "**stopP2P.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado.
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones P2P.
|
||||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
521
api/README.md
521
api/README.md
|
@ -16,23 +16,26 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará
|
|||
6. [Eliminar una Imagen](#eliminar-una-imagen) - `DELETE /ogrepository/v1/images/{ID_img}?method={method}`
|
||||
7. [Recuperar una Imagen](#recuperar-una-imagen) - `POST /ogrepository/v1/trash/images`
|
||||
8. [Eliminar una Imagen de la Papelera](#eliminar-una-imagen-de-la-papelera) - `DELETE /ogrepository/v1/trash/images/{ID_img}`
|
||||
9. [Transferir una Imagen entre Repositorios](#transferir-una-imagen-entre-repositorios) - `POST /ogrepository/v1/repo/images`
|
||||
10. [Hacer Backup de una Imagen](#hacer-backup-de-una-imagen) - `PUT /ogrepository/v1/repo/images`
|
||||
11. [Crear archivos auxiliares](#crear-archivos-auxiliares) - `POST /ogrepository/v1/images/torrentsum`
|
||||
12. [Enviar paquete Wake On Lan](#enviar-paquete-wake-on-lan) - `POST /ogrepository/v1/wol`
|
||||
13. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast`
|
||||
14. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp`
|
||||
9. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast`
|
||||
10. [Ver Estado de Transmisiones UDPcast](#ver-estado-de-transmisiones-udpcast) - `GET /ogrepository/v1/udpcast`
|
||||
11. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}`
|
||||
12. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp`
|
||||
13. [Ver Estado de Transmisiones UFTP](#ver-estado-de-transmisiones-uftp) - `GET /ogrepository/v1/uftp`
|
||||
14. [Cancelar Transmisión UFTP](#cancelar-transmisión-uftp) - `DELETE /ogrepository/v1/uftp/images/{ID_img}`
|
||||
15. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/p2p`
|
||||
16. [Ver Estado de Transmisiones UDPcast](#ver-estado-de-transmisiones-udpcast) - `GET /ogrepository/v1/udpcast`
|
||||
17. [Ver Estado de Transmisiones UFTP](#ver-estado-de-transmisiones-uftp) - `GET /ogrepository/v1/uftp`
|
||||
18. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}`
|
||||
19. [Cancelar Transmisión UFTP](#cancelar-transmisión-uftp) - `DELETE /ogrepository/v1/uftp/images/{ID_img}`
|
||||
20. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p`
|
||||
16. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p`
|
||||
17. [Transferir una Imagen entre Repositorios](#transferir-una-imagen-entre-repositorios) - `POST /ogrepository/v1/repo/images`
|
||||
18. [Hacer Backup de una Imagen](#hacer-backup-de-una-imagen) - `PUT /ogrepository/v1/repo/images`
|
||||
19. [Convertir Imagen Virtual a Imagen OpenGnsys](#convertir-imagen-virtual-a-imagen-opengnsys) - `POST /ogrepository/v1/images/virtual`
|
||||
20. [Convertir Imagen OpenGnsys a Imagen Virtual](#convertir-imagen-opengnsys-a-imagen-virtual) - `PUT /ogrepository/v1/images/virtual`
|
||||
21. [Renombrar una Imagen](#renombrar-una-imagen) - `POST /ogrepository/v1/images/rename`
|
||||
22. [Crear archivos auxiliares](#crear-archivos-auxiliares) - `POST /ogrepository/v1/images/torrentsum`
|
||||
23. [Enviar paquete Wake On Lan](#enviar-paquete-wake-on-lan) - `POST /ogrepository/v1/wol`
|
||||
|
||||
---
|
||||
### Obtener Información de Estado de ogRepository
|
||||
|
||||
Se devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato JSON.
|
||||
Se devolverá informacion de CPU, memoria RAM, disco duro, el estado de ciertos servicios y procesos de ogRepository, y el estado de instalación de ogGit, en formato JSON.
|
||||
Se puede utilizar el script "**getRepoStatus.py**, que debe ser llamado por el endpoint.
|
||||
**NOTA**: En los apartados "services" y "processes" he especificado los servicios y procesos que me han parecido interesantes, pero se puede añadir o eliminar los que se desee.
|
||||
|
||||
|
@ -51,6 +54,9 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
- **Contenido:** Información de estado en formato JSON.
|
||||
```json
|
||||
{
|
||||
"oggit": {
|
||||
"installed": "True"
|
||||
},
|
||||
"cpu": {
|
||||
"used_percentage": "35%"
|
||||
},
|
||||
|
@ -317,6 +323,210 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/t
|
|||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se eliminó exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UDPcast
|
||||
|
||||
Se enviará la imagen especificada por Multicast, mediante la aplicación UDPcast.
|
||||
Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binario "**udp-sender**", que es quien realmente realiza el envío.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **method**: Modalidad half-duplex o full-duplex ("half" o "full").
|
||||
- **ip**: IP Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (en Mbps).
|
||||
- **nclients**: Número mínimo de clientes.
|
||||
- **maxtime**: Tiempo máximo de espera.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UDPcast.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UDPcast
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UDPcast activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUDPcastInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UDPcast.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UDPcast activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UDPcast activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UDPcast activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"6720": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"6721": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UDPcast
|
||||
|
||||
Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUDPcast.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UDPcast.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UDPcast activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UDPcast se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UFTP
|
||||
|
||||
Se enviará la imagen especificada por Unicast o Multicast, mediante el protocolo "UFTP".
|
||||
Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente los clientes ogLive destino se pongan en escucha con un daemon "UFTPD" (ejecutando el script "**listenUFTPD.py**"). Esto funciona al revés que "UDPcast", ya que primero se debe ejecutar un comando en los clientes, y luego en el servidor.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **ip**: IP Unicast/Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (con "K" para Kbps, "M" para Mbps o "G" para Gbps).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UFTP.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UFTP
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UFTP activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUFTPInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UFTP.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UFTP activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UFTP activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UFTP activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"3427": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"4966": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UFTP
|
||||
|
||||
Se cancelará la transmisión por UFTP activa de la imagen especificada como parámetro, deteniendo el proceso "uftp" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUFTP.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UFTP.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UFTP activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UFTP se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante P2P
|
||||
|
||||
Se enviará la imagen especificada mediante "P2P", iniciando el tracker y el seeder (que harán tracking y seed de los torrents contenidos en el directorio de imágenes).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts no reciben parámetros, pero es necesario que el endpoint compruebe si la imagen a enviar existe antes de llamarlos, por lo que se le debe enviar el ID de la imagen (que corresponde al contenido del archivo "full.sum") desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d"}' http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al intentar enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante P2P.
|
||||
|
||||
---
|
||||
### Cancelar Transmisiones P2P
|
||||
|
||||
Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado".
|
||||
Se puede hacer con el script "**stopP2P.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado.
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones P2P.
|
||||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Transferir una Imagen entre Repositorios
|
||||
|
||||
|
@ -340,9 +550,9 @@ Se puede hacer con el script "**importImage.py**", que debe ser llamado por el e
|
|||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "repo_ip":"192.168.56.100", "user":"opengnsys"}' http://example.com/ogrepository/v1/repo/images
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al importar la imagen.
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al transferir la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se está importando.
|
||||
- **Código 200 OK:** La imagen se está transfiriendo.
|
||||
|
||||
---
|
||||
### Hacer Backup de una Imagen
|
||||
|
@ -368,9 +578,83 @@ Se puede hacer con el script "**backupImage.py**", que debe ser llamado por el e
|
|||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "repo_ip":"192.168.56.100", "user":"opengnsys", "remote_path":"/home/opengnsys"}' http://example.com/ogrepository/v1/repo/images
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al exportar la imagen.
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al hacer backup de la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se ha exportando exitosamente.
|
||||
- **Código 200 OK:** Se está haciendo backup de la imagen.
|
||||
|
||||
---
|
||||
### Convertir Imagen Virtual a Imagen OpenGnsys
|
||||
|
||||
Se convertirá la imagen virtual especificada (que debe haberse copiado previamente en la ruta "opt/opengnsys/ogrepository/images_virtual") en una imagen "img" como las que se generan desde OpenGnsys (con "partclone" y "lzop").
|
||||
Se puede hacer con el script "**convertVMtoIMG.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen virtual (con extensión) como primer parámetro, y el sistema de archivos de la partición a clonar como segundo parámetro (en formato "blkid"). Estos parámetros deben enviarse desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen virtual se está convirtiendo, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/virtual`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **virtual_image**: Nombre de la imagen virtual (con extensión).
|
||||
- **filesystem**: Sistema de archivos de la partición a clonar, en formato "blkid".
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"virtual_image":"UbuntuVM.vdi", "filesystem":"ext4"}' http://example.com/ogrepository/v1/images/virtual
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al convertir la imagen virtual.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen virtual especificada.
|
||||
- **Código 200 OK:** La imagen virtual se está convirtiendo.
|
||||
|
||||
---
|
||||
### Convertir Imagen OpenGnsys a Imagen Virtual
|
||||
|
||||
Se convertirá la imagen "img" especificada en una imagen virtual con la extensión especificada ("vdi", "vmdk", etc), guardándola en la ruta "opt/opengnsys/ogrepository/images_virtual/export".
|
||||
Se puede hacer con el script "**convertIMGtoVM.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y la extensión del disco virtual destino ("vdi", "vmdk", etc) como segundo parámetro. El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero la extensión del disco virtual debe enviarse en el JSON.
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está convirtiendo a virtual, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/virtual`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **vm_extension**: Extensión del disco virtual destino ("vdi", "vmdk", etc).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "vm_extension":"vdi"}' http://example.com/ogrepository/v1/images/virtual
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al convertir la imagen a virtual.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está convirtiendo a virtual.
|
||||
|
||||
---
|
||||
### Renombrar una Imagen
|
||||
|
||||
Se renombrará la imagen especificada como primer parámetro (y todos sus archivos asociados), asignando el nombre especificado como segundo parámetro.
|
||||
Se puede hacer con el script "**renameImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (sin extensión) como primer parámetro, y el nuevo nombre a asignar como segundo parámetro. El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero el nuevo nombre a asignar debe enviarse en el JSON.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/rename`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **image_new_name**: Nuevo nombre a asignar a la imagen.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "image_new_name":"Ubuntu_BKP"}' http://example.com/ogrepository/v1/images/rename
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al renombrar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se ha renombrado exitosamente.
|
||||
|
||||
---
|
||||
### Crear archivos auxiliares
|
||||
|
@ -419,209 +703,4 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar el paquete Wake On Lan.
|
||||
- **Código 200 OK:** El paquete Wake On Lan se ha enviado exitosamente.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UDPcast
|
||||
|
||||
Se enviará la imagen especificada por Multicast, mediante la aplicación UDPcast.
|
||||
Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binario "**udp-sender**", que es quien realmente realiza el envío.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **method**: Modalidad half-duplex o full-duplex ("half" o "full").
|
||||
- **ip**: IP Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (en Mbps).
|
||||
- **nclients**: Número mínimo de clientes.
|
||||
- **maxtime**: Tiempo máximo de espera.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UDPcast.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante UFTP
|
||||
|
||||
Se enviará la imagen especificada por Unicast o Multicast, mediante el protocolo "UFTP".
|
||||
Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente los clientes ogLive destino se pongan en escucha con un daemon "UFTPD" (ejecutando el script "**listenUFTPD.py**"). Esto funciona al revés que "UDPcast", ya que primero se debe ejecutar un comando en los clientes, y luego en el servidor.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y los datos de transferencia como segundo parámetro (en una cadena, con los datos separados por dos puntos). El primer parámetro se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), pero los datos de transferencia deben enviarse desde ogCore (y luego son tratados en la API, para construir la cadena correspondiente al parámetro).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **port**: Puerto Multicast.
|
||||
- **ip**: IP Unicast/Multicast.
|
||||
- **bitrate**: Velocidad de transmisión (con "K" para Kbps, "M" para Mbps o "G" para Gbps).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante UFTP.
|
||||
|
||||
---
|
||||
### Enviar una Imagen mediante P2P
|
||||
|
||||
Se enviará la imagen especificada mediante "P2P", iniciando el tracker y el seeder (que harán tracking y seed de los torrents contenidos en el directorio de imágenes).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts no reciben parámetros, pero es necesario que el endpoint compruebe si la imagen a enviar existe antes de llamarlos, por lo que se le debe enviar el ID de la imagen (que corresponde al contenido del archivo "full.sum") desde ogCore (en el JSON).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está enviando, y abre un proceso paralelo (pero no avisa a ogCore de su finalización, porque no puede comprobar cuando acaba la tarea de restauración de la imagen).
|
||||
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d"}' http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al intentar enviar la imagen.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** La imagen se está enviando mediante P2P.
|
||||
|
||||
---
|
||||
### Ver Estado de Transmisiones UDPcast
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UDPcast activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUDPcastInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UDPcast.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UDPcast activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UDPcast activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UDPcast activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"6720": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"6721": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Ver Estado de Transmisiones UFTP
|
||||
|
||||
Se devolverá el pid de los procesos de transferencias UFTP activas, y sus imágenes asociadas (con nombre e ID), en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
|
||||
Se puede hacer con el script "**getUFTPInfo.py**", que debe ser llamado por el endpoint.
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp`
|
||||
**Método HTTP:** GET
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UFTP.
|
||||
- **Código 400 Bad Request:** No se han encontrado transmisiones UFTP activas.
|
||||
- **Código 200 OK:** La información de las transmisiones UFTP activas se obtuvo exitosamente.
|
||||
- **Contenido:** Información de las transmisiones UFTP activas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"3427": {
|
||||
"image_id": "22735b9070e4a8043371b8c6ae52b90d",
|
||||
"image_name": "Ubuntu20.img"
|
||||
},
|
||||
"4966": {
|
||||
"image_id": "9e7cd32c606ebe5bd39ba212ce7aeb02",
|
||||
"image_name": "Windows10.img"
|
||||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### Cancelar Transmisión UDPcast
|
||||
|
||||
Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUDPcast.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/udpcast/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UDPcast.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UDPcast activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UDPcast se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Cancelar Transmisión UFTP
|
||||
|
||||
Se cancelará la transmisión por UFTP activa de la imagen especificada como parámetro, deteniendo el proceso "uftp" asociado a dicha imagen.
|
||||
Se puede hacer con el script "**stopUFTP.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
|
||||
**URL:** `/ogrepository/v1/uftp/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp/images/22735b9070e4a8043371b8c6ae52b90d
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar la transmisión UFTP.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 400 Bad Request:** No hay transmisiones UFTP activas para la imagen especificada.
|
||||
- **Código 200 OK:** La transmisión UFTP se ha cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Cancelar Transmisiones P2P
|
||||
|
||||
Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado".
|
||||
Se puede hacer con el script "**stopP2P.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado.
|
||||
|
||||
**URL:** `/ogrepository/v1/p2p`
|
||||
**Método HTTP:** DELETE
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p2p
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones P2P.
|
||||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
1290
api/repo_api.py
1290
api/repo_api.py
File diff suppressed because it is too large
Load Diff
875
api/swagger.yaml
875
api/swagger.yaml
|
@ -4,7 +4,7 @@ info:
|
|||
version: "1.0"
|
||||
description: |
|
||||
---
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Esto hace que el Swagger se ordene por los tags (apartados), de la forma especificada:
|
||||
|
@ -16,8 +16,9 @@ tags:
|
|||
- name: "Transferencia de Imágenes (UFTP)"
|
||||
- name: "Transferencia de Imágenes (P2P)"
|
||||
- name: "Transferencia entre Repositorios y Backup"
|
||||
- name: "Importar y Exportar Máquinas Virtuales"
|
||||
- name: "Varios"
|
||||
|
||||
- name: "Git"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Apartado "Estado de ogRepository"
|
||||
|
@ -29,7 +30,7 @@ paths:
|
|||
summary: "Obtener Información de Estado de ogRepository"
|
||||
description: >
|
||||
Este endpoint ejecuta el script "**getRepoStatus.py**" y devuelve su salida en formato JSON,
|
||||
incluyendo información sobre la CPU, memoria RAM, disco duro, servicios, y procesos específicos de ogRepository.
|
||||
incluyendo información sobre la CPU, memoria RAM, disco duro, servicios, y procesos específicos de ogRepository, e instalación de ogGit.
|
||||
tags:
|
||||
- "Estado de ogRepository"
|
||||
responses:
|
||||
|
@ -44,6 +45,12 @@ paths:
|
|||
output:
|
||||
type: object
|
||||
properties:
|
||||
oggit:
|
||||
type: object
|
||||
properties:
|
||||
installed:
|
||||
type: string
|
||||
example: "True"
|
||||
cpu:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -133,14 +140,14 @@ paths:
|
|||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Apartado "Información de Imágenes"
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/ogrepository/v1/images:
|
||||
put:
|
||||
summary: "Actualizar Información del Repositorio"
|
||||
description: |
|
||||
Este endpoint actualiza la información de las imágenes almacenadas en el repositorio, reflejándola en los archivos "**repoinfo.json**" y "**trashinfo.json**".
|
||||
Utiliza el script "**updateRepoInfo.py**", que a su vez llama al script "**updateTrashInfo.py**", para actualizar también la información de la papelera.
|
||||
|
||||
|
||||
No hace falta que se le llame al crear o exportar una imagen, ya que lo llama el endpoint "**Crear archivos auxiliares**" (que sí debe ser llamado en esos casos).
|
||||
tags:
|
||||
- "Información de Imágenes"
|
||||
|
@ -185,7 +192,7 @@ paths:
|
|||
get:
|
||||
summary: "Obtener Información de todas las Imágenes"
|
||||
description: |
|
||||
Este endpoint ejecuta el script "**getRepoInfo.py**" con el parámetro "**all**", para devolver información de todas las imágenes almacenadas en el repositorio y en la papelera, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
Este endpoint ejecuta el script "**getRepoInfo.py**" con el parámetro "**all**", para devolver información de todas las imágenes almacenadas en el repositorio y en la papelera, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
Devuelve detalles como el nombre de la imagen, tipo, nombre del cliente, clonador, compresor, sistema de archivos, tamaño de los datos, tamaño de la imagen, y hashes MD5.
|
||||
tags:
|
||||
- "Información de Imágenes"
|
||||
|
@ -1250,7 +1257,7 @@ paths:
|
|||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#/ogrepository/v1/p2p:
|
||||
#/ogrepository/v1/p2p:
|
||||
delete:
|
||||
summary: "Cancelar Transmisiones P2P"
|
||||
description: |
|
||||
|
@ -1304,10 +1311,10 @@ paths:
|
|||
Este endpoint importa la imagen especificada desde un repositorio remoto al repositorio local (en el que se ejecuta el endpoint).
|
||||
Utiliza el script "**importImage.py**", que recibe como parámetros el nombre de la imagen, la IP o hostname del servidor remoto, y el usuario con el que conectar al servidor remoto.
|
||||
que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
|
||||
|
||||
**NOTA**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está importando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
tags:
|
||||
- "Transferencia entre Repositorios y Backup"
|
||||
- "Transferencia entre Repositorios y Backup"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
|
@ -1332,7 +1339,7 @@ paths:
|
|||
example: "user_name"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen se está importando."
|
||||
description: "La imagen se está transfiriendo."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1429,7 +1436,7 @@ paths:
|
|||
* **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum'
|
||||
* **repo_ip** - Dirección IP del servidor remoto
|
||||
* **user** - Usuario con el que conectar al servidor remoto
|
||||
* **remote_path** - Ruta remota en la que copiar la imagen
|
||||
* **remote_path** - Ruta remota en la que copiar la imagen
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1450,7 +1457,7 @@ paths:
|
|||
example: "/home/opengnsys"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen se está copiando."
|
||||
description: "Se está haciendo backup de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1493,17 +1500,6 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Can't connect to remote host"
|
||||
"400 (Image present)":
|
||||
description: "La imagen ya existe en el equipo remoto."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Image already exists on remote host"
|
||||
"500 (Error)":
|
||||
description: "Error al copiar la imagen."
|
||||
schema:
|
||||
|
@ -1527,6 +1523,224 @@ paths:
|
|||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Apartado "Importar y Exportar a Máquinas Virtuales"
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
/ogrepository/v1/images/virtual:
|
||||
post:
|
||||
summary: "Convertir Imagen Virtual a Imagen OpenGnsys"
|
||||
description: |
|
||||
Este endpoint convierte la imagen virtual especificada como primer parámetro en una imagen "img" como las que se generan desde OpenGnsys, debiendo haberse copiado previamente en la ruta "opt/opengnsys/ogrepository/images_virtual".
|
||||
Utiliza el script "**convertVMtoIMG.py**", que recibe como parámetros el nombre de la imagen virtual, y el sistema de archivos de la partición a clonar (en formato "blkid").
|
||||
Se puede comprobar todos los sistemas de archivos aceptados por "blkid" ejecutando el comando "blkid -k".
|
||||
|
||||
**NOTA**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen virtual se está convirtiendo, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
tags:
|
||||
- "Importar y Exportar Máquinas Virtuales"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **virtual_image** - Nombre de la imagen virtual, con extensión
|
||||
* **filesystem** - Sistema de archivos de la partición a clonar, en formato "blkid"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
virtual_image:
|
||||
type: string
|
||||
example: "UbuntuVM.vdi"
|
||||
filesystem:
|
||||
type: string
|
||||
example: "ext4"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen virtual se está convirtiendo."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: true
|
||||
output:
|
||||
type: string
|
||||
example: "Converting virtual image..."
|
||||
"400 (Virtual image not found)":
|
||||
description: "No se ha encontrado la imagen virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Virtual image not found"
|
||||
"400 (Name incorrect)":
|
||||
description: "Ya existe una imagen con el mismo nombre que la imagen virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "There is an image with the same name as the virtual image"
|
||||
"400 (No disk space)":
|
||||
description: "No hay espacio suficiente en disco."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "There is not enough free disk space"
|
||||
"500":
|
||||
description: "Error al convertir la imagen virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "Virtual image conversion failed"
|
||||
"500 (Error)":
|
||||
description: "Error al convertir la imagen virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "(Error description)"
|
||||
"500 (Exception)":
|
||||
description: "Excepción inesperada al convertir la imagen virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#/ogrepository/v1/images/virtual:
|
||||
put:
|
||||
summary: "Convertir Imagen OpenGnsys a Imagen Virtual"
|
||||
description: |
|
||||
Este endpoint convierte la imagen "img" especificada como primer parámetro en una imagen virtual con la extensión especificada como segundo parámetro ("vdi", "vmdk", etc), guardándola en la ruta "opt/opengnsys/ogrepository/images_virtual/export".
|
||||
Utiliza el script "**convertIMGtoVM.py**", que recibe como parámetros el nombre de la imagen, y la extensión del disco virtual destino ("vdi", "vmdk", etc).
|
||||
|
||||
**NOTA**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está convirtiendo a virtual, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
tags:
|
||||
- "Importar y Exportar Máquinas Virtuales"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum'
|
||||
* **vm_extension** - Extensión del disco virtual destino ("vdi", "vmdk", etc)
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ID_img:
|
||||
type: string
|
||||
example: "22735b9070e4a8043371b8c6ae52b90d"
|
||||
vm_extension:
|
||||
type: string
|
||||
example: "vdi"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen se está convirtiendo a virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: true
|
||||
output:
|
||||
type: string
|
||||
example: "Converting image to virtual..."
|
||||
"400 (Image not found)":
|
||||
description: "No se ha encontrado la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
"400 (Name incorrect)":
|
||||
description: "Ya existe una imagen virtual exportada con el mismo nombre que la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "There is an exported virtual image with the same name as the image"
|
||||
"400 (No disk space)":
|
||||
description: "No hay espacio suficiente en disco."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "There is not enough free disk space"
|
||||
"500":
|
||||
description: "Error al convertir la imagen a virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "Image conversion to virtual failed"
|
||||
"500 (Error)":
|
||||
description: "Error al convertir la imagen a virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "(Error description)"
|
||||
"500 (Exception)":
|
||||
description: "Excepción inesperada al convertir la imagen a virtual."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Apartado "Varios"
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
@ -1578,17 +1792,6 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
"400 (Image locked)":
|
||||
description: "La imagen está bloqueada."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Image is locked"
|
||||
"500 (Error)":
|
||||
description: "Error al crear los archivos auxiliares."
|
||||
schema:
|
||||
|
@ -1674,3 +1877,607 @@ paths:
|
|||
example: "(Exception description)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
/ogrepository/v1/images/rename:
|
||||
put:
|
||||
summary: "Renombrar una Imagen"
|
||||
description: |
|
||||
Este endpoint renombra la imagen especificada como primer parámetro (y todos sus archivos asociados), asignando el nombre especificado como segundo parámetro.
|
||||
Utiliza el script "**renameImage.py**", que recibe como parámetros el nombre original y el nuevo nombre a asignar.
|
||||
tags:
|
||||
- "Varios"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum'
|
||||
* **image_new_name** - Nuevo nombre a asignar a la imagen
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ID_img:
|
||||
type: string
|
||||
example: "22735b9070e4a8043371b8c6ae52b90d"
|
||||
image_new_name:
|
||||
type: string
|
||||
example: "Ubuntu_BKP"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen se ha renombrado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: true
|
||||
output:
|
||||
type: string
|
||||
example: "Image renamed successfully"
|
||||
"400 (Image not found)":
|
||||
description: "No se ha encontrado la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
"400 (Name incorrect)":
|
||||
description: "Ya existe una imagen con el nombre a asignar."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "There is an image with the name to assign"
|
||||
"500 (Error)":
|
||||
description: "Error al renombrar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "(Error description)"
|
||||
"500 (Exception)":
|
||||
description: "Excepción inesperada al renombrar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# ____ _ _
|
||||
# / ___(_) |_
|
||||
# | | _| | __|
|
||||
# | |_| | | |_
|
||||
# \____|_|\__|
|
||||
#
|
||||
# -----------------------------------------------------------
|
||||
|
||||
/ogrepository/v1/git/ssh_key:
|
||||
post:
|
||||
summary: "Agregar clave de SSH de ogLive"
|
||||
description: |
|
||||
Agrega una clave de SSH que va a usarse desde el ogLive
|
||||
para interactuar con Git.
|
||||
|
||||
Es necesario especificar **ssh_key** o **oglive**.
|
||||
|
||||
Especificando **ssh_key** se agrega la cclave especificada directamente.
|
||||
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **ssh_key** - Clave de SSH (opcional)
|
||||
* **oglive** - URL a ogLive (opcional, NO USAR DE MOMENTO)
|
||||
* **description** - Descripcion (opcional)
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
ssh_key:
|
||||
type: string
|
||||
example: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINEOttwhJ+9THRZ1Zv/6QUwPUDq1X7opG9V7EFLVWxQV"
|
||||
required: False
|
||||
description:
|
||||
type: string
|
||||
example: "OgLive r20250518"
|
||||
required: False
|
||||
responses:
|
||||
"200":
|
||||
description: "Exito"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: True
|
||||
required: True
|
||||
output:
|
||||
type: string
|
||||
example: "SSH key added"
|
||||
required: True
|
||||
job_id:
|
||||
type: string
|
||||
example: "GitSshKey_873f353f"
|
||||
required: False
|
||||
|
||||
/ogrepository/v1/git/repositories:
|
||||
get:
|
||||
summary: "Obtener lista de repositorios"
|
||||
description: |
|
||||
Devuelve una lista de repositorios de Git
|
||||
tags:
|
||||
- "Git"
|
||||
responses:
|
||||
"200":
|
||||
description: "Lista de repositorios"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
repositories:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: linux
|
||||
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
post:
|
||||
summary: "Crear repositorio"
|
||||
description: |
|
||||
Crea un repositorio nuevo de Git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **name** - Nombre de repositorio
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: linux
|
||||
responses:
|
||||
"201":
|
||||
description: "Repositorio creado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: "Repository created"
|
||||
"500 (Exception)":
|
||||
description: "JSON post data missing"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Parameters missing"
|
||||
/ogrepository/v1/git/repositories/{repository}/tags:
|
||||
get:
|
||||
summary: "Obtener lista de tags"
|
||||
description: |
|
||||
Devuelve una lista de tags de Git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Lista de tags"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: v0.1
|
||||
commit:
|
||||
type: string
|
||||
example: db8e84d5d2548f589ee503c1c6d5003cc6a0d803
|
||||
committer:
|
||||
type: string
|
||||
example: John Smith
|
||||
committed_datetime:
|
||||
type: int
|
||||
example: 1745360193
|
||||
message:
|
||||
type: string
|
||||
example: "Initial release"
|
||||
required: False
|
||||
tagged_date:
|
||||
type: int
|
||||
example: 1745360194
|
||||
required: False
|
||||
tagger:
|
||||
type: string
|
||||
example: John Smith
|
||||
required: False
|
||||
tagger_tz_offset:
|
||||
type: int
|
||||
example: -7200
|
||||
required: False
|
||||
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
post:
|
||||
summary: "Crear tag"
|
||||
description: |
|
||||
Crea una tag de git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **name** - Nombre del tag
|
||||
* **commit** - Commit al que apunta el tag nuevo. Puede ser un nombre de otra rama/tag.
|
||||
* **message** - Mensaje descriptivo para el tag. Opcional, si no se especifica se asume una cadena vacía.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: v1.0
|
||||
required: True
|
||||
commit:
|
||||
type: string
|
||||
example: HEAD
|
||||
required: True
|
||||
message:
|
||||
type: string
|
||||
example: Version 1.0
|
||||
required: False
|
||||
responses:
|
||||
"201":
|
||||
description: "Tag creado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: created
|
||||
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
"404":
|
||||
description: "El repositorio no existe"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Repository not found"
|
||||
"409":
|
||||
description: "El tag ya existe"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Tag already exists"
|
||||
delete:
|
||||
summary: "Eliminar tag"
|
||||
description: |
|
||||
Elimina un tag de git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: tag
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Rama del repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Tag eliminado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: deleted
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
/ogrepository/v1/git/repositories/{repository}/branches/{branch}/commits:
|
||||
get:
|
||||
summary: "Obtener lista de commits en una rama"
|
||||
description: |
|
||||
Devuelve una lista de commits de Git.
|
||||
|
||||
**Filtrado de commits:**
|
||||
Por defecto algunos commits que no son utiles para restaurar una imagen se ocultan.
|
||||
Pasar filter_commits=0 para desactivar esta funcionalidad y ver todos los commits
|
||||
del repositorio.
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: branch
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Rama dentro del repositorio"
|
||||
- name: max_commits
|
||||
in: query
|
||||
required: false
|
||||
type: int
|
||||
description: "Máximo de commits a obtener"
|
||||
- name: skip
|
||||
in: query
|
||||
required: false
|
||||
type: int
|
||||
description: "Commits a saltar (para paginación)"
|
||||
- name: filter_commits
|
||||
in: query
|
||||
required: false
|
||||
type: int
|
||||
description: "Si aplicar filtrado de commits. Por defecto 1."
|
||||
responses:
|
||||
"200":
|
||||
description: "Lista de commits"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
commits:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
committed_date:
|
||||
type: int
|
||||
example: 1745360193
|
||||
hexsha:
|
||||
type: string
|
||||
example: "db8e84d5d2548f589ee503c1c6d5003cc6a0d803"
|
||||
message:
|
||||
type: string
|
||||
example: "Install updates"
|
||||
size:
|
||||
type: int
|
||||
example: 67108864
|
||||
tags:
|
||||
type: array
|
||||
example: ["updates"]
|
||||
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
"404":
|
||||
description: "El repositorio o branch no existe"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Repository not found"
|
||||
|
||||
/ogrepository/v1/git/repositories/{repository}/branches:
|
||||
get:
|
||||
summary: "Obtener lista de branches"
|
||||
description: |
|
||||
Devuelve una lista de branches de Git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Lista de branches"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
branches:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: main
|
||||
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
"404":
|
||||
description: "El repositorio no existe"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Repository not found"
|
||||
"409":
|
||||
description: "El branch ya existe"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
example: "Branch already exists"
|
||||
post:
|
||||
summary: "Crear branch"
|
||||
description: |
|
||||
Crea una rama de git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **commit** - Commit al que apunta la rama nueva. Puede ser un nombre de otra rama/tag.
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: devel
|
||||
required: True
|
||||
commit:
|
||||
type: string
|
||||
example: HEAD
|
||||
required: True
|
||||
responses:
|
||||
"201":
|
||||
description: "Rama creada"
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: main
|
||||
|
||||
"500":
|
||||
description: "Git no instalado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
||||
delete:
|
||||
summary: "Eliminar branch"
|
||||
description: |
|
||||
Elimina una rama de git
|
||||
tags:
|
||||
- "Git"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Nombre de repositorio"
|
||||
- name: branch
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
description: "Branch del repositorio"
|
||||
responses:
|
||||
"200":
|
||||
description: "Branch eliminado"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: deleted
|
||||
"500":
|
||||
description: "Excepción"
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "(Exception description)"
|
|
@ -27,7 +27,7 @@ import unittest
|
|||
from unittest.mock import patch, mock_open, MagicMock, AsyncMock
|
||||
from flask import json
|
||||
import os
|
||||
from repo_api import app, get_image_params, search_process, check_remote_connection, check_remote_image, check_lock_local, check_aux_files, check_file_exists, check_remote_backup
|
||||
from repo_api import app, get_image_params, search_process, check_remote_connection, check_remote_image, check_lock_local, check_aux_files, check_file_exists, check_remote_backup, check_virtual_image_conversion, check_free_space, check_virtual_image_reconversion
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -35,7 +35,8 @@ from repo_api import app, get_image_params, search_process, check_remote_connect
|
|||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
repo_path = '/opt/opengnsys/ogrepository/images'
|
||||
trash_path = '/opt/opengnsys/ogrepository/images_trash/'
|
||||
trash_path = '/opt/opengnsys/ogrepository/images_trash'
|
||||
vm_path = '/opt/opengnsys/ogrepository/images_virtual'
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -56,23 +57,28 @@ class RepoApiTestCase(unittest.TestCase):
|
|||
def setUp(self):
|
||||
""" Configura el cliente de prueba de Flask y habilita el modo de prueba (antes de cada test).
|
||||
Esto permite simular peticiones HTTP a la API sin necesidad de un servidor en ejecución.
|
||||
Además, crea el archivo "test4unittest.img", para realizar las pruebas.
|
||||
Además, crea los archivos "test4unittest.img" y "test4unittest.vdi", para realizar las pruebas.
|
||||
"""
|
||||
self.app = app.test_client()
|
||||
self.app.testing = True
|
||||
# Hay que crear la imagen de prueba, y eliminarla al finalizar las pruebas.
|
||||
# Creamos las imágenes de prueba ("img" y "vdi"):
|
||||
with open(f"{repo_path}/test4unittest.img", 'w') as test_image:
|
||||
test_image.write(' ')
|
||||
with open(f"{vm_path}/test4unittestvm.vdi", 'w') as vtest_image:
|
||||
vtest_image.write(' ')
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
""" Limpia el entorno de pruebas (después de cada test).
|
||||
En este caso, elimina el archivo "test4unittest.img" (de "repo_path" y de "trash_path").
|
||||
En este caso, elimina el archivo "test4unittest.img" (de "repo_path" y de "trash_path"),
|
||||
y el archivo "test4unittestvm.vdi" (de "vm_path").
|
||||
"""
|
||||
if os.path.exists(f"{repo_path}/test4unittest.img"):
|
||||
os.remove(f"{repo_path}/test4unittest.img")
|
||||
if os.path.exists(f"{trash_path}/test4unittest.img"):
|
||||
os.remove(f"{trash_path}/test4unittest.img")
|
||||
if os.path.exists(f"{vm_path}/test4unittestvm.vdi"):
|
||||
os.remove(f"{vm_path}/test4unittestvm.vdi")
|
||||
|
||||
|
||||
def mock_search_process(process, string_to_search):
|
||||
|
@ -545,22 +551,6 @@ class RepoApiTestCase(unittest.TestCase):
|
|||
self.assertIn("Image is locked", json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
@patch('repo_api.check_remote_connection')
|
||||
@patch('repo_api.get_image_params')
|
||||
@patch('repo_api.subprocess.Popen')
|
||||
def test_backup_image_error400_remote_image_exists(self, mock_popen, mock_get_image_params, mock_check_remote_connection):
|
||||
""" Método de prueba del endpoint "Hacer backup de una Imagen"
|
||||
(en caso de error "400", por imagen remota ya existente).
|
||||
"""
|
||||
print("Testing endpoint 'Hacer backup de una Imagen' (error 400, remote image exists)...")
|
||||
mock_check_remote_connection.return_value = True
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_popen.side_effect = Exception("exit status 5")
|
||||
response = self.app.put('/ogrepository/v1/repo/images', data=json.dumps({"ID_img": "test_image_id", "repo_ip": "127.0.0.1", "user": "test_user", "remote_path": "/tmp"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn("Image already exists on remote host", json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
# ------------------------------------------------------------------- Tests "Crear archivos auxiliares"
|
||||
|
||||
|
||||
|
@ -601,16 +591,146 @@ class RepoApiTestCase(unittest.TestCase):
|
|||
self.assertIn('Image not found', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
# ------------------------------------------------------------------- Tests "Convertir imagen virtual a imagen OpenGnsys"
|
||||
|
||||
|
||||
@patch('repo_api.subprocess.Popen')
|
||||
def test_create_torrent_sum_error400_image_locked(self, mock_popen):
|
||||
""" Método de prueba del endpoint "Crear archivos auxiliares"
|
||||
(en caso de error "400", por imagen bloqueada).
|
||||
@patch('repo_api.check_virtual_image_conversion')
|
||||
def test_convert_virtual_image(self, mock_popen, mock_check_virtual_image_conversion):
|
||||
""" Método de prueba del endpoint "Convertir imagen virtual a imagen OpenGnsys".
|
||||
"""
|
||||
print("Testing endpoint 'Crear archivos auxiliares' (error 400, image locked)...")
|
||||
mock_popen.side_effect = Exception("exit status 3")
|
||||
response = self.app.post('/ogrepository/v1/images/torrentsum', data=json.dumps({"image": "test4unittest.img"}), content_type='application/json')
|
||||
print("Testing endpoint 'Convertir imagen virtual a imagen OpenGnsys'...")
|
||||
mock_popen.return_value = MagicMock(returncode=None)
|
||||
mock_check_virtual_image_conversion.return_value = AsyncMock(returncode=None)
|
||||
response = self.app.post('/ogrepository/v1/images/virtual', data=json.dumps({"virtual_image":"test4unittestvm.vdi", "filesystem":"ext4"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn('Converting virtual image...', json.loads(response.data)['output'])
|
||||
|
||||
|
||||
@patch('repo_api.check_virtual_image_conversion')
|
||||
@patch('repo_api.check_file_exists')
|
||||
@patch('repo_api.subprocess.Popen')
|
||||
def test_convert_virtual_image_error500(self, mock_popen, mock_check_virtual_image_conversion, mock_check_file_exists):
|
||||
""" Método de prueba del endpoint "Convertir imagen virtual a imagen OpenGnsys"
|
||||
(en caso de error "500").
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen virtual a imagen OpenGnsys' (error 500)...")
|
||||
mock_check_file_exists.return_value = True
|
||||
mock_popen.side_effect = Exception("Error al convertir la imagen virtual")
|
||||
mock_check_virtual_image_conversion.return_value = AsyncMock(returncode=None)
|
||||
response = self.app.post('/ogrepository/v1/images/virtual', data=json.dumps({"virtual_image":"test4unittestvm.vdi", "filesystem":"ext4"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
self.assertIn('Error al convertir la imagen virtual', response.data.decode())
|
||||
|
||||
|
||||
@patch('repo_api.check_file_exists')
|
||||
def test_convert_virtual_image_error400_no_virtual_image(self, mock_check_file_exists):
|
||||
""" Método de prueba del endpoint "Convertir imagen virtual a imagen OpenGnsys"
|
||||
(en caso de error "400", por imagen virtual inexistente).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen virtual a imagen OpenGnsys' (error 400, no virtual image)...")
|
||||
mock_check_file_exists.return_value = False
|
||||
response = self.app.post('/ogrepository/v1/images/virtual', data=json.dumps({"virtual_image":"test4unittestvm.vdi", "filesystem":"ext4"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('Image is locked', json.loads(response.data)['exception'])
|
||||
self.assertIn('Virtual image not found', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
@patch('repo_api.check_file_exists')
|
||||
def test_convert_virtual_image_error400_name_incorrect(self, mock_check_file_exists):
|
||||
""" Método de prueba del endpoint "Convertir imagen virtual a imagen OpenGnsys"
|
||||
(en caso de error "400", por nombre incorrecto).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen virtual a imagen OpenGnsys' (error 400, name incorrect)...")
|
||||
mock_check_file_exists.return_value = True
|
||||
response = self.app.post('/ogrepository/v1/images/virtual', data=json.dumps({"virtual_image":"test4unittestvm.vdi", "filesystem":"ext4"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('There is an image with the same name as the virtual image', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
@patch('repo_api.check_free_space')
|
||||
def test_convert_virtual_image_error400_not_enough_space(self, mock_check_free_space):
|
||||
""" Método de prueba del endpoint "Convertir imagen virtual a imagen OpenGnsys"
|
||||
(en caso de error "400", por falta de espacio en disco).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen virtual a imagen OpenGnsys' (error 400, not enough space)...")
|
||||
mock_check_free_space.return_value = False
|
||||
response = self.app.post('/ogrepository/v1/images/virtual', data=json.dumps({"virtual_image":"test4unittestvm.vdi", "filesystem":"ext4"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('There is not enough free disk space', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
# ------------------------------------------------------------------- Tests "Convertir imagen OpenGnsys a imagen virtual"
|
||||
|
||||
|
||||
@patch('repo_api.subprocess.Popen')
|
||||
@patch('repo_api.get_image_params')
|
||||
@patch('repo_api.check_virtual_image_reconversion')
|
||||
def test_convert_image_to_virtual(self, mock_popen, mock_get_image_params, mock_check_virtual_image_reconversion):
|
||||
""" Método de prueba del endpoint "Convertir imagen OpenGnsys a imagen virtual".
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen OpenGnsys a imagen virtual'...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_popen.return_value = MagicMock(returncode=None)
|
||||
mock_check_virtual_image_reconversion.return_value = AsyncMock(returncode=None)
|
||||
response = self.app.put('/ogrepository/v1/images/virtual', data=json.dumps({"ID_img": "test_image_id", "vm_extension":"vdi"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn('Converting image to virtual...', json.loads(response.data)['output'])
|
||||
|
||||
|
||||
@patch('repo_api.check_virtual_image_reconversion')
|
||||
@patch('repo_api.get_image_params')
|
||||
@patch('repo_api.subprocess.Popen')
|
||||
def test_convert_image_to_virtual_error500(self, mock_popen, mock_get_image_params, mock_check_virtual_image_reconversion):
|
||||
""" Método de prueba del endpoint "Convertir imagen OpenGnsys a imagen virtual"
|
||||
(en caso de error "500").
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen OpenGnsys a imagen virtual' (error 500)...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_popen.side_effect = Exception("Error al convertir la imagen a virtual")
|
||||
mock_check_virtual_image_reconversion.return_value = AsyncMock(returncode=None)
|
||||
response = self.app.put('/ogrepository/v1/images/virtual', data=json.dumps({"ID_img": "test_image_id", "vm_extension":"vdi"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
self.assertIn('Error al convertir la imagen a virtual', response.data.decode())
|
||||
|
||||
|
||||
@patch('repo_api.get_image_params')
|
||||
def test_convert_image_to_virtual_error400_no_image(self, mock_get_image_params):
|
||||
""" Método de prueba del endpoint "Convertir imagen OpenGnsys a imagen virtual"
|
||||
(en caso de error "400", por imagen virtual inexistente).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen OpenGnsys a imagen virtual' (error 400, no image)...")
|
||||
mock_get_image_params.return_value = None
|
||||
response = self.app.put('/ogrepository/v1/images/virtual', data=json.dumps({"ID_img": "test_image_id", "vm_extension":"vdi"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn("Image not found", json.loads(response.data)['error'])
|
||||
|
||||
|
||||
@patch('repo_api.check_file_exists')
|
||||
@patch('repo_api.get_image_params')
|
||||
def test_convert_image_to_virtual_error400_name_incorrect(self, mock_get_image_params, mock_check_file_exists):
|
||||
""" Método de prueba del endpoint "Convertir imagen OpenGnsys a imagen virtual"
|
||||
(en caso de error "400", por nombre incorrecto).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen OpenGnsys a imagen virtual' (error 400, name incorrect)...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_check_file_exists.return_value = True
|
||||
response = self.app.put('/ogrepository/v1/images/virtual', data=json.dumps({"ID_img": "test_image_id", "vm_extension":"vdi"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('There is an exported virtual image with the same name as the image', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
@patch('repo_api.check_free_space')
|
||||
@patch('repo_api.get_image_params')
|
||||
def test_convert_image_to_virtual_error400_not_enough_space(self, mock_get_image_params, mock_check_free_space):
|
||||
""" Método de prueba del endpoint "Convertir imagen OpenGnsys a imagen virtual"
|
||||
(en caso de error "400", por falta de espacio en disco).
|
||||
"""
|
||||
print("Testing endpoint 'Convertir imagen OpenGnsys a imagen virtual' (error 400, not enough space)...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_check_free_space.return_value = False
|
||||
response = self.app.put('/ogrepository/v1/images/virtual', data=json.dumps({"ID_img": "test_image_id", "vm_extension":"vdi"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('There is not enough free disk space', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
# ------------------------------------------------------------------- Tests "Enviar paquete Wake On Lan"
|
||||
|
@ -989,6 +1109,62 @@ class RepoApiTestCase(unittest.TestCase):
|
|||
self.assertIn('Error al cancelar las transmisiones P2P', response.data.decode())
|
||||
|
||||
|
||||
# ------------------------------------------------------------------- Tests "Renombrar una Imagen"
|
||||
|
||||
|
||||
@patch('repo_api.get_image_params')
|
||||
@patch('repo_api.subprocess.run')
|
||||
def test_rename_image(self, mock_subprocess, mock_get_image_params):
|
||||
""" Método de prueba del endpoint "Renombrar una Imagen".
|
||||
"""
|
||||
print("Testing endpoint 'Renombrar una Imagen'...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_subprocess.return_value = MagicMock(returncode=0)
|
||||
response = self.app.put('/ogrepository/v1/images/rename', data=json.dumps({"ID_img":"test_image_id", "image_new_name":"new_name"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn('Image renamed successfully', json.loads(response.data)['output'])
|
||||
|
||||
|
||||
@patch('repo_api.get_image_params')
|
||||
@patch('repo_api.subprocess.run')
|
||||
def test_rename_image_error500(self, mock_subprocess, mock_get_image_params):
|
||||
""" Método de prueba del endpoint "Renombrar una Imagen"
|
||||
(en caso de error "500").
|
||||
"""
|
||||
print("Testing endpoint 'Renombrar una Imagen' (error 500)...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_subprocess.side_effect = Exception("Error al renombrar la imagen")
|
||||
response = self.app.put('/ogrepository/v1/images/rename', data=json.dumps({"ID_img":"test_image_id", "image_new_name":"new_name"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 500)
|
||||
self.assertIn('Error al renombrar la imagen', response.data.decode())
|
||||
|
||||
|
||||
@patch('repo_api.get_image_params')
|
||||
def test_rename_image_error400_no_image(self, mock_get_image_params):
|
||||
""" Método de prueba del endpoint "Renombrar una Imagen"
|
||||
(en caso de error "400", por imagen inexistente).
|
||||
"""
|
||||
print("Testing endpoint 'Renombrar una Imagen' (error 400, no image)...")
|
||||
mock_get_image_params.return_value = None
|
||||
response = self.app.put('/ogrepository/v1/images/rename', data=json.dumps({"ID_img":"test_image_id", "image_new_name":"new_name"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('Image not found', json.loads(response.data)['error'])
|
||||
|
||||
|
||||
@patch('repo_api.check_file_exists')
|
||||
@patch('repo_api.get_image_params')
|
||||
def test_rename_image_error400_name_incorrect(self, mock_get_image_params, mock_check_file_exists):
|
||||
""" Método de prueba del endpoint "Renombrar una Imagen"
|
||||
(en caso de error "400", por nombre incorrecto).
|
||||
"""
|
||||
print("Testing endpoint 'Renombrar una Imagen' (error 400, name incorrect)...")
|
||||
mock_get_image_params.return_value = {'name': 'test4unittest', 'extension': 'img'}
|
||||
mock_check_file_exists.return_value = True
|
||||
response = self.app.put('/ogrepository/v1/images/rename', data=json.dumps({"ID_img":"test_image_id", "image_new_name":"new_name"}), content_type='application/json')
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn('There is an image with the name to assign', json.loads(response.data)['exception'])
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,452 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script convierte la imagen de OpengGnsys especificada como primer parámetro en una imagen virtual con la extensión especificada como segundo parámetro ("vdi", "vmdk", etc).
|
||||
La imagen virtual se exporta a la ruta "/opt/opengnsys/ogrepository/images_virtual/export/", desde donde puede ser descargada para importarla en VirtualBox, VMware, etc.
|
||||
|
||||
Paquetes APT requeridos: "qemu" (se puede instalar con "sudo apt install qemu-utils").
|
||||
"partclone" (se puede instalar con "sudo apt install partclone").
|
||||
"lzop" (se puede instalar con "sudo apt install lzop").
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a convertir (sin ruta).
|
||||
- Ejemplo1: Ubuntu.img
|
||||
- Ejemplo2: Windows.img
|
||||
|
||||
sys.argv[2] - Extensión del disco virtual destino (sin punto).
|
||||
- Ejemplo1: vdi
|
||||
- Ejemplo2: vmdk
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./comvertIMGtoVM.py image_name virtual_extension
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./comvertIMGtoVM.py Ubuntu.img vdi
|
||||
./comvertIMGtoVM.py Windows.img vmdk
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# IMPORTS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
import os
|
||||
import pwd
|
||||
import grp
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
|
||||
vm_export_path = '/opt/opengnsys/ogrepository/images_virtual/export/' # No borrar la barra final
|
||||
partclone_logfile = '/opt/opengnsys/ogrepository/log/partclone.log'
|
||||
|
||||
raw_img = '/opt/opengnsys/ogrepository/images_virtual/export/disk.raw'
|
||||
mount_point = "/mnt/recovery"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# FUNCTIONS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def show_help():
|
||||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name virtual_extension
|
||||
Ejemplo1: {script_name} Ubuntu.img vdi
|
||||
Ejemplo2: {script_name} Windows.img vmdk
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
||||
def check_params():
|
||||
""" Comprueba que se haya enviado la cantidad correcta de parámetros, y en el formato correcto.
|
||||
Si no es así, muestra un mensaje de error, y sale del script.
|
||||
LLama a la función "show_help" cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
# Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script:
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "help":
|
||||
show_help()
|
||||
sys.exit(0)
|
||||
# Si se ejecuta el script con más o menos de 2 parámetroa, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 3:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def create_export_folder():
|
||||
""" Crea el directorio '/opt/opengnsys/ogrepository/images_virtual/export/', y le asigna propietarios y permisos.
|
||||
Evidentemente, esta función solo es llamada cuando no existe el directorio.
|
||||
"""
|
||||
# Obtenemos el UID del usuario "opengnsys" y el GID del grupo "opengnsys":
|
||||
uid = pwd.getpwnam('opengnsys').pw_uid
|
||||
gid = grp.getgrnam('opengnsys').gr_gid
|
||||
# Creamos el directorio '/opt/opengnsys/ogrepository/images_virtual/export/':
|
||||
os.mkdir(vm_export_path)
|
||||
# Asignamos el usuario y el grupo propietarios del directorio:
|
||||
os.chown(vm_export_path, uid, gid)
|
||||
# Asignamos permisos "755" al directorio :
|
||||
os.chmod(vm_export_path, 0o755)
|
||||
|
||||
|
||||
def create_raw_disk(raw_size):
|
||||
""" Crea un disco "RAW", sobre el que luego se creará una tabla de particiones, mediante "qemu-img create".
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'qemu-img create'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['qemu-img', 'create', '-f', 'raw', raw_img, raw_size], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'qemu-img create' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'qemu-img create' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def create_partition_table(partition_size):
|
||||
""" Crea una tabla de particiones en el disco "RAW", mediante "fdisk".
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'fdisk'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Construimos el parámetro "input", que debe codificarse en bytes (con "encode"):
|
||||
input_data = f"o\nn\np\n1\n\n+{partition_size}\nw".encode()
|
||||
|
||||
result = subprocess.run(['fdisk', raw_img], input=input_data, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'fdisk' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'fdisk' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def associate_loop_device():
|
||||
""" Asocia el disco "RAW" a un dispositivo loopback, mediante "losetup".
|
||||
Si se ejecuta correctamente retorna "True", el dispositivo loopback y la partición de destino, y si da error retorna "False", "None" y "None".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'losetup'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['losetup', '-P', '--find', '--show', raw_img], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Si el resultado de la ejecución es correcto, obtenemos el dispositivo loopback y la partición de destino, y los retornamos:
|
||||
if result.returncode == 0:
|
||||
# Obtenemos la partición de destino, y la imprimimos en el log, junto con el dispositivo loopback:
|
||||
loop_device = result.stdout.strip()
|
||||
dest_partition = f"{loop_device}p1"
|
||||
journal.send(f"convertIMGtoVM.py: Loopback device obtained: {loop_device}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
journal.send(f"convertIMGtoVM.py: Destination partition obtained: {dest_partition}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return True, loop_device, dest_partition
|
||||
else:
|
||||
return False, None, None
|
||||
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False", "None" y "None" (entrará aquí si el return code no es "0"):
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'losetup' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False, None, None
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'losetup' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False, None, None
|
||||
|
||||
|
||||
def decompress_image(image_name_full):
|
||||
""" Descomprime la imagen "IMG" origen, con "lzop".
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'lzop'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['lzop', '-d', f"{repo_path}{image_name_full}", '-o', f"{vm_export_path}{image_name_full}"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'lzop' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'lzop' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def restore_image(image_name_full, dest_partition):
|
||||
""" Restaura la imagen descomprimida en la partición de destino (que hemos obtenido con "losetup").
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'partclone.restore'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['partclone.restore', '-s', f"{vm_export_path}{image_name_full}", '-o', dest_partition, '-L', partclone_logfile], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'partclone.restore' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'partclone.restore' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def mount_partition(dest_partition):
|
||||
""" Crea un directorio de montaje, y monta allí la partición de destino (que hemos obtenido con "losetup").
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
NOTA: Los comandos "mkdir" y "mount" deben ejecutarse con "sudo", o darán error.
|
||||
"""
|
||||
try:
|
||||
# Creamos el directorio de montaje:
|
||||
subprocess.run(['sudo', 'mkdir', '-p', mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'mkdir' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
try:
|
||||
# Montamos la partición en el directorio de montaje:
|
||||
journal.send("convertIMGtoVM.py: Running command 'mount'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['sudo', 'mount', dest_partition, mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'mount' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'mount' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def install_grub(loop_device):
|
||||
""" Instala GRUB en el dispositivo loopback.
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
NOTA: Los comandos deben ejecutarse con "sudo", o darán error.
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Installing GRUB...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Ejecutamos los comandos necesarios para instalar GRUB:
|
||||
subprocess.run(['sudo', 'mount', '--bind', '/dev', f"{mount_point}/dev"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'mount', '--bind', '/proc', f"{mount_point}/proc"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'mount', '--bind', '/sys', f"{mount_point}/sys"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'chroot', mount_point, 'grub-install', '--target=i386-pc', loop_device], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'chroot', mount_point, 'grub-mkconfig', '-o', '/boot/grub/grub.cfg'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Como no ha habido errores, retornamos "True":
|
||||
return True
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: GRUB install error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: GRUB install exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def umount_partitions(loop_device):
|
||||
""" Desmonta todas las particiones montadas previamente, con "umount" y "losetup".
|
||||
No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen.
|
||||
NOTA: Los comandos deben ejecutarse con "sudo", o darán error.
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Umounting partitions...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Desmontamos las particiones, con "umount" y "losetup":
|
||||
subprocess.run(['sudo', 'umount', f"{mount_point}/dev"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'umount', f"{mount_point}/proc"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'umount', f"{mount_point}/sys"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'umount', '-l', mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(['sudo', 'losetup', '-d', loop_device], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Como no ha habido errores, imprimimos un mensaje en el log:
|
||||
journal.send("convertIMGtoVM.py: Umount partitions OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Si se produce un error o una excepción lo imprimimos en el log:
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'umount' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'umount' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
def convert_image(image_name, vm_extension):
|
||||
""" Convierte el disco "RAW" en un disco virtual, con la extensión especificada como parámetro.
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertIMGtoVM.py: Running command 'qemu-img convert'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['qemu-img', 'convert', '-f', 'raw', '-O', vm_extension, raw_img, f"{vm_export_path}{image_name}.{vm_extension}"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'qemu-img convert' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertIMGtoVM.py: 'qemu-img convert' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
def erase_image_file(file2del):
|
||||
""" Borra el archivo correspondiente a la ruta "file2del".
|
||||
No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen.
|
||||
"""
|
||||
journal.send(f"convertIMGtoVM.py: Erasing file {file2del}...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Si existe el archivo "file2del", lo borramos:
|
||||
if os.path.exists(file2del):
|
||||
os.remove(file2del)
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# Almacenamos el nombre completo de la imagen y la extensión del disco virtual de destino (desde los parámetros), y extraemos el nombre sin extensión:
|
||||
image_name_full = sys.argv[1]
|
||||
image_name = image_name_full.split('.')[0]
|
||||
vm_extension = sys.argv[2].lower()
|
||||
|
||||
# Obtenemos el tamaño de la imagen, y calculamos el tamaño a asignar al disco "RAW" y a la partición:
|
||||
image_size = os.path.getsize(f"{repo_path}{image_name_full}")
|
||||
raw_size = image_size * 6.5 # El disco "RAW" debe ser "6,5" veces más grande que la imagen
|
||||
partition_size = (90 * raw_size) / 100 # La partición debe tener el 90% del tamaño del disco "RAW"
|
||||
|
||||
# Si no existe el directorio '/opt/opengnsys/ogrepository/images_virtual/export/', lo creamos:
|
||||
if not os.path.exists(vm_export_path):
|
||||
journal.send("convertIMGtoVM.py: Creating export folder...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
create_export_folder()
|
||||
|
||||
# Creamos el disco "RAW" (con "qemu-img create"):
|
||||
create_raw = create_raw_disk(f"{raw_size / 1024 / 1024 / 1024}G")
|
||||
if create_raw == False:
|
||||
journal.send("convertIMGtoVM.py: RAW disk creation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
sys.exit(2)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: RAW disk creation OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Creamos una tabla de particiones en el disco "RAW" (con "fdisk"):
|
||||
create_table = create_partition_table(f"{int(partition_size / 1024 / 1024 / 1024)}G")
|
||||
if create_table == False:
|
||||
journal.send("convertIMGtoVM.py: Partition table creation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
sys.exit(3)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: Partition table creation OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Asociamos el disco "RAW" a un dispositivo loopback, y almacenamos este y la partición de destino
|
||||
assoc_loop_result, loop_device, dest_partition = associate_loop_device()
|
||||
if assoc_loop_result == False:
|
||||
journal.send("convertIMGtoVM.py: Loop device association failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
sys.exit(4)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: Loop device association OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Descomprimimos la imagen original (con "lzop"):
|
||||
image_decompressed = decompress_image(image_name_full)
|
||||
if image_decompressed == False:
|
||||
journal.send("convertIMGtoVM.py: Image decompression failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
erase_image_file(f"{vm_export_path}{image_name_full}") # Como ha fallado, borramos la imagen descomprimida
|
||||
sys.exit(5)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: Image decompression OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Restauramos la imagen descomprimida en la partición de destino (con "partclone.restore"):
|
||||
image_restored = restore_image(image_name_full, dest_partition)
|
||||
if image_restored == False:
|
||||
journal.send("convertIMGtoVM.py: Image restoration failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
erase_image_file(f"{vm_export_path}{image_name_full}") # Como ha fallado, borramos la imagen descomprimida
|
||||
sys.exit(6)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: Image restoration OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(f"{vm_export_path}{image_name_full}") # Si ha ido OK también borramos la imagen descomprimida, porque ya no la necesitamos.
|
||||
|
||||
# Montamos la partición de destino (con "mount"):
|
||||
partition_mounted = mount_partition(dest_partition)
|
||||
if partition_mounted == False:
|
||||
journal.send("convertIMGtoVM.py: Partition mount failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
sys.exit(7)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: Partition mount OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Instalamos GRUB en el dispositivo loopback (con "mount" y "chroot"):
|
||||
grub_installed = install_grub(loop_device)
|
||||
if grub_installed == False:
|
||||
journal.send("convertIMGtoVM.py: GRUB install failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
umount_partitions(loop_device) # Como ha fallado, desmontamos todas las particiones
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
sys.exit(8)
|
||||
else:
|
||||
journal.send("convertIMGtoVM.py: GRUB install OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Desmontamos las particiones montadas previamente (con "umount" y "losetup"):
|
||||
umount_partitions(loop_device)
|
||||
|
||||
# Convertimos el disco "RAW" en un disco virtual (con "qemu-img convert"):
|
||||
image_conversion = convert_image(image_name, vm_extension)
|
||||
if image_conversion == False:
|
||||
journal.send("convertIMGtoVM.py: Image conversion failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW"
|
||||
erase_image_file(f"{vm_export_path}{image_name}.{vm_extension}") # Como ha fallado, borramos la imagen virtual (por si ha creado algo)
|
||||
sys.exit(9)
|
||||
else:
|
||||
erase_image_file(raw_img) # Si ha funcionado OK, también borramos el disco "RAW"
|
||||
journal.send("convertIMGtoVM.py: Image conversion OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -0,0 +1,415 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script convierte la imagen virtual especificada como primer parámetro (que debe haberse copiado previamente en la ruta "opt/opengnsys/ogrepository/images_virtual")
|
||||
en una imagen "img" como las que se generan desde OpenGnsys (con "partclone" y "lzop"), por lo que luego puede ser restaurada como cualquier otra imagen del repositorio.
|
||||
|
||||
Como segundo parámetro debe especificarse el sistema de archivos de la partición a clonar, en formato "blkid" ("ext4", "ntfs", etc).
|
||||
NOTA: Se puede comprobar todos los sistemas de archivos aceptados por "blkid" ejecutando el comando "blkid -k".
|
||||
|
||||
Una vez realizada la conversión llama al script "createTorrentSum.py", para crear los archivos auxiliares y actualizar la info del repositorio.
|
||||
|
||||
Paquetes APT requeridos: "qemu" (se puede instalar con "sudo apt install qemu-utils").
|
||||
"partclone" (se puede instalar con "sudo apt install partclone").
|
||||
"lzop" (se puede instalar con "sudo apt install lzop").
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen virtual a convertir (sin ruta).
|
||||
- Ejemplo1: UbuntuVM.vdi
|
||||
- Ejemplo2: WindowsVM.vmdk
|
||||
|
||||
sys.argv[2] - Sistema de archivos de la partición a convertir (en formato "blkid").
|
||||
- Ejemplo1: ext4
|
||||
- Ejemplo2: ntfs
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./convertVMtoIMG.py vm_image_name partition_filesystem
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./convertVMtoIMG.py UbuntuVM.vdi ext4
|
||||
./convertVMtoIMG.py WindowsVM.vmdk ntfs
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# IMPORTS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
|
||||
vm_path = '/opt/opengnsys/ogrepository/images_virtual/' # No borrar la barra final
|
||||
partclone_logfile = '/opt/opengnsys/ogrepository/log/partclone.log'
|
||||
create_torrent_script = '/opt/opengnsys/ogrepository/bin/createTorrentSum.py'
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# FUNCTIONS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def show_help():
|
||||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} vm_image_name partition_filesystem
|
||||
Ejemplo1: {script_name} UbuntuVM.vdi ext4
|
||||
Ejemplo2: {script_name} WindowsVM.vmdk ntfs
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
||||
|
||||
def check_params():
|
||||
""" Comprueba que se haya enviado la cantidad correcta de parámetros, y en el formato correcto.
|
||||
Si no es así, muestra un mensaje de error, y sale del script.
|
||||
LLama a la función "show_help" cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
# Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script:
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "help":
|
||||
show_help()
|
||||
sys.exit(0)
|
||||
# Si se ejecuta el script con más o menos de 2 parámetroa, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 3:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def convert_to_raw(vm_image_name, vm_extension):
|
||||
""" Convierte la imagen virtual a formato "RAW", mediante "qemu-img".
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running command 'qemu-img convert'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['qemu-img', 'convert', '-O', 'raw', f"{vm_path}{vm_image_name}.{vm_extension}", f"{vm_path}{vm_image_name}.raw"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'qemu-img' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'qemu-img' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Unexpected error: {error}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def map_vm_partitions(vm_image_name):
|
||||
""" Mapea las particiones de la imagen RAW en "dev/mapper", para que "partclone" pueda convertir la imagen.
|
||||
Si se ejecuta correctamente retorna "True" y la lista de mapeos, y si da error retorna "False" y "None".
|
||||
NOTA: Debe ejecutarse con "sudo", o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running command 'kpartx -av'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['sudo', 'kpartx', '-av', f"{vm_path}{vm_image_name}.raw"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" y la lista de mapeos si es correcta, o "False" y "None" si no lo es:
|
||||
if result.returncode == 0:
|
||||
# Parseamos la salida del comando, para añadir cada mapeo a "map_list":
|
||||
map_list = []
|
||||
for line in result.stdout.split('\n'):
|
||||
if "loop" in line:
|
||||
#map_list.append(line.split()[2]) # Así pilla el "loop" con "split"
|
||||
map_list.append(line[line.find('loop') : line.find(' ', line.index('loop'))]) # Así pilla el rango desde "loop" hasta el siguiente espacio, y es mejor hacerlo así
|
||||
return True, map_list
|
||||
else:
|
||||
return False, None
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False" y "None":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'kpartx -av' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False, None
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'kpartx -av' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False, None
|
||||
|
||||
|
||||
|
||||
def get_target_device(map_list, filesystem):
|
||||
""" Busca entre los mapeos generados por "kpartx" el dispositivo correspondiente a la partición a restaurar (en base al filesystem especificado como parámetro),
|
||||
ejecutando el comando "blkid" sobre cada dispositivo mapeado (por lo que el filesystem debe respetar la nomenclatura de "blkid").
|
||||
Si se ejecuta correctamente retorna el dispositivo de destino, y si da error retorna un mensaje que incluye "Filesystem".
|
||||
No estoy seguro de que sea necesario, pero por las dudas lo ejecuto con "sudo" (como no crea ningún archivo, no dará problemas de propietario).
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Getting target device...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Sobre cada mapeo ejecutamos el comando "blkid", buscamos el filesystem en la respuesta, y si lo encontramos extraemos el nombre del dispositivo (para pasárselo a "partclone"):
|
||||
for device in map_list:
|
||||
# Ejecutamos el comando "blkid" sobre el mapeo actual:
|
||||
result = subprocess.run(['sudo', 'blkid', f"/dev/mapper/{device}"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Si encontramos el filesystem, extraemos el dispositivo, y lo retornamos:
|
||||
if f'TYPE="{filesystem}"' in result.stdout:
|
||||
target_device = result.stdout.split('/')[3].split(':')[0]
|
||||
journal.send(f"convertVMtoIMG.py: Target device obtained: {target_device}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return target_device
|
||||
|
||||
# Si no encontramos el filesystem en ninguno de los mapeos, guardamos un log y retornamos un mensaje informativo:
|
||||
journal.send("convertVMtoIMG.py: Filesystem not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return "Filesystem not found"
|
||||
|
||||
# Si se produce una excepción lo imprimimos en el log, y retornamos un mensaje informativo:
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'get_target_device' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return "Error getting Filesystem"
|
||||
|
||||
|
||||
|
||||
def convert_to_partclone(vm_image_name, target_device):
|
||||
""" Convierte la imagen "vm_image_name" con "partclone", para que pueda ser restaurada desde ogLive.
|
||||
Como origen no utiliza la imagen "RAW", sino una partición mapeada en "/dev/mapper" (almacenada en "target_device").
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running command 'partclone.extfs'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['partclone.extfs', '-c', '-s', f"/dev/mapper/{target_device}", '-o', f"{vm_path}{vm_image_name}.img", '-L', partclone_logfile], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'partclone.extfs' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'partclone.extfs' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def umap_vm_partitions(vm_image_name):
|
||||
""" Desmapea las particiones de la imagen RAW, desde "dev/mapper".
|
||||
No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen.
|
||||
NOTA: Debe ejecutarse con "sudo", o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running command 'kpartx -d'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['sudo', 'kpartx', '-d', f"{vm_path}{vm_image_name}.raw"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, imprimiendo en el log el mensaje correspondiente:
|
||||
if result.returncode == 0:
|
||||
journal.send("convertVMtoIMG.py: Partitions ummap OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Partitions umap failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Si se produce un error o una excepción lo imprimimos en el log:
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'kpartx -d' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'kpartx -d' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
|
||||
def compress_image(vm_image_name):
|
||||
""" Comprime la imagen generada con "partclone", con "lzop".
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running command 'lzop'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['lzop', f"{vm_path}{vm_image_name}.img"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'lzop' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'lzop' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def prepare_image(vm_image_name):
|
||||
""" Mueve la imagen comprimida al repositorio de imágenes, sustituyendo la extensión ".img.lzo" por ".img".
|
||||
Calcula el "datasize" aproximado, y crea el archivo "info", para dejar la imagen preparada para añadir al repositorio.
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Preparing image...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Movemos la imagen comprimida al repositorio de imágenes, y sustituimos la extensión ".img.lzo" por ".img":
|
||||
shutil.move(f"{vm_path}{vm_image_name}.img.lzo", f"{repo_path}{vm_image_name}.img")
|
||||
|
||||
# Calculamos aproximadamente lo que puede ocupar la imagen una vez restaurada (multiplicando el tamaño de la imagen por "2.5"):
|
||||
datasize = int(os.path.getsize(f"{repo_path}{vm_image_name}.img") * 2.5)
|
||||
|
||||
# Creamos el archivo "info":
|
||||
line_to_write = f"PARTCLONE:LZOP:EXTFS:{datasize}:unknown"
|
||||
with open(f"{repo_path}{vm_image_name}.img.info", 'w') as file:
|
||||
file.write(line_to_write)
|
||||
|
||||
# Como todo ha ido bien hasta aquí, retornamos "True":
|
||||
return True
|
||||
|
||||
# Si se produce una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: Prepare image exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def create_torrentsum(vm_image_name):
|
||||
""" Crea los archivos auxiliares asociados a la imagen convertida, y actualiza la información del repositorio
|
||||
(llamando al script "createTorrentSum.py", que a su vez llama al script "updateRepoInfo.py").
|
||||
Si se ejecuta correctamente retorna "True", y si da error retorna "False".
|
||||
"""
|
||||
try:
|
||||
journal.send("convertVMtoIMG.py: Running script 'createTorrentSum.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['python3', create_torrent_script, f"{repo_path}{vm_image_name}.img"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
# Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es:
|
||||
if result.returncode == 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
# Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False":
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'createTorrentSum.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
except Exception as error:
|
||||
journal.send(f"convertVMtoIMG.py: 'createTorrentSum.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def erase_image_file(vm_image_name, ext):
|
||||
""" Borra el archivo "vm_image_name" con extensión "ext",
|
||||
desde el directorio de imágenes virtuales.
|
||||
No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen.
|
||||
"""
|
||||
journal.send(f"convertVMtoIMG.py: Erasing file with extension {ext}...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Si existe el archivo "vm_image_name.ext", lo borramos:
|
||||
if os.path.exists(f"{vm_path}{vm_image_name}{ext}"):
|
||||
os.remove(f"{vm_path}{vm_image_name}{ext}")
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# Almacenamos el nombre completo de la imagen y el sistema de archivos (desde los parámetros), y extraemos el nombre y la extensión:
|
||||
vm_image_name_full = sys.argv[1]
|
||||
vm_image_name = vm_image_name_full.split('.')[0]
|
||||
vm_extension = vm_image_name_full.split('.')[1]
|
||||
filesystem = sys.argv[2].lower()
|
||||
|
||||
|
||||
# Convertimos la imagen virtual a RAW (con "qemu-img"):
|
||||
raw_conversion = convert_to_raw(vm_image_name, vm_extension)
|
||||
if raw_conversion == False:
|
||||
journal.send("convertVMtoIMG.py: Conversion to RAW failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(vm_image_name, '.raw') # Como ha fallado, borramos la imagen "RAW"
|
||||
sys.exit(2)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Conversion to RAW OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Mapeamos las particiones de la imagen RAW (con "kpartx -av"):
|
||||
map_result, map_list = map_vm_partitions(vm_image_name)
|
||||
if map_result == False:
|
||||
journal.send("convertVMtoIMG.py: Partitions map failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(vm_image_name, '.raw') # Como ha fallado, borramos la imagen "RAW"
|
||||
sys.exit(3)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Partitions map OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Obtenemos la partición mapeada de destino (con "blkid"):
|
||||
target_device = get_target_device(map_list, filesystem)
|
||||
if "Filesystem" in target_device:
|
||||
journal.send("convertVMtoIMG.py: Get target device failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
umap_vm_partitions(vm_image_name) # Como ha fallado, desmapeamos las particiones de la imagen "RAW"
|
||||
erase_image_file(vm_image_name, '.raw') # Como ha fallado, borramos la imagen "RAW"
|
||||
sys.exit(4)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Get target device OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Convertimos la imagen con "partclone", desde la partición mapeada:
|
||||
partclone_conversion = convert_to_partclone(vm_image_name, target_device)
|
||||
if partclone_conversion == False:
|
||||
journal.send("convertVMtoIMG.py: Conversion to Partclone failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(vm_image_name, '.raw') # Como ha fallado, borramos la imagen "RAW"
|
||||
erase_image_file(vm_image_name, '.img') # Como ha fallado, borramos la imagen generada con "partclone" (sin comprimir)
|
||||
sys.exit(5)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Conversion to Partclone OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Desmapeamos las particiones de la imagen RAW (con "kpartx -d"):
|
||||
umap_vm_partitions(vm_image_name)
|
||||
|
||||
|
||||
# Borramos la imagen "RAW", generada con "qemu-img":
|
||||
erase_image_file(vm_image_name, '.raw')
|
||||
|
||||
|
||||
# Comprimimos la imagen con "lzop":
|
||||
image_compression = compress_image(vm_image_name)
|
||||
if image_compression == False:
|
||||
journal.send("convertVMtoIMG.py: Image compression failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
erase_image_file(vm_image_name, '.img') # Como ha fallado, borramos la imagen generada con "partclone" (sin comprimir)
|
||||
sys.exit(6)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Image compression OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Borramos la imagen generada con "partclone" (sin comprimir):
|
||||
erase_image_file(vm_image_name, '.img')
|
||||
|
||||
|
||||
# Movemos la imagen comprimida al repositorio de imágenes, y creamos el archivo "info":
|
||||
image_prepared = prepare_image(vm_image_name)
|
||||
if image_prepared == False:
|
||||
journal.send("convertVMtoIMG.py: Image preparation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(7)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Image preparation OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
# Creamos los archivos auxiliares, y actualizamos la información del repositorio:
|
||||
image_ready = create_torrentsum(vm_image_name)
|
||||
if image_ready == False:
|
||||
journal.send("convertVMtoIMG.py: Auxiliar files creation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(8)
|
||||
else:
|
||||
journal.send("convertVMtoIMG.py: Auxiliar files creation OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -134,8 +134,8 @@ def create_torrent(file_path, torrent_file, datafullsum):
|
|||
repo_ip = get_IPlocal()
|
||||
tracker_url = f"http://{repo_ip}:6969/announce"
|
||||
|
||||
# Creamos una lista con el comando para crear el torrrent, y lo imprimimos con espacios:
|
||||
splitted_cmd = f"nice -n 0 ctorrent -t {file_path} -u {tracker_url} -s {torrent_file} -c {datafullsum} -l 4194304".split()
|
||||
# Creamos una litas para ejecutar el comando mktorrent para crear el archivo torrent
|
||||
splitted_cmd = f"nice -n 0 mktorrent -a {tracker_url} -c {datafullsum} -o {torrent_file} {file_path}".split()
|
||||
print(f"Sending command: {' '.join(splitted_cmd)}")
|
||||
|
||||
# Ejecutamos el comando en el sistema, e imprimimos el resultado:
|
||||
|
|
|
@ -113,15 +113,15 @@ def create_trash_folder():
|
|||
""" Crea el directorio correspondiente a la papelera, y le asigna propietarios y permisos.
|
||||
Evidentemente, esta función solo es llamada cuando no existe el directorio.
|
||||
"""
|
||||
# Obtenemos el UID del usuario "root" y el GID del grupo "opengnsys":
|
||||
uid = pwd.getpwnam('root').pw_uid
|
||||
# Obtenemos el UID del usuario "opengnsys" y el GID del grupo "opengnsys":
|
||||
uid = pwd.getpwnam('opengnsys').pw_uid
|
||||
gid = grp.getgrnam('opengnsys').gr_gid
|
||||
# Creamos el directorio correspondiente a la papelera:
|
||||
os.mkdir(trash_path)
|
||||
# Asignamos el usuario y el grupo propietarios del directorio:
|
||||
os.chown(trash_path, uid, gid)
|
||||
# Asignamos permisos "775" al directorio :
|
||||
os.chmod(trash_path, 0o775)
|
||||
os.chmod(trash_path, 0o755)
|
||||
|
||||
|
||||
def delete_image(file_path, method, extensions):
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
"""
|
||||
Este script devuelve información de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato json.
|
||||
También comprueba si ogGit está instalado en el repositorio, y devuelve dicha información.
|
||||
No recibe ningún parámetro.
|
||||
|
||||
Librerías Python requeridas: "psutil" (se puede instalar con "sudo apt install python3-psutil". o "pip install psutil")
|
||||
|
@ -18,11 +19,29 @@ import json
|
|||
import subprocess
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
config_file = '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# FUNCTIONS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_oggit_info():
|
||||
""" Obtiene el valor asociado a la variable "oggit", desde el archivo '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'.
|
||||
Retorna el valor asociado capitalizado ("True" o "False").
|
||||
"""
|
||||
with open(config_file, 'r') as file:
|
||||
for line in file:
|
||||
if line.startswith('oggit'):
|
||||
oggit_info = line.split('=')[1].strip()
|
||||
return oggit_info.capitalize()
|
||||
|
||||
|
||||
def get_cpu_info():
|
||||
""" Obtiene y retorna información de la CPU.
|
||||
"""
|
||||
|
@ -74,6 +93,9 @@ def get_process_status(process):
|
|||
def main():
|
||||
"""
|
||||
"""
|
||||
# Comprobamos si ogGit está instalado en el repositorio o no:
|
||||
oggit_installed = get_oggit_info()
|
||||
|
||||
# Obtenemos información de la CPU:
|
||||
cpu_percent = get_cpu_info()
|
||||
|
||||
|
@ -84,15 +106,18 @@ def main():
|
|||
total_disk, used_disk, free_disk, percent_disk = get_disk_info()
|
||||
|
||||
# Obtenemos el estado de los servicios listados, que almacenamos en un diccionario:
|
||||
service_list = ['ssh', 'smbd', 'rsync']
|
||||
service_list = ['ssh', 'smbd', 'opentracker']
|
||||
services_status = {service: get_service_status(service) for service in service_list}
|
||||
|
||||
# Obtenemos el estado de los procesos listados, que almacenamos en un diccionario:
|
||||
process_list = ['udp-sender', 'uftp', 'bttrack', 'btlaunchmany.bittornado']
|
||||
process_list = ['udp-sender', 'uftp', 'aria2c']
|
||||
process_status = {process: get_process_status(process) for process in process_list}
|
||||
|
||||
# Creamos un diccionario con toda la información obtenida:
|
||||
data_dict = {
|
||||
'oggit': {
|
||||
'installed': oggit_installed
|
||||
},
|
||||
'cpu': {
|
||||
'used_percentage': f"{int(cpu_percent)}%"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script renombra la imagen especificada como primer parámetro (y todos sus archivos asociados), asignando el nombre especificado como segundo parámetro.
|
||||
|
||||
Una vez renombrados los archivos, llama al script "updateRepoInfo.py", para actualizar la información del repositorio.
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre de la imagen a renombrar (sin extensión y sin ruta).
|
||||
- Ejemplo1: Ubuntu24
|
||||
- Ejemplo2: Windows10
|
||||
|
||||
sys.argv[2] - Nuevo nombre a asignar a la imagen (sin extensión y sin ruta).
|
||||
- Ejemplo1: Ubuntu24_BKP
|
||||
- Ejemplo2: Windows10_BKP
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./renameImage.py image_to_rename image_new_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./renameImage.py Ubuntu24 Ubuntu24_BKP
|
||||
./renameImage.py Windows10 Windows10_BKP
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# IMPORTS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
|
||||
update_repo_script = '/opt/opengnsys/ogrepository/bin/updateRepoInfo.py'
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# FUNCTIONS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def show_help():
|
||||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_to_rename image_new_name
|
||||
Ejemplo1: {script_name} Ubuntu24 Ubuntu24_BKP
|
||||
Ejemplo2: {script_name} Windows10 Windows10_BKP
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
||||
|
||||
def check_params():
|
||||
""" Comprueba que se haya enviado la cantidad correcta de parámetros, y en el formato correcto.
|
||||
Si no es así, muestra un mensaje de error, y sale del script.
|
||||
LLama a la función "show_help" cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
# Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script:
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "help":
|
||||
show_help()
|
||||
sys.exit(0)
|
||||
# Si se ejecuta el script con más o menos de 2 parámetros, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 3:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def rename_image(image_original_name, image_new_name):
|
||||
""" Asigna el nuevo nombre especificado a la imagen y a todos los archivos asociados.
|
||||
Al archivo ".info.checked" también le cambia la extensión a ".info",
|
||||
para poder actualizar la información del repositorio posteriormente.
|
||||
"""
|
||||
try:
|
||||
journal.send("renameImage.py: Renaming image files...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Creamos una lista con las extensiones de los archivos de la imagen (menos "info.checked"):
|
||||
extensions = ['.img', '.img.full.sum', '.img.size', '.img.sum', '.img.torrent']
|
||||
|
||||
# Renombramos cada uno de los archivos (menos "info.checked"):
|
||||
for ext in extensions:
|
||||
os.rename(f"{repo_path}{image_original_name}{ext}", f"{repo_path}{image_new_name}{ext}")
|
||||
|
||||
# Renombramos separadamente el archivo "info.checked" (porque también le cambiamos la extensión a "info"):
|
||||
os.rename(f"{repo_path}{image_original_name}.img.info.checked", f"{repo_path}{image_new_name}.img.info")
|
||||
|
||||
except Exception as error:
|
||||
journal.send(f"renameImage.py: Rename Image exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
"""
|
||||
try:
|
||||
journal.send("renameImage.py: Running script 'updateRepoInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"renameImage.py: 'updateRepoInfo.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(3)
|
||||
except Exception as error:
|
||||
journal.send(f"renameImage.py: 'updateRepoInfo.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(4)
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# Almacenamos el nombre original de la imagen, y el nuevo nombre a asignar (desde los parámetros):
|
||||
image_original_name = sys.argv[1]
|
||||
image_new_name = sys.argv[2]
|
||||
|
||||
# Renombramos la imagen y sus archivos asociados:
|
||||
rename_image(image_original_name, image_new_name)
|
||||
|
||||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
update_repo_info()
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -16,6 +16,8 @@ No recibe ningún parámetro.
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import psutil
|
||||
import re
|
||||
from systemd import journal
|
||||
|
||||
|
||||
|
@ -31,29 +33,73 @@ repo_path = '/opt/opengnsys/ogrepository/images' # En este caso, no lleva barra
|
|||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def run_bittornado(repo_path):
|
||||
""" Ejecuta el comando "btlaunchmany.bittornado", con sus parámetros correspondientes.
|
||||
Además, captura el resultado y los posibles errores, y los imprime.
|
||||
"""
|
||||
# Creamos una lista con el comando "btlaunchmany.bittornado" y sus parámetros, y lo imprimimos con espacios:
|
||||
splitted_cmd = f"btlaunchmany.bittornado {repo_path}".split()
|
||||
print(f"Sending command: {' '.join(splitted_cmd)}")
|
||||
journal.send(f"runTorrentSeeder.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Ejecutamos el comando "btlaunchmany.bittornado" en el sistema, e imprimimos el resultado:
|
||||
# def run_bittornado(repo_path):
|
||||
# """ Ejecuta el comando "btlaunchmany.bittornado", con sus parámetros correspondientes.
|
||||
# Además, captura el resultado y los posibles errores, y los imprime.
|
||||
# """
|
||||
# # Creamos una lista con el comando "btlaunchmany.bittornado" y sus parámetros, y lo imprimimos con espacios:
|
||||
# splitted_cmd = f"btlaunchmany.bittornado {repo_path}".split()
|
||||
# print(f"Sending command: {' '.join(splitted_cmd)}")
|
||||
# journal.send(f"runTorrentSeeder.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# # Ejecutamos el comando "btlaunchmany.bittornado" en el sistema, e imprimimos el resultado:
|
||||
# try:
|
||||
# result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
# journal.send(f"runTorrentSeeder.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# print(f"Bittornado ReturnCode: {result.returncode}")
|
||||
# except subprocess.CalledProcessError as error:
|
||||
# journal.send("runTorrentSeeder.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# print(f"Bittornado ReturnCode: {error.returncode}")
|
||||
# print(f"Bittornado Error Output: {error.stderr.decode()}")
|
||||
# except Exception as error:
|
||||
# journal.send(f"runTorrentSeeder.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# print(f"Unexpected bittornado error: {error}")
|
||||
|
||||
|
||||
|
||||
def run_aria2c_seeder(image_name):
|
||||
"""Lanza aria2c como seeder puro para una imagen concreta ya existente."""
|
||||
|
||||
repo_path = '/opt/opengnsys/ogrepository/images'
|
||||
torrent_file = os.path.join(repo_path, f"{image_name}.img.torrent")
|
||||
image_file = os.path.join(repo_path, f"{image_name}.img")
|
||||
|
||||
# Verificación básica
|
||||
if not os.path.exists(torrent_file):
|
||||
print(f"Torrent file not found: {torrent_file}")
|
||||
journal.send(f"Seeder error: Torrent file not found: {torrent_file}",
|
||||
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
|
||||
return
|
||||
|
||||
if not os.path.exists(image_file):
|
||||
print(f"Image file not found: {image_file}")
|
||||
journal.send(f"Seeder error: Image file not found: {image_file}",
|
||||
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
|
||||
return
|
||||
|
||||
# Comando aria2c como seeder puro
|
||||
cmd = [
|
||||
'aria2c',
|
||||
'--enable-peer-exchange=true',
|
||||
'--bt-seed-unverified=true',
|
||||
'--check-integrity=true',
|
||||
'--seed-ratio=0.0',
|
||||
'--dir=' + repo_path,
|
||||
torrent_file
|
||||
]
|
||||
|
||||
journal.send(f"Launching aria2c seeder for {image_name}",
|
||||
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api")
|
||||
journal.send(f"Command: {' '.join(cmd)}",
|
||||
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api")
|
||||
print("Running command:", ' '.join(cmd))
|
||||
try:
|
||||
result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
journal.send(f"runTorrentSeeder.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Bittornado ReturnCode: {result.returncode}")
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send("runTorrentSeeder.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Bittornado ReturnCode: {error.returncode}")
|
||||
print(f"Bittornado Error Output: {error.stderr.decode()}")
|
||||
except Exception as error:
|
||||
journal.send(f"runTorrentSeeder.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Unexpected bittornado error: {error}")
|
||||
|
||||
|
||||
subprocess.run(cmd, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
journal.send(f"aria2c seeder failed: {e}",
|
||||
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api")
|
||||
print(f"Seeder process exited with code {e.returncode}")
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
|
@ -64,16 +110,40 @@ def main():
|
|||
"""
|
||||
"""
|
||||
# Finalizamos el proceso "btlaunchmany.bittornado" (en caso de que estuviera corriendo):
|
||||
try:
|
||||
journal.send("runTorrentSeeder.py: Killing process 'btlaunchmany.bittornado'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
subprocess.run(f"pkill btlaunchmany".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except Exception as error_description:
|
||||
journal.send("runTorrentSeeder.py: No 'btlaunchmany.bittornado' process running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"No btlaunchmany.bittornado process running? Returned error: {error_description}")
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: runTorrentSeeder.py <image_name>")
|
||||
journal.send("runTorrentSeeder.py: Invalid number of arguments. Expected 1 argument: <image_name>",
|
||||
PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sys.exit(1)
|
||||
|
||||
image_name = sys.argv[1]
|
||||
torrent_file = os.path.join(repo_path, f"{image_name}.img.torrent")
|
||||
found = False
|
||||
# Matamos los procesos de aria2c que sirvan la imagen en concreto. Chequeamos todos los procesos
|
||||
|
||||
# Ejecutamos el comando "btlaunchmany.bittornado" (para hacer seed de los torrents):
|
||||
run_bittornado(repo_path)
|
||||
journal.send(f"runTorrentSeeder.py: looking for aria2c processes for {image_name}.torrent",
|
||||
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
for proc in psutil.process_iter(['pid','name','cmdline']):
|
||||
try:
|
||||
if proc.info['name'] != 'aria2c':
|
||||
continue
|
||||
|
||||
if any(arg.endswith(torrent_file) for arg in proc.info['cmdline']):
|
||||
proc.terminate()
|
||||
found = True
|
||||
print(f"Killed aria2c process with PID {proc.info['pid']} for {image_name}.torrent")
|
||||
journal.send(f"runTorrentSeeder.py: Killed aria2c process with PID {proc.info['pid']} for {image_name}.torrent",
|
||||
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
continue
|
||||
|
||||
if not found:
|
||||
print(f"No aria2c process found for {image_name}.torrent")
|
||||
journal.send(f"runTorrentSeeder.py: No aria2c process found for {image_name}.torrent",
|
||||
PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Lanzamos aria2c como seeder para la imagen proporcionada
|
||||
run_aria2c_seeder(image_name)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -27,7 +27,7 @@ def kill_seeder():
|
|||
que corresponde al seeder P2P.
|
||||
"""
|
||||
try:
|
||||
subprocess.run(f"pkill btlaunchmany".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(f"sudo pkill -9 btlaunchmany".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
print("Process btlaunchmany.bittornado finalized")
|
||||
except Exception as error_description:
|
||||
print(f"No btlaunchmany.bittornado process running? Returned error: {error_description}")
|
||||
|
@ -39,7 +39,7 @@ def kill_tracker():
|
|||
que corresponde al tracker P2P.
|
||||
"""
|
||||
try:
|
||||
subprocess.run(f"pkill bttrack".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(f"sudo pkill -9 bttrack".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
print("Process bttrack finalized")
|
||||
except Exception as error_description:
|
||||
print(f"No bttrack process running? Returned error: {error_description}")
|
||||
|
|
|
@ -115,7 +115,7 @@ def kill_udp_sender(pid):
|
|||
"""
|
||||
try:
|
||||
# Finalizamos el proceso asociado al pid especificado como parámetro, e imprimimos el return code:
|
||||
result = subprocess.run(f"kill {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(f"sudo kill -9 {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
print(f"ReturnCode: {result.returncode}")
|
||||
# Si se ha producido una excepción, imprimimos el error y salimos del script:
|
||||
except Exception as error_description:
|
||||
|
|
|
@ -115,7 +115,7 @@ def kill_uftp(pid):
|
|||
"""
|
||||
try:
|
||||
# Finalizamos el proceso asociado al pid especificado como parámetro, e imprimimos el return code:
|
||||
result = subprocess.run(f"kill {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(f"sudo kill -9 {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
print(f"ReturnCode: {result.returncode}")
|
||||
# Si se ha producido una excepción, imprimimos el error y salimos del script:
|
||||
except Exception as error_description:
|
||||
|
|
|
@ -1,3 +1,43 @@
|
|||
ogrepository (1.1.5) UNRELEASED; urgency=medium
|
||||
|
||||
* refs #2363 Fix breaking forgejo permissions
|
||||
|
||||
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 1 Jul 2025 16:05:12 +0000
|
||||
|
||||
ogrepository (1.1.4) UNRELEASED; urgency=medium
|
||||
|
||||
* refs #2363 Reduce number of required dependencies
|
||||
|
||||
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:50:11 +0000
|
||||
|
||||
ogrepository (1.1.3) UNRELEASED; urgency=medium
|
||||
|
||||
* refs #2317 Fix performance problems, remove stats
|
||||
* refs #2298 Add commmits endpoint
|
||||
|
||||
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:50:11 +0000
|
||||
|
||||
|
||||
ogrepository (1.1.2) UNRELEASED; urgency=medium
|
||||
|
||||
* Fix path handling when there are no repositories
|
||||
* Add another search path for installer module
|
||||
* Fix path handling
|
||||
* Add SSH key endpoint
|
||||
* Update dependencies
|
||||
|
||||
-- OpenGnsys <opengnsys@opengnsys.com> Tue, 30 Jun 2025 15:20:23 +0000
|
||||
|
||||
ogrepository (1.1.1) unstable; urgency=medium
|
||||
* OgGit - fix repo path handling
|
||||
|
||||
-- Tu Nombre <tuemail@example.com> Jue, 5 Jun 2025 08:43:58 +0000
|
||||
|
||||
ogrepository (1.1.0) unstable; urgency=medium
|
||||
* OgGit
|
||||
|
||||
-- Tu Nombre <tuemail@example.com> Tue, 11 Mar 2025 04:43:58 +0000
|
||||
|
||||
ogrepository (1.0.0+deb-packages20250311-1) unstable; urgency=medium
|
||||
|
||||
* First debian version
|
||||
|
|
|
@ -8,6 +8,7 @@ Build-Depends: debhelper-compat (= 12)
|
|||
Package: ogrepository
|
||||
Architecture: all
|
||||
Pre-Depends: debian-archive-keyring , debconf (>= 1.5.0),
|
||||
Depends: ${misc:Depends}, git, python3, python3-pip, python3-flask, python3-paramiko, python3-psutil, python3-flasgger, samba, gunicorn, wakeonlan , lzop , partclone , qemu-utils , udpcast
|
||||
Depends: ${misc:Depends}, git, python3, python3-pip, python3-flask, python3-paramiko, python3-psutil, python3-flasgger, samba, gunicorn, wakeonlan , lzop , partclone , qemu-utils , udpcast, uftp, mktorrent, aria2 , opengnsys-opentracker, opengnsys-forgejo, python3-git
|
||||
Description: Ogrepsoitory Package
|
||||
This package provides Ogrepsoitory service.
|
||||
This package provides Ogrepository service.
|
||||
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -x
|
||||
set -x
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
restore_config_if_modified() {
|
||||
local new="$1"
|
||||
local backup="$1.bak.upgrade_package"
|
||||
|
||||
if [ -f "$backup" ]; then
|
||||
if ! cmp -s "$new" "$backup"; then
|
||||
echo ">>> Archivo modificado por el usuario detectado en $new"
|
||||
echo " - Guardando archivo nuevo como ${new}.new"
|
||||
mv -f "$new" "${new}.new"
|
||||
echo " - Restaurando archivo anterior desde backup"
|
||||
mv -f "$backup" "$new"
|
||||
else
|
||||
echo ">>> El archivo $new no ha cambiado desde la última versión, eliminando backup"
|
||||
rm -f "$backup"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Cargar variables de configuración
|
||||
db_get opengnsys/ogrepository_ogrepoIp
|
||||
OGREPO_IP="$RET"
|
||||
|
@ -19,10 +38,20 @@ SAMBA_PASS="$RET"
|
|||
USER="opengnsys"
|
||||
|
||||
|
||||
# Provisionar base de datos si es necesario en caso de instalación.
|
||||
# Provisionar base de datos si es necesario en caso de instalación.
|
||||
|
||||
|
||||
# Detectar si es una instalación nueva o una actualización
|
||||
# if [ "$1" = "configure" ] && [ -z "$2" ]; then
|
||||
# systemd-run --no-block /bin/bash -c "
|
||||
# sleep 10;
|
||||
# apt update -y;
|
||||
# for pkg in bittorrent bittornado ctorrent; do
|
||||
# if ! dpkg -l | grep -qw \"\$pkg\"; then
|
||||
# apt install -y \"\$pkg\"
|
||||
# fi
|
||||
# done
|
||||
# "
|
||||
if [ "$1" = "configure" ] && [ -z "$2" ]; then
|
||||
systemd-run --no-block /bin/bash -c "
|
||||
sleep 10;
|
||||
|
@ -33,7 +62,7 @@ for pkg in bittorrent bittornado ctorrent; do
|
|||
fi
|
||||
done
|
||||
"
|
||||
|
||||
|
||||
sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/systemd/system/ogrepo-api.service
|
||||
sed -i "s/%%OGREPOSITORY_USER%%/$SAMBA_USER/g" /etc/samba/ogrepo-smb.conf
|
||||
|
||||
|
@ -45,30 +74,72 @@ done
|
|||
# Copy ssh keys
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys $OPENGNSYS_HOME/.ssh/id_ed25519
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys.pub $OPENGNSYS_HOME/.ssh/id_ed25519.pub
|
||||
# Change permissions
|
||||
chmod 700 $OPENGNSYS_HOME/.ssh
|
||||
chmod 600 $OPENGNSYS_HOME/.ssh/id_ed25519
|
||||
chmod 644 $OPENGNSYS_HOME/.ssh/id_ed25519.pub
|
||||
# Genera authorized_keys
|
||||
cat $OPENGNSYS_HOME/.ssh/id_ed25519.pub >> $OPENGNSYS_HOME/.ssh/authorized_keys
|
||||
chmod 600 $OPENGNSYS_HOME/.ssh/authorized_keys
|
||||
chown -R opengnsys:opengnsys $OPENGNSYS_HOME/.ssh
|
||||
|
||||
if [ -f /etc/samba/smb.conf ]; then
|
||||
dpkg-divert --package ogrepository --add --rename --divert /etc/samba/smb.conf.orig /etc/samba/smb.conf
|
||||
cp /etc/samba/smb.conf.orig /etc/samba/smb.conf
|
||||
if ! grep -q "include = /etc/samba/ogrepo-smb.conf" /etc/samba/smb.conf; then
|
||||
echo "include = /etc/samba/ogrepo-smb.conf" >> /etc/samba/smb.conf
|
||||
fi
|
||||
(echo "$SAMBA_PASS"; echo "$SAMBA_PASS") | smbpasswd -a $SAMBA_USER
|
||||
fi
|
||||
# Incluir el archivo de configuración de samba si no está incluido ya
|
||||
if ! grep -q "include = /etc/samba/ogrepo-smb.conf" /etc/samba/smb.conf; then
|
||||
echo "include = /etc/samba/ogrepo-smb.conf" >> /etc/samba/smb.conf
|
||||
fi
|
||||
|
||||
(echo "$SAMBA_PASS"; echo "$SAMBA_PASS") | smbpasswd -a $SAMBA_USER
|
||||
|
||||
# Configure Repo
|
||||
systemctl enable ogrepo-api
|
||||
# Configure Repo
|
||||
|
||||
cp /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg.tmpl /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg
|
||||
sed -i "s/SERVERIP/$OGREPO_IP/g" /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg
|
||||
sed -i "s/OGCOREIP/$OGCORE_IP/g" /opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg
|
||||
|
||||
# Copiar sudoers file ogrepository/etc/opengnsys-repository
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys-repository /etc/sudoers.d/opengnsys
|
||||
elif [ "$1" = "configure" ] && [ -n "$2" ]; then
|
||||
echo "Actualización desde la versión $2"
|
||||
# Recopy static files without configuration
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys-repository /etc/sudoers.d/opengnsys-repository
|
||||
OPENGNSYS_HOME=$(getent passwd opengnsys | cut -d: -f6)
|
||||
# Create .ssh directory
|
||||
mkdir -p $OPENGNSYS_HOME/.ssh
|
||||
# Copy ssh keys
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys $OPENGNSYS_HOME/.ssh/id_ed25519
|
||||
cp /opt/opengnsys/ogrepository/etc/opengnsys.pub $OPENGNSYS_HOME/.ssh/id_ed25519.pub
|
||||
cat $OPENGNSYS_HOME/.ssh/id_ed25519.pub >> $OPENGNSYS_HOME/.ssh/authorized_keys
|
||||
|
||||
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg"
|
||||
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/repoinfo.json"
|
||||
restore_config_if_modified "/opt/opengnsys/ogrepository/etc/trashinfo.json"
|
||||
restore_config_if_modified "/etc/samba/smb.conf"
|
||||
restore_config_if_modified "/etc/samba/ogrepo-smb.conf"
|
||||
restore_config_if_modified "/etc/sudoers.d/opengnsys-repository"
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Cambiar la propiedad de los archivos al usuario especificado
|
||||
chown opengnsys:www-data /opt/opengnsys/
|
||||
chown -R opengnsys:www-data /opt/opengnsys/ogrepository
|
||||
chmod 755 /opt/opengnsys
|
||||
chmod 755 /opt/opengnsys/ogrepository/bin/*
|
||||
|
||||
# oggit -- these are from opengnsys-forgejo, and we're overwriting their
|
||||
# permissions above.
|
||||
#
|
||||
# Check if the paths exist just in case the opengnsys-forgejo package
|
||||
# stops being a dependency.
|
||||
if [ -d "/opt/opengnsys/ogrepository/var/lib/forgejo/" ] ; then
|
||||
chown -R oggit:oggit /opt/opengnsys/ogrepository/var/lib/forgejo/
|
||||
fi
|
||||
|
||||
if [ -d "/opt/opengnsys/ogrepository/oggit/" ] ; then
|
||||
chown -R oggit:oggit /opt/opengnsys/ogrepository/oggit/
|
||||
fi
|
||||
|
||||
# Install http server stuff
|
||||
# Reiniciar servicios si es necesario
|
||||
|
|
|
@ -2,19 +2,13 @@
|
|||
|
||||
set -e
|
||||
|
||||
|
||||
NGINX_FILE="/etc/nginx/sites-enabled/oggui.conf"
|
||||
UNIT_FILE="/etc/systemd/system/oggui.service"
|
||||
UNIT_FILE="/etc/systemd/system/ogrepo-api.service"
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove)
|
||||
echo "El paquete se está desinstalando..."
|
||||
# Aquí puedes hacer limpieza de archivos o servicios
|
||||
if [ -L "$NGINX_FILE" ]; then
|
||||
rm -f "$NGINX_FILE"
|
||||
systemctl restart nginx
|
||||
fi
|
||||
if [ -L "$UNIT_FILE" ]; then
|
||||
rm -f "$UNIT_FILE"
|
||||
systemctl daemon-reload
|
||||
|
|
|
@ -2,8 +2,18 @@
|
|||
|
||||
set -e
|
||||
|
||||
KEY_FILE="/usr/share/keyrings/debian-archive-buster-stable.gpg"
|
||||
REPO_FILE="/etc/apt/sources.list.d/buster.list"
|
||||
backup_file_if_exists() {
|
||||
local original="$1"
|
||||
local backup="$1.bak.upgrade_package"
|
||||
|
||||
if [ -e "$original" ]; then
|
||||
echo " - Guardando backup de $original en $backup"
|
||||
cp -a "$original" "$backup"
|
||||
fi
|
||||
}
|
||||
|
||||
# KEY_FILE="/usr/share/keyrings/debian-archive-buster-stable.gpg"
|
||||
# REPO_FILE="/etc/apt/sources.list.d/buster.list"
|
||||
|
||||
# Asegurarse de que el usuario exista
|
||||
USER="opengnsys"
|
||||
|
@ -20,10 +30,17 @@ echo "Añadiendo el repositorio de Debian Buster en $REPO_FILE..."
|
|||
mkdir -p "$(dirname "$REPO_FILE")"
|
||||
|
||||
# Crear el archivo de repositorio si no existe
|
||||
if [ ! -f "$REPO_FILE" ]; then
|
||||
echo "deb [signed-by=$KEY_FILE] http://ftp.de.debian.org/debian buster main" > "$REPO_FILE"
|
||||
else
|
||||
echo "El repositorio ya está configurado en $REPO_FILE"
|
||||
fi
|
||||
# if [ ! -f "$REPO_FILE" ]; then
|
||||
# echo "deb [signed-by=$KEY_FILE] http://ftp.de.debian.org/debian buster main" > "$REPO_FILE"
|
||||
# else
|
||||
# echo "El repositorio ya está configurado en $REPO_FILE"
|
||||
# fi
|
||||
|
||||
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg"
|
||||
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/repoinfo.json"
|
||||
backup_file_if_exists "/opt/opengnsys/ogrepository/etc/trashinfo.json"
|
||||
backup_file_if_exists "/etc/samba/smb.conf"
|
||||
backup_file_if_exists "/etc/samba/ogrepo-smb.conf"
|
||||
backup_file_if_exists "/etc/sudoers.d/ogrepository"
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -44,11 +44,18 @@ case "$1" in
|
|||
rm -f /var/lib/dpkg/info/ogrepository.post-invoke
|
||||
fi
|
||||
|
||||
# Remove sudoers file
|
||||
if [ -f /etc/sudoers.d/opengnsys-repository ]; then
|
||||
echo "Removing sudoers file..."
|
||||
rm -f /etc/sudoers.d/opengnsys-repository
|
||||
fi
|
||||
|
||||
echo "Limpieza completada."
|
||||
;;
|
||||
|
||||
upgrade|deconfigure)
|
||||
# No hacer nada en actualización o desconfiguración
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# Variables para facilitar la lectura
|
||||
Cmnd_Alias MOUNT_RECOVERY = \
|
||||
/usr/bin/mkdir -p /mnt/recovery, \
|
||||
/usr/bin/mount /dev/* /mnt/recovery, \
|
||||
/usr/bin/mount --bind /dev /mnt/recovery/dev, \
|
||||
/usr/bin/mount --bind /proc /mnt/recovery/proc, \
|
||||
/usr/bin/mount --bind /sys /mnt/recovery/sys, \
|
||||
/usr/bin/umount /mnt/recovery/dev, \
|
||||
/usr/bin/umount /mnt/recovery/proc, \
|
||||
/usr/bin/umount /mnt/recovery/sys, \
|
||||
/usr/bin/umount -l /mnt/recovery
|
||||
|
||||
Cmnd_Alias CHROOT_GRUB = \
|
||||
/usr/sbin/chroot /mnt/recovery /usr/sbin/grub-install --target=i386-pc *, \
|
||||
/usr/sbin/chroot /mnt/recovery /usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg
|
||||
|
||||
Cmnd_Alias LOOP_KPARTX = \
|
||||
/usr/sbin/losetup -d *, \
|
||||
/usr/sbin/kpartx -av /opt/opengnsys/ogrepository/images_virtual/*, \
|
||||
/usr/sbin/kpartx -d /opt/opengnsys/ogrepository/images_virtual/*, \
|
||||
/usr/sbin/blkid /dev/mapper/*
|
||||
|
||||
Cmnd_Alias KILL_BT = \
|
||||
/usr/bin/pkill -9 btlaunchmany, \
|
||||
/usr/bin/pkill -9 bttrack, \
|
||||
/usr/bin/kill -9 *
|
||||
|
||||
Cmnd_Alias PYTHON_OGREPO = /usr/bin/python3 /opt/opengnsys/ogrepository/bin/*
|
||||
|
||||
# Permitir al usuario opengnsys ejecutar estos comandos sin contraseña
|
||||
opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, KILL_BT, PYTHON_OGREPO
|
|
@ -3,8 +3,8 @@ Description=Gunicorn instance to serve repo_api
|
|||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=%%OGREPOSITORY_USER%%
|
||||
Group=%%OGREPOSITORY_USER%%
|
||||
User=opengnsys
|
||||
Group=opengnsys
|
||||
WorkingDirectory=/opt/opengnsys/ogrepository/api
|
||||
ExecStart=/usr/bin/gunicorn -w 4 -b 0.0.0.0:8006 repo_api:app
|
||||
|
||||
|
|
Loading…
Reference in New Issue