From ec2fd05fdf5cd53a0512179bb33b927d90510f29 Mon Sep 17 00:00:00 2001 From: Vadim Troshchinskiy Date: Mon, 31 Mar 2025 12:24:33 +0200 Subject: [PATCH] Load swagger from disk --- api_server/api_server.py | 16 +- api_server/blueprints/repo_api.yaml | 1879 +++++++++++++++++++++++++++ 2 files changed, 1894 insertions(+), 1 deletion(-) create mode 100644 api_server/blueprints/repo_api.yaml diff --git a/api_server/api_server.py b/api_server/api_server.py index 595d849..03bd3b5 100755 --- a/api_server/api_server.py +++ b/api_server/api_server.py @@ -9,9 +9,11 @@ import importlib import logging import uuid import argparse +import yaml from flask import Flask, request from flask_executor import Executor from flask_restx import Api +from flasgger import Swagger from werkzeug.exceptions import HTTPException from systemd.journal import JournalHandler @@ -71,7 +73,7 @@ api = Api(app, version='0.50', title = "OpenGnsys Git API", description = "API for managing disk images stored in Git", - doc = "/swagger/") + doc = "/apidocs/") executor = Executor(app) @@ -85,6 +87,7 @@ for filename in os.listdir(blueprints_dir): log.info("Loading %s/%s", blueprints_dir, filename) module_name = filename.replace(".py", "") + swagger_file = os.path.join(blueprints_dir, filename.replace(".py", ".yaml")) log.info("Importing %s", module_name) importlib.invalidate_caches() @@ -93,6 +96,17 @@ for filename in os.listdir(blueprints_dir): app.register_blueprint(module.blueprint) + if os.path.exists(swagger_file): + log.info("Loading Swagger documentation from %s...", swagger_file) + + with open(swagger_file, "r", encoding='utf-8') as file: + swagger_template = yaml.safe_load(file) + + swagger = Swagger(app, template=swagger_template) + else: + log.warning("Swagger not found for this module, looked in %s", swagger_file) + + @app.errorhandler(HTTPException) def handle_exception(e): diff --git a/api_server/blueprints/repo_api.yaml b/api_server/blueprints/repo_api.yaml new file mode 100644 index 0000000..b239ab2 --- /dev/null +++ b/api_server/blueprints/repo_api.yaml @@ -0,0 +1,1879 @@ +swagger: "2.0" +info: + title: "ogRepository API" + version: "1.0" + description: | + --- + +# ----------------------------------------------------------------------------------------------------------- + +# Esto hace que el Swagger se ordene por los tags (apartados), de la forma especificada: +tags: + - name: "Estado de ogRepository" + - name: "Información de Imágenes" + - name: "Eliminar y Recuperar Imágenes" + - 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: "Varios" + + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Estado de ogRepository" +# ----------------------------------------------------------------------------------------------------------- + +paths: + /ogrepository/v1/status: + get: + 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. + tags: + - "Estado de ogRepository" + responses: + "200": + description: "La información de estado se obtuvo exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: object + properties: + oggit: + type: object + properties: + installed: + type: string + example: "True" + cpu: + type: object + properties: + used_percentage: + type: string + example: "35%" + ram: + type: object + properties: + total: + type: string + example: "7.8GB" + used: + type: string + example: "0.3GB" + available: + type: string + example: "7.2GB" + used_percentage: + type: string + example: "7%" + disk: + type: object + properties: + total: + type: string + example: "11.7GB" + used: + type: string + example: "7.7GB" + available: + type: string + example: "3.4GB" + used_percentage: + type: string + example: "69%" + services: + type: object + properties: + ssh: + type: string + example: "active" + smbd: + type: string + example: "active" + rsync: + type: string + example: "active" + processes: + type: object + properties: + udp-sender: + type: string + example: "stopped" + uftp: + type: string + example: "stopped" + bttrack: + type: string + example: "stopped" + btlaunchmany.bittornado: + type: string + example: "stopped" + "500 (Error)": + description: "Error al consultar y/o devolver la información de estado." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al consultar y/o devolver la información de estado." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Información de Imágenes" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/images: + put: + summary: "Actualizar Información del Repositorio" + description: | + Este endpoint actualiza la información de las imágenes almacenadas en el repositorio, reflejándola en los archivos "**repoinfo.json**" y "**trashinfo.json**". + Utiliza el script "**updateRepoInfo.py**", que a su vez llama al script "**updateTrashInfo.py**", para actualizar también la información de la papelera. + + No hace falta que se le llame al crear o exportar una imagen, ya que lo llama el endpoint "**Crear archivos auxiliares**" (que sí debe ser llamado en esos casos). + tags: + - "Información de Imágenes" + responses: + "200": + description: "La actualización de la información de las imágenes se realizó exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Repository info updated successfully" + "500 (Error)": + description: "Error al actualizar la información de las imágenes." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al actualizar la información de las imágenes." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/images: + 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. + 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" + responses: + "200": + description: "La información de las imágenes se obtuvo exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: object + properties: + REPOSITORY: + type: object + properties: + directory: + type: string + example: "/opt/opengnsys/ogrepository/images" + images: + type: array + items: + type: object + properties: + name: + type: string + example: "Ubuntu24" + type: + type: string + example: "img" + clientname: + type: string + example: "Ubuntu24_clientname" + clonator: + type: string + example: "partclone" + compressor: + type: string + example: "lzop" + filesystem: + type: string + example: "EXTFS" + datasize: + type: integer + example: 9859634200000 + size: + type: integer + example: 4505673214 + sum: + type: string + example: "065a933c780ab1aaa044435ad5d4bf87" + fullsum: + type: string + example: "33575b9070e4a8043371b8c6ae52b80e" + TRASH: + type: object + properties: + directory: + type: string + example: "/opt/opengnsys/ogrepository/images_trash" + images: + type: array + items: + type: object + properties: + name: + type: string + example: "Windows10" + type: + type: string + example: "img" + clientname: + type: string + example: "Windows10_clientname" + clonator: + type: string + example: "partclone" + compressor: + type: string + example: "lzop" + filesystem: + type: string + example: "NTFS" + datasize: + type: integer + example: 8912896000000 + size: + type: integer + example: 3803794535 + sum: + type: string + example: "081a933c780ab1aaa044435ad5d4bf56" + fullsum: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + "500 (Error)": + description: "Error al consultar y/o devolver la información de las imágenes." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al consultar y/o devolver la información de las imágenes." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/images/{imageId}: + get: + 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. + 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" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + responses: + "200": + description: "La información de la imagen se obtuvo exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: object + properties: + directory: + type: string + example: "/opt/opengnsys/ogrepository/images" + images: + type: array + items: + type: object + properties: + name: + type: string + example: "Ubuntu24" + type: + type: string + example: "img" + clientname: + type: string + example: "Ubuntu24_clientname" + clonator: + type: string + example: "partclone" + compressor: + type: string + example: "lzop" + filesystem: + type: string + example: "EXTFS" + datasize: + type: integer + example: 9859634200000 + size: + type: integer + example: 4505673214 + sum: + type: string + example: "065a933c780ab1aaa044435ad5d4bf87" + fullsum: + type: string + example: "33575b9070e4a8043371b8c6ae52b80e" + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found" + "500 (Error)": + description: "Error al consultar y/o devolver la información de la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al consultar y/o devolver la información de la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/status/images/{imageId}: + get: + 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. + tags: + - "Información de Imágenes" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + responses: + "200 (Check OK)": + description: "La imagen se ha chequeado exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image file passed the Integrity Check correctly" + "200 (Check KO)": + description: "La imagen se ha chequeado exitosamente, pero no ha pasado el test de integridad." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image file didn't pass the Integrity Check" + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found (inexistent or deleted)" + "500 (Error)": + description: "Error al chequear la integridad de la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al chequear la integridad de la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Eliminar y Recuperar Imágenes" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/images/{imageId}?method={method}: + delete: + 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. + tags: + - "Eliminar y Recuperar Imágenes" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + - name: method + in: query + required: true + type: string + description: "Método de eliminación (puede ser 'trash', para enviar la imagen a la papelera, o 'permanent', para eliminarla definitivamente)" + responses: + "200": + description: "La imagen se eliminó exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image deleted successfully" + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found (inexistent or deleted)" + "500 (Error)": + description: "Error al eliminar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al eliminar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/trash/images: + post: + 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. + tags: + - "Eliminar y Recuperar Imágenes" + parameters: + - name: JSON + in: body + required: true + description: | + * **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum' + schema: + type: object + properties: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + responses: + "200": + description: "La imagen se recuperó exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image recovered successfully" + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found (inexistent or recovered previously)" + "500 (Error)": + description: "Error al recuperar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al recuperar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/trash/images/{imageId}: + delete: + 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. + tags: + - "Eliminar y Recuperar Imágenes" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + responses: + "200": + description: "La imagen se eliminó exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image deleted successfully" + "400": + description: "No se ha encontrado la imagen especificada en la papelera." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found at trash" + "500 (Error)": + description: "Error al eliminar la imagen de la papelera." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al eliminar la imagen de la papelera." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Transferencia de Imágenes (UDPcast)" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/udpcast: + post: + summary: "Enviar una Imagen mediante UDPcast" + description: | + Este endpoint envía la imagen especificada a través de UDPcast, utilizando el script "**sendFileMcast.py**". + Recibe la imagen y los parámetros de configuración de transferencia, que son usados para construir la cadena de parámetros que se envía al script. + + **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: + - "Transferencia de Imágenes (UDPcast)" + parameters: + - name: JSON + in: body + required: true + description: | + * **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum' + * **port** - Puerto Multicast + * **method** - Modalidad half-duplex o full-duplex ("half" o "full") + * **ip** - IP Multicast + * **bitrate** - Velocidad de transmisión, en Mbps + * **nclients** - Número minimo de clientes + * **maxtime** - Tiempo máximo de espera + schema: + type: object + properties: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + port: + type: string + description: "Puerto Multicast a utilizar para la transmisión" + example: "9000" + method: + type: string + description: "Modalidad de transmisión (puede ser 'half' o 'full' para half-duplex o full-duplex)" + example: "full" + ip: + type: string + description: "IP Multicast a la que se enviará la imagen" + example: "239.194.17.2" + bitrate: + type: string + description: "Velocidad de transmisión en Mbps" + example: "70M" + nclients: + type: integer + description: "Número mínimo de clientes" + example: 20 + maxtime: + type: integer + description: "Tiempo máximo de espera en segundos" + example: 120 + responses: + "200": + description: "La imagen se está enviando mediante UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Sending image.." + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found" + "500 (Error)": + description: "Error al enviar la imagen mediante UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image send failed" + "500 (Exception)": + description: "Excepción inesperada al enviar la imagen mediante UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/udpcast: + get: + summary: "Ver Estado de Transmisiones UDPcast" + description: | + Este endpoint devuelve información sobre los procesos activos de "**udp-sender**" en formato JSON, permitiendo comprobar las transferencias UDPcast activas. + Utiliza el script "**getUDPcastInfo.py**" para obtener esta información. + tags: + - "Transferencia de Imágenes (UDPcast)" + responses: + "200": + description: "La información de las transmisiones UDPcast activas se obtuvo exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: object + additionalProperties: + type: object + properties: + image_id: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + image_name: + type: string + example: "Ubuntu20.img" + "400": + description: "No se han encontrado transmisiones UDPcast activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "No UDPCast active transmissions" + "500 (Error)": + description: "Error al comprobar las transmisiones UDPcast activas." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al comprobar las transmisiones UDPcast activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/udpcast/images/{imageId}: + delete: + summary: "Cancelar Transmisión UDPcast" + description: | + Este endpoint cancela la transmisión UDPcast activa de la imagen especificada, deteniendo el proceso "**udp-sender**" asociado. + Utiliza el script "**stopUDPcast.py**" para finalizar la transmisión. + tags: + - "Transferencia de Imágenes (UDPcast)" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + responses: + "200": + description: "La transmisión UDPcast se ha cancelado exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image transmission canceled successfully" + "400 (Image not found)": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Image not found" + "400 (No transmissions for image)": + description: "No hay transmisiones UDPcast activas para la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "No UDPCast active transmissions for specified image" + "500 (Error)": + description: "Error al cancelar la transmisión UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Check Exception)": + description: "Error al verificar las transmisiones UDPcast activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Unexpected error checking UDPcast transmissions" + "500 (Finalize Exception)": + description: "Error inesperado al finalizar la transmisión UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Unexpected error finalizing UDPcast transmission" + "500 (General Exception)": + description: "Excepción inesperada al cancelar la transmisión UDPcast." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Transferencia de Imágenes (UFTP)" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/uftp: + post: + summary: "Enviar una Imagen mediante UFTP" + description: | + Este endpoint envía una imagen especificada a través de UFTP, utilizando el script "**sendFileUFTP.py**". + Requiere que los clientes ogLive estén previamente en escucha con un daemon "UFTPD", ejecutando el script "**listenUFTPD.py**". + Recibe la imagen y los parámetros de configuración de transferencia, que son usados para construir la cadena de parámetros que se envía al script. + + **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: + - "Transferencia de Imágenes (UFTP)" + parameters: + - name: JSON + in: body + required: true + description: | + * **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum' + * **port** - Puerto Multicast + * **ip** - IP Unicast/Multicast), + * **bitrate** - Velocidad de transmisión, con 'K' para Kbps, 'M' para Mbps o 'G' para Gbps + schema: + type: object + properties: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + port: + type: string + description: "Puerto para la transmisión UFTP" + example: "9000" + ip: + type: string + description: "IP Unicast o Multicast para la transmisión" + example: "239.194.17.2" + bitrate: + type: string + description: "Velocidad de transmisión (con 'K' para Kbps, 'M' para Mbps, o 'G' para Gbps)" + example: "1G" + responses: + "200": + description: "La imagen se está enviando mediante UFTP." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Sending image..." + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found" + "500 (Error)": + description: "Error al enviar la imagen mediante UFTP." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image send failed" + "500 (Exception)": + description: "Excepción inesperada al enviar la imagen mediante UFTP." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/uftp: + get: + summary: "Ver Estado de Transmisiones UFTP" + description: | + Este endpoint devuelve información sobre los procesos activos de "**uftp**" en formato JSON, permitiendo comprobar las transferencias UFTP activas. + Utiliza el script "**getUFTPInfo.py**" para obtener esta información. + tags: + - "Transferencia de Imágenes (UFTP)" + responses: + "200": + description: "La información de las transmisiones UFTP activas se obtuvo exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: object + additionalProperties: + type: object + properties: + image_id: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + image_name: + type: string + example: "Ubuntu20.img" + "400": + description: "No se han encontrado transmisiones UFTP activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "No UFTP active transmissions" + "500 (Error)": + description: "Error al comprobar las transmisiones UFTP activas." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al comprobar las transmisiones UFTP activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/uftp/images/{imageId}: + delete: + summary: "Cancelar Transmisión UFTP" + description: | + Este endpoint cancela la transmisión UFTP activa de una imagen especificada, deteniendo el proceso "**uftp**" asociado. + Utiliza el script "**stopUFTP.py**" para finalizar la transmisión. + tags: + - "Transferencia de Imágenes (UFTP)" + parameters: + - name: imageId + in: path + required: true + type: string + description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum')" + responses: + "200": + description: "La transmisión UFTP se ha cancelado exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Image transmission canceled successfully" + "400 (Image not found)": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Image not found" + "400 (No transmissions for image)": + description: "No hay transmisiones UFTP activas para la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "No UFTP active transmissions for specified image" + "500 (Error)": + description: "Error al cancelar la transmisión UFTP." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Check Exception)": + description: "Error al verificar las transmisiones UFTP activas." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Unexpected error checking UFTP transmissions" + "500 (Finalize Exception)": + description: "Error inesperado al finalizar la transmisión UFTP." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Unexpected error finalizing UFTP transmission" + "500 (General Exception)": + description: "Excepción inesperada al cancelar la transmisión UFTP." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Transferencia de Imágenes (P2P)" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/p2p: + post: + 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. + + **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: + - "Transferencia de Imágenes (P2P)" + parameters: + - name: JSON + in: body + required: true + description: | + * **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum' + schema: + type: object + properties: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + responses: + "200": + description: "La imagen se está enviando mediante P2P." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Tracker and Seeder serving image correctly" + "400": + description: "No se ha encontrado la imagen especificada." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image not found" + "500": + description: "Error al enviar la imagen mediante P2P." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Tracker or Seeder (or both) not running" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/p2p: + delete: + summary: "Cancelar Transmisiones P2P" + description: | + Este endpoint cancela todas las transmisiones P2P activas, finalizando los procesos "**bttrack**" (tracker) y "**btlaunchmany.bittornado**" (seeder). + Utiliza el script "**stopP2P.py**" para detener las transmisiones P2P activas en el servidor. + tags: + - "Transferencia de Imágenes (P2P)" + responses: + "200": + description: "Las transmisiones P2P se han cancelado exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "P2P transmissions canceled successfully" + "500 (Error)": + description: "Error al cancelar las transmisiones P2P." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al cancelar las transmisiones P2P." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Transferencia entre Repositorios y Backup" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/repo/images: + post: + summary: "Transferir una Imagen entre Repositorios" + 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. + 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" + parameters: + - name: JSON + in: body + required: true + description: | + * **image** - Nombre de la imagen, con extensión + * **repo_ip** - Dirección IP del servidor remoto + * **user** - Usuario con el que conectar al servidor remoto + schema: + type: object + properties: + image: + type: string + example: "Windows10.img" + repo_ip: + type: string + description: "Dirección IP del repositorio remoto" + example: "192.168.56.100" + user: + type: string + description: "Usuario para acceder al repositorio remoto" + example: "user_name" + responses: + "200": + description: "La imagen se está transfiriendo." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Importing image..." + "400 (Connection fail)": + description: "Error de conexión con el servidor remoto." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Can't connect to remote server" + "400 (Image not found)": + description: "No se ha encontrado la imagen remota." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Remote image not found" + "400 (Image locked)": + description: "La imagen remota está bloqueada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Remote image is locked" + "500": + description: "Error al importar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image import failed" + "500 (Error)": + description: "Error al importar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al importar la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/repo/images: + put: + summary: "Hacer Backup de 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. + + **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). + tags: + - "Transferencia entre Repositorios y Backup" + parameters: + - name: JSON + in: body + required: true + description: | + * **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: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + repo_ip: + type: string + description: "Dirección IP del repositorio remoto" + example: "192.168.56.100" + user: + 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." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Making image backup..." + "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 (Image locked)": + description: "La imagen está bloqueada." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Image is locked" + "400 (Connection fail)": + description: "Error de conexión con el equipo remoto." + schema: + type: object + properties: + success: + type: boolean + 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." + schema: + type: object + properties: + success: + type: boolean + 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" + "500": + description: "Error al convertir la imagen virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Virtual image conversion failed" + "500 (Error)": + description: "Error al convertir la imagen virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al convertir la imagen virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + #/ogrepository/v1/images/virtual: + put: + summary: "Convertir Imagen OpenGnsys a Imagen Virtual" + description: | + Este endpoint convierte la imagen "img" especificada como primer parámetro en una imagen virtual con la extensión especificada como segundo parámetro ("vdi", "vmdk", etc), guardándola en la ruta "opt/opengnsys/ogrepository/images_virtual/export". + Utiliza el script "**convertIMGtoVM.py**", que recibe como parámetros el nombre de la imagen, y la extensión del disco virtual destino ("vdi", "vmdk", etc). + + **NOTA**: Este endpoint es asíncrono, ya que puede tardar mucho tiempo, por lo que solo informa de que la imagen se está convirtiendo a virtual, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore). + tags: + - "Importar y Exportar Máquinas Virtuales" + parameters: + - name: JSON + in: body + required: true + description: | + * **ID_img** - Identificador de la imagen, correspondiente al contenido del archivo 'full.sum' + * **vm_extension** - Extensión del disco virtual destino ("vdi", "vmdk", etc) + schema: + type: object + properties: + ID_img: + type: string + example: "22735b9070e4a8043371b8c6ae52b90d" + vm_extension: + type: string + example: "vdi" + responses: + "200": + description: "La imagen se está convirtiendo a virtual." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Converting image to virtual..." + "400 (Image not found)": + description: "No se ha encontrado la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "Image not found" + "400 (Name incorrect)": + description: "Ya existe una imagen virtual exportada con el mismo nombre que la imagen." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "There is an exported virtual image with the same name as the image" + "400 (No disk space)": + description: "No hay espacio suficiente en disco." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "There is not enough free disk space" + "500": + description: "Error al convertir la imagen a virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "Image conversion to virtual failed" + "500 (Error)": + description: "Error al convertir la imagen a virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al convertir la imagen a virtual." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- +# Apartado "Varios" +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/images/torrentsum: + post: + 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". + + 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). + + **NOTA**: Este endpoint es asíncrono, ya que puede tardar cierto tiempo, por lo que solo informa de que se están creando los archivos auxiliares, y abre un proceso paralelo, que avisará a ogCore cuando finalice la tarea (llamando a un endpoint de ogCore). + tags: + - "Varios" + parameters: + - name: JSON + in: body + required: true + description: | + * **image** - Nombre de la imagen, con extensión + schema: + type: object + properties: + image: + type: string + example: "Windows10.img" + responses: + "200": + description: "Los archivos auxiliares se están creando." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Creating auxiliar files..." + "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" + "500 (Error)": + description: "Error al crear los archivos auxiliares." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al crear los archivos auxiliares." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# ----------------------------------------------------------------------------------------------------------- + + /ogrepository/v1/wol: + post: + summary: "Enviar paquete Wake On Lan" + description: | + Este endpoint envía un paquete mágico Wake On Lan (**WOL**) a la dirección MAC especificada, a través de la IP de broadcast especificada. + Utiliza el script "**sendWakeOnLan.py**", que recibe como parámetros la IP de broadcast y la dirección MAC del equipo a encender. + tags: + - "Varios" + parameters: + - name: JSON + in: body + required: true + description: | + * **broadcast_ip** - IP de broadcast a la que se enviará el paquete WOL, que 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 + schema: + type: object + properties: + broadcast_ip: + type: string + example: "255.255.255.255" + mac: + type: string + example: "00:19:99:5c:bb:bb" + responses: + "200": + description: "El paquete Wake On Lan se ha enviado exitosamente." + schema: + type: object + properties: + success: + type: boolean + example: true + output: + type: string + example: "Wake On Lan packet sent successfully" + "500 (Error)": + description: "Error al enviar el paquete Wake On Lan." + schema: + type: object + properties: + success: + type: boolean + example: false + error: + type: string + example: "(Error description)" + "500 (Exception)": + description: "Excepción inesperada al enviar el paquete Wake On Lan." + schema: + type: object + properties: + success: + type: boolean + example: false + exception: + type: string + example: "(Exception description)" + +# -----------------------------------------------------------------------------------------------------------