Compare commits
No commits in common. "main" and "fix_installer" have entirely different histories.
main
...
fix_instal
|
@ -1,9 +0,0 @@
|
|||
### Debian packaging
|
||||
debian/ogrepository
|
||||
debian/*.substvars
|
||||
debian/*.log
|
||||
debian/.debhelper/
|
||||
debian/files
|
||||
debian/*.debhelper
|
||||
debian/*.debhelper.log
|
||||
debian/debhelper-build-stamp
|
209
CHANGELOG.md
209
CHANGELOG.md
|
@ -1,209 +0,0 @@
|
|||
# Changelog
|
||||
|
||||
## [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)
|
|
@ -1,113 +0,0 @@
|
|||
@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"
|
||||
// }
|
||||
// }
|
||||
|
523
README.md
523
README.md
|
@ -4,6 +4,7 @@ ogRepository - OpenGnsys Repository Manager
|
|||
|
||||
Este repositorio GIT contiene la estructura de datos del repositorio de imágenes de OpenGnsys.
|
||||
|
||||
- **admin** --- Archivos de configuración de ogRepository.
|
||||
- **api** ------ API de ogRepository.
|
||||
- **bin** ------ Scripts en Python 3 y binarios de gestión de ogRepository.
|
||||
- **etc** ------ Ficheros y plantillas de configuración de ogRepository.
|
||||
|
@ -14,34 +15,27 @@ Este repositorio GIT contiene la estructura de datos del repositorio de imágene
|
|||
## Requerimientos:
|
||||
|
||||
Paquetes APT requeridos:
|
||||
- **uftp** (se puede instalar con "sudo DEBIAN_FRONTEND=noninteractive apt install uftp -y", para que no pida la ruta predeterminada, y se debe deshabilitar el servicio)
|
||||
- **uftp** (se puede instalar con "sudo DEBIAN_FRONTEND=noninteractive apt install uftp -y", para que no pida la ruta predeterminada)
|
||||
- **udpcast** (se puede instalar con "sudo apt install ./udpcast_20230924_amd64.deb", apuntando al paquete)
|
||||
- **ctorrent** (se puede instalar con "sudo apt install ctorrent")
|
||||
- **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")
|
||||
- **paramiko** (se puede instalar con "sudo apt install python3-paramiko")
|
||||
- **psutil** (se puede instalar con "sudo apt install python3-psutil")
|
||||
- **flasgger** (se puede instalar con "sudo apt install python3-flasgger")
|
||||
- **requests** (se puede instalar con "sudo apt install python3-requests", pero no es necesario en Ubuntu 24)
|
||||
|
||||
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")
|
||||
- **/opt/opengnsys/ogrepository/log/** (aquí se guardan los logs)
|
||||
|
||||
Y también debe existir el siguiente archivo:
|
||||
- **/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg** (de aquí pilla su IP y la de ogCore)
|
||||
- **/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg** (de aquí pilla la IP de ogRepository)
|
||||
|
||||
---
|
||||
|
||||
|
@ -62,26 +56,23 @@ 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. [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}`
|
||||
9. [Importar una Imagen](#importar-una-imagen) - `POST /ogrepository/v1/repo/images`
|
||||
10. [Exportar una Imagen](#exportar-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`
|
||||
15. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /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`
|
||||
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`
|
||||
|
||||
---
|
||||
### Obtener Información de Estado de ogRepository
|
||||
|
||||
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 devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, 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.
|
||||
|
||||
|
@ -100,9 +91,6 @@ 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%"
|
||||
},
|
||||
|
@ -127,7 +115,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
"udp-sender": "stopped",
|
||||
"uftp": "stopped",
|
||||
"bttrack": "stopped",
|
||||
"btlaunchmany.bittornado": "stopped"
|
||||
"btlaunchmany": "stopped"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -136,7 +124,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
|
||||
Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/ogrepository/etc/repoinfo.json**" (que corresponde a todas las imágenes almacenadas en el repositorio), y en el archivo "**/opt/opengnsys/ogrepository/etc/trashinfo.json**" (que corresponde a las imágenes que fueron eliminadas, que estarán en la papelera).
|
||||
Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
**NOTA**: El script requiere que en este caso se le pase "all" como parámetro, pero el endpoint se ejecuta sin parámetros.
|
||||
**NOTA**: El script requiere que se le pase "all" como primer parámetro (que correspondería al nombre de la imagen) y "none" como segundo parámetro (que corresponderia al nombre del subdirectorio correspondiente a la OU). Esta transformación de parámetros se realiza en la API.
|
||||
|
||||
**URL:** `/ogrepository/v1/images`
|
||||
**Método HTTP:** GET
|
||||
|
@ -159,7 +147,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Ubuntu24",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu24_clientname",
|
||||
"clientname": "Ubuntu_24",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
|
@ -171,7 +159,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Windows10",
|
||||
"type": "img",
|
||||
"clientname": "Windows10_clientname",
|
||||
"clientname": "Windows_10",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "NTFS",
|
||||
|
@ -180,15 +168,15 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
"sum": "8874d5ab84314f44841c36c69bb5aa82",
|
||||
"fullsum": "9e7cd32c606ebe5bd39ba212ce7aeb02"
|
||||
}
|
||||
]
|
||||
},
|
||||
"TRASH": {
|
||||
"directory": "/opt/opengnsys/ogrepository/images_trash",
|
||||
],
|
||||
"ous": [
|
||||
{
|
||||
"subdir": "OU_subdir",
|
||||
"images": [
|
||||
{
|
||||
"name": "Ubuntu20",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu20_clientname",
|
||||
"clientname": "Ubuntu_20",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
|
@ -199,6 +187,31 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"TRASH": {
|
||||
"directory": "/opt/opengnsys/ogrepository/images_trash",
|
||||
"images": [],
|
||||
"ous": [
|
||||
{
|
||||
"subdir": "CentroVirtual",
|
||||
"images": [
|
||||
{
|
||||
"name": "Ubuntu20OLD",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu_20",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
"datasize": 8912896000000,
|
||||
"size": 3803794535,
|
||||
"sum": "081a933c780ab1aaa044435ad5d4bf56",
|
||||
"fullsum": "22735b9070e4a8043371b8c6ae52b90d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- **name**: Nombre de la imagen, sin extensión.
|
||||
|
@ -217,7 +230,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
|
||||
Se devolverá la informacion de la imagen especificada, que puede estar en el archivo "**/opt/opengnsys/ogrepository/etc/repoinfo.json**" o en el archivo "**/opt/opengnsys/ogrepository/etc/trashinfo.json**" (en este último caso, si la imagen está en la papelera).
|
||||
Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
**NOTA**: El script requiere que en este caso 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el subdirectorio correspondiente a la OU (o "none" si no es el caso) como segundo parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/{ID_img}`
|
||||
**Método HTTP:** GET
|
||||
|
@ -240,7 +253,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Windows10",
|
||||
"type": "img",
|
||||
"clientname": "Windows10_clientname",
|
||||
"clientname": "Windows_10",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "NTFS",
|
||||
|
@ -287,7 +300,7 @@ curl -X PUT -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
|
||||
Se comprobará la integridad del fichero de imagen especificado como parámetro.
|
||||
Se puede hacer con el script "**checkImage.py**", que compara el tamaño actual del archivo con el almacenado en el archivo "**.size**", y el hash MD5 del último MB del archivo con el almacenado en el archivo "**.sum**".
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/status/images/{ID_img}`
|
||||
**Método HTTP:** GET
|
||||
|
@ -308,7 +321,7 @@ curl -X POST -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/sta
|
|||
|
||||
Se eliminará la imagen especificada como parámetro, pudiendo eliminarla permanentemente o enviarla a la papelera.
|
||||
Se puede hacer con el script "**deleteimage.py**", que debe ser llamado por el endpoint (y que incluye la funcionalidad "papelera"), y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). 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 también hay que especificar el método de eliminación en la URL, para enviar o no el parámetro opcional.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros, pero también hay que especificar el método de eliminación en la URL, como parámetro adicional.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/{ID_img}?method={method}`
|
||||
**Método HTTP:** DELETE
|
||||
|
@ -331,7 +344,7 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/i
|
|||
|
||||
Se recuperará la imagen especificada como parámetro, desde la papelera.
|
||||
Se puede hacer con el script "**recoverImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/trash/images`
|
||||
**Método HTTP:** POST
|
||||
|
@ -354,7 +367,7 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
|
||||
Se eliminará permanentemente la imagen especificada como parámetro, desde la papelera.
|
||||
Se puede hacer con el script "**deleteTrashImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera.
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/trash/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
@ -369,12 +382,113 @@ 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.
|
||||
|
||||
---
|
||||
### Importar una Imagen
|
||||
|
||||
Se importará una imagen de un repositorio remoto al repositorio local.
|
||||
Se puede hacer con el script "**importImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. Estos parámetros deben enviarse desde ogCore (en el JSON), porque el repositorio local no puede extraer la información de la imagen de un ID almacenado en un repositorio remoto.
|
||||
**NOTA2**: 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).
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (desde el que se importará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none", "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 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se está importando.
|
||||
|
||||
---
|
||||
### Exportar una Imagen
|
||||
|
||||
Se exportará una imagen del repositorio local a un repositorio remoto.
|
||||
Se puede hacer con el script "**exportImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer 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 IP del repositorio remoto y el usuario remoto 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 se está exportando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (al que se exportrará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "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 exportar 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á exportando.
|
||||
|
||||
---
|
||||
### Crear archivos auxiliares
|
||||
|
||||
Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro.
|
||||
Se puede hacer con el script "**createTorrentSum.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como unico parámetro. Este parámetro no puede obtenerse en la API, a partir del ID de imagen (como en otros casos), porque el ID corresponde al contenido del archivo "full.sum" asociado (que no estará creado hasta que no se ejecute este script).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar cierto tiempo, por lo que solo informa de que los archivos auxiliares se están creando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/torrentsum`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/torrentsum
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al crear los archivos auxiliares.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** Los archivos auxiliares se están creando.
|
||||
|
||||
---
|
||||
### Enviar paquete Wake On Lan
|
||||
|
||||
Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada.
|
||||
Se puede hacer con el script "**sendWakeOnLan.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase la dirección IP de broadcast como primer parámetro, y la dirección MAC destino como segundo parámetro. Estos datos deben enviarse desde ogCore (en el JSON).
|
||||
|
||||
**URL:** `/ogrepository/v1/wol`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **broadcast_ip**: IP de broadcast a la que enviar el paquete (puede ser "255.255.255.255", o la IP de broadcast de una subred).
|
||||
- **mac**: Dirección MAC del equipo que se desea encender via Wake On Lan.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"broadcast_ip":"255.255.255.255", "mac":"00:19:99:5c:bb:bb"}' http://example.com/ogrepository/v1/wol
|
||||
```
|
||||
**Respuestas:**
|
||||
- **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).
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) 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`
|
||||
|
@ -399,6 +513,58 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
- **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, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) 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 la raiz del directorio especificado).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts requieren que se les pase el directorio en el que está situada la imagen a enviar como único parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
**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
|
||||
|
||||
|
@ -430,54 +596,6 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpc
|
|||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### 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
|
||||
|
||||
|
@ -509,12 +627,33 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
|||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### 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, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único 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").
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único 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
|
||||
|
@ -530,30 +669,6 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/u
|
|||
- **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
|
||||
|
||||
|
@ -574,179 +689,3 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p
|
|||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Transferir una Imagen entre Repositorios
|
||||
|
||||
Se importará una imagen de un repositorio remoto al repositorio local (donde se ejecuta el endpoint).
|
||||
Se puede hacer con el script "**importImage.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, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. Estos parámetros deben enviarse desde ogCore (en el JSON), porque el repositorio local no puede extraer la información de la imagen de un ID almacenado en un repositorio remoto.
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está transfiriendo, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
**NOTA3**: Este endpoint comprueba si la importación se ha realizado correctamente, comparando el contenido de los archivos "sum" y "size" con los valores reales (que vuelve a calcular). Si la importación ha sido correcta llama al script "createTorrentSum.py", para crear el archivo ".torrent" (que debe crearse desde el repositorio en el que esté), y actualizar la info del repositorio. Si la importación no ha sido correcta (porque la imagen no ha pasado el check de integridad), borra los archivos importados.
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (desde el que se importará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
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 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á transfiriendo.
|
||||
|
||||
---
|
||||
### Hacer Backup de una Imagen
|
||||
|
||||
Se hará backup de una imagen en un equipo remoto, que no tiene por qué tener OpenGnsys instalado, pero que debe poder conectar por SSH (mediante claves) con el repositorio local.
|
||||
Se puede hacer con el script "**backupImage.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, la IP o hostname del repositorio remoto como segundo parámetro, el usuario remoto como tercer parámetro, y la ruta remota en la que se guardará el backup como cuarto 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 IP del repositorio remoto, el usuario remoto y la ruta remota deben 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á exportando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
**NOTA3**: Este endpoint comprueba si el backup se ha realizado correctamente, comparando el contenido de los archivos "sum" y "size" con los valores reales (que vuelve a calcular). Si el backup no ha sido correcto (porque la imagen no ha pasado el check de integridad), borra los archivos exportados.
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (al que se exportrará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
- **remote_path**: Ruta remota en la que copiar la imagen.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
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 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:** 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
|
||||
|
||||
Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro.
|
||||
Se puede hacer con el script "**createTorrentSum.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 parámetro. Este parámetro no puede obtenerse en la API, a partir del ID de imagen (como en otros casos), porque el ID corresponde al contenido del archivo "full.sum" asociado (que no estará creado hasta que no se ejecute este script).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar cierto tiempo, por lo que solo informa de que los archivos auxiliares se están creando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/torrentsum`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/torrentsum
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al crear los archivos auxiliares.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** Los archivos auxiliares se están creando.
|
||||
|
||||
---
|
||||
### Enviar paquete Wake On Lan
|
||||
|
||||
Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada.
|
||||
Se puede hacer con el script "**sendWakeOnLan.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: Este script requiere que se le pase la dirección IP de broadcast como primer parámetro, y la dirección MAC destino como segundo parámetro. Estos datos deben enviarse desde ogCore (en el JSON).
|
||||
|
||||
**URL:** `/ogrepository/v1/wol`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **broadcast_ip**: IP de broadcast a la que enviar el paquete (puede ser "255.255.255.255", o la IP de broadcast de una subred).
|
||||
- **mac**: Dirección MAC del equipo que se desea encender via Wake On Lan.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"broadcast_ip":"255.255.255.255", "mac":"00:19:99:5c:bb:bb"}' http://example.com/ogrepository/v1/wol
|
||||
```
|
||||
**Respuestas:**
|
||||
- **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.
|
||||
|
||||
---
|
|
@ -0,0 +1,285 @@
|
|||
#!/bin/bash
|
||||
PARM=`cat`
|
||||
#PARM=$@
|
||||
|
||||
|
||||
#TODO: ticket 379
|
||||
#buscar parametro de identificador de operacion.
|
||||
#usar parametro de identificacion para anexarlo al nombre de log
|
||||
#Comprobar si la variable está seteas.
|
||||
#Si no lo está setearla.
|
||||
#Si esta seteada (en progreso) salir.
|
||||
|
||||
|
||||
TIME=$SECONDS
|
||||
|
||||
BASEDIR=/opt/opengnsys
|
||||
PATH=$PATH:$BASEDIR/bin
|
||||
REPONAME=ogAdmRepo
|
||||
REPODIR="$BASEDIR/images/"
|
||||
|
||||
# Para las sincronizadas
|
||||
# BACKUP: Define si se realiza copia de seguridad al crear una imagen (true|false).
|
||||
# IMGFS: Sistema de ficheros al crear las sincronizadas tipo archivo (EXT4|BTRFS).
|
||||
[ -z $OGENGINECONFIGURATE ] && source $BASEDIR/client/etc/engine.cfg
|
||||
# FS segun la configuracion y la version del kernel. ext4 para < 3.7, para >= BTRFS
|
||||
KERNEL=$(file -bkr /opt/opengnsys/tftpboot/ogclient/ogvmlinuz |awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);printf("%d",v);sub(/[0-9]*\./,"",v);printf(".%02d",v)}}')
|
||||
[ $KERNEL \< 3.07 ] && IMGFS="EXT4" || IMGFS=${IMGFS:-"BTRFS"}
|
||||
|
||||
# Añade registro de incidencias.
|
||||
function echolog () {
|
||||
logger --tag $0 --priority local0.info "$*"
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
function mountImage () {
|
||||
#@param 1 image_file
|
||||
#@param 2 mount_dir
|
||||
#@param 3 openciones mount
|
||||
[ "$3" != "" ] && OPTMOUNT=" -o $3 "
|
||||
# Si está montado nada que hacer
|
||||
df |grep "$2$" 2>&1 >/dev/null && return 0
|
||||
# FS de la imagen segun el contenido del archivo .img
|
||||
if file "$1" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
echolog "mount $OPTMOUNT -t ext4 $1 $2"
|
||||
mount $OPTMOUNT -t ext4 $1 $2
|
||||
else
|
||||
echolog "mount $OPTMOUNT -o compress=lzo $1 $2"
|
||||
mount $OPTMOUNT -o compress=lzo "$1" "$2"
|
||||
fi
|
||||
# Si esta montado da error 32, lo damos como bueno
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 32 ] && RETVAL=0
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
|
||||
PARM1=$(echo $PARM | cut -f1 -d" ")
|
||||
PARM2=$(echo $PARM | cut -f2 -d" ")
|
||||
PARM3=$(echo $PARM | cut -f3 -d" ")
|
||||
PARM4=$(echo $PARM | cut -f4 -d" ")
|
||||
|
||||
# Determinamos el tipo de sistema de fichero de las imagenes segun el kernel que tenga
|
||||
|
||||
|
||||
case "$PARM1" in
|
||||
START_MULTICAST)
|
||||
#1 START_MULTICAST
|
||||
#2 fichero a enviar
|
||||
#3 opciones de multicast
|
||||
FILE="$PARM2"
|
||||
MCASTOPT="$PARM3"
|
||||
echolog "Ejecutar $(which sendFileMcast) $FILE $MCASTOPT"
|
||||
sendFileMcast $FILE $MCASTOPT |logger --tag $0 --priority local0.info
|
||||
case $? in
|
||||
1) echolog "Parametros insuficientes"
|
||||
exit 1 ;;
|
||||
2) echolog "Fichero no accesible"
|
||||
exit 2 ;;
|
||||
3) echolog "Sesion multicast no valida"
|
||||
exit 3 ;;
|
||||
esac
|
||||
;;
|
||||
CREATE_IMAGE)
|
||||
# Creamos/Redimensionamos el fichero de imagen y lo montamos para que se pueda escribir sobre el
|
||||
#1 CREATE_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
#4 tamaño imagen
|
||||
LOOPDEVICE=$(losetup -f)
|
||||
DIRMOUNT="$REPODIR/mount/$PARM2"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR/$PARM2.$IMGEXT"
|
||||
IMGDIR="$(dirname $IMGFILE)"
|
||||
[ -d $IMGDIR ] || mkdir -p $IMGDIR
|
||||
mkdir -p "$DIRMOUNT"
|
||||
|
||||
LOCKFILE="$IMGFILE.lock"
|
||||
|
||||
SIZEREQUIRED="$PARM4"
|
||||
|
||||
# Si existe la imagen hacemos copia de seguridad y la redimesionamos
|
||||
if [ -f "$IMGFILE" ]; then
|
||||
echolog "La imagen $IMGFILE ya existe."
|
||||
# TODO modificar ogGetImageSize
|
||||
IMGSIZE=$(ls -l --block-size=1024 $IMGFILE| cut -f5 -d" ")
|
||||
|
||||
if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" -o $IMGSIZE -lt $SIZEREQUIRED ]; then
|
||||
# Si la imagen esta montada la desmonto
|
||||
if [ -r "$DIRMOUNT/ogimg.info" ]; then
|
||||
echolog "umount $DIRMOUNT"
|
||||
umount "$DIRMOUNT"
|
||||
[ $? -ne 0 ] && echolog "Error: No podemos desmontar la imagen para hacer copia de seguridad o redimensionar" && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Copia de seguridad de la imagen
|
||||
if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" ]; then
|
||||
echolog "Copia de seguridad de la imagen anterior"
|
||||
echolog "cp $IMGFILE $IMGFILE.ant"
|
||||
cp "$IMGFILE" "$IMGFILE.ant"
|
||||
echolog mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null
|
||||
mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Redimensionamos la imagen al tamaño necesario
|
||||
if [ $IMGSIZE -lt $SIZEREQUIRED ];then
|
||||
echolog "Redimensionamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED"
|
||||
echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE"
|
||||
truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info
|
||||
# FS de la imagen segun el contenido del archivo .img
|
||||
if file "$IMGFILE" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
echolog "resize2fs -f $LOOPDEVICE"
|
||||
resize2fs -f $LOOPDEVICE |logger --tag $0 --priority local0.info
|
||||
else
|
||||
mount -o compress=lzo "$IMGFILE" "$DIRMOUNT"
|
||||
echolog "btrfs filesystem resize max $DIRMOUNT"
|
||||
btrfs filesystem resize max "$DIRMOUNT" 2>&1 |logger --tag $0 --priority local0.info
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Si no existe la imagen creamos el fichero.
|
||||
else
|
||||
echolog "Creamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED"
|
||||
touch "$IMGFILE"
|
||||
echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE"
|
||||
truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info
|
||||
#Formateamos imagen
|
||||
echo losetup $LOOPDEVICE "$IMGFILE"
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
if [ $IMGFS == "EXT4" ] ; then
|
||||
echolog " mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE"
|
||||
mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE
|
||||
else
|
||||
echolog mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE
|
||||
mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE #&> $OGLOGCOMMAND
|
||||
fi
|
||||
fi
|
||||
# Montamos la imagen.
|
||||
mountImage "$IMGFILE" "$DIRMOUNT"
|
||||
if [ $? -ne 0 ]; then
|
||||
rmdir "$DIRMOUNT"
|
||||
echolog "Error al crear/redimensionar la imagen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#touch "$DIRMOUNT/ogimg.info"
|
||||
echo "mounted"> "$LOCKFILE"
|
||||
TIME2=$[SECONDS-TIME]
|
||||
echolog "Fin creación/redimension de la imagen: $[TIME2/60]m $[TIME2%60]s"
|
||||
# Si existe dispositivo loop lo borramos.
|
||||
[ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE
|
||||
# TODO: comprobar que no se quede el losetup bloqueado.
|
||||
|
||||
;;
|
||||
MOUNT_IMAGE)
|
||||
# Montamos el fichero imagen para que se pueda
|
||||
#1 MOUNT_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
DIRMOUNT="$REPODIR""mount/$PARM2"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR/$PARM2.$IMGEXT"
|
||||
echolog "Montamos la imagen $IMGFILE "
|
||||
mkdir -p "$DIRMOUNT"
|
||||
mountImage "$IMGFILE" "$DIRMOUNT" ro || (echolog "Error al montar la imagen"; exit 1)
|
||||
;;
|
||||
UMOUNT_IMAGE)
|
||||
# Desmontamos el fichero imagen.
|
||||
# Si el directorio esta ocupado no se desmontará
|
||||
#1 UMOUNT_IMAGE
|
||||
#2 nombre imagen
|
||||
#3 tipo de imagen [ img | diff ]
|
||||
IMGTYPE="$PARM3"
|
||||
DIRMOUNT="$REPODIR/mount/$PARM2"
|
||||
if [ "$IMGTYPE" == "img" ]; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
DIRMOUNT="$DIRMOUNT.$IMGTYPE"
|
||||
IMGEXT="img.diff"
|
||||
fi
|
||||
LOCKFILE="$REPODIR/$PARM2.$IMGEXT.lock"
|
||||
echolog "Desmontamos la imagen $PARM2 $PARM3 "
|
||||
umount $DIRMOUNT
|
||||
rmdir $DIRMOUNT
|
||||
[ -f $LOCKFILE ] && sed -i s/mounted//g $LOCKFILE
|
||||
|
||||
;;
|
||||
REDUCE_IMAGE)
|
||||
# Reduce el archivo de la imagen a tamaño datos + 500M
|
||||
#1 REDUCE_IMAGE
|
||||
#2 Nombre Imagen
|
||||
#3 Tipo de imagen [ img |diff ]
|
||||
DIRMOUNT="${REPODIR}mount/${PARM2}"
|
||||
if [ "$PARM3" == "img" ] ; then
|
||||
IMGEXT="img"
|
||||
else
|
||||
IMGEXT="img.diff"
|
||||
DIRMOUNT="$DIRMOUNT.diff"
|
||||
fi
|
||||
IMGFILE="$REPODIR$PARM2.$IMGEXT"
|
||||
LOCKFILE="$IMGFILE.lock"
|
||||
[ ! -f $IMGFILE ] && echolog "Imagen $IMGFILE no existe" && exit 1
|
||||
|
||||
# Para imagenes EXT4 reduzco, para BTRFS solo desmonto.
|
||||
if file $IMGFILE |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then
|
||||
|
||||
[ -d $DIRMOUNT ] || mkdir $DIRMOUNT
|
||||
mountImage "$IMGFILE" "$DIRMOUNT" || (echolog "Error al montar la imagen $IMGFILE"; exit 1)
|
||||
|
||||
|
||||
# Si el espacio libre menor que 200Mb desmontamos la imagen y nos salimos
|
||||
AVAILABLE=$(df -k|grep $DIRMOUNT|awk '{print $4}')
|
||||
if [ $AVAILABLE -lt 200000 ]; then
|
||||
echolog "reducir imagen REPO $PARM2 $IMGEXT. tamaño minimo, nada que hacer"
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
else
|
||||
|
||||
# Calculamos la diferencia entre el tamaño interno y externo
|
||||
EXTSIZE=$(ls -l --block-size=1024 $IMGFILE | cut -f5 -d" ")
|
||||
INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}')
|
||||
let EDGESIZE=$EXTSIZE-$INTSIZE
|
||||
|
||||
echolog "reducir imagen REPO $PARM2 $IMGEXT, tamaño final: $ENDSIZE"
|
||||
umount $DIRMOUNT
|
||||
LOOPDEVICE=$(losetup -f)
|
||||
losetup $LOOPDEVICE "$IMGFILE"
|
||||
|
||||
# Redimensiono sistema de ficheros
|
||||
echolog "resize2fs -fpM $LOOPDEVICE "
|
||||
resize2fs -fpM $LOOPDEVICE # 2>&1 |logger --tag $0 --priority local0.info
|
||||
mountImage "$IMGFILE" "$DIRMOUNT"
|
||||
# Calculamos el tamaño final del archivo
|
||||
INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}')
|
||||
let EXTSIZE=$INTSIZE+$EDGESIZE
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
# Si existe dispositivo loop lo borramos.
|
||||
[ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE
|
||||
# Corto el archivo al tamaño del sistema de ficheros
|
||||
echo "truncate --size=\"$EXTSIZE\"k $IMGFILE"
|
||||
echolog "truncate --size=\"$EXTSIZE\"k $IMGFILE"
|
||||
truncate --size="$EXTSIZE"k $IMGFILE
|
||||
fi
|
||||
else
|
||||
umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1)
|
||||
fi
|
||||
rmdir $DIRMOUNT
|
||||
echo "reduced" >$LOCKFILE
|
||||
|
||||
;;
|
||||
default)
|
||||
echolog "Solicitud con parametros \"$PARM\" no realizada, no registrada o con errores"
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,15 @@
|
|||
# RUN_OGADMSERVER defined as OpenGnsys Admin Server
|
||||
# RUN_OGADMREPO defined as OpenGnsys Repository Manager
|
||||
# RUN_OGADMAGENT run task scheduler service, only if Admin Server is enabled
|
||||
# RUN_BTTRACKER run Bittorrent Tracker, only if Repository is enabled
|
||||
# RUN_BTSEEDER start seeding of selected torrent files, only if Repository is enabled
|
||||
# BTSEEDER_PRIORITY nice priority to seed torrent files; recommended values:
|
||||
# 8 for Admin Server or Repo without Torrent
|
||||
# 0 for Admin Server and Repo with Torrent
|
||||
# -8 for Repo with Torrent
|
||||
RUN_OGADMSERVER="yes"
|
||||
RUN_OGADMREPO="yes"
|
||||
RUN_OGADMAGENT="yes"
|
||||
RUN_BTTRACKER="yes"
|
||||
RUN_BTSEEDER="yes"
|
||||
BTSEEDER_PRIORITY=0
|
|
@ -0,0 +1,224 @@
|
|||
#!/bin/bash
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: opengnsys
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 1
|
||||
# Short-Description: Servicios del sistema OpenGnsys
|
||||
# Description: Servicios del sistema OpenGnsys
|
||||
### END INIT INFO
|
||||
|
||||
#
|
||||
# Definiciones globales
|
||||
#
|
||||
BASEDIR=/opt/opengnsys
|
||||
OPENGNSYSUSER="opengnsys"
|
||||
IMAGEDIR=$BASEDIR/images
|
||||
CLIENTLOGDIR=$BASEDIR/log/clients
|
||||
|
||||
#
|
||||
# Servidor de OpenGnsys
|
||||
#
|
||||
SERVERNAME=ogAdmServer
|
||||
SERVERDAEMON=$BASEDIR/sbin/$SERVERNAME
|
||||
SERVERCFG=$BASEDIR/etc/$SERVERNAME.cfg
|
||||
SERVERLOG=$BASEDIR/log/$SERVERNAME.log
|
||||
SERVERDAEMON_OPTIONS="-f $SERVERCFG -l $SERVERLOG"
|
||||
|
||||
#
|
||||
# Servidor de Repositorio
|
||||
#
|
||||
############## ADV
|
||||
REPOAUXNAME=ogAdmRepoAux
|
||||
REPOAUXDAEMON=$BASEDIR/sbin/$REPOAUXNAME
|
||||
REPOAUXPORT=$(awk -F= '/PUERTO/ {print $2+1}' $SERVERCFG 2>/dev/null)
|
||||
############## ADV
|
||||
############# IRINA # para setBootMode desde el cliente
|
||||
SERVERAUXNAME=ogAdmServerAux
|
||||
SERVERAUXDAEMON=$BASEDIR/sbin/$SERVERAUXNAME
|
||||
SERVERAUXPORT=2011
|
||||
############# IRINA
|
||||
|
||||
#
|
||||
# Servidor de tareas programadas
|
||||
#
|
||||
AGENTNAME=ogAdmAgent
|
||||
AGENTDAEMON=$BASEDIR/sbin/$AGENTNAME
|
||||
AGENTCFG=$BASEDIR/etc/$AGENTNAME.cfg
|
||||
AGENTLOG=$BASEDIR/log/$AGENTNAME.log
|
||||
AGENTDAEMON_OPTIONS="-f $AGENTCFG -l $AGENTLOG"
|
||||
|
||||
#
|
||||
# Opciones Bittorrent
|
||||
#
|
||||
|
||||
BTTRACK=/usr/bin/bttrack.bittorrent
|
||||
BTSEEDER=/usr/bin/btlaunchmany.bittornado
|
||||
BTTRACKPORT=6969
|
||||
BTTRACKDFILE=/tmp/dstate
|
||||
BTTRACKLOG=$BASEDIR/log/bttrack.log
|
||||
BTINTERVAL=30
|
||||
BTTORRENTSDIR=$BASEDIR/images
|
||||
BTTRACK_OPTIONS=" --port $BTTRACKPORT --dfile $BTTRACKDFILE --reannounce_interval $BTINTERVAL --logfile $BTTRACKLOG --allowed_dir $BTTORRENTSDIR --allow_get 1"
|
||||
BTTRACKPID="/var/run/bttrack.pid"
|
||||
BTSEEDERPID="/var/run/btseeder.pid"
|
||||
|
||||
|
||||
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/bin"
|
||||
|
||||
# Read config file if it is present.
|
||||
if [ -r /etc/default/opengnsys ]; then
|
||||
source /etc/default/opengnsys
|
||||
fi
|
||||
|
||||
# Configuración de arranque según la distribución Linux usada.
|
||||
config() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
source /etc/os-release
|
||||
OSDISTRIB="$ID"
|
||||
else
|
||||
OSDISTRIB=$(lsb_release -is 2>/dev/null)
|
||||
fi
|
||||
OSDISTRIB="${OSDISTRIB,,}"
|
||||
case "$OSDISTRIB" in
|
||||
ubuntu|debian|linuxmint)
|
||||
INITFUNCTIONS=/lib/lsb/init-functions
|
||||
DAEMONSTART="start-stop-daemon --start --quiet --background --exec"
|
||||
EXTRAOPTS="--"
|
||||
DAEMONSTOP="start-stop-daemon --stop --quiet --oknodo --name"
|
||||
ACTIONMSG="log_daemon_msg"
|
||||
SUCCESSMSG="log_end_msg 0"
|
||||
FAILMSG="log_end_msg 1"
|
||||
TRACKERSTART="start-stop-daemon --make-pidfile --pidfile $BTTRACKPID --start --quiet --background --exec"
|
||||
BTTRACK_OPTIONS="$BTTRACK_OPTIONS --parse_allowed_interval 1"
|
||||
TRACKERSTOP="start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $BTTRACKPID"
|
||||
SEEDERSTART="start-stop-daemon --make-pidfile --pidfile $BTSEEDERPID --start --quiet --background --exec"
|
||||
SEEDERSTOP="start-stop-daemon --stop --quiet --oknodo --pidfile $BTSEEDERPID"
|
||||
;;
|
||||
centos|fedora)
|
||||
INITFUNCTIONS=/etc/init.d/functions
|
||||
DAEMONSTART="daemon"
|
||||
ENDOPTS="&"
|
||||
DAEMONSTOP="killproc"
|
||||
ACTIONMSG="echo -n"
|
||||
SUCCESSMSG="eval ( success; echo )"
|
||||
FAILMSG="eval ( failure; echo )"
|
||||
BTTRACK=/usr/bin/bttrack.py
|
||||
BTSEEDER=/usr/bin/btlaunchmany.py
|
||||
TRACKERSTART="daemon --pidfile $BTTRACKPID"
|
||||
TRACKERSTOP="killproc -p $BTTRACKPID $BTTRACK"
|
||||
SEEDERSTART="daemon --pidfile $BTSEEDERPID"
|
||||
SEEDERSTOP="killproc -p $BTSEEDERPID $BTSEEDER"
|
||||
;;
|
||||
*) echo "Distribución Linux desconcocida o no soportada."
|
||||
exit ;;
|
||||
esac
|
||||
if [ -r $INITFUNCTIONS ]; then
|
||||
source $INITFUNCTIONS
|
||||
fi
|
||||
}
|
||||
|
||||
arranca_demonios() {
|
||||
# Comprobar que está instalado OpenGnsys.
|
||||
if [ ! -d $BASEDIR ]; then
|
||||
$ACTIONMSG "ERROR: No existe el directorio $BASEDIR"
|
||||
$FAILMSG
|
||||
exit $?
|
||||
fi
|
||||
# Deshabilitar modo reforzado de SELinux.
|
||||
[ -f /selinux/enforce ] && echo 0 > /selinux/enforce
|
||||
# Verificar permisos básicos.
|
||||
if [ "$(stat --printf="%A%G" $IMAGEDIR 2>/dev/null)" != "drwxrwxr-x$OPENGNSYSUSER" ]; then
|
||||
mkdir $IMAGEDIR 2>/dev/null
|
||||
chmod 775 $IMAGEDIR
|
||||
chgrp $OPENGNSYSUSER $IMAGEDIR
|
||||
fi
|
||||
if [ "$(stat --printf="%A%G" $CLIENTLOGDIR 2>/dev/null)" != "drwxrwxr-x$OPENGNSYSUSER" ]; then
|
||||
mkdir -p $CLIENTLOGDIR 2>/dev/null
|
||||
chmod 775 $CLIENTLOGDIR
|
||||
chgrp $OPENGNSYSUSER $CLIENTLOGDIR
|
||||
fi
|
||||
# Arrancar los servicios indicados.
|
||||
if [ $RUN_OGADMSERVER = "yes" ]; then
|
||||
$ACTIONMSG "Iniciando demonio: $SERVERNAME"
|
||||
$DAEMONSTART $SERVERDAEMON $EXTRAOPTS $SERVERDAEMON_OPTIONS $ENDOPTS
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
# Para SetBootmode desde el cliente
|
||||
$ACTIONMSG "Iniciando demonio: $SERVERAUXNAME" #
|
||||
faucet $SERVERAUXPORT --daemon --in bash -c "$SERVERAUXDAEMON" # NUEVO
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
fi
|
||||
if [ $RUN_OGADMREPO = "yes" ]; then
|
||||
$ACTIONMSG "Iniciando demonio: $REPOAUXNAME"
|
||||
faucet $REPOAUXPORT --daemon --in bash -c "$REPOAUXDAEMON"
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
fi
|
||||
if [ $RUN_OGADMSERVER = "yes" ] && [ $RUN_OGADMAGENT = "yes" ]; then
|
||||
sleep 5 # Damos tiempo a que ogAdmServer este funcionando
|
||||
fi
|
||||
if [ $RUN_OGADMAGENT = "yes" ]; then
|
||||
$ACTIONMSG "Iniciando demonio: $AGENTNAME"
|
||||
$DAEMONSTART $AGENTDAEMON $EXTRAOPTS $AGENTDAEMON_OPTIONS $ENDOPTS
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
fi
|
||||
if [ $RUN_BTTRACKER = "yes" ]; then
|
||||
$ACTIONMSG "Iniciando demonio: $BTTRACK"
|
||||
$TRACKERSTART $BTTRACK $EXTRAOPTS $BTTRACK_OPTIONS $ENDOPTS
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
fi
|
||||
if [ $RUN_BTSEEDER = "yes" ]; then
|
||||
$ACTIONMSG "Iniciando demonio: $BTSEEDER"
|
||||
$SEEDERSTART $BTSEEDER $EXTRAOPTS $BTTORRENTSDIR &>/dev/null $ENDOPTS
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
para_demonios() {
|
||||
if [ -e $BTSEEDERPID ]; then
|
||||
$ACTIONMSG "Parando demonio: $BTSEEDER"
|
||||
$SEEDERSTOP
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
rm -f $BTSEEDERPID
|
||||
fi
|
||||
if [ -e $BTTRACKPID ]; then
|
||||
$ACTIONMSG "Parando demonio: $BTTRACK"
|
||||
$TRACKERSTOP
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
rm -f $BTTRACKPID
|
||||
fi
|
||||
$ACTIONMSG "Parando demonio: $AGENTNAME"
|
||||
$DAEMONSTOP $AGENTNAME
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
$ACTIONMSG "Parando demonio: $REPOAUXNAME"
|
||||
pkill faucet
|
||||
[ $? -le 1 ] && $SUCCESSMSG || $FAILMSG
|
||||
$ACTIONMSG "Parando demonio: $SERVERNAME"
|
||||
$DAEMONSTOP $SERVERNAME
|
||||
[ $? = 0 ] && $SUCCESSMSG || $FAILMSG
|
||||
}
|
||||
|
||||
config
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
arranca_demonios
|
||||
;;
|
||||
stop)
|
||||
para_demonios
|
||||
;;
|
||||
restart)
|
||||
para_demonios
|
||||
arranca_demonios
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Uso: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
511
api/README.md
511
api/README.md
|
@ -16,26 +16,23 @@ 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. [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}`
|
||||
9. [Importar una Imagen](#importar-una-imagen) - `POST /ogrepository/v1/repo/images`
|
||||
10. [Exportar una Imagen](#exportar-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`
|
||||
15. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /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`
|
||||
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`
|
||||
|
||||
---
|
||||
### Obtener Información de Estado de ogRepository
|
||||
|
||||
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 devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, 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.
|
||||
|
||||
|
@ -54,9 +51,6 @@ 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%"
|
||||
},
|
||||
|
@ -81,7 +75,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
"udp-sender": "stopped",
|
||||
"uftp": "stopped",
|
||||
"bttrack": "stopped",
|
||||
"btlaunchmany.bittornado": "stopped"
|
||||
"btlaunchmany": "stopped"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -90,7 +84,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
|
|||
|
||||
Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/ogrepository/etc/repoinfo.json**" (que corresponde a todas las imágenes almacenadas en el repositorio), y en el archivo "**/opt/opengnsys/ogrepository/etc/trashinfo.json**" (que corresponde a las imágenes que fueron eliminadas, que estarán en la papelera).
|
||||
Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
**NOTA**: El script requiere que en este caso se le pase "all" como parámetro, pero el endpoint se ejecuta sin parámetros.
|
||||
**NOTA**: El script requiere que se le pase "all" como primer parámetro (que correspondería al nombre de la imagen) y "none" como segundo parámetro (que corresponderia al nombre del subdirectorio correspondiente a la OU). Esta transformación de parámetros se realiza en la API.
|
||||
|
||||
**URL:** `/ogrepository/v1/images`
|
||||
**Método HTTP:** GET
|
||||
|
@ -113,7 +107,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Ubuntu24",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu24_clientname",
|
||||
"clientname": "Ubuntu_24",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
|
@ -125,7 +119,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Windows10",
|
||||
"type": "img",
|
||||
"clientname": "Windows10_clientname",
|
||||
"clientname": "Windows_10",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "NTFS",
|
||||
|
@ -134,15 +128,15 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
"sum": "8874d5ab84314f44841c36c69bb5aa82",
|
||||
"fullsum": "9e7cd32c606ebe5bd39ba212ce7aeb02"
|
||||
}
|
||||
]
|
||||
},
|
||||
"TRASH": {
|
||||
"directory": "/opt/opengnsys/ogrepository/images_trash",
|
||||
],
|
||||
"ous": [
|
||||
{
|
||||
"subdir": "OU_subdir",
|
||||
"images": [
|
||||
{
|
||||
"name": "Ubuntu20",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu20_clientname",
|
||||
"clientname": "Ubuntu_20",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
|
@ -153,6 +147,31 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"TRASH": {
|
||||
"directory": "/opt/opengnsys/ogrepository/images_trash",
|
||||
"images": [],
|
||||
"ous": [
|
||||
{
|
||||
"subdir": "CentroVirtual",
|
||||
"images": [
|
||||
{
|
||||
"name": "Ubuntu20OLD",
|
||||
"type": "img",
|
||||
"clientname": "Ubuntu_20",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "EXTFS",
|
||||
"datasize": 8912896000000,
|
||||
"size": 3803794535,
|
||||
"sum": "081a933c780ab1aaa044435ad5d4bf56",
|
||||
"fullsum": "22735b9070e4a8043371b8c6ae52b90d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- **name**: Nombre de la imagen, sin extensión.
|
||||
|
@ -171,7 +190,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
|
||||
Se devolverá la informacion de la imagen especificada, que puede estar en el archivo "**/opt/opengnsys/ogrepository/etc/repoinfo.json**" o en el archivo "**/opt/opengnsys/ogrepository/etc/trashinfo.json**" (en este último caso, si la imagen está en la papelera).
|
||||
Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint, que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
**NOTA**: El script requiere que en este caso 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el subdirectorio correspondiente a la OU (o "none" si no es el caso) como segundo parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/{ID_img}`
|
||||
**Método HTTP:** GET
|
||||
|
@ -194,7 +213,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
{
|
||||
"name": "Windows10",
|
||||
"type": "img",
|
||||
"clientname": "Windows10_clientname",
|
||||
"clientname": "Windows_10",
|
||||
"clonator": "partclone",
|
||||
"compressor": "lzop",
|
||||
"filesystem": "NTFS",
|
||||
|
@ -241,7 +260,7 @@ curl -X PUT -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
|
|||
|
||||
Se comprobará la integridad del fichero de imagen especificado como parámetro.
|
||||
Se puede hacer con el script "**checkImage.py**", que compara el tamaño actual del archivo con el almacenado en el archivo "**.size**", y el hash MD5 del último MB del archivo con el almacenado en el archivo "**.sum**".
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/status/images/{ID_img}`
|
||||
**Método HTTP:** GET
|
||||
|
@ -262,7 +281,7 @@ curl -X POST -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/sta
|
|||
|
||||
Se eliminará la imagen especificada como parámetro, pudiendo eliminarla permanentemente o enviarla a la papelera.
|
||||
Se puede hacer con el script "**deleteimage.py**", que debe ser llamado por el endpoint (y que incluye la funcionalidad "papelera"), y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). 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 también hay que especificar el método de eliminación en la URL, para enviar o no el parámetro opcional.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros, pero también hay que especificar el método de eliminación en la URL, como parámetro adicional.
|
||||
|
||||
**URL:** `/ogrepository/v1/images/{ID_img}?method={method}`
|
||||
**Método HTTP:** DELETE
|
||||
|
@ -285,7 +304,7 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/i
|
|||
|
||||
Se recuperará la imagen especificada como parámetro, desde la papelera.
|
||||
Se puede hacer con el script "**recoverImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/trash/images`
|
||||
**Método HTTP:** POST
|
||||
|
@ -308,7 +327,7 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
|
||||
Se eliminará permanentemente la imagen especificada como parámetro, desde la papelera.
|
||||
Se puede hacer con el script "**deleteTrashImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera.
|
||||
**NOTA**: El 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").
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. Estos datos se obtienen en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum"), y alli se realiza la transformación de parámetros.
|
||||
|
||||
**URL:** `/ogrepository/v1/trash/images/{ID_img}`
|
||||
**Método HTTP:** DELETE
|
||||
|
@ -323,12 +342,113 @@ 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.
|
||||
|
||||
---
|
||||
### Importar una Imagen
|
||||
|
||||
Se importará una imagen de un repositorio remoto al repositorio local.
|
||||
Se puede hacer con el script "**importImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. Estos parámetros deben enviarse desde ogCore (en el JSON), porque el repositorio local no puede extraer la información de la imagen de un ID almacenado en un repositorio remoto.
|
||||
**NOTA2**: 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).
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (desde el que se importará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none", "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 400 Bad Request:** No se ha encontrado la imagen y/o el equipo remoto especificados.
|
||||
- **Código 200 OK:** La imagen se está importando.
|
||||
|
||||
---
|
||||
### Exportar una Imagen
|
||||
|
||||
Se exportará una imagen del repositorio local a un repositorio remoto.
|
||||
Se puede hacer con el script "**exportImage.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer 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 IP del repositorio remoto y el usuario remoto 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 se está exportando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (al que se exportrará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ID_img":"22735b9070e4a8043371b8c6ae52b90d", "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 exportar 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á exportando.
|
||||
|
||||
---
|
||||
### Crear archivos auxiliares
|
||||
|
||||
Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro.
|
||||
Se puede hacer con el script "**createTorrentSum.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como unico parámetro. Este parámetro no puede obtenerse en la API, a partir del ID de imagen (como en otros casos), porque el ID corresponde al contenido del archivo "full.sum" asociado (que no estará creado hasta que no se ejecute este script).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar cierto tiempo, por lo que solo informa de que los archivos auxiliares se están creando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/torrentsum`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/torrentsum
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al crear los archivos auxiliares.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** Los archivos auxiliares se están creando.
|
||||
|
||||
---
|
||||
### Enviar paquete Wake On Lan
|
||||
|
||||
Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada.
|
||||
Se puede hacer con el script "**sendWakeOnLan.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: La versión actual de este script requiere que se le pase la dirección IP de broadcast como primer parámetro, y la dirección MAC destino como segundo parámetro. Estos datos deben enviarse desde ogCore (en el JSON).
|
||||
|
||||
**URL:** `/ogrepository/v1/wol`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **broadcast_ip**: IP de broadcast a la que enviar el paquete (puede ser "255.255.255.255", o la IP de broadcast de una subred).
|
||||
- **mac**: Dirección MAC del equipo que se desea encender via Wake On Lan.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"broadcast_ip":"255.255.255.255", "mac":"00:19:99:5c:bb:bb"}' http://example.com/ogrepository/v1/wol
|
||||
```
|
||||
**Respuestas:**
|
||||
- **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).
|
||||
**NOTA**: El script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) 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`
|
||||
|
@ -353,6 +473,58 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
|
|||
- **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, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) 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 la raiz del directorio especificado).
|
||||
Se puede hacer con los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**", que deben ser llamados por el endpoint.
|
||||
**NOTA**: Estos scripts requieren que se les pase el directorio en el que está situada la imagen a enviar como único parámetro. Este dato se obtiene en la API, a partir del ID de la imagen (que corresponde al contenido del archivo "full.sum").
|
||||
**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
|
||||
|
||||
|
@ -384,54 +556,6 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpc
|
|||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### 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
|
||||
|
||||
|
@ -463,12 +587,33 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/uftp
|
|||
}
|
||||
}
|
||||
```
|
||||
---
|
||||
### 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, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único 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").
|
||||
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único 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
|
||||
|
@ -484,30 +629,6 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/u
|
|||
- **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
|
||||
|
||||
|
@ -528,179 +649,3 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p
|
|||
- **Código 200 OK:** Las transmisiones P2P se han cancelado exitosamente.
|
||||
|
||||
---
|
||||
### Transferir una Imagen entre Repositorios
|
||||
|
||||
Se importará una imagen de un repositorio remoto al repositorio local (donde se ejecuta el endpoint).
|
||||
Se puede hacer con el script "**importImage.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, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. Estos parámetros deben enviarse desde ogCore (en el JSON), porque el repositorio local no puede extraer la información de la imagen de un ID almacenado en un repositorio remoto.
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está transfiriendo, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
**NOTA3**: Este endpoint comprueba si la importación se ha realizado correctamente, comparando el contenido de los archivos "sum" y "size" con los valores reales (que vuelve a calcular). Si la importación ha sido correcta llama al script "createTorrentSum.py", para crear el archivo ".torrent" (que debe crearse desde el repositorio en el que esté), y actualizar la info del repositorio. Si la importación no ha sido correcta (porque la imagen no ha pasado el check de integridad), borra los archivos importados.
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (desde el que se importará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
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 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á transfiriendo.
|
||||
|
||||
---
|
||||
### Hacer Backup de una Imagen
|
||||
|
||||
Se hará backup de una imagen en un equipo remoto, que no tiene por qué tener OpenGnsys instalado, pero que debe poder conectar por SSH (mediante claves) con el repositorio local.
|
||||
Se puede hacer con el script "**backupImage.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, la IP o hostname del repositorio remoto como segundo parámetro, el usuario remoto como tercer parámetro, y la ruta remota en la que se guardará el backup como cuarto 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 IP del repositorio remoto, el usuario remoto y la ruta remota deben 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á exportando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
**NOTA3**: Este endpoint comprueba si el backup se ha realizado correctamente, comparando el contenido de los archivos "sum" y "size" con los valores reales (que vuelve a calcular). Si el backup no ha sido correcto (porque la imagen no ha pasado el check de integridad), borra los archivos exportados.
|
||||
|
||||
**URL:** `/ogrepository/v1/repo/images`
|
||||
**Método HTTP:** PUT
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **ID_img**: Identificador de la imagen (correspondiente al contenido del archivo "full.sum" asociado).
|
||||
- **repo_ip**: Dirección IP del repositorio remoto (al que se exportrará la imagen).
|
||||
- **user**: Usuario con el que acceder al repositorio remoto.
|
||||
- **remote_path**: Ruta remota en la que copiar la imagen.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
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 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:** 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
|
||||
|
||||
Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro.
|
||||
Se puede hacer con el script "**createTorrentSum.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 parámetro. Este parámetro no puede obtenerse en la API, a partir del ID de imagen (como en otros casos), porque el ID corresponde al contenido del archivo "full.sum" asociado (que no estará creado hasta que no se ejecute este script).
|
||||
**NOTA2**: Este endpoint es asíncrono, ya que puede tardar cierto tiempo, por lo que solo informa de que los archivos auxiliares se están creando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
|
||||
**URL:** `/ogrepository/v1/images/torrentsum`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **image**: Nombre de la imagen (con extensión).
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/torrentsum
|
||||
```
|
||||
**Respuestas:**
|
||||
- **Código 500 Internal Server Error:** Ocurrió un error al crear los archivos auxiliares.
|
||||
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
|
||||
- **Código 200 OK:** Los archivos auxiliares se están creando.
|
||||
|
||||
---
|
||||
### Enviar paquete Wake On Lan
|
||||
|
||||
Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada.
|
||||
Se puede hacer con el script "**sendWakeOnLan.py**", que debe ser llamado por el endpoint.
|
||||
**NOTA**: Este script requiere que se le pase la dirección IP de broadcast como primer parámetro, y la dirección MAC destino como segundo parámetro. Estos datos deben enviarse desde ogCore (en el JSON).
|
||||
|
||||
**URL:** `/ogrepository/v1/wol`
|
||||
**Método HTTP:** POST
|
||||
|
||||
**Cuerpo de la Solicitud (JSON):**
|
||||
- **broadcast_ip**: IP de broadcast a la que enviar el paquete (puede ser "255.255.255.255", o la IP de broadcast de una subred).
|
||||
- **mac**: Dirección MAC del equipo que se desea encender via Wake On Lan.
|
||||
|
||||
**Ejemplo de Solicitud:**
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"broadcast_ip":"255.255.255.255", "mac":"00:19:99:5c:bb:bb"}' http://example.com/ogrepository/v1/wol
|
||||
```
|
||||
**Respuestas:**
|
||||
- **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.
|
||||
|
||||
---
|
1357
api/repo_api.py
1357
api/repo_api.py
File diff suppressed because it is too large
Load Diff
482
api/swagger.yaml
482
api/swagger.yaml
|
@ -1,10 +1,42 @@
|
|||
swagger: "2.0"
|
||||
info:
|
||||
title: "ogRepository API"
|
||||
title: "OgRepository API"
|
||||
version: "1.0"
|
||||
description: |
|
||||
---
|
||||
|
||||
**API de ogRepository, programada en Flask**.
|
||||
|
||||
Responde a peticiones HTTP mediante endpoints, que a su vez ejecutan los scripts de Python 3 almacenados en ogRepository. En el entorno real, estas peticiones HTTP se enviarán desde ogCore.
|
||||
En la mayoría de los casos, transforma los parámetros recibidos para adaptarlos a los que es necesario enviar a los scripts (por ejemplo, a partir del ID de una imagen obtiene su nombre, su extensión y el subdirectorio de OU).
|
||||
|
||||
---
|
||||
|
||||
Paquetes APT requeridos:
|
||||
- **uftp** (se puede instalar con "sudo DEBIAN_FRONTEND=noninteractive apt install uftp -y", para que no pida la ruta predeterminada)
|
||||
- **udpcast** (se puede instalar con "sudo apt install ./udpcast_20230924_amd64.deb", apuntando al paquete)
|
||||
- **ctorrent** (se puede instalar con "sudo apt install ctorrent")
|
||||
- **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)
|
||||
|
||||
Librerías Python requeridas:
|
||||
- **flask** (se puede instalar con "sudo apt install python3-flask")
|
||||
- **paramiko** (se puede instalar con "sudo apt install python3-paramiko")
|
||||
- **psutil** (se puede instalar con "sudo apt install python3-psutil")
|
||||
- **flasgger** (se puede instalar con "sudo apt install python3-flasgger")
|
||||
|
||||
Para que todos los endpoints de la API 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/bin/** (aquí deben estar todos los scripts de Python, y el binario "udp-sender")
|
||||
- **/opt/opengnsys/ogrepository/etc/** (aquí se guardan los archivos "repoinfo.json" y "trashinfo.json")
|
||||
- **/opt/opengnsys/ogrepository/log/** (aquí se guardan los logs)
|
||||
|
||||
Y también debe existir el siguiente archivo:
|
||||
- **/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg** (de aquí pilla la IP de ogRepository)
|
||||
|
||||
---
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
# Esto hace que el Swagger se ordene por los tags (apartados), de la forma especificada:
|
||||
|
@ -15,8 +47,7 @@ tags:
|
|||
- name: "Transferencia de Imágenes (UDPcast)"
|
||||
- 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: "Importar y Exportar Imágenes"
|
||||
- name: "Varios"
|
||||
|
||||
|
||||
|
@ -30,7 +61,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, e instalación de ogGit.
|
||||
incluyendo información sobre la CPU, memoria RAM, disco duro, servicios, y procesos específicos de ogRepository.
|
||||
tags:
|
||||
- "Estado de ogRepository"
|
||||
responses:
|
||||
|
@ -45,12 +76,6 @@ paths:
|
|||
output:
|
||||
type: object
|
||||
properties:
|
||||
oggit:
|
||||
type: object
|
||||
properties:
|
||||
installed:
|
||||
type: string
|
||||
example: "True"
|
||||
cpu:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -111,7 +136,7 @@ paths:
|
|||
bttrack:
|
||||
type: string
|
||||
example: "stopped"
|
||||
btlaunchmany.bittornado:
|
||||
btlaunchmany:
|
||||
type: string
|
||||
example: "stopped"
|
||||
"500 (Error)":
|
||||
|
@ -192,7 +217,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 los parámetros "**all**" y "**none**" 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"
|
||||
|
@ -227,7 +252,7 @@ paths:
|
|||
example: "img"
|
||||
clientname:
|
||||
type: string
|
||||
example: "Ubuntu24_clientname"
|
||||
example: "Ubuntu_24"
|
||||
clonator:
|
||||
type: string
|
||||
example: "partclone"
|
||||
|
@ -249,12 +274,67 @@ paths:
|
|||
fullsum:
|
||||
type: string
|
||||
example: "33575b9070e4a8043371b8c6ae52b80e"
|
||||
ous:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
subdir:
|
||||
type: string
|
||||
example: "OU_subdir"
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: "Ubuntu20"
|
||||
type:
|
||||
type: string
|
||||
example: "img"
|
||||
clientname:
|
||||
type: string
|
||||
example: "Ubuntu_20"
|
||||
clonator:
|
||||
type: string
|
||||
example: "partclone"
|
||||
compressor:
|
||||
type: string
|
||||
example: "lzop"
|
||||
filesystem:
|
||||
type: string
|
||||
example: "EXTFS"
|
||||
datasize:
|
||||
type: integer
|
||||
example: 8912896000000
|
||||
size:
|
||||
type: integer
|
||||
example: 3803794535
|
||||
sum:
|
||||
type: string
|
||||
example: "081a933c780ab1aaa044435ad5d4bf56"
|
||||
fullsum:
|
||||
type: string
|
||||
example: "22735b9070e4a8043371b8c6ae52b90d"
|
||||
TRASH:
|
||||
type: object
|
||||
properties:
|
||||
directory:
|
||||
type: string
|
||||
example: "/opt/opengnsys/ogrepository/images_trash"
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
ous:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
subdir:
|
||||
type: string
|
||||
example: "CentroVirtual"
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
|
@ -262,13 +342,13 @@ paths:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: "Windows10"
|
||||
example: "Ubuntu20OLD"
|
||||
type:
|
||||
type: string
|
||||
example: "img"
|
||||
clientname:
|
||||
type: string
|
||||
example: "Windows10_clientname"
|
||||
example: "Ubuntu_20"
|
||||
clonator:
|
||||
type: string
|
||||
example: "partclone"
|
||||
|
@ -277,7 +357,7 @@ paths:
|
|||
example: "lzop"
|
||||
filesystem:
|
||||
type: string
|
||||
example: "NTFS"
|
||||
example: "EXTFS"
|
||||
datasize:
|
||||
type: integer
|
||||
example: 8912896000000
|
||||
|
@ -320,7 +400,7 @@ paths:
|
|||
summary: "Obtener Información de una Imagen concreta"
|
||||
description: |
|
||||
Este endpoint devuelve información de la imagen especificada mediante su ID, en formato JSON.
|
||||
Utiliza el script "**getRepoInfo.py**" que recibe como parámetro el nombre de la imagen (con extensión), que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
Utiliza el script "**getRepoInfo.py**" que recibe como parámetros el nombre de la imagen con extensión y el subdirectorio correspondiente a la OU (o "none" si no es el caso), que a su vez llama al script "**updateRepoInfo.py**", para actualizar previamente la información del repositorio.
|
||||
La imagen puede estar en el archivo "**repoinfo.json**" (si está almacenada en el repositorio) o en "**trashinfo.json**" (si está en la papelera).
|
||||
tags:
|
||||
- "Información de Imágenes"
|
||||
|
@ -352,13 +432,13 @@ paths:
|
|||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: "Ubuntu24"
|
||||
example: "Windows10"
|
||||
type:
|
||||
type: string
|
||||
example: "img"
|
||||
clientname:
|
||||
type: string
|
||||
example: "Ubuntu24_clientname"
|
||||
example: "Windows_10"
|
||||
clonator:
|
||||
type: string
|
||||
example: "partclone"
|
||||
|
@ -367,7 +447,7 @@ paths:
|
|||
example: "lzop"
|
||||
filesystem:
|
||||
type: string
|
||||
example: "EXTFS"
|
||||
example: "NTFS"
|
||||
datasize:
|
||||
type: integer
|
||||
example: 9859634200000
|
||||
|
@ -421,7 +501,7 @@ paths:
|
|||
summary: "Chequear Integridad de Imagen"
|
||||
description: |
|
||||
Este endpoint comprueba la integridad de la imagen especificada como parámetro, comparando el tamaño y el hash MD5 del último MB con los valores almacenados en los archivos ".size" y ".sum".
|
||||
Utiliza el script "**checkImage.py**", que recibe el nombre de la imagen (con extensión) como parámetro.
|
||||
Utiliza el script "**checkImage.py**", que recibe el nombre de la imagen (con extensión) y el subdirectorio correspondiente a la OU, si aplica.
|
||||
tags:
|
||||
- "Información de Imágenes"
|
||||
parameters:
|
||||
|
@ -496,7 +576,7 @@ paths:
|
|||
summary: "Eliminar una Imagen"
|
||||
description: |
|
||||
Este endpoint elimina la imagen especificada como parámetro (y todos sus archivos asociados), moviéndolos a la papelera o eliminándolos permanentemente (dependiendo del parámetro "method").
|
||||
Utiliza el script "**deleteImage.py**" que recibe el nombre de la imagen (con extensión) como primer parámetro, y opcionalmente el parámetro "-p" (para eliminación permanente), que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
Utiliza el script "**deleteImage.py**" que recibe el nombre de la imagen (con extensión y subdirectorio correspondiente a la OU, si aplica) como primer parámetro, y opcionalmente el parámetro "-p" (para eliminación permanente), que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
tags:
|
||||
- "Eliminar y Recuperar Imágenes"
|
||||
parameters:
|
||||
|
@ -563,7 +643,7 @@ paths:
|
|||
summary: "Recuperar una Imagen"
|
||||
description: |
|
||||
Este endpoint recupera la imagen especificada, moviéndola desde la papelera al repositorio de imágenes.
|
||||
Utiliza el script "**recoverImage.py**", que recibe el nombre de la imagen (con extensión), que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
Utiliza el script "**recoverImage.py**", que recibe el nombre de la imagen (con extensión y subdirectorio correspondiente a la OU, si aplica), que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
|
||||
tags:
|
||||
- "Eliminar y Recuperar Imágenes"
|
||||
parameters:
|
||||
|
@ -631,7 +711,7 @@ paths:
|
|||
summary: "Eliminar una Imagen de la Papelera"
|
||||
description: |
|
||||
Este endpoint elimina permanentemente la imagen especificada, desde la papelera.
|
||||
Utiliza el script "**deleteTrashImage.py**", que recibe el nombre de la imagen (con extensión), que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera.
|
||||
Utiliza el script "**deleteTrashImage.py**", que recibe el nombre de la imagen (con extensión y subdirectorio correspondiente a la OU, si aplica), que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera.
|
||||
tags:
|
||||
- "Eliminar y Recuperar Imágenes"
|
||||
parameters:
|
||||
|
@ -1203,7 +1283,7 @@ paths:
|
|||
summary: "Enviar una Imagen mediante P2P"
|
||||
description: |
|
||||
Este endpoint inicia el tracker y el seeder de torrents para enviar una imagen especificada mediante P2P.
|
||||
Utiliza los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**" para iniciar el tracker y el seeder en el directorio de imágenes.
|
||||
Utiliza los scripts "**runTorrentTracker.py**" y "**runTorrentSeeder.py**" para iniciar el tracker y el seeder en el directorio de la imagen.
|
||||
|
||||
**NOTA**: 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).
|
||||
tags:
|
||||
|
@ -1301,26 +1381,27 @@ paths:
|
|||
example: "(Exception description)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
# Apartado "Transferencia entre Repositorios y Backup"
|
||||
# Apartado "Importar y Exportar Imágenes"
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
/ogrepository/v1/repo/images:
|
||||
post:
|
||||
summary: "Transferir una Imagen entre Repositorios"
|
||||
summary: "Importar una Imagen"
|
||||
description: |
|
||||
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.
|
||||
Este endpoint importa la imagen especificada desde un servidor remoto al servidor local.
|
||||
Utiliza el script "**importImage.py**", que recibe como parámetros el nombre de la imagen, la IP o hostname del servidor remoto, el usuario para la conexión, y el subdirectorio correspondiente a la OU (si aplica),
|
||||
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"
|
||||
- "Importar y Exportar Imágenes"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
required: true
|
||||
description: |
|
||||
* **image** - Nombre de la imagen, con extensión
|
||||
* **ou_subdir** - Subdirectorio correspondiente a la OU, o 'none' si no procede
|
||||
* **repo_ip** - Dirección IP del servidor remoto
|
||||
* **user** - Usuario con el que conectar al servidor remoto
|
||||
schema:
|
||||
|
@ -1329,6 +1410,10 @@ paths:
|
|||
image:
|
||||
type: string
|
||||
example: "Windows10.img"
|
||||
ou_subdir:
|
||||
type: string
|
||||
description: "Subdirectorio correspondiente a la OU (o 'none' si no es el caso)"
|
||||
example: "none"
|
||||
repo_ip:
|
||||
type: string
|
||||
description: "Dirección IP del repositorio remoto"
|
||||
|
@ -1339,7 +1424,7 @@ paths:
|
|||
example: "user_name"
|
||||
responses:
|
||||
"200":
|
||||
description: "La imagen se está transfiriendo."
|
||||
description: "La imagen se está importando."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1420,14 +1505,16 @@ paths:
|
|||
|
||||
#/ogrepository/v1/repo/images:
|
||||
put:
|
||||
summary: "Hacer Backup de una Imagen"
|
||||
summary: "Exportar una Imagen"
|
||||
description: |
|
||||
Este endpoint hace un backup de la imagen especificada, exportándola desde el servidor local a un equipo remoto (que no tiene por qué tener OpenGnsys instalado, pero si conectividad SSH).
|
||||
Utiliza el script "**backupImage.py**", que recibe como parámetros el nombre de la imagen, la IP o hostname del servidor remoto, el usuario con el que conectar al servidor remoto, y la ruta remota en la que guardar el backup.
|
||||
Este endpoint exporta la imagen especificada desde el servidor local a un servidor remoto.
|
||||
Utiliza el script "**exportImage.py**", que recibe como parámetros el nombre de la imagen, la IP o hostname del servidor remoto, el usuario para la conexión, y el subdirectorio correspondiente a la OU (si aplica).
|
||||
|
||||
**NOTA**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está copiando, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore).
|
||||
Una vez que acabe, debe llamarse al endpoint "**Actualizar Información del Repositorio**" en el ogRepository destino de la exportación, 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á exportando, 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"
|
||||
- "Importar y Exportar Imágenes"
|
||||
parameters:
|
||||
- name: JSON
|
||||
in: body
|
||||
|
@ -1436,7 +1523,6 @@ 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
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1451,13 +1537,9 @@ paths:
|
|||
type: string
|
||||
description: "Usuario para acceder al repositorio remoto"
|
||||
example: "user_name"
|
||||
remote_path:
|
||||
type: string
|
||||
description: "Ruta remota en la que copiar la imagen"
|
||||
example: "/home/opengnsys"
|
||||
responses:
|
||||
"200":
|
||||
description: "Se está haciendo backup de la imagen."
|
||||
description: "La imagen se está exportando."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1466,7 +1548,7 @@ paths:
|
|||
example: true
|
||||
output:
|
||||
type: string
|
||||
example: "Making image backup..."
|
||||
example: "Exporting image..."
|
||||
"400 (Image not found)":
|
||||
description: "No se ha encontrado la imagen."
|
||||
schema:
|
||||
|
@ -1490,7 +1572,7 @@ paths:
|
|||
type: string
|
||||
example: "Image is locked"
|
||||
"400 (Connection fail)":
|
||||
description: "Error de conexión con el equipo remoto."
|
||||
description: "Error de conexión con el servidor remoto."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1499,20 +1581,9 @@ paths:
|
|||
example: false
|
||||
exception:
|
||||
type: string
|
||||
example: "Can't connect to remote host"
|
||||
"500 (Error)":
|
||||
description: "Error al copiar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
success:
|
||||
type: boolean
|
||||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "(Error description)"
|
||||
"500 (Exception)":
|
||||
description: "Excepción inesperada al copiar la imagen."
|
||||
example: "Can't connect to remote server"
|
||||
"400 (Image present)":
|
||||
description: "La imagen ya existe en el servidor remoto."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1521,87 +1592,9 @@ paths:
|
|||
example: false
|
||||
exception:
|
||||
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"
|
||||
example: "Image already exists on remote server"
|
||||
"500":
|
||||
description: "Error al convertir la imagen virtual."
|
||||
description: "Error al exportar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1610,9 +1603,9 @@ paths:
|
|||
example: false
|
||||
error:
|
||||
type: string
|
||||
example: "Virtual image conversion failed"
|
||||
example: "Export image failed"
|
||||
"500 (Error)":
|
||||
description: "Error al convertir la imagen virtual."
|
||||
description: "Error al exportar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1623,114 +1616,7 @@ paths:
|
|||
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."
|
||||
description: "Excepción inesperada al exportar la imagen."
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1750,7 +1636,7 @@ paths:
|
|||
summary: "Crear archivos auxiliares"
|
||||
description: |
|
||||
Este endpoint crea los archivos "**size**", "**sum**", "**full.sum**" y "**torrent**" para la imagen especificada.
|
||||
Utiliza el script "**createTorrentSum.py**", que recibe como parámetro el nombre de la imagen (con extensión), que a su vez llama al script "**updateRepoInfo.py**, para actualizar la información del repositorio".
|
||||
Utiliza el script "**createTorrentSum.py**", que recibe como parámetro el nombre de la imagen (con subdirectorio de OU, si aplica), que a su vez llama al script "**updateRepoInfo.py**, para actualizar la información del repositorio".
|
||||
|
||||
Debe ser llamado cada vez que se cree una imagen desde un ogLive, y cada vez que se llame al endpoint "**Exportar una Imagen**" (en este último caso, debe ejecutarse en el ogRepository destino de la exportación).
|
||||
|
||||
|
@ -1763,12 +1649,16 @@ paths:
|
|||
required: true
|
||||
description: |
|
||||
* **image** - Nombre de la imagen, con extensión
|
||||
* **ou_subdir** - Subdirectorio correspondiente a la OU, o 'none' si no procede
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
image:
|
||||
type: string
|
||||
example: "Windows10.img"
|
||||
ou_subdir:
|
||||
type: string
|
||||
example: "none"
|
||||
responses:
|
||||
"200":
|
||||
description: "Los archivos auxiliares se están creando."
|
||||
|
@ -1792,6 +1682,17 @@ 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:
|
||||
|
@ -1876,87 +1777,4 @@ paths:
|
|||
type: string
|
||||
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)"
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
|
1177
api/test_repo_api.py
1177
api/test_repo_api.py
File diff suppressed because it is too large
Load Diff
|
@ -1,188 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script hace un backup de la imagen especificada como primer parámetro (y sus archivos asociados), en el equipo remoto especificado como segundo parámetro,
|
||||
con las credenciales del usuario especificado como tercer parámetro (en principio, mediante claves), y en la ruta remota especificada como cuarto parámetro.
|
||||
|
||||
Realiza la misma acción que el script "exportImage.py", pero con la salvedad de que requiere la ruta remota en la que se copiará la imagen, y que no requiere que el equipo remoto sea un repositorio.
|
||||
Lo que si es necesario es que ambos equipos puedan conectar por SSH mediante claves (que deben haberse generado y distribuido previamente).
|
||||
|
||||
Librerías Python requeridas: "paramiko" (se puede instalar con "sudo apt install python3-paramiko")
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a copiar (SIN ruta).
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: image2.img
|
||||
|
||||
sys.argv[2] - IP o hostname del equipo remoto.
|
||||
- Ejemplo1: 192.168.56.100
|
||||
- Ejemplo2: remote_repo
|
||||
|
||||
sys.argv[3] - Usuario con el que conectar al equipo remoto.
|
||||
- Ejemplo1: remote_user
|
||||
- Ejemplo2: root
|
||||
|
||||
sys.argv[4] - Ruta remota en la que se copiará la imagen.
|
||||
- Ejemplo1: /tmp
|
||||
- Ejemplo2: /home/opengnsys
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./backupImage.py image_name remote_host remote_user remote_path
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./backupImage.py image1.img 192.168.56.100 user /tmp
|
||||
./backupImage.py image2.img remote_hostname user /home/opengnsys
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# IMPORTS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore")
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import paramiko
|
||||
import warnings
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# 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 remote_host remote_user remote_path
|
||||
Ejemplo1: {script_name} image1.img 192.168.56.100 user /tmp
|
||||
Ejemplo2: {script_name} image2.img remote_hostname user /home/opengnsys
|
||||
"""
|
||||
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 4 parámetros, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 5:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 4 parámetros")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def backup_image(image_name, remote_host, remote_user, remote_path):
|
||||
""" Conecta al equipo remoto por SSH e inicia un cliente SFTP.
|
||||
Luego copia la imagen al equipo remoto (junto con sus archivos asociados).
|
||||
"""
|
||||
# Creamos una lista con las extensiones de los archivos asociados a la imagen
|
||||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.info.checked']
|
||||
|
||||
# Iniciamos un cliente SSH:
|
||||
ssh_client = paramiko.SSHClient()
|
||||
# Establecemos la política por defecto para localizar la llave del host localmente:
|
||||
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
# Intentamos conectar con el equipo remoto por SSH, e iniciar un cliente SFTP,
|
||||
try: # y en caso de fallar devolvemos un error y salimos del script:
|
||||
ssh_client.connect(hostname=remote_host, port=22, username=remote_user, passphrase='')
|
||||
sftp_client = ssh_client.open_sftp()
|
||||
except Exception as error_description:
|
||||
journal.send(f"backupImage.py: Connection exception: {error_description}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Connection has returned an exception: {error_description}")
|
||||
sys.exit(4)
|
||||
|
||||
# Comprobamos si la imagen ya existe en el equipo remoto, en cuyo caso devolvemos un error y salimos del script:
|
||||
try:
|
||||
sftp_client.stat(f"{remote_path}{image_name}")
|
||||
journal.send("backupImage.py: Image already exists on remote host", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image already exists on remote host.")
|
||||
sys.exit(5)
|
||||
except IOError:
|
||||
print("As expected, image doesn't exist on remote host.")
|
||||
|
||||
# Copiamos la imagen al equipo remoto, junto con sus archivos asociados:
|
||||
for ext in extensions:
|
||||
sftp_client.put(f"{repo_path}{image_name}{ext}", f"{remote_path}{image_name}{ext}")
|
||||
|
||||
# Renombramos el archivo remoto ".info.checked" a ".info", para que lo pille el script "updateRepoInfo.py":
|
||||
journal.send("backupImage.py: Renaming '.info.checked' file to '.info'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sftp_client.rename(f"{remote_path}{image_name}.info.checked", f"{remote_path}{image_name}.info")
|
||||
|
||||
# Cerramos el cliente SSH y el cliente SFTP:
|
||||
journal.send("backupImage.py: Closing remote connection...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
ssh_client.close()
|
||||
sftp_client.close()
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# Obtenemos el nombre de la imagen a copiar (desde los parámetros):
|
||||
image_name = sys.argv[1]
|
||||
|
||||
# Si no existe el archivo de imagen, imprimimos un mensaje de error y salimos del script:
|
||||
if not os.path.exists(f"{repo_path}{image_name}"):
|
||||
journal.send("backupImage.py: Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image file doesn't exist")
|
||||
sys.exit(2)
|
||||
|
||||
# Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script:
|
||||
if os.path.exists(f"{repo_path}{image_name}.lock"):
|
||||
journal.send("backupImage.py: Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image is locked.")
|
||||
sys.exit(3)
|
||||
|
||||
# Almacenamos la IP/hostname del equipo remoto, el usuario remoto y la ruta remota (desde los parámetros):
|
||||
remote_host = sys.argv[2]
|
||||
remote_user = sys.argv[3]
|
||||
remote_path = sys.argv[4]
|
||||
|
||||
# Si el úitimo carácter de "remote_path" no es una barra, la añadimos:
|
||||
if remote_path[-1] != "/":
|
||||
remote_path = f"{remote_path}/"
|
||||
|
||||
# Copiamos la imagen al equipo remoto:
|
||||
backup_image(image_name, remote_host, remote_user, remote_path)
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -7,18 +7,24 @@ Este script comprueba la integridad de la imagen que recibe como parámetro, vol
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a chequear (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a chequear (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./checkImage.py image_name|/image_path/image_name
|
||||
./checkImage.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./checkImage.py image1.img
|
||||
./checkImage.py /opt/opengnsys/ogrepository/images/image1.img
|
||||
./checkImage.py ou_subdir/image1.img
|
||||
./checkImage.py /ou_subdir/image1.img
|
||||
./checkImage.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -47,9 +53,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -72,9 +81,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa del archivo a chequear
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
|
|
@ -1,452 +0,0 @@
|
|||
#!/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()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -1,415 +0,0 @@
|
|||
#!/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()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -10,18 +10,24 @@ Debería ser llamado por ogCore u ogLive cada vez que se cree una imagen.
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen.
|
||||
sys.argv[1] - Nombre completo de la imagen (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./createTorrentSum.py image_name|/image_path/image_name
|
||||
./createTorrentSum.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./createTorrentSum.py image1.img
|
||||
./createTorrentSum.py /opt/opengnsys/ogrepository/images/image1.img
|
||||
./createTorrentSum.py ou_subdir/image1.img
|
||||
./createTorrentSum.py /ou_subdir/image1.img
|
||||
./createTorrentSum.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -32,7 +38,6 @@ import os
|
|||
import sys
|
||||
import subprocess
|
||||
import hashlib
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -55,9 +60,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -80,9 +88,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo de imagen
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -115,7 +127,7 @@ def get_md5_fullsum(file_path):
|
|||
|
||||
|
||||
def get_IPlocal():
|
||||
""" Retorna la IP asociada a la variable "IPlocal", del archivo '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'
|
||||
""" Retorna la IP asociada a la variable "IPlocal", del archivo '/opt/opengnsys/etc/ogAdmRepo.cfg'
|
||||
(que corresponde a la IP del repositorio).
|
||||
"""
|
||||
with open(config_file, 'r') as file:
|
||||
|
@ -128,7 +140,7 @@ def get_IPlocal():
|
|||
def create_torrent(file_path, torrent_file, datafullsum):
|
||||
""" Crea un archivo ".torrent" para la imagen que recibe como primer parámetro.
|
||||
Obtiene la IP del repositorio llamando a la función "get_IPlocal",
|
||||
que a su vez la obtiene del archivo '/opt/opengnsys/ogrepository/etc/ogAdmRepo.cfg'.
|
||||
que a su vez la obtiene del archivo '/opt/opengnsys/etc/ogAdmRepo.cfg'.
|
||||
"""
|
||||
# Almacenamos la IP del repositorio, y construimos la URL del tracker:
|
||||
repo_ip = get_IPlocal()
|
||||
|
@ -140,31 +152,25 @@ def create_torrent(file_path, torrent_file, datafullsum):
|
|||
|
||||
# Ejecutamos el comando en el sistema, e imprimimos el resultado:
|
||||
try:
|
||||
journal.send(f"createTorrentSum.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
journal.send(f"createTorrentSum.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {result.returncode}")
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"createTorrentSum.py: Command error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {error.returncode}")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
except Exception as error:
|
||||
journal.send(f"createTorrentSum.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
|
||||
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("createTorrentSum.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)
|
||||
result = subprocess.run(['sudo', 'python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"createTorrentSum.py: 'updateRepoInfo.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
except Exception as error:
|
||||
journal.send(f"createTorrentSum.py: 'updateRepoInfo.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
sys.exit(4)
|
||||
|
||||
|
@ -186,18 +192,15 @@ def main():
|
|||
|
||||
# Si no existe el archivo de imagen, imprimimos un mensaje de error y salimos del script:
|
||||
if not os.path.exists(file_path):
|
||||
journal.send("createTorrentSum.py: Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image file doesn't exist")
|
||||
sys.exit(2)
|
||||
|
||||
# Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script:
|
||||
if os.path.exists(f"{file_path}.lock"):
|
||||
journal.send("createTorrentSum.py: Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image is locked")
|
||||
sys.exit(3)
|
||||
|
||||
# Creamos un archivo de bloqueo:
|
||||
journal.send("createTorrentSum.py: Creating '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
open(f"{file_path}.lock", "w").close()
|
||||
|
||||
# Construimos las rutas completas de los archivos ".size", ".sum", ".full.sum" y ".torrent":
|
||||
|
@ -208,54 +211,41 @@ def main():
|
|||
|
||||
# Creamos el archivo ".size" (pque almacenará el tamaño del archivo), siempre que no exista:
|
||||
if not os.path.exists(size_file):
|
||||
journal.send("createTorrentSum.py: Creating '.size' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating '.size' file...")
|
||||
with open(size_file, 'w') as file:
|
||||
datasize = os.path.getsize(file_path)
|
||||
file.write(str(datasize))
|
||||
else:
|
||||
journal.send("createTorrentSum.py: '.size' file exists", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Size file exists")
|
||||
|
||||
# Creamos el archivo ".sum" (para transferencias Unicast y Multicast), siempre que no exista:
|
||||
if not os.path.exists(sum_file):
|
||||
journal.send("createTorrentSum.py: Creating '.sum' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating '.sum' file...")
|
||||
with open(sum_file, 'w') as file:
|
||||
datasum = get_md5_sum(file_path)
|
||||
file.write(datasum)
|
||||
else:
|
||||
journal.send("createTorrentSum.py: '.sum' file exists", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Sum file exists")
|
||||
|
||||
# Creamos el archivo ".full.sum" (para transferencias P2P), siempre que no exista:
|
||||
if not os.path.exists(fullsum_file):
|
||||
journal.send("createTorrentSum.py: Creating '.full.sum' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating '.ful.sum' file...")
|
||||
with open(fullsum_file, 'w') as file:
|
||||
datafullsum = get_md5_fullsum(file_path)
|
||||
file.write(datafullsum)
|
||||
else:
|
||||
# Si el archivo existe, almacenamos el "full.sum" en la variable "datafullsum", porque es requerido para crear el torrent:
|
||||
with open(fullsum_file, 'r') as file:
|
||||
datafullsum = file.read().strip('\n')
|
||||
journal.send("createTorrentSum.py: '.full.sum' file exists", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Fullsum file exists")
|
||||
|
||||
# Creamos el archivo ".torrent" (siempre que no exista):
|
||||
if not os.path.exists(torrent_file):
|
||||
journal.send("createTorrentSum.py: Creating '.torrent' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
create_torrent(file_path, torrent_file, datafullsum)
|
||||
else:
|
||||
journal.send("createTorrentSum.py: '.torrent' file exists", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Torrent file exists")
|
||||
|
||||
# Eliminamos el archivo de bloqueo:
|
||||
journal.send("createTorrentSum.py: Removing '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
os.remove(f"{file_path}.lock")
|
||||
|
||||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
journal.send("createTorrentSum.py: Updating repository info...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Updating Repository Info...")
|
||||
update_repo_info()
|
||||
|
||||
|
|
|
@ -2,28 +2,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script elimina la imagen que recibe como parámetro (y todos sus archivos asociados), moviendo los archivos a la papelera,
|
||||
o eliminándolos permanentemente si se especifica el parámetro "-p".
|
||||
Este script elimina la imagen que recibe como parámetro (y todos sus archivos asociados), moviendo los archivos a la papelera
|
||||
(respetando el subdirectorio correspondiente a la OU, si fuera el caso), o eliminándolos permanentemente si se especifica el parámetro "-p".
|
||||
Es similar al script bash original (cuyo nombre es "deleteimage", a secas), pero este no incluía la funcionalidad papelera.
|
||||
Llama al script "updateRepoInfo.py", para actualizar la información del repositorio.
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a eliminar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a eliminar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
sys.argv[2] - Parámetro opcional para especificar que la eliminación sea permanente (sin papelera).
|
||||
- Ejemplo: -p
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./deleteImage.py image_name|/image_path/image_name [-p]
|
||||
./deleteImage.py [ou_subdir/]image_name|/image_path/image_name [-p]
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./deleteImage.py image1.img -p
|
||||
./deleteImage.py /opt/opengnsys/ogrepository/images/image1.img -p
|
||||
./deleteImage.py ou_subdir/image1.img -p
|
||||
./deleteImage.py /ou_subdir/image1.img
|
||||
./deleteImage.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -58,9 +64,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name [-p]
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name [-p]
|
||||
Ejemplo1: {script_name} image1.img -p
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img -p
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img -p
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -98,9 +107,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a eliminar
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -113,19 +126,19 @@ 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 "opengnsys" y el GID del grupo "opengnsys":
|
||||
uid = pwd.getpwnam('opengnsys').pw_uid
|
||||
# Obtenemos el UID del usuario "root" y el GID del grupo "opengnsys":
|
||||
uid = pwd.getpwnam('root').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, 0o755)
|
||||
os.chmod(trash_path, 0o775)
|
||||
|
||||
|
||||
def delete_image(file_path, method, extensions):
|
||||
""" Elimina la imagen que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
def delete_normal_image(file_path, method, extensions):
|
||||
""" Elimina la imagen "normal" que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
moviéndolos a la papelera o eliminándolos permanentemente (en función del parámetro "method").
|
||||
"""
|
||||
# Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos:
|
||||
|
@ -140,11 +153,32 @@ def delete_image(file_path, method, extensions):
|
|||
os.remove(file_to_remove)
|
||||
|
||||
|
||||
def delete_ou_image(file_path, method, extensions):
|
||||
""" Elimina la imagen basada en OU que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
moviéndolos a la papelera o eliminándolos permanentemente (en función del parámetro "method").
|
||||
"""
|
||||
# Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos:
|
||||
for ext in extensions:
|
||||
file_to_remove = f"{file_path}{ext}"
|
||||
# Si el archivo actual existe, lo eliminamos o lo movemos a la papelera (dependiendo del valor del parámetro "method"),
|
||||
# y en el último caso lo situamos en un subdirectorio correspondiente a la OU:
|
||||
if os.path.exists(file_to_remove):
|
||||
if method == 'trash':
|
||||
ou_subdir = file_to_remove.split('/')[4]
|
||||
# Comprobamos si en la papelera existe un subdirectorio correspondiente a la OU (y si no existe lo creamos):
|
||||
if not os.path.exists(f"{trash_path}{ou_subdir}"):
|
||||
os.mkdir(f"{trash_path}{ou_subdir}")
|
||||
shutil.move(file_to_remove, f"{trash_path}{ou_subdir}")
|
||||
elif method == 'permanent':
|
||||
os.remove(file_to_remove)
|
||||
|
||||
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(['python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
|
@ -188,9 +222,14 @@ def main():
|
|||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.torrent', '.info', '.info.checked']
|
||||
|
||||
# Llamamos a la función que elimina la imagen:
|
||||
print("Deleting image...")
|
||||
delete_image(file_path, method, extensions)
|
||||
# Evaluamos la cantidad de barras que hay en la ruta de la imagen, para diferenciar entre imágenes "normales" y basadas en OU
|
||||
# (y llamamos a la función correspondiente para eliminarla):
|
||||
if file_path.count('/') == 5:
|
||||
print("Deleting normal image...")
|
||||
delete_normal_image(file_path, method, extensions)
|
||||
elif file_path.count('/') == 6:
|
||||
print("Deleting OU based image...")
|
||||
delete_ou_image(file_path, method, extensions)
|
||||
|
||||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
print("Updating Repository Info...")
|
||||
|
|
|
@ -7,18 +7,24 @@ Llama al script "updateTrashInfo.py", para actualizar la información de las im
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a eliminar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a eliminar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./deleteTrashImage.py image_name|/image_path/image_name
|
||||
./deleteTrashImage.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./deleteTrashImage.py image1.img
|
||||
./deleteTrashImage.py /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
./deleteTrashImage.py ou_subdir/image1.img
|
||||
./deleteTrashImage.py /ou_subdir/image1.img
|
||||
./deleteTrashImage.py /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -49,9 +55,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -74,9 +83,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a eliminar
|
||||
(agregando "/opt/opengnsys/ogrepository/images_trash/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images_trash/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "trash_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(trash_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(trash_path):
|
||||
file_path = os.path.join(trash_path, param_path)
|
||||
|
@ -98,9 +111,10 @@ def delete_image(file_path, extensions):
|
|||
|
||||
def update_trash_info():
|
||||
""" Actualiza la información de la papelera, ejecutando el script "updateTrashInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(['python3', update_trash_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_trash_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
|
|
|
@ -4,18 +4,19 @@
|
|||
"""
|
||||
Este script exporta la imagen especificada como primer parámetro (y sus archivos asociados), al repositorio remoto especificado como segundo parámetro,
|
||||
con las credenciales del usuario especificado como tercer parámetro (en principio, mediante claves).
|
||||
Realiza la acción contraria que el script "importImage.py", pero es preferible usar "importImage.py" (porque chequea la integridad de la imagen, genera el archivo ".torrent" y actualiza el repositorio).
|
||||
|
||||
Cuando se utilice "exportImage.py" (este script) se debe generar el archivo ".torrent" (llamando al script "createTorrentSum.py" o a su endpoint asociado), que también actualizará la info del repoisitorio,
|
||||
y es conveniente chequear la integridad de la imagen exportada (llamando al script "checkImage.py" o a su endpoint asociado). Ambas acciones deben realizarse en el equipo destino.
|
||||
Realiza la acción contraria que el script "importImage.py", pero es preferible usar "exportImage.py" (porque permite buscar la imagen por ID).
|
||||
Al acabar, ogCore debe llamar al script "updateRepoInfo.py" en el repositorio remoto, para actualizar la información de dicho repositorio.
|
||||
|
||||
Librerías Python requeridas: "paramiko" (se puede instalar con "sudo apt install python3-paramiko")
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a exportar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a exportar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
sys.argv[2] - IP o hostname del repositorio remoto.
|
||||
- Ejemplo1: 192.168.56.100
|
||||
|
@ -27,12 +28,15 @@ sys.argv[3] - Usuario con el que conectar al repositorio remoto.
|
|||
|
||||
Sintaxis
|
||||
----------
|
||||
./exportImage.py image_name|/image_path/image_name remote_host remote_user
|
||||
./exportImage.py [ou_subdir/]image_name|/image_path/image_name remote_host remote_user
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./exportImage.py image1.img 192.168.56.100 user
|
||||
./exportImage.py /opt/opengnsys/ogrepository/images/image1.img remote_hostname user
|
||||
./exportImage.py /opt/opengnsys/ogrepository/images/image1.img 192.168.56.100 user
|
||||
./exportImage.py ou_subdir/image1.img remote_hostname user
|
||||
./exportImage.py /ou_subdir/image1.img remote_hostname root
|
||||
./exportImage.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img remote_hostname root
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -46,7 +50,6 @@ import sys
|
|||
import subprocess
|
||||
import paramiko
|
||||
import warnings
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -66,9 +69,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name remote_host remote_user
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name remote_host remote_user
|
||||
Ejemplo1: {script_name} image1.img 192.168.56.100 user
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img remote_hostname user
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img 192.168.56.100 user
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img remote_hostname user
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img remote_hostname root
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img remote_hostname root
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -93,9 +99,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a exportar
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -111,7 +121,7 @@ def export_image(file_path, remote_host, remote_user):
|
|||
"""
|
||||
# Creamos una lista con las extensiones de los archivos asociados a la imagen
|
||||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.info.checked']
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.torrent', '.info.checked']
|
||||
|
||||
# Iniciamos un cliente SSH:
|
||||
ssh_client = paramiko.SSHClient()
|
||||
|
@ -120,24 +130,32 @@ def export_image(file_path, remote_host, remote_user):
|
|||
|
||||
# Intentamos conectar con el equipo remoto por SSH, e iniciar un cliente SFTP,
|
||||
try: # y en caso de fallar devolvemos un error y salimos del script:
|
||||
ssh_client.connect(hostname=remote_host, port=22, username=remote_user, passphrase='')
|
||||
ssh_client.connect(remote_host, 22, remote_user) # Así se hace con claves
|
||||
#ssh_client.connect(remote_host, 22, remote_user, 'opengnsys') # Así se haría con password
|
||||
sftp_client = ssh_client.open_sftp()
|
||||
except Exception as error_description:
|
||||
journal.send(f"exportImage.py: Connection exception: {error_description}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Connection has returned an exception: {error_description}")
|
||||
sys.exit(4)
|
||||
|
||||
# Comprobamos si la imagen ya existe en el equipo remoto, en cuyo caso devolvemos un error y salimos del script:
|
||||
try:
|
||||
sftp_client.stat(file_path)
|
||||
journal.send("exportImage.py: Image already exists on remote repository", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image already exists on remote repository.")
|
||||
sys.exit(5)
|
||||
except IOError:
|
||||
print("As expected, image doesn't exist on remote repository.")
|
||||
|
||||
# Evaluamos si la ruta de la imagen tiene 6 barras, en cuyo caso corresponderá a una imagen basada en OU,
|
||||
# y almacenamos el nombre del directorio correspondiente a la OU:
|
||||
if file_path.count('/') == 6:
|
||||
ou_subdir = file_path.split('/')[5]
|
||||
# Comprobamos si el directorio de OU existe en el equipo remoto, y en caso contrario lo creamos:
|
||||
try:
|
||||
sftp_client.stat(f"{repo_path}{ou_subdir}")
|
||||
except IOError:
|
||||
sftp_client.mkdir(f"{repo_path}{ou_subdir}", mode=755)
|
||||
|
||||
# Creamos un archivo de bloqueo en el servidor remoto:
|
||||
journal.send("exportImage.py: Creating '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sftp_client.open(f"{file_path}.lock", 'w')
|
||||
|
||||
# Exportamos la imagen al servidor remoto, junto con sus archivos asociados:
|
||||
|
@ -145,15 +163,12 @@ def export_image(file_path, remote_host, remote_user):
|
|||
sftp_client.put(f"{file_path}{ext}", f"{file_path}{ext}")
|
||||
|
||||
# Renombramos el archivo remoto ".info.checked" a ".info", para que lo pille el script "updateRepoInfo.py":
|
||||
journal.send("exportImage.py: Renaming '.info.checked' file to '.info'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sftp_client.rename(f"{file_path}.info.checked", f"{file_path}.info")
|
||||
|
||||
# Eliminamos el archivo de bloqueo del servidor remoto:
|
||||
journal.send("exportImage.py: Removing '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
sftp_client.remove(f"{file_path}.lock")
|
||||
|
||||
# Cerramos el cliente SSH y el cliente SFTP:
|
||||
journal.send("exportImage.py: Closing remote connection...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
ssh_client.close()
|
||||
sftp_client.close()
|
||||
|
||||
|
@ -175,13 +190,11 @@ def main():
|
|||
|
||||
# Si no existe el archivo de imagen, imprimimos un mensaje de error y salimos del script:
|
||||
if not os.path.exists(file_path):
|
||||
journal.send("exportImage.py: Image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image file doesn't exist")
|
||||
sys.exit(2)
|
||||
|
||||
# Si la imagen está bloqueada, imprimimos un mensaje de error y salimos del script:
|
||||
if os.path.exists(f"{file_path}.lock"):
|
||||
journal.send("exportImage.py: Image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image is locked.")
|
||||
sys.exit(3)
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script devuelve información (en formato json) de todas las imágenes contenidas en el repositorio (incluída la papelera), o de la imagen que se especifique como parámetro.
|
||||
Este script devuelve información (en formato json) de todas las imágenes contenidas en el repositorio (incluída la papelera),
|
||||
o de la imagen que se especifique como primer parámetro (debiendo especificar también el subdirectorio de OU como segundo parámetro, si procede).
|
||||
Previamente, llama al script "updateRepoInfo.py", para actualizar la información del repositorio (para evitar que dé error si no hay ninguna, por ejemplo).
|
||||
|
||||
Parámetros
|
||||
|
@ -11,14 +12,19 @@ sys.argv[1] - Nombre completo de la imagen a consultar (con extensión y sin rut
|
|||
- Ejemplo1: all
|
||||
- Ejemplo2: image1.img
|
||||
|
||||
sys.argv[2] - Subdirectorio correspondiente a la OU, o "none" si no procede..
|
||||
- Ejemplo1: none
|
||||
- Ejemplo2: OU_subdirectory
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./getRepoInfo.py image_name|all
|
||||
./getRepoInfo.py image_name|all ou_subdir|none
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./getRepoInfo.py all
|
||||
./getRepoInfo.py image1.img
|
||||
./getRepoInfo.py all none
|
||||
./getRepoInfo.py image1.img none
|
||||
./getRepoInfo.py image1.img OU_subdirectory
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -50,9 +56,10 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|all
|
||||
Ejemplo1: {script_name} all
|
||||
Ejemplo2: {script_name} image1.img
|
||||
Sintaxis: {script_name} image_name|all ou_subdir|none
|
||||
Ejemplo1: {script_name} all none
|
||||
Ejemplo2: {script_name} image1.img none
|
||||
Ejemplo3: {script_name} image1.img OU_subdirectory
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -67,9 +74,9 @@ def check_params():
|
|||
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 1 parámetro, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 2:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 1 parámetro")
|
||||
# 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)
|
||||
|
||||
|
@ -77,9 +84,10 @@ def check_params():
|
|||
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(['python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
|
@ -130,6 +138,38 @@ def get_image_info(repo_data, trash_data, image_name, image_ext):
|
|||
|
||||
|
||||
|
||||
def get_ou_image_info(repo_data, trash_data, image_name, image_ext, ou_subdir):
|
||||
""" Busca la imagen basada en OU en el repositorio y en la papelera, devolviendo la información asociada si la encuentra,
|
||||
(o devolviendo un mensaje de error y saliendo del script si no la encuentra).
|
||||
"""
|
||||
dictionary = ""
|
||||
# Buscamos la OU y la imagen en el repositorio, y si los encontramos creamos un diccionario con los datos:
|
||||
if repo_data != "":
|
||||
for ou in repo_data['ous']:
|
||||
if ou['subdir'] == ou_subdir:
|
||||
for image in ou['images']:
|
||||
if image['name'] == image_name and image['type'] == image_ext:
|
||||
dictionary = {"directory": repo_data['directory'],
|
||||
"ous": [{"subdir": ou_subdir, "images": [image]}]}
|
||||
# Buscamos la OU y la imagen en la papelera, y si los encontramos creamos un diccionario con los datos:
|
||||
if trash_data != "":
|
||||
for ou in trash_data['ous']:
|
||||
if ou['subdir'] == ou_subdir:
|
||||
for image in ou['images']:
|
||||
if image['name'] == image_name:
|
||||
dictionary = {"directory": trash_data['directory'],
|
||||
"ous": [{"subdir": ou_subdir, "images": [image]}]}
|
||||
# Si hemos obtenido datos de la imagen, los pasamos a json y los imprmimos,
|
||||
# y si no, imprimimos un mensaje de error y salimos del script:
|
||||
if dictionary != "":
|
||||
final_json = json.dumps(dictionary, indent=2)
|
||||
print(final_json)
|
||||
else:
|
||||
print("No se ha encontrado la imagen especificada en el repositorio")
|
||||
sys.exit(3)
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# MAIN
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -161,13 +201,18 @@ def main():
|
|||
trash_data = ""
|
||||
|
||||
# Dependiendo del valor de los parámetros, llamamos a la función correspondiente, para imprimir la información
|
||||
# (extrayendo el nombre y la extensión de la imagen):
|
||||
# (extrayendo el nombre, la extensión de la imagen, y/o la OU cuando se necesite):
|
||||
if sys.argv[1] == 'all':
|
||||
get_all_info(repo_data, trash_data)
|
||||
else:
|
||||
elif sys.argv[2] == 'none':
|
||||
image_name = sys.argv[1].split('.')[0]
|
||||
image_ext = sys.argv[1].split('.')[1]
|
||||
get_image_info(repo_data, trash_data, image_name, image_ext)
|
||||
else:
|
||||
image_name = sys.argv[1].split('.')[0]
|
||||
image_ext = sys.argv[1].split('.')[1]
|
||||
ou_subdir = sys.argv[2]
|
||||
get_ou_image_info(repo_data, trash_data, image_name, image_ext, ou_subdir)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
"""
|
||||
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")
|
||||
|
@ -19,29 +18,11 @@ 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.
|
||||
"""
|
||||
|
@ -78,10 +59,10 @@ def get_service_status(service):
|
|||
def get_process_status(process):
|
||||
""" Obtiene y retorna el estado del proceso que recibe como parámetro.
|
||||
"""
|
||||
#for proc in psutil.process_iter(['pid', 'name', 'status']):
|
||||
for proc in psutil.process_iter(['name']):
|
||||
if proc.info['name'] in process:
|
||||
if proc.info['name'] == process:
|
||||
return 'running'
|
||||
# Esto no debe ir asociado a un "else" (porque comprueba todos los procesos):
|
||||
return 'stopped'
|
||||
|
||||
|
||||
|
@ -93,9 +74,6 @@ 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()
|
||||
|
||||
|
@ -110,14 +88,11 @@ def main():
|
|||
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', 'bttrack', 'btlaunchmany']
|
||||
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)}%"
|
||||
},
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
"""
|
||||
Este script importa la imagen especificada como primer parámetro (y sus archivos asociados), desde el repositorio remoto especificado como segundo parámetro,
|
||||
con las credenciales del usuario especificado como tercer parámetro (en principio, mediante claves).
|
||||
Es similar al script bash original (cuyo nombre es "importimage", a secas), pero con ciertas diferencias.
|
||||
|
||||
Comprueba si la importación se ha realizado correctamente, comparando el contenido de los archivos "sum" y "size" con los valores reales (que vuelve a calcular).
|
||||
Si la importación ha sido correcta llama al script "createTorrentSum.py", para crear el archivo ".torrent" (que debe crearse desde el repositorio en el que esté), y actualizar la info del repositorio.
|
||||
Si la importación no ha sido correcta (porque la imagen no ha pasado el check de integridad), borra los archivos importados.
|
||||
Es muy similar al script bash original (cuyo nombre es "importimage", a secas), pero con ciertas diferencias.
|
||||
Al acabar, llama al script "updateRepoInfo.py", para actualizar la información del repositorio.
|
||||
|
||||
Librerías Python requeridas: "paramiko" (se puede instalar con "sudo apt install python3-paramiko")
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a importar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a importar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
sys.argv[2] - IP o hostname del repositorio remoto.
|
||||
- Ejemplo1: 192.168.56.100
|
||||
|
@ -28,12 +28,15 @@ sys.argv[3] - Usuario con el que conectar al repositorio remoto.
|
|||
|
||||
Sintaxis
|
||||
----------
|
||||
./importImage.py image_name|/image_path/image_name remote_host remote_user
|
||||
./importImage.py [ou_subdir/]image_name|/image_path/image_name remote_host remote_user
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./importImage.py image1.img 192.168.56.100 user
|
||||
./importImage.py /opt/opengnsys/ogrepository/images/image1.img remote_hostname user
|
||||
./importImage.py /opt/opengnsys/ogrepository/images/image1.img 192.168.56.100 user
|
||||
./importImage.py ou_subdir/image1.img remote_hostname user
|
||||
./importImage.py /ou_subdir/image1.img remote_hostname root
|
||||
./importImage.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img remote_hostname root
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -44,11 +47,9 @@ import warnings
|
|||
warnings.filterwarnings("ignore")
|
||||
import os
|
||||
import sys
|
||||
import hashlib
|
||||
import subprocess
|
||||
import paramiko
|
||||
import warnings
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -57,7 +58,7 @@ from systemd import journal
|
|||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final
|
||||
create_torrent_script = '/opt/opengnsys/ogrepository/bin/createTorrentSum.py'
|
||||
update_repo_script = '/opt/opengnsys/ogrepository/bin/updateRepoInfo.py'
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -69,9 +70,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name remote_host remote_user
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name remote_host remote_user
|
||||
Ejemplo1: {script_name} image1.img 192.168.56.100 user
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img remote_hostname user
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img 192.168.56.100 user
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img remote_hostname user
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img remote_hostname root
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img remote_hostname root
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -96,9 +100,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a importar
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -114,7 +122,7 @@ def import_image(file_path, remote_host, remote_user):
|
|||
"""
|
||||
# Creamos una lista con las extensiones de los archivos asociados a la imagen
|
||||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.info.checked'] # Quitamos la extensión ".torrent", porque hay que generarlo en el repo que almacena la imagen
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.torrent', '.info.checked']
|
||||
|
||||
# Iniciamos un cliente SSH:
|
||||
ssh_client = paramiko.SSHClient()
|
||||
|
@ -123,10 +131,10 @@ def import_image(file_path, remote_host, remote_user):
|
|||
|
||||
# Intentamos conectar con el equipo remoto por SSH, e iniciar un cliente SFTP,
|
||||
try: # y en caso de fallar devolvemos un error y salimos del script:
|
||||
ssh_client.connect(hostname=remote_host, port=22, username=remote_user, passphrase='')
|
||||
ssh_client.connect(remote_host, 22, remote_user) # Así se hace con claves
|
||||
#ssh_client.connect(remote_host, 22, remote_user, 'opengnsys') # Así se haría con password
|
||||
sftp_client = ssh_client.open_sftp()
|
||||
except Exception as error_description:
|
||||
journal.send(f"importImage.py: Connection exception: {error_description}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Connection has returned an exception: {error_description}")
|
||||
sys.exit(2)
|
||||
|
||||
|
@ -134,99 +142,38 @@ def import_image(file_path, remote_host, remote_user):
|
|||
try:
|
||||
sftp_client.stat(file_path)
|
||||
except IOError:
|
||||
journal.send("importImage.py: Remote image not found", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Remote image doesn't exist")
|
||||
sys.exit(3)
|
||||
|
||||
# Comprobamos si la imagen remota está bloqueada, en cuyo caso devolvemos un error y salimos del script,
|
||||
try: # y en caso contrario la importamos (junto con todos sus archivos asociados):
|
||||
sftp_client.stat(f"{file_path}.lock")
|
||||
journal.send("importImage.py: Remote image is locked", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Remote image is locked.")
|
||||
sys.exit(4)
|
||||
except IOError:
|
||||
print("Importing remote image...")
|
||||
journal.send("importImage.py: Creating '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
open(f"{file_path}.lock", "w").close() # Creamos un archivo de bloqueo
|
||||
for ext in extensions:
|
||||
sftp_client.get(f"{file_path}{ext}", f"{file_path}{ext}")
|
||||
|
||||
# Cerramos el cliente SSH y el cliente SFTP:
|
||||
journal.send("importImage.py: Closing remote connection...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
ssh_client.close()
|
||||
sftp_client.close()
|
||||
|
||||
|
||||
|
||||
def get_md5_sum(file_path, megabytes=1):
|
||||
""" Calcula y retorna el hash MD5 del último MB del archivo de imagen que recibe como parámetro.
|
||||
Se utiliza para comprobar el valor del archivo ".sum".
|
||||
"""
|
||||
hash_md5 = hashlib.md5()
|
||||
with open(file_path, "rb") as f:
|
||||
f.seek(-megabytes * 1024 * 1024, os.SEEK_END)
|
||||
data = f.read(megabytes * 1024 * 1024)
|
||||
hash_md5.update(data)
|
||||
return hash_md5.hexdigest()
|
||||
|
||||
|
||||
|
||||
def check_image(file_path):
|
||||
""" Comprueba si los valores actuales de "sum" y "size"
|
||||
coinciden con los almacenados en los archivos ".sum" y ".size".
|
||||
Si coinciden retorna "True", y si no retorna "False".
|
||||
"""
|
||||
# Almacenamos los valores actuales de "sum" y "size":
|
||||
actual_datasum = get_md5_sum(file_path)
|
||||
actual_size = os.path.getsize(file_path)
|
||||
|
||||
# Almacenamos el valor de "sum" almacenado en el archivo:
|
||||
with open(f"{file_path}.sum", 'r') as file:
|
||||
file_datasum = file.read().strip('\n')
|
||||
# Almacenamos el valor de "size" almacenado en el archivo:
|
||||
with open(f"{file_path}.size", 'r') as file:
|
||||
file_datasize = int(file.read().strip('\n'))
|
||||
|
||||
# Si los valores actuales coinciden con los almacenados en los archivos retornamos "True", y si no "False":
|
||||
if actual_datasum == file_datasum and actual_size == file_datasize:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def create_torrent(file_path):
|
||||
""" Crea el archivo ".torrent" asociado a la imagen importada (los demás archivos auxiliares ya están creados), y actualiza la información del repositorio
|
||||
(llamando al script "createTorrentSum.py", que a su vez llama al script "updateRepoInfo.py").
|
||||
Se le llama cuando se ha comprobado que la imagen se ha importado correctamente (pasando el check de integridad).
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("importImage.py: Running script 'createTorrentSum.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['python3', create_torrent_script, file_path], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"importImage.py: 'createTorrentSum.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(5)
|
||||
sys.exit(2)
|
||||
except Exception as error:
|
||||
journal.send(f"importImage.py: 'createTorrentSum.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
sys.exit(6)
|
||||
|
||||
|
||||
|
||||
def erase_image(file_path):
|
||||
""" Borra la imagen importada y cada uno de los archivos asociados.
|
||||
Se le llama cuando se ha comprobado que la imagen NO se ha importado correctamente (porque NO ha pasado el check de integridad).
|
||||
"""
|
||||
journal.send("importImage.py: Removing imported image files...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Creamos una lista con las extensiones de los archivos asociados a la imagen
|
||||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.info']
|
||||
|
||||
# Borramos cada uno de los archivos (incluyendo la imagen):
|
||||
for ext in extensions:
|
||||
if os.path.exists(f"{file_path}{ext}"):
|
||||
os.remove(f"{file_path}{ext}")
|
||||
sys.exit(3)
|
||||
|
||||
|
||||
|
||||
|
@ -248,31 +195,26 @@ def main():
|
|||
remote_host = sys.argv[2]
|
||||
remote_user = sys.argv[3]
|
||||
|
||||
# Evaluamos si la ruta de la imagen tiene 6 barras, en cuyo caso corresponderá a una imagen basada en OU,
|
||||
# y almacenamos el nombre del directorio correspondiente a la OU:
|
||||
if file_path.count('/') == 6:
|
||||
ou_subdir = file_path.split('/')[5]
|
||||
# Si no existe un directorio correspondiente a la OU en el repo local, lo creamos:
|
||||
if not os.path.exists(f"{repo_path}{ou_subdir}"):
|
||||
os.mkdir(f"{repo_path}{ou_subdir}", 0o755)
|
||||
|
||||
# Importamos la imagen del repositorio remoto:
|
||||
import_image(file_path, remote_host, remote_user)
|
||||
|
||||
# Comprobamos si la imagen se ha importado correctamente (comparando los archivos ".size" y ".sum" con los valores actuales):
|
||||
image_OK = check_image(file_path)
|
||||
|
||||
# Renombramos el archivo ".info.checked" a ".info", para que lo pille el script "updateRepoInfo.py":
|
||||
journal.send("importImage.py: Renaming '.info.checked' file to '.info'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
os.rename(f"{file_path}.info.checked", f"{file_path}.info")
|
||||
|
||||
# Eliminamos el archivo de bloqueo:
|
||||
journal.send("importImage.py: Removing '.lock' file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
os.remove(f"{file_path}.lock")
|
||||
|
||||
# Si la imagen ha pasado el check de integridad, creamos el archivo ".torrent" y actualizamos el repositorio,
|
||||
# y si no lo ha pasado borramos la imagen y los archivos asociados:
|
||||
if image_OK == True:
|
||||
create_torrent(file_path)
|
||||
journal.send("importImage.py: Image imported successfully (Integrity Check OK)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Image imported successfully")
|
||||
else:
|
||||
erase_image(file_path)
|
||||
journal.send("importImage.py: Imported image didn't pass the Integrity Check", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Imported image didn't pass the Integrity Check")
|
||||
sys.exit(7)
|
||||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
print("Updating Repository Info...")
|
||||
update_repo_info()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2,23 +2,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Este script recupera la imagen que recibe como parámetro (y todos sus archivos asociados), moviendo los archivos a "/opt/opengnsys/ogrepository/images", desde la papelera.
|
||||
Este script recupera la imagen que recibe como parámetro (y todos sus archivos asociados), moviendo los archivos a "/opt/opengnsys/ogrepository/images", desde la papelera
|
||||
(respetando el subdirectorio correspondiente a la OU, si fuera el caso).
|
||||
Llama al script "updateRepoInfo.py", para actualizar la información del repositorio.
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a recuperar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a recuperar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./recoverImage.py image_name|/image_path/image_name
|
||||
./recoverImage.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./recoverImage.py image1.img
|
||||
./recoverImage.py /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
./recoverImage.py ou_subdir/image1.img
|
||||
./recoverImage.py /ou_subdir/image1.img
|
||||
./recoverImage.py /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -50,9 +57,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images_trash/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -80,9 +90,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a recuperar
|
||||
(agregando "/opt/opengnsys/ogrepository/images_trash/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images_trash/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "trash_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(trash_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(trash_path):
|
||||
file_path = os.path.join(trash_path, param_path)
|
||||
|
@ -91,14 +105,14 @@ def build_file_path():
|
|||
return file_path
|
||||
|
||||
|
||||
def recover_image(file_path, extensions):
|
||||
""" Recupera la imagen que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
moviéndolos a "/opt/opengnsys/ogrepository/images" (desde la papelera).
|
||||
def recover_normal_image(file_path, extensions):
|
||||
""" Recupera la imagen "normal" que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
moviéndolos a "/opt/opengnsys/images" (desde la papelera).
|
||||
"""
|
||||
# Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos:
|
||||
for ext in extensions:
|
||||
file_to_recover = f"{file_path}{ext}"
|
||||
# Si el archivo actual existe, lo movemos a "/opt/opengnsys/ogrepository/images" (recuperándolo desde la papelera):
|
||||
# Si el archivo actual existe, lo movemos a "/opt/opengnsys/images" (recuperándolo desde la papelera):
|
||||
if os.path.exists(file_to_recover):
|
||||
# Si la extensión del archivo actual es ".info.checked" la renombramos a ".info" (para que lo pille "updateRepoInfo"):
|
||||
if ext == '.info.checked':
|
||||
|
@ -107,11 +121,32 @@ def recover_image(file_path, extensions):
|
|||
shutil.move(file_to_recover, repo_path)
|
||||
|
||||
|
||||
def recover_ou_image(file_path, extensions):
|
||||
""" Recupera la imagen basada en OU que recibe en el parámetro "file_path", y todos sus archivos asociados,
|
||||
moviéndolos a "/opt/opengnsys/images" (desde la papelera), respetando el subdirectorio correspondiente a la OU.
|
||||
"""
|
||||
# Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos:
|
||||
for ext in extensions:
|
||||
file_to_recover = f"{file_path}{ext}"
|
||||
# Si el archivo actual existe, lo movemos a "/opt/opengnsys/images/ou_subdir":
|
||||
if os.path.exists(file_to_recover):
|
||||
# Si la extensión del archivo actual es ".info.checked" la renombramos a ".info" (para que lo pille "updateRepoInfo"):
|
||||
if ext == '.info.checked':
|
||||
os.rename(file_to_recover, file_to_recover.strip('.checked'))
|
||||
file_to_recover = file_to_recover.strip('.checked')
|
||||
ou_subdir = file_to_recover.split('/')[4]
|
||||
# Comprobamos si en "repo_path" existe un subdirectorio correspondiente a la OU (y si no existe lo creamos):
|
||||
if not os.path.exists(f"{repo_path}{ou_subdir}"):
|
||||
os.mkdir(f"{repo_path}{ou_subdir}")
|
||||
shutil.move(file_to_recover, f"{repo_path}{ou_subdir}")
|
||||
|
||||
|
||||
def update_repo_info():
|
||||
""" Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(['python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_repo_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
|
@ -139,9 +174,14 @@ def main():
|
|||
# (incluyendo ninguna extensión, que corresponde a la propia imagen):
|
||||
extensions = ['', '.size', '.sum', '.full.sum', '.torrent', '.info', '.info.checked']
|
||||
|
||||
# Llamamos a la función que recupera la imagen:
|
||||
print("Recovering image...")
|
||||
recover_image(file_path, extensions)
|
||||
# Evaluamos la cantidad de barras que hay en la ruta de la imagen, para diferenciar entre imágenes "normales" y basadas en OU
|
||||
# (y llamamos a la función correspondiente para recuperarla):
|
||||
if file_path.count('/') == 5:
|
||||
print("Recovering normal image...")
|
||||
recover_normal_image(file_path, extensions)
|
||||
elif file_path.count('/') == 6:
|
||||
print("Recovering OU based image...")
|
||||
recover_ou_image(file_path, extensions)
|
||||
|
||||
# Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py":
|
||||
print("Updating Repository Info...")
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
#!/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()
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
|
@ -5,8 +5,22 @@
|
|||
Este script inicia el seeder "bittornado" (o lo reinicia, si ya estuviera iniciado), finalizando previamente cualquier proceso activo.
|
||||
En principio, debería hacer lo mismo que la sección correspondiente del script "/etc/init.d/opengnsys", que se ejecuta al inicio (pero que debería dejar de hacerlo).
|
||||
Creemos que debe ser llamado únicamente cuando se quiera hacer una descarga mediante P2P (junto al script "runTorrentTracker.py").
|
||||
NOTA: El paquete no hace una búsqueda recursiva, por lo que se debe especificar el subdirectorio correspondiente a la OU, si es el caso.
|
||||
|
||||
No recibe ningún parámetro.
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
- Ejemplo1: none
|
||||
- Ejemplo2: ou_subdir
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./runTorrentSeeder.py none|ou_subdir
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./runTorrentSeeder.py none
|
||||
./runTorrentSeeder.py ou_subdir
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -16,13 +30,13 @@ No recibe ningún parámetro.
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images' # En este caso, no lleva barra final
|
||||
|
||||
|
||||
|
@ -31,26 +45,51 @@ repo_path = '/opt/opengnsys/ogrepository/images' # En este caso, no lleva barra
|
|||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def run_bittornado(repo_path):
|
||||
def show_help():
|
||||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} none|ou_subdir
|
||||
Ejemplo1: {script_name} none
|
||||
Ejemplo2: {script_name} ou_subdir
|
||||
"""
|
||||
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 1 parámetro, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 2:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 1 parámetro")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def run_bittornado(torrent_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()
|
||||
splitted_cmd = f"btlaunchmany.bittornado {torrent_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}")
|
||||
|
||||
|
||||
|
@ -63,16 +102,23 @@ def run_bittornado(repo_path):
|
|||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# 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}")
|
||||
|
||||
# Construimos la ruta en la que buscar los torrents, en base al parámetro especificado:
|
||||
if sys.argv[1] == 'none':
|
||||
torrent_path = repo_path
|
||||
else:
|
||||
torrent_path = f"{repo_path}/{sys.argv[1]}"
|
||||
|
||||
# Ejecutamos el comando "btlaunchmany.bittornado" (para hacer seed de los torrents):
|
||||
run_bittornado(repo_path)
|
||||
run_bittornado(torrent_path)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,20 @@ En principio, debería hacer lo mismo que el script bash original (cuyo nombre e
|
|||
Creemos que debe ser llamado únicamente cuando se quiera hacer una descarga mediante P2P (junto al script "runTorrentSeeder.py").
|
||||
NOTA: El paquete no hace una búsqueda recursiva, por lo que se debe especificar el subdirectorio correspondiente a la OU, si es el caso.
|
||||
|
||||
No recibe ningún parámetro.
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Subdirectorio correspondiente a la OU (o "none" si no es el caso).
|
||||
- Ejemplo1: none
|
||||
- Ejemplo2: ou_subdir
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./runTorrentTracker.py none|ou_subdir
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./runTorrentTracker.py none
|
||||
./runTorrentTracker.py ou_subdir
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -18,13 +31,13 @@ import os
|
|||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
script_name = os.path.basename(__file__)
|
||||
repo_path = '/opt/opengnsys/ogrepository/images' # En este caso, no lleva barra final
|
||||
|
||||
bttrack_port = 6969
|
||||
|
@ -39,26 +52,51 @@ bttrack_allow_get = 0 # Este valor impide la descarga desde clientes no autoriza
|
|||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def run_bttrack(repo_path):
|
||||
def show_help():
|
||||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} none|ou_subdir
|
||||
Ejemplo1: {script_name} none
|
||||
Ejemplo2: {script_name} ou_subdir
|
||||
"""
|
||||
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 1 parámetro, se muestra un error y la ayuda, y se sale del script:
|
||||
elif len(sys.argv) != 2:
|
||||
print(f"{script_name} Error: Formato incorrecto: Se debe especificar 1 parámetro")
|
||||
show_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
def run_bttrack(torrent_path):
|
||||
""" Ejecuta el comando "bttrack", con sus parámetros correspondientes.
|
||||
Además, captura el resultado y los posibles errores, y los imprime.
|
||||
"""
|
||||
# Creamos una lista con el comando "bttrack" y sus parámetros, y lo imprimimos con espacios:
|
||||
splitted_cmd = f"bttrack --port {bttrack_port} --dfile {bttrack_dfile} --save_dfile_interval {bttrack_interval} --reannounce_interval {bttrack_interval} --logfile {bttrack_log} --allowed_dir {repo_path} --allow_get {bttrack_allow_get}".split()
|
||||
splitted_cmd = f"bttrack --port {bttrack_port} --dfile {bttrack_dfile} --save_dfile_interval {bttrack_interval} --reannounce_interval {bttrack_interval} --logfile {bttrack_log} --allowed_dir {torrent_path} --allow_get {bttrack_allow_get}".split()
|
||||
print(f"Sending command: {' '.join(splitted_cmd)}")
|
||||
journal.send(f"runTorrentTracker.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Ejecutamos el comando "bttrack" en el sistema, e imprimimos el resultado:
|
||||
try:
|
||||
result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
journal.send(f"runTorrentTracker.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Bttrack ReturnCode: {result.returncode}")
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send("runTorrentTracker.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Bttrack ReturnCode: {error.returncode}")
|
||||
print(f"Bttrack Error Output: {error.stderr.decode()}")
|
||||
except Exception as error:
|
||||
journal.send(f"runTorrentTracker.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Unexpected bttrack error: {error}")
|
||||
|
||||
|
||||
|
@ -71,24 +109,30 @@ def run_bttrack(repo_path):
|
|||
def main():
|
||||
"""
|
||||
"""
|
||||
# Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto:
|
||||
check_params()
|
||||
|
||||
# Finalizamos el proceso "bttrack" (en caso de que estuviera corriendo):
|
||||
try:
|
||||
journal.send("runTorrentTracker.py: Killing process 'bttrack'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
subprocess.run(f"pkill bttrack".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except Exception as error_description:
|
||||
journal.send("runTorrentTracker.py: No 'bttrack' process running", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"No bttrack process running? Returned error: {error_description}")
|
||||
|
||||
# Si existe el archivo "/tmp/dstate", lo eliminamos:
|
||||
if os.path.exists(bttrack_dfile):
|
||||
journal.send("runTorrentTracker.py: Removing '/tmp/dstate'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
os.remove(bttrack_dfile)
|
||||
|
||||
# Esperamos 2 segundos:
|
||||
time.sleep(2)
|
||||
|
||||
# Construimos la ruta en la que buscar los torrents, en base al parámetro especificado:
|
||||
if sys.argv[1] == 'none':
|
||||
torrent_path = repo_path
|
||||
else:
|
||||
torrent_path = f"{repo_path}/{sys.argv[1]}"
|
||||
|
||||
# Ejecutamos el comando "bttrack" (para hacer tracking de los torrents):
|
||||
run_bttrack(repo_path)
|
||||
run_bttrack(torrent_path)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,21 +7,27 @@ En principio, debería hacer lo mismo que el script bash original (cuyo nombre e
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
sys.argv[2] - Parámetros Multicast (en formato "Port:Duplex:IP:Mpbs:Nclients:Timeout")
|
||||
- Ejemplo: 9000:full:239.194.17.2:70M:20:120
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./sendFileMcast.py image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout
|
||||
./sendFileMcast.py [ou_subdir/]image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./sendFileMcast.py image1.img 9000:full:239.194.17.2:70M:20:120
|
||||
./sendFileMcast.py /opt/opengnsys/ogrepository/images/image1.img 9000:full:239.194.17.2:70M:20:120
|
||||
./sendFileMcast.py ou_subdir/image1.img 9000:full:239.194.17.2:70M:20:120
|
||||
./sendFileMcast.py /ou_subdir/image1.img 9000:full:239.194.17.2:70M:20:120
|
||||
./sendFileMcast.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img 9000:full:239.194.17.2:70M:20:120
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -31,7 +37,6 @@ sys.argv[2] - Parámetros Multicast (en formato "Port:Duplex:IP:Mpbs:Nclients:Ti
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -54,9 +59,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout
|
||||
Ejemplo1: {script_name} image1.img 9000:full-duplex:239.194.17.2:70M:20:120
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img 9000:full-duplex:239.194.17.2:70M:20:120
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img 9000:full-duplex:239.194.17.2:70M:20:120
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img 9000:full-duplex:239.194.17.2:70M:20:120
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img 9000:full-duplex:239.194.17.2:70M:20:120
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -83,9 +91,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a enviar
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -96,18 +108,16 @@ def build_file_path():
|
|||
|
||||
def get_repo_iface():
|
||||
""" Obtiene y retorna la interfaz del repositorio, ejecutando el script "getRepoIface.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("sendFileMcast.py: Running script 'getRepoIface.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['python3', repo_iface_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', repo_iface_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
repo_iface = result.stdout.decode().strip() # Es necesario poner "strip", o dará error.
|
||||
return repo_iface
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"sendFileMcast.py: 'getRepoIface.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
except Exception as error:
|
||||
journal.send(f"sendFileMcast.py: 'getRepoIface.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
sys.exit(4)
|
||||
|
||||
|
@ -144,7 +154,6 @@ def main():
|
|||
cerror = "8x8/128"
|
||||
|
||||
# Obtenemos y almacenamos la interfaz del repositorio, mediante el script "getRepoIface.py":
|
||||
journal.send("sendFileMcast.py: Getting repository interface...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
repo_iface = get_repo_iface()
|
||||
|
||||
# Creamos una lista con el comando a enviar (esto es requerido por la función "subprocess.run").
|
||||
|
@ -171,16 +180,12 @@ def main():
|
|||
|
||||
# Ejecutamos el comando en el sistema, e imprimimos el resultado:
|
||||
try:
|
||||
journal.send(f"sendFileMcast.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
journal.send(f"sendFileMcast.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {result.returncode}")
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send("sendFileMcast.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {error.returncode}")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
except Exception as error:
|
||||
journal.send(f"sendFileMcast.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
|
||||
|
||||
|
|
|
@ -11,9 +11,12 @@ Paquetes APT requeridos: "uftp" (se puede instalar con "sudo apt install uftp").
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
sys.argv[2] - Parámetros Multicast/Unicast (en formato "Port:IP:Bitrate")
|
||||
- Ejemplo1: 9000:239.194.17.2:100M
|
||||
|
@ -21,12 +24,15 @@ sys.argv[2] - Parámetros Multicast/Unicast (en formato "Port:IP:Bitrate")
|
|||
|
||||
Sintaxis
|
||||
----------
|
||||
./sendFileUFTP.py image_name|/image_path/image_name Port:IP:Bitrate
|
||||
./sendFileUFTP.py [ou_subdir/]image_name|/image_path/image_name Port:IP:Bitrate
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./sendFileUFTP.py image1.img 9000:239.194.17.2:100M
|
||||
./sendFileUFTP.py /opt/opengnsys/ogrepository/images/image1.img 9000:192.168.56.101:1G
|
||||
./sendFileUFTP.py /opt/opengnsys/ogrepository/images/image1.img 9000:239.194.17.2:100M
|
||||
./sendFileUFTP.py ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
./sendFileUFTP.py /ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
./sendFileUFTP.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -36,7 +42,6 @@ sys.argv[2] - Parámetros Multicast/Unicast (en formato "Port:IP:Bitrate")
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -58,9 +63,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name Port:IP:Bitrate
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name Port:IP:Bitrate
|
||||
Ejemplo1: {script_name} image1.img 9000:239.194.17.2:100M
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img 9000:239.194.17.2:1G
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img 9000:239.194.17.2:100M
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img 9000:192.168.56.101:1G
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -87,9 +95,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa al archivo a enviar
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -148,19 +160,15 @@ def main():
|
|||
splitted_cmd = f"uftp -M {ip} -p {port} -L {log_file} -o -D {cache_path} -Y aes256-cbc -h sha256 -e rsa -c -K 1024 -R {bitrate} {file_path}".split()
|
||||
|
||||
print(f"Sending command: {' '.join(splitted_cmd)}")
|
||||
journal.send(f"sendFileUFTP.py: Running command: {' '.join(splitted_cmd)}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
|
||||
# Ejecutamos el comando en el sistema, e imprimimos el resultado:
|
||||
try:
|
||||
result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
journal.send(f"sendFileUFTP.py: Command ReturnCode: {result.returncode}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {result.returncode}")
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send("sendFileUFTP.py: Process finalized", PRIORITY=journal.LOG_WARNING, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"ReturnCode: {error.returncode}")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
except Exception as error:
|
||||
journal.send(f"sendFileUFTP.py: Command exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
Este script envía un paquete mágico WOL a la dirección MAC especificada como segundo parámetro, a través de la IP de broadcast especificada como primer parámetro.
|
||||
La IP de broadcast puede corresponder a toda la red ("255.255.255.255"), que es el valor por defecto, o a una subred concreta (por ejemplo, "10.2.7.255").
|
||||
|
||||
Paquetes APT requeridos: "wakeonlan" (se puede instalar con "sudo apt install wakeonlan").
|
||||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Dirección IP de broadcast de toda la red o de una subred concreta.
|
||||
|
|
|
@ -27,7 +27,7 @@ def kill_seeder():
|
|||
que corresponde al seeder P2P.
|
||||
"""
|
||||
try:
|
||||
subprocess.run(f"sudo pkill -9 btlaunchmany".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(f"pkill 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"sudo pkill -9 bttrack".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subprocess.run(f"pkill 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}")
|
||||
|
|
|
@ -8,18 +8,24 @@ Este script finaliza el proceso "udp-sender" asociado a la imagen que recibe com
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a cancelar su transmisión (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a cancelar su transmisión (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./stopUDPcast.py image_name|/image_path/image_name
|
||||
./stopUDPcast.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./stopUDPcast.py image1.img
|
||||
./stopUDPcast.py /opt/opengnsys/ogrepository/images/image1.img
|
||||
./stopUDPcast.py ou_subdir/image1.img
|
||||
./stopUDPcast.py /ou_subdir/image1.img
|
||||
./stopUDPcast.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -48,9 +54,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -73,9 +82,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa del archivo a chequear
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -115,7 +128,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"sudo kill -9 {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(f"kill {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:
|
||||
|
|
|
@ -8,18 +8,24 @@ Este script finaliza el proceso "uftp" asociado a la imagen que recibe como par
|
|||
|
||||
Parámetros
|
||||
------------
|
||||
sys.argv[1] - Nombre completo de la imagen a cancelar su transmisión (con o sin ruta).
|
||||
sys.argv[1] - Nombre completo de la imagen a cancelar su transmisión (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso.
|
||||
- Ejemplo1: image1.img
|
||||
- Ejemplo2: /opt/opengnsys/ogrepository/images/image1.img
|
||||
- Ejemplo3: ou_subdir/image1.img
|
||||
- Ejemplo4: /ou_subdir/image1.img
|
||||
- Ejemplo5: /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
|
||||
Sintaxis
|
||||
----------
|
||||
./stopUDPcast.py image_name|/image_path/image_name
|
||||
./stopUDPcast.py [ou_subdir/]image_name|/image_path/image_name
|
||||
|
||||
Ejemplos
|
||||
---------
|
||||
./stopUDPcast.py image1.img
|
||||
./stopUDPcast.py /opt/opengnsys/ogrepository/images/image1.img
|
||||
./stopUDPcast.py ou_subdir/image1.img
|
||||
./stopUDPcast.py /ou_subdir/image1.img
|
||||
./stopUDPcast.py /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -48,9 +54,12 @@ def show_help():
|
|||
""" Imprime la ayuda, cuando se ejecuta el script con el parámetro "help".
|
||||
"""
|
||||
help_text = f"""
|
||||
Sintaxis: {script_name} image_name|/image_path/image_name
|
||||
Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name
|
||||
Ejemplo1: {script_name} image1.img
|
||||
Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images/image1.img
|
||||
Ejemplo3: {script_name} ou_subdir/image1.img
|
||||
Ejemplo4: {script_name} /ou_subdir/image1.img
|
||||
Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images/ou_subdir/image1.img
|
||||
"""
|
||||
print(help_text)
|
||||
|
||||
|
@ -73,9 +82,13 @@ def check_params():
|
|||
|
||||
def build_file_path():
|
||||
""" Construye la ruta completa del archivo a chequear
|
||||
(agregando "/opt/opengnsys/ogrepository/images/" si no se ha especificado en el parámetro).
|
||||
(agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro).
|
||||
"""
|
||||
param_path = sys.argv[1]
|
||||
# Si la ruta comienza con una barra, pero que no corresponde a "repo_path"
|
||||
# (porque corresponderá al subdirectorio de una OU), eliminamos la barra:
|
||||
if param_path.startswith('/') and not param_path.startswith(repo_path):
|
||||
param_path = param_path.lstrip('/')
|
||||
# Construimos la ruta completa:
|
||||
if not param_path.startswith(repo_path):
|
||||
file_path = os.path.join(repo_path, param_path)
|
||||
|
@ -115,7 +128,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"sudo kill -9 {pid}".split(), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(f"kill {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:
|
||||
|
|
|
@ -21,7 +21,6 @@ import sys
|
|||
import json
|
||||
import subprocess
|
||||
import shutil
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -43,7 +42,7 @@ def create_empty_json():
|
|||
Evidentemente, solo es llamada cuando no existe el archivo.
|
||||
"""
|
||||
# Creamos un diccionario con la estructura básica que debe tener el archivo json:
|
||||
json_data = {"directory": repo_path, "images": []}
|
||||
json_data = {"directory": repo_path, "images": [], "ous": []}
|
||||
|
||||
# Abrimos el archivo json en modo escritura (creándolo si no existe, como es el caso),
|
||||
# y le añadimos la estructura almacenada en el diccionario "json_data":
|
||||
|
@ -51,17 +50,20 @@ def create_empty_json():
|
|||
json.dump(json_data, file, indent=2)
|
||||
|
||||
|
||||
|
||||
def check_files():
|
||||
""" Esta función recorre el directorio de imágenes, para buscar archivos con extensión ".img".
|
||||
""" Esta función recorre el directorio de imágenes, para buscar archivos con extensiones ".img" o ".dsk".
|
||||
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
|
||||
que además tengan un archivo ".info" asociado (siempre que este no se haya modificado antes que la propia imagen).
|
||||
Originalmente eliminaba los archivos ".info" después de extraer la información, pero ahora los renombra (agrega ".checked").
|
||||
"""
|
||||
# Iteramos todos los archivos y directorios de "/opt/opengnsys/ogrepository/images":
|
||||
for item in os.listdir(repo_path):
|
||||
# Si el item actual acaba con ".img", construimos la ruta completa de la imagen ("img_path"):
|
||||
if item.endswith(".img"):
|
||||
img_path = os.path.join(repo_path, item)
|
||||
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images",
|
||||
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
|
||||
for root, dirs, files in os.walk(repo_path):
|
||||
for file in files:
|
||||
# Si la imagen actual tiene extensión ".img" o ".dsk", construimos la ruta completa ("img_path"):
|
||||
if file.endswith((".img", ".dsk")):
|
||||
img_path = os.path.join(root, file)
|
||||
# Si existe un archivo ".lock" asociado a la imagen actual, pasamos a la siguiente:
|
||||
if os.path.exists(f"{img_path}.lock"):
|
||||
continue
|
||||
|
@ -93,12 +95,61 @@ def check_files():
|
|||
os.rename(info_file, f"{info_file}.checked")
|
||||
|
||||
|
||||
|
||||
def check_dirs():
|
||||
""" Esta función recorre el directorio de imágenes, para buscar archivos con nombre "ogimg.info".
|
||||
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
|
||||
que además tengan un archivo "ogimg.info" asociado (pero no sé que tipo de imágenes son esas).
|
||||
"""
|
||||
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images",
|
||||
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
|
||||
for root, dirs, files in os.walk(repo_path):
|
||||
for file in files:
|
||||
# Si el nombre del archivo actual es "ogimg.info", construimos su ruta completa ("info_path"), y la ruta del directorio ("img_path"):
|
||||
if file == "ogimg.info":
|
||||
info_path = os.path.join(root, file)
|
||||
img_path = os.path.dirname(info_path)
|
||||
# Si existe un archivo ".lock" asociado a la imagen actual, o si la ruta coincide con "repo_path", pasamos a la siguiente:
|
||||
if img_path == repo_path or os.path.exists(f"{img_path}.lock"):
|
||||
continue
|
||||
# Almacenamos el contenido del archivo "ogimg.info", en la variable "lines":
|
||||
with open(info_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
# Iteramos las lineas obtenidas, para extraer el tipo de sistema de archivos ("fstype") y el tamaño de los datos ("sizedata"),
|
||||
# y con ello construimos una cadena "rsync::{fstype}:{sizedata}:" (que almacenamos en "data"):
|
||||
for line in lines:
|
||||
if line.startswith("# fstype"):
|
||||
fstype = line.split("=")[1].strip()
|
||||
elif line.startswith("# sizedata"):
|
||||
sizedata = line.split("=")[1].strip()
|
||||
info_data = f"rsync::{fstype}:{sizedata}:"
|
||||
# Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum":
|
||||
with open(f"{img_path}.size", 'r') as file:
|
||||
size = file.read().strip('\n')
|
||||
with open(f"{img_path}.sum", 'r') as file:
|
||||
_sum = file.read().strip('\n')
|
||||
with open(f"{img_path}.full.sum", 'r') as file:
|
||||
fullsum = file.read().strip('\n')
|
||||
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
|
||||
# (pasándole el nombre de la imagen, el tipo "dir"", y los datos extraídos del archivo "ogimg.info"):
|
||||
img_name = os.path.relpath(img_path, repo_path)
|
||||
add_to_json(img_name, "dir", info_data, size, _sum, fullsum)
|
||||
|
||||
|
||||
|
||||
def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
||||
""" Esta función añade al archivo "repoinfo.json" la información de las imágenes que aun no ha sido introducida en él (imágenes nuevas, básicamente).
|
||||
El procedimiento es diferente para las imágenes "normales" y para las imágenes basadas en OU.
|
||||
"""
|
||||
# Almacenamos el contenido de la variable "data" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en variables separadas:
|
||||
clonator, compressor, fstype, datasize, client = data.split(":")
|
||||
|
||||
# Si la imagen está dentro de una OU (directorio), extraemos el nombre de la OU y de la imagen:
|
||||
ou_name = None
|
||||
if '/' in image_name:
|
||||
ou_name = os.path.dirname(image_name)
|
||||
image_name = os.path.basename(image_name)
|
||||
|
||||
# Creamos un diccionario con los datos de la imagen, que luego insertaremos en el json:
|
||||
json_data = {
|
||||
"name": image_name,
|
||||
|
@ -118,12 +169,13 @@ def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
|||
with open(info_file, 'r') as file:
|
||||
info_data = json.load(file)
|
||||
else:
|
||||
info_data = {"directory": repo_path, "images": []}
|
||||
info_data = {"directory": repo_path, "images": [], "ous": []}
|
||||
|
||||
# Comprobamos si las claves "info_data" (o sea, del archivo json) son las correctas:
|
||||
if set(info_data.keys()) == {"directory", "images"}:
|
||||
if set(info_data.keys()) == {"directory", "images", "ous"}:
|
||||
|
||||
# Actualizamos la información de las imágenes:
|
||||
# Actualizamos la información de las imágenes "normales" (no basadas en OU):
|
||||
if ou_name is None:
|
||||
img_index = next((i for i, img in enumerate(info_data["images"]) if img["name"] == image_name), None)
|
||||
if img_index is not None:
|
||||
# Update if image data changes
|
||||
|
@ -133,9 +185,28 @@ def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
|||
# Append a new entry
|
||||
info_data["images"].append(json_data)
|
||||
|
||||
# Actualizamos la información de las imágenes basadas en OU:
|
||||
else:
|
||||
ou_index = next((i for i, ou in enumerate(info_data["ous"]) if ou["subdir"] == ou_name), None)
|
||||
if ou_index is None:
|
||||
# Append a new OU entry
|
||||
info_data["ous"].append({"subdir": ou_name, "images": [json_data]})
|
||||
else:
|
||||
img_index = next((i for i, img in enumerate(info_data["ous"][ou_index]["images"]) if img["name"] == image_name), None)
|
||||
if img_index is not None:
|
||||
# Update if image data changes
|
||||
if info_data["ous"][ou_index]["images"][img_index] != json_data:
|
||||
info_data["ous"][ou_index]["images"][img_index] = json_data
|
||||
else:
|
||||
# Append a new entry
|
||||
info_data["ous"][ou_index]["images"].append(json_data)
|
||||
|
||||
# Si las claves de "info_data" no son las correctas, creamos toda la estructura:
|
||||
else:
|
||||
info_data = {"directory": repo_path, "images": [json_data]}
|
||||
if ou_name is None:
|
||||
info_data = {"directory": repo_path, "images": [json_data], "ous": []}
|
||||
else:
|
||||
info_data = {"directory": repo_path, "images": [], "ous": [{"subdir": ou_name, "images": [json_data]}]}
|
||||
|
||||
# Sobreescribimos el archivo "repoinfo.json", con el contenido de "info_data" (que estará actualizado):
|
||||
with open(info_file, 'w') as file:
|
||||
|
@ -162,6 +233,23 @@ def remove_from_json():
|
|||
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
|
||||
json_data["images"].pop(i)
|
||||
|
||||
# Iteramos las imágenes de la clave "ous" de "json_data", construimos sus rutas y comprobamos su existencia
|
||||
# (si no existen, las eliminamos de "json_data"):
|
||||
for j, ou in enumerate(json_data.get("ous", [])):
|
||||
ou_name = ou["subdir"]
|
||||
ou_path = os.path.join(repo_path, ou_name)
|
||||
if not os.path.exists(ou_path):
|
||||
json_data["ous"].pop(j)
|
||||
else:
|
||||
for i, image in enumerate(ou.get("images", [])):
|
||||
img_name = image["name"]
|
||||
img_type = image["type"]
|
||||
if img_type != "dir":
|
||||
img_name = f"{img_name}.{img_type}"
|
||||
img_path = os.path.join(ou_path, img_name)
|
||||
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
|
||||
ou["images"].pop(i)
|
||||
|
||||
# Sobreescribimos el archivo "repoinfo.json", con el contenido de "json_data"
|
||||
# (una vez eliminadas las imágenes inexistentes):
|
||||
with open(info_file, 'w') as file:
|
||||
|
@ -171,16 +259,14 @@ def remove_from_json():
|
|||
|
||||
def update_trash_info():
|
||||
""" Actualiza la información de la papelera del repositorio, ejecutando el script "updateTrashInfo.py".
|
||||
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
|
||||
"""
|
||||
try:
|
||||
journal.send("updateRepoInfo.py: Running script 'updateTrashInfo.py'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
result = subprocess.run(['python3', update_trash_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = subprocess.run(['sudo', 'python3', update_trash_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except subprocess.CalledProcessError as error:
|
||||
journal.send(f"updateRepoInfo.py: 'updateTrashInfo.py' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Error Output: {error.stderr.decode()}")
|
||||
sys.exit(3)
|
||||
except Exception as error:
|
||||
journal.send(f"updateRepoInfo.py: 'updateTrashInfo.py' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print(f"Se ha producido un error inesperado: {error}")
|
||||
sys.exit(4)
|
||||
|
||||
|
@ -197,35 +283,34 @@ def main():
|
|||
# Comprobamos si tenemos permisos de escritura sobre el directorio que contiene el archivo "repoinfo.json"
|
||||
# ("/opt/opengnsys/etc"), y en caso contrario lanzamos una excepción:
|
||||
if not os.access(os.path.dirname(info_file), os.W_OK):
|
||||
journal.send(f"updateRepoInfo.py: Cant't access to '{info_file}' directory", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
raise PermissionError(f"Cannot access {info_file}")
|
||||
|
||||
# Comprobamos si existe el archivo "repoinfo.json", y en caso contrario lo creamos:
|
||||
if not os.path.exists(info_file):
|
||||
journal.send("updateRepoInfo.py: Creating empty json file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating empty json file...")
|
||||
create_empty_json()
|
||||
|
||||
# Comprobamos si tenemos permisos de escritura sobre el archivo, y en caso contrario lanzamos un error:
|
||||
if not os.access(info_file, os.W_OK):
|
||||
journal.send(f"updateRepoInfo.py: Cant't write on '{info_file}'", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
raise PermissionError(f"Cannot access {info_file}")
|
||||
|
||||
# Llamamos a la función "check_files", para añadir al archivo json las imágenes aun no añadidas
|
||||
# Llamamos a la función "check_files", para añadir al archivo json las imágenes ".img" o ".dsk" aun no añadidas
|
||||
# (que son las que tienen asociado un archivo ".info", aun no renombrado o eliminado):
|
||||
journal.send("updateRepoInfo.py: Checking file images...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Checking file images...")
|
||||
check_files()
|
||||
|
||||
# Llamamos a la función "remove_from_json", para eliminar del archivo json las imágenes que fueron eliminadas del repositorio
|
||||
# (solo si el archivo tiene contenido, o dará error):
|
||||
# Llamamos a la función "check_dirs", para añadir al archivo json las imágenes aun no añadidas que tienen asociado un archivo "ogimg.info"
|
||||
# (no sé qué imágenes son estas, pero de alguna forma están basadas en directorios):
|
||||
print("Checking dir images...")
|
||||
check_dirs()
|
||||
|
||||
# Llamamos a la función "remove_from_json", para eliminar del archivo json las imágenes que fueron eliminadas del repositorio:
|
||||
if os.path.getsize(info_file) > 0:
|
||||
journal.send("updateRepoInfo.py: Removing deleted images from json file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Removing deleted images...")
|
||||
remove_from_json()
|
||||
|
||||
# Actualizamos la información de la papelera, ejecutando el script "updateTrashInfo.py":
|
||||
journal.send("updateRepoInfo.py: Updating trash info...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
# Actualizamos la información de la papelera, ejecutando el script "updateTrashInfo.py"
|
||||
# (solo si el archivo tiene contenido, o dará error):
|
||||
print("Updating Trash Info...")
|
||||
update_trash_info()
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import grp
|
|||
import json
|
||||
import subprocess
|
||||
import shutil
|
||||
from systemd import journal
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -59,7 +58,7 @@ def create_empty_json():
|
|||
Evidentemente, solo es llamada cuando no existe el archivo.
|
||||
"""
|
||||
# Creamos un diccionario con la estructura básica que debe tener el archivo json:
|
||||
json_data = {"directory": trash_path, "images": []}
|
||||
json_data = {"directory": trash_path, "images": [], "ous": []}
|
||||
|
||||
# Abrimos el archivo json en modo escritura (creándolo si no existe, como es el caso),
|
||||
# y le añadimos la estructura almacenada en el diccionario "json_data":
|
||||
|
@ -69,15 +68,17 @@ def create_empty_json():
|
|||
|
||||
|
||||
def check_files():
|
||||
""" Esta función recorre el directorio de papelera de imágenes, para buscar archivos con extensión ".img".
|
||||
""" Esta función recorre el directorio de imágenes, para buscar archivos con extensiones ".img" o ".dsk".
|
||||
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
|
||||
que además tengan un archivo ".info.checked" asociado (siempre que este no se haya modificado antes que la propia imagen).
|
||||
"""
|
||||
# Iteramos todos los archivos y directorios de "/opt/opengnsys/ogrepository/images_trash":
|
||||
for item in os.listdir(trash_path):
|
||||
# Si el item actual acaba con ".img", construimos la ruta completa de la imagen ("img_path"):
|
||||
if item.endswith(".img"):
|
||||
img_path = os.path.join(trash_path, item)
|
||||
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images_trash",
|
||||
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
|
||||
for root, dirs, files in os.walk(trash_path):
|
||||
for file in files:
|
||||
# Si la imagen actual tiene extensión ".img" o ".dsk", construimos la ruta completa ("img_path"):
|
||||
if file.endswith((".img", ".dsk")):
|
||||
img_path = os.path.join(root, file)
|
||||
# Si existe un archivo ".lock" asociado a la imagen actual, pasamos a la siguiente:
|
||||
if os.path.exists(f"{img_path}.lock"):
|
||||
continue
|
||||
|
@ -106,12 +107,60 @@ def check_files():
|
|||
|
||||
|
||||
|
||||
def check_dirs():
|
||||
""" Esta función recorre el directorio de imágenes, para buscar archivos con nombre "ogimg.info".
|
||||
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
|
||||
que además tengan un archivo "ogimg.info" asociado (pero no sé que tipo de imágenes son esas).
|
||||
"""
|
||||
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images_trash",
|
||||
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
|
||||
for root, dirs, files in os.walk(trash_path):
|
||||
for file in files:
|
||||
# Si el nombre del archivo actual es "ogimg.info", construimos su ruta completa ("info_path"), y la ruta del directorio ("img_path"):
|
||||
if file == "ogimg.info":
|
||||
info_path = os.path.join(root, file)
|
||||
img_path = os.path.dirname(info_path)
|
||||
# Si existe un archivo ".lock" asociado a la imagen actual, o si la ruta coincide con "trash_path", pasamos a la siguiente:
|
||||
if img_path == trash_path or os.path.exists(f"{img_path}.lock"):
|
||||
continue
|
||||
# Almacenamos el contenido del archivo "ogimg.info", en la variable "lines":
|
||||
with open(info_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
# Iteramos las lineas obtenidas, para extraer el tipo de sistema de archivos ("fstype") y el tamaño de los datos ("sizedata"),
|
||||
# y con ello construimos una cadena "rsync::{fstype}:{sizedata}:" (que almacenamos en "data"):
|
||||
for line in lines:
|
||||
if line.startswith("# fstype"):
|
||||
fstype = line.split("=")[1].strip()
|
||||
elif line.startswith("# sizedata"):
|
||||
sizedata = line.split("=")[1].strip()
|
||||
info_data = f"rsync::{fstype}:{sizedata}:"
|
||||
# Almacenamos el contenido de los archivos ".size", ".sum" y ".full.sum":
|
||||
with open(f"{img_path}.size", 'r') as file:
|
||||
size = file.read().strip('\n')
|
||||
with open(f"{img_path}.sum", 'r') as file:
|
||||
_sum = file.read().strip('\n')
|
||||
with open(f"{img_path}.full.sum", 'r') as file:
|
||||
fullsum = file.read().strip('\n')
|
||||
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
|
||||
# (pasándole el nombre de la imagen, el tipo "dir"", y los datos extraídos del archivo "ogimg.info"):
|
||||
img_name = os.path.relpath(img_path, trash_path)
|
||||
add_to_json(img_name, "dir", info_data, size, _sum, fullsum)
|
||||
|
||||
|
||||
|
||||
def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
||||
""" Esta función añade al archivo "trashinfo.json" la información de las imágenes que aun no ha sido introducida en él (imágenes eliminadas recientemente, básicamente).
|
||||
El procedimiento es diferente para las imágenes "normales" y para las imágenes basadas en OU.
|
||||
"""
|
||||
# Almacenamos el contenido de la variable "data" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en variables separadas:
|
||||
clonator, compressor, fstype, datasize, client = data.split(":")
|
||||
|
||||
# Si la imagen está dentro de una OU (directorio), extraemos el nombre de la OU y de la imagen:
|
||||
ou_name = None
|
||||
if '/' in image_name:
|
||||
ou_name = os.path.dirname(image_name)
|
||||
image_name = os.path.basename(image_name)
|
||||
|
||||
# Creamos un diccionario con los datos de la imagen, que luego insertaremos en el json:
|
||||
json_data = {
|
||||
"name": image_name,
|
||||
|
@ -131,12 +180,13 @@ def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
|||
with open(info_file, 'r') as file:
|
||||
info_data = json.load(file)
|
||||
else:
|
||||
info_data = {"directory": trash_path, "images": []}
|
||||
info_data = {"directory": trash_path, "images": [], "ous": []}
|
||||
|
||||
# Comprobamos si las claves "info_data" (o sea, del archivo json) son las correctas:
|
||||
if set(info_data.keys()) == {"directory", "images"}:
|
||||
if set(info_data.keys()) == {"directory", "images", "ous"}:
|
||||
|
||||
# Actualizamos la información de las imágenes:
|
||||
# Actualizamos la información de las imágenes "normales" (no basadas en OU):
|
||||
if ou_name is None:
|
||||
img_index = next((i for i, img in enumerate(info_data["images"]) if img["name"] == image_name), None)
|
||||
if img_index is not None:
|
||||
# Update if image data changes
|
||||
|
@ -146,9 +196,28 @@ def add_to_json(image_name, image_type, data, size, _sum, fullsum):
|
|||
# Append a new entry
|
||||
info_data["images"].append(json_data)
|
||||
|
||||
# Actualizamos la información de las imágenes basadas en OU:
|
||||
else:
|
||||
ou_index = next((i for i, ou in enumerate(info_data["ous"]) if ou["subdir"] == ou_name), None)
|
||||
if ou_index is None:
|
||||
# Append a new OU entry
|
||||
info_data["ous"].append({"subdir": ou_name, "images": [json_data]})
|
||||
else:
|
||||
img_index = next((i for i, img in enumerate(info_data["ous"][ou_index]["images"]) if img["name"] == image_name), None)
|
||||
if img_index is not None:
|
||||
# Update if image data changes
|
||||
if info_data["ous"][ou_index]["images"][img_index] != json_data:
|
||||
info_data["ous"][ou_index]["images"][img_index] = json_data
|
||||
else:
|
||||
# Append a new entry
|
||||
info_data["ous"][ou_index]["images"].append(json_data)
|
||||
|
||||
# Si las claves de "info_data" no son las correctas, creamos toda la estructura:
|
||||
else:
|
||||
if ou_name is None:
|
||||
info_data = {"directory": trash_path, "images": [json_data], "ous": []}
|
||||
else:
|
||||
info_data = {"directory": trash_path, "images": [], "ous": [{"subdir": ou_name, "images": [json_data]}]}
|
||||
|
||||
# Sobreescribimos el archivo "trashinfo.json", con el contenido de "info_data" (que estará actualizado):
|
||||
with open(info_file, 'w') as file:
|
||||
|
@ -175,6 +244,23 @@ def remove_from_json():
|
|||
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
|
||||
json_data["images"].pop(i)
|
||||
|
||||
# Iteramos las imágenes de la clave "ous" de "json_data", construimos sus rutas y comprobamos su existencia
|
||||
# (si no existen, las eliminamos de "json_data"):
|
||||
for j, ou in enumerate(json_data.get("ous", [])):
|
||||
ou_name = ou["subdir"]
|
||||
ou_path = os.path.join(trash_path, ou_name)
|
||||
if not os.path.exists(ou_path):
|
||||
json_data["ous"].pop(j)
|
||||
else:
|
||||
for i, image in enumerate(ou.get("images", [])):
|
||||
img_name = image["name"]
|
||||
img_type = image["type"]
|
||||
if img_type != "dir":
|
||||
img_name = f"{img_name}.{img_type}"
|
||||
img_path = os.path.join(ou_path, img_name)
|
||||
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
|
||||
ou["images"].pop(i)
|
||||
|
||||
# Sobreescribimos el archivo "trashinfo.json", con el contenido de "json_data"
|
||||
# (una vez eliminadas las imágenes inexistentes):
|
||||
with open(info_file, 'w') as file:
|
||||
|
@ -192,37 +278,36 @@ def main():
|
|||
"""
|
||||
# Comprobamos si existe el directorio correspondiente a la papelera, y en caso contrario lo creamos:
|
||||
if not os.path.exists(trash_path):
|
||||
journal.send("updateTrashInfo.py: Creting trash folder...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating trash folder...")
|
||||
create_trash_folder()
|
||||
|
||||
# Comprobamos si tenemos permisos de escritura sobre el directorio que contiene el archivo "trashinfo.json"
|
||||
# ("/opt/opengnsys/etc"), y en caso contrario lanzamos una excepción:
|
||||
if not os.access(os.path.dirname(info_file), os.W_OK):
|
||||
journal.send(f"updateTrashInfo.py: Cant't access to '{info_file}' directory", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
raise PermissionError(f"Cannot access {info_file}")
|
||||
|
||||
# Comprobamos si existe el archivo "trashinfo.json", y en caso contrario lo creamos:
|
||||
if not os.path.exists(info_file):
|
||||
journal.send("updateTrashInfo.py: Creating empty json file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Creating empty json file...")
|
||||
create_empty_json()
|
||||
|
||||
# Comprobamos si tenemos permisos de escritura sobre el archivo, y en caso contrario lanzamos un error:
|
||||
if not os.access(info_file, os.W_OK):
|
||||
journal.send(f"updateTrashInfo.py: Cant't write on '{info_file}'", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
raise PermissionError(f"Cannot access {info_file}")
|
||||
|
||||
# Llamamos a la función "check_files", para añadir al archivo json las imágenes aun no añadidas
|
||||
# Llamamos a la función "check_files", para añadir al archivo json las imágenes ".img" o ".dsk" aun no añadidas
|
||||
# (que son las que tienen asociado un archivo ".info.checked"):
|
||||
journal.send("updateTrashInfo.py: Checking file images...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Checking file images...")
|
||||
check_files()
|
||||
|
||||
# Llamamos a la función "check_dirs", para añadir al archivo json las imágenes aun no añadidas que tienen asociado un archivo "ogimg.info"
|
||||
# (no sé qué imágenes son estas, pero de alguna forma están basadas en directorios):
|
||||
print("Checking dir images...")
|
||||
check_dirs()
|
||||
|
||||
# Llamamos a la función "remove_from_json", para eliminar del archivo json las imágenes que ya no están en la papelera
|
||||
# (solo si el archivo tiene contenido, o dará error):
|
||||
if os.path.getsize(info_file) > 0:
|
||||
journal.send("updateTrashInfo.py: Removing inexistent images from json file...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG")
|
||||
print("Removing inexistent images...")
|
||||
remove_from_json()
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
The Debian Package ogrepository
|
||||
----------------------------
|
||||
|
||||
<Comments regarding the Package.>
|
||||
|
||||
-- vagrant <vagrant@build> Thu, 06 Mar 2025 07:16:52 +0000
|
|
@ -1,6 +0,0 @@
|
|||
ogrepository for Debian
|
||||
----------------------
|
||||
|
||||
<Possible notes regarding this package - if none, delete this file.>
|
||||
|
||||
-- vagrant <vagrant@build> Thu, 06 Mar 2025 07:16:52 +0000
|
|
@ -1,10 +0,0 @@
|
|||
ogrepository for Debian
|
||||
----------------------
|
||||
|
||||
<This file describes information about the source package, see Debian policy
|
||||
manual section 4.14. You WILL either need to modify or delete this file.>
|
||||
|
||||
|
||||
|
||||
-- vagrant <vagrant@build> Thu, 06 Mar 2025 07:16:52 +0000
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
ogrepository (1.0.0+deb-packages20250311-1) unstable; urgency=medium
|
||||
|
||||
* First debian version
|
||||
* Merge pull request 'refs #1530 - Add 'backupImage.py' and related endpoint' (#22) from add_python_scripts into main
|
||||
* refs #1530 - Add 'backupImage.py' and related endpoint
|
||||
* Merge pull request 'refs #1482 - Modify Paramiko SSH Client parameters' (#21) from add_python_scripts into main
|
||||
* refs #1482 - Modify Paramiko SSH Client parameters
|
||||
* Merge pull request 'add_python_scripts' (#20) from add_python_scripts into main
|
||||
* refs #1444 - Modify API help
|
||||
* refs #1444 - Modify transfers between repositories
|
||||
* Merge pull request 'refs #1437 - Scripts corrections' (#19) from add_python_scripts into main
|
||||
* refs #1437 - Scripts corrections
|
||||
|
||||
-- Tu Nombre <tuemail@example.com> Tue, 11 Mar 2025 04:43:58 +0000
|
|
@ -1,14 +0,0 @@
|
|||
Source: ogrepository
|
||||
Section: base
|
||||
Priority: optional
|
||||
Maintainer: Nicolas Arenas <nicolas.arenas@qindel.com>
|
||||
Standards-Version: 4.5.0
|
||||
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, uftp
|
||||
Description: Ogrepsoitory Package
|
||||
This package provides Ogrepository service.
|
||||
X-OG-Release: opengnsys-1.6.0-beta, opengnsys-1.6.1-beta
|
|
@ -1,43 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Source: <url://example.com>
|
||||
Upstream-Name: ogrepository
|
||||
Upstream-Contact: <preferred name and address to reach the upstream project>
|
||||
|
||||
Files:
|
||||
*
|
||||
Copyright:
|
||||
<years> <put author's name and email here>
|
||||
<years> <likewise for another author>
|
||||
License: GPL-3.0+
|
||||
|
||||
Files:
|
||||
debian/*
|
||||
Copyright:
|
||||
2025 vagrant <vagrant@build>
|
||||
License: GPL-3.0+
|
||||
|
||||
License: GPL-3.0+
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
Comment:
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
||||
|
||||
# Please also look if there are files or directories which have a
|
||||
# different copyright/license attached and list them here.
|
||||
# Please avoid picking licenses with terms that are more restrictive than the
|
||||
# packaged work, as it may make Debian's contributions unacceptable upstream.
|
||||
#
|
||||
# If you need, there are some extra license texts available in two places:
|
||||
# /usr/share/debhelper/dh_make/licenses/
|
||||
# /usr/share/common-licenses/
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
|
||||
# Leer las variables de configuración
|
||||
|
||||
db_input high opengnsys/ogrepository_ogrepoIp || true
|
||||
db_input high opengnsys/ogrepository_ogcoreIp || true
|
||||
db_input high opengnsys/ogrepository_sambaUser || true
|
||||
db_input high opengnsys/ogrepository_sambaUserPass || true
|
||||
|
||||
db_go
|
|
@ -1,4 +0,0 @@
|
|||
/opt/opengnsys/ogrepository/images_virtual
|
||||
/opt/opengnsys/ogrepository/images
|
||||
/opt/opengnsys/ogrepository/images_trash
|
||||
/opt/opengnsys/ogrepository/log
|
|
@ -1,8 +0,0 @@
|
|||
api/* /opt/opengnsys/ogrepository/api/
|
||||
bin/* /opt/opengnsys/ogrepository/bin/
|
||||
etc/* /opt/opengnsys/ogrepository/etc/
|
||||
installer/files/ctorrent.sources /etc/apt/sources.list.d/
|
||||
installer/files/ogrepo-api.service /etc/systemd/system/
|
||||
installer/files/ogrepo-smb.conf /etc/samba/
|
||||
installer/ssh-keys/* /opt/opengnsys/ogrepository/etc/
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
# Cargar variables de configuración
|
||||
db_get opengnsys/ogrepository_ogrepoIp
|
||||
OGREPO_IP="$RET"
|
||||
db_get opengnsys/ogrepository_ogcoreIp
|
||||
OGCORE_IP="$RET"
|
||||
db_get opengnsys/ogrepository_sambaUser
|
||||
SAMBA_USER="$RET"
|
||||
db_get opengnsys/ogrepository_sambaUserPass
|
||||
SAMBA_PASS="$RET"
|
||||
|
||||
# Asegurarse de que el usuario exista
|
||||
USER="opengnsys"
|
||||
|
||||
|
||||
# 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
|
||||
"
|
||||
|
||||
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
|
||||
|
||||
# Install ssh keys on opengnsys user
|
||||
# Get opengnsys home directory
|
||||
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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
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/ogrepository/bin/*
|
||||
|
||||
# Install http server stuff
|
||||
# Reiniciar servicios si es necesario
|
||||
# systemctl restart nombre_del_servicio
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable ogrepo-api
|
||||
systemctl restart ogrepo-api
|
||||
systemctl restart smbd
|
||||
|
||||
# echo "ogrepository-trigger" > /var/lib/dpkg/triggers/ogrepository.trigger
|
||||
# POST_INVOKE_SCRIPT="/var/lib/dpkg/info/ogrepository.trigger"
|
||||
|
||||
# echo "Registrando post-invoke para instalación de paquetes adicionales..."
|
||||
|
||||
# cat <<EOF > "$POST_INVOKE_SCRIPT"
|
||||
# #!/bin/sh
|
||||
# set -e
|
||||
|
||||
# echo "Ejecutando post-trigger: Instalando bittorrent, bittornado y ctorrent..."
|
||||
|
||||
# export DEBIAN_FRONTEND=noninteractive
|
||||
# apt-get update
|
||||
# apt-get install -y bittorrent bittornado ctorrent
|
||||
|
||||
# echo "Instalación de paquetes adicionales completada."
|
||||
|
||||
# exit 0
|
||||
# EOF
|
||||
|
||||
# chmod +x "$POST_INVOKE_SCRIPT"
|
||||
|
||||
# # Intentar ejecutar el script ahora si no hay otro proceso de apt corriendo
|
||||
# if ! pgrep -x "apt" > /dev/null; then
|
||||
# echo "Ejecutando instalación de paquetes adicionales inmediatamente..."
|
||||
# "$POST_INVOKE_SCRIPT"
|
||||
# else
|
||||
# echo "Apt está en uso, los paquetes se instalarán después."
|
||||
# fi
|
||||
|
||||
# find /opt/opengnsys/ogrepository -type f -name "*.py" -exec chmod +x {} \;
|
||||
|
||||
# dpkg-trigger --by-package=ogrepository ogrepository-trigger
|
||||
|
||||
exit 0
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
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 "$UNIT_FILE" ]; then
|
||||
rm -f "$UNIT_FILE"
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
;;
|
||||
purge)
|
||||
echo "Eliminando configuración residual..."
|
||||
;;
|
||||
|
||||
upgrade)
|
||||
echo "Actualizando paquete..."
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
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"
|
||||
HOME_DIR="/opt/opengnsys"
|
||||
if id "$USER" >/dev/null 2>&1; then
|
||||
echo "El usuario $USER ya existe."
|
||||
else
|
||||
echo "Creando el usuario $USER con home en $HOME_DIR."
|
||||
useradd -m -d "$HOME_DIR" -s /bin/bash "$USER"
|
||||
fi
|
||||
echo "Añadiendo el repositorio de Debian Buster en $REPO_FILE..."
|
||||
|
||||
# Crear el directorio si no existe
|
||||
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
|
||||
|
||||
exit 0
|
|
@ -1,67 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
remove|purge)
|
||||
echo "Deteniendo y deshabilitando servicios..."
|
||||
systemctl stop ogrepo-api || true
|
||||
systemctl disable ogrepo-api || true
|
||||
|
||||
systemctl stop smbd || true
|
||||
systemctl stop nmbd || true
|
||||
|
||||
# Restaurar configuración original de Samba si fue modificada
|
||||
if [ -f /etc/samba/smb.conf.ogrepository ]; then
|
||||
echo "Restaurando configuración original de Samba..."
|
||||
mv /etc/samba/smb.conf.ogrepository /etc/samba/smb.conf
|
||||
dpkg-divert --remove --rename /etc/samba/smb.conf
|
||||
fi
|
||||
|
||||
# Eliminar configuración específica de ogrepository en Samba
|
||||
if grep -q "include = /etc/samba/ogrepo-smb.conf" /etc/samba/smb.conf; then
|
||||
echo "Eliminando referencia a ogrepo-smb.conf en smb.conf..."
|
||||
sed -i '/include = \/etc\/samba\/ogrepo-smb.conf/d' /etc/samba/smb.conf
|
||||
fi
|
||||
|
||||
# Eliminar usuario de Samba si es necesario
|
||||
if pdbedit -L | grep -q "^$SAMBA_USER:"; then
|
||||
echo "Eliminando usuario Samba $SAMBA_USER..."
|
||||
smbpasswd -x "$SAMBA_USER"
|
||||
fi
|
||||
|
||||
# Eliminar archivos de configuración si se trata de una purga
|
||||
if [ "$1" = "purge" ]; then
|
||||
echo "Eliminando archivos de configuración..."
|
||||
rm -rf /opt/opengnsys/ogrepository
|
||||
rm -rf /etc/samba/ogrepo-smb.conf
|
||||
rm -rf /etc/systemd/system/ogrepo-api.service
|
||||
fi
|
||||
|
||||
# Eliminar el script post-invoke si existe
|
||||
if [ -f /var/lib/dpkg/info/ogrepository.post-invoke ]; then
|
||||
echo "Eliminando script post-invoke..."
|
||||
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
|
||||
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm llamado con un argumento desconocido '$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -1,19 +0,0 @@
|
|||
Template: opengnsys/ogrepository_ogrepoIp
|
||||
Type: string
|
||||
Default: 127.0.0.1
|
||||
Description: IP del repositorio.
|
||||
|
||||
Template: opengnsys/ogrepository_ogcoreIp
|
||||
Default: 127.0.0.1
|
||||
Type: string
|
||||
Description: IP del servidor OGCore.
|
||||
|
||||
Template: opengnsys/ogrepository_sambaUser
|
||||
Type: string
|
||||
Default: opengnsys
|
||||
Description: Usuario de Samba.
|
||||
|
||||
Template: opengnsys/ogrepository_sambaUserPass
|
||||
Type: password
|
||||
Default: og
|
||||
Description: Contraseña para el usuario de Samba.
|
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
# See debhelper(7) (uncomment to enable).
|
||||
# Output every command that modifies files on the build system.
|
||||
#export DH_VERBOSE = 1
|
||||
|
||||
|
||||
# See FEATURE AREAS in dpkg-buildflags(1).
|
||||
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
# See ENVIRONMENT in dpkg-buildflags(1).
|
||||
# Package maintainers to append CFLAGS.
|
||||
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
# Package maintainers to append LDFLAGS.
|
||||
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
|
||||
# dh_make generated override targets.
|
||||
# This is an example for Cmake (see <https://bugs.debian.org/641051>).
|
||||
#override_dh_auto_configure:
|
||||
# dh_auto_configure -- \
|
||||
# -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)
|
|
@ -1 +0,0 @@
|
|||
3.0 (native)
|
|
@ -1,3 +1,2 @@
|
|||
IPlocal=SERVERIP
|
||||
IPcore=OGCOREIP
|
||||
ApiToken=REPOKEY
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# 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 *
|
||||
|
||||
# Permitir al usuario opengnsys ejecutar estos comandos sin contraseña
|
||||
opengnsys ALL=(root) NOPASSWD: MOUNT_RECOVERY, CHROOT_GRUB, LOOP_KPARTX, KILL_BT
|
|
@ -3,8 +3,8 @@ Description=Gunicorn instance to serve repo_api
|
|||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=opengnsys
|
||||
Group=opengnsys
|
||||
User=%%OGREPOSITORY_USER%%
|
||||
Group=%%OGREPOSITORY_USER%%
|
||||
WorkingDirectory=/opt/opengnsys/ogrepository/api
|
||||
ExecStart=/usr/bin/gunicorn -w 4 -b 0.0.0.0:8006 repo_api:app
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ GIT_BRANCH=$1
|
|||
GIT_REPO=https://ognproject.evlt.uma.es/gitea/opengnsys/ogrepository.git
|
||||
GIT_SSL_NO_VERIFY=true
|
||||
REPO_IP=${REPO_IP:-"127.0.0.1"}
|
||||
CORE_IP=${CORE_IP:-"127.0.0.1"}
|
||||
OGUSER=${OGUSER:-"opengnsys"}
|
||||
OGPASS=${OGPASS:-"og"}
|
||||
INSTALL_DIR=/opt/opengnsys/ogrepository
|
||||
|
@ -59,7 +58,7 @@ create_directories() {
|
|||
|
||||
install_dependencies() {
|
||||
apt update -y
|
||||
apt install -y git python3 python3-pip python3-flask python3-paramiko python3-psutil python3-flasgger debian-archive-keyring samba gunicorn wakeonlan python3-requests
|
||||
apt install -y git python3 python3-pip python3-flask python3-paramiko python3-psutil python3-flasgger debian-archive-keyring samba gunicorn wakeonlan
|
||||
}
|
||||
|
||||
install_ext_repo() {
|
||||
|
@ -84,7 +83,6 @@ install_files() {
|
|||
chown -R $OGUSER:$OGUSER $INSTALL_DIR
|
||||
chmod 755 $INSTALL_DIR/bin/*
|
||||
echo IPlocal="$REPO_IP" > $INSTALL_DIR/etc/ogAdmRepo.cfg
|
||||
echo IPcore="$CORE_IP" >> $INSTALL_DIR/etc/ogAdmRepo.cfg
|
||||
sudo chown $OGUSER:$OGUSER $INSTALL_DIR/etc/ogAdmRepo.cfg
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBs7Wbqztq5ixPGFL+1DlTa0T6QUBMiLq6KxZnCJ5rofQAAAJD7Xj89+14/
|
||||
PQAAAAtzc2gtZWQyNTUxOQAAACBs7Wbqztq5ixPGFL+1DlTa0T6QUBMiLq6KxZnCJ5rofQ
|
||||
AAAEC4UmYDisgl5jNR6SUwRA80k6Qc06cBHg1mW3+2NU6SfmztZurO2rmLE8YUv7UOVNrR
|
||||
PpBQEyIurorFmcInmuh9AAAABm5vbmFtZQECAwQFBgc=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
|
@ -1 +0,0 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGztZurO2rmLE8YUv7UOVNrRPpBQEyIurorFmcInmuh9 noname
|
Loading…
Reference in New Issue