refs #631 - Modify API and Swagger
parent
43846b0382
commit
e7c5de8628
276
api/repo_api.py
276
api/repo_api.py
|
@ -8,7 +8,10 @@ Responde a peticiones HTTP (en principio, enviadas desde ogCore) mediante endpoi
|
|||
En ciertos casos, transforma los parámetros recibidos desde el portal, 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).
|
||||
|
||||
Librerías Python requeridas: Flask (se puede instalar con "sudo apt install python3-flask").
|
||||
Librerías Python requeridas: - "flask" (se puede instalar con "sudo apt install python3-flask")
|
||||
- "paramiko" (se puede instalar con "sudo apt install python3-paramiko")
|
||||
- "requests" (se puede instalar con "sudo apt install python3-requests") - No tengo claro que para este paquete sea necesario
|
||||
- "flasgger" (se puede instalar con "sudo apt install python3-flasgger")
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -20,8 +23,15 @@ import os
|
|||
import subprocess
|
||||
import json
|
||||
from time import sleep
|
||||
import paramiko
|
||||
import logging
|
||||
import threading
|
||||
import requests
|
||||
# Imports para Swagger:
|
||||
from flasgger import Swagger
|
||||
import yaml
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# VARIABLES
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
@ -31,6 +41,12 @@ script_path = '/opt/opengnsys/bin'
|
|||
repo_file = '/opt/opengnsys/etc/repoinfo.json'
|
||||
trash_file = '/opt/opengnsys/etc/trashinfo.json'
|
||||
|
||||
"""
|
||||
repo_path = '/home/user/images/'
|
||||
script_path = '/home/user'
|
||||
repo_file = '/home/user/jsons/repoinfo.json'
|
||||
trash_file = '/home/user/jsons/trashinfo.json'
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# FUNCTIONS
|
||||
|
@ -40,9 +56,14 @@ trash_file = '/opt/opengnsys/etc/trashinfo.json'
|
|||
# Creamos una instancia de la aplicación Flask:
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
# Configuración Swagger:
|
||||
with open("swagger.yaml", "r") as file:
|
||||
swagger_template = yaml.safe_load(file)
|
||||
|
||||
swagger = Swagger(app, template=swagger_template)
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -123,13 +144,104 @@ def search_process(process, string_to_search):
|
|||
print(f"Unexpected error: {error_description}")
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
def check_lock_local(image_file_path):
|
||||
""" Cada minuto comprueba si existe un archivo ".lock" asociado a la imagen que recibe como parámetro
|
||||
(lo que significará que hay una tarea en curso), en el repositorio local.
|
||||
Cuando no encuentre el archivo ".lock" lo comunicará a ogCore, llamando a un endpoint,
|
||||
y dejará de realizar la comprobación (saliendo del bucle).
|
||||
"""
|
||||
# Esperamos 30 segundos, para dar tiempo a que se cree el archivo ".lock":
|
||||
sleep(30)
|
||||
|
||||
# Creamos un bucle infinito:
|
||||
while True:
|
||||
# Si ya no existe el archivo ".lock", imprimimos un mensaje en la API, y salimos del bucle:
|
||||
if not os.path.exists(f"{image_file_path}.lock"):
|
||||
app.logger.info("Task finalized (no .lock file)") # De momento solamente imprimimos un mensaje en la API (pero debe llamar a un endpoint)
|
||||
break
|
||||
# Si aun existe el archivo ".lock", imprimimos un mensaje en la API:
|
||||
else:
|
||||
app.logger.info("Task in process (.lock file exists)")
|
||||
# Esperamos 1 minuto para volver a realizar la comprobación:
|
||||
sleep(60)
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
def check_lock_remote(image_file_path, remote_host, remote_user):
|
||||
""" Cada minuto comprueba si existe un archivo ".lock" asociado a la imagen que recibe como parámetro
|
||||
(lo que significará que hay una tarea en curso), en un repositorio remoto (al que conecta por SSH/SFTP).
|
||||
Cuando no encuentre el archivo ".lock" lo comunicará a ogCore, llamando a un endpoint,
|
||||
y dejará de realizar la comprobación (saliendo del bucle).
|
||||
"""
|
||||
# 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())
|
||||
|
||||
# Conectamos con el equipo remoto por SSH:
|
||||
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
|
||||
|
||||
# Iniciamos un cliente SFTP:
|
||||
sftp_client = ssh_client.open_sftp()
|
||||
# Esperamos 30 segundos, para dar tiempo a que se cree el archivo ".lock":
|
||||
sleep(30)
|
||||
|
||||
# Creamos un bucle infinito:
|
||||
while True:
|
||||
try:
|
||||
# Si aun existe el archivo ".lock", imprimimos un mensaje en la API:
|
||||
sftp_client.stat(f"{image_file_path}.lock")
|
||||
app.logger.info("Task in process (.lock file exists)")
|
||||
except IOError:
|
||||
# Si ya no existe el archivo ".lock", imprimimos un mensaje en la API, y salimos del bucle:
|
||||
app.logger.info("Task finalized (no .lock file)") # De momento solamente imprimimos un mensaje en la API (pero debe llamar a un endpoint)
|
||||
break
|
||||
# Esperamos 1 minuto para volver a realizar la comprobación:
|
||||
sleep(60)
|
||||
|
||||
# Ya fuera del bucle, cerramos el cliente SSH y el cliente SFTP:
|
||||
ssh_client.close()
|
||||
sftp_client.close()
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
def check_aux_files(image_file_path):
|
||||
""" Cada 10 segundos comprueba si se han creado todos los archivos auxiliares de la imagen que recibe como parámetro,
|
||||
en cuyo caso lo comunicará a ogCore, llamando a un endpoint, y dejará de realizar la comprobación.
|
||||
También obtiene el valor del archivo ".full.sum" (que corresonde al ID), y se lo comunica a ogCore.
|
||||
"""
|
||||
# Creamos un bucle infinito:
|
||||
while True:
|
||||
# Si faltan archivos auxiliares por crear, imprimimos un mensaje en la API:
|
||||
if not os.path.exists(f"{image_file_path}.size") or not os.path.exists(f"{image_file_path}.sum") or not os.path.exists(f"{image_file_path}.full.sum") or not os.path.exists(f"{image_file_path}.torrent") or not os.path.exists(f"{image_file_path}.info.checked"):
|
||||
app.logger.info("Task in process (auxiliar files remaining)")
|
||||
# Si ya se han creado todos los archivos auxiliares, imprimimos un mensaje en la API, y salimos del bucle:
|
||||
else:
|
||||
app.logger.info("Task finalized (all auxilar files created)") # De momento solamente imprimimos un mensaje en la API (pero debe llamar a un endpoint)
|
||||
# Obtenemos el valor del archivo "full.sum", que corresponde al ID, y lo imprimimos:
|
||||
with open(f"{image_file_path}.full.sum", 'r') as file:
|
||||
image_id = file.read().strip('\n')
|
||||
app.logger.info(f"Image_ID: {image_id}")
|
||||
break
|
||||
# Esperamos 10 segundos para volver a realizar la comprobación:
|
||||
sleep(10)
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# ENDPOINTS
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# 1 - Endpoint "Obtener Información de Estado de ogRepository":
|
||||
# 1 - Endpoint "Obtener Información de Estado de ogRepository" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/status", methods=['GET'])
|
||||
def get_repo_status():
|
||||
""" Este endpoint devuelve información de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato json.
|
||||
|
@ -160,7 +272,7 @@ def get_repo_status():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 2 - Endpoint "Obtener Información de todas las Imágenes":
|
||||
# 2 - Endpoint "Obtener Información de todas las Imágenes" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/images", methods=['GET'])
|
||||
def get_repo_info():
|
||||
""" Este endpoint devuelve información de todas las imágenes contenidas en el repositorio (incluída la papelera), en formato json.
|
||||
|
@ -191,7 +303,7 @@ def get_repo_info():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 3 - Endpoint "Obtener Información de una Imagen concreta":
|
||||
# 3 - Endpoint "Obtener Información de una Imagen concreta" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/images/<string:imageId>", methods=['GET'])
|
||||
def get_repo_image_info(imageId):
|
||||
""" Este endpoint devuelve información de la imagen especificada como parámetro, en formato json.
|
||||
|
@ -238,7 +350,7 @@ def get_repo_image_info(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 4 - Endpoint "Actualizar Información del Repositorio":
|
||||
# 4 - Endpoint "Actualizar Información del Repositorio" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/images", methods=['PUT'])
|
||||
def update_repo_info():
|
||||
""" Este endpoint actualiza la información del repositorio y de la papelera, reflejándola en los archivos "repoinfo.json" y "trashinfo.josn".
|
||||
|
@ -269,7 +381,7 @@ def update_repo_info():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 5 - Endpoint "Chequear Integridad de Imagen":
|
||||
# 5 - Endpoint "Chequear Integridad de Imagen" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/status/images/<string:imageId>", methods=['GET'])
|
||||
def check_image(imageId):
|
||||
""" Este endpoint comprueba la integridad de la imagen especificada como parámetro,
|
||||
|
@ -323,7 +435,7 @@ def check_image(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 6 - Endpoint "Eliminar una Imagen":
|
||||
# 6 - Endpoint "Eliminar una Imagen" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/images/<string:imageId>", methods=['DELETE'])
|
||||
def delete_image(imageId):
|
||||
""" Este endpoint elimina la imagen especificada como parámetro (y todos sus archivos asociados),
|
||||
|
@ -379,7 +491,7 @@ def delete_image(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 7 - Endpoint "Recuperar una Imagen":
|
||||
# 7 - Endpoint "Recuperar una Imagen" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/trash/images", methods=['POST'])
|
||||
def recover_image():
|
||||
""" Este endpoint recupera la imagen especificada como parámetro (y todos sus archivos asociados),
|
||||
|
@ -431,7 +543,7 @@ def recover_image():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 8 - Endpoint "Eliminar una Imagen de la Papelera":
|
||||
# 8 - Endpoint "Eliminar una Imagen de la Papelera" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/trash/images/<string:imageId>", methods=['DELETE'])
|
||||
def delete_trash_image(imageId):
|
||||
""" Este endpoint elimina permanentemente la imagen especificada como parámetro (y todos sus archivos asociados), desde la papelera.
|
||||
|
@ -478,7 +590,7 @@ def delete_trash_image(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 9 - Endpoint "Importar una Imagen":
|
||||
# 9 - Endpoint "Importar una Imagen" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/repo/images", methods=['POST'])
|
||||
def import_image():
|
||||
""" Este endpoint importa la imagen especificada como primer parámetro (y todos sus archivos asociados),
|
||||
|
@ -493,26 +605,39 @@ def import_image():
|
|||
remote_ip = json_data.get("repo_ip")
|
||||
remote_user = json_data.get("user")
|
||||
|
||||
# Evaluamos los parámetros obtenidos, para construir la llamada al script:
|
||||
# Evaluamos los parámetros obtenidos, para construir la ruta de la imagen:
|
||||
if ou_subdir == "none":
|
||||
cmd = ['sudo', 'python3', f"{script_path}/importImage.py", f"{repo_path}{image_name}", remote_ip, remote_user]
|
||||
image_file_path = f"{repo_path}{image_name}"
|
||||
else:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/importImage.py", f"{repo_path}{ou_subdir}/{image_name}", remote_ip, remote_user]
|
||||
image_file_path = f"{repo_path}{ou_subdir}/{image_name}"
|
||||
|
||||
# Construimos la llamada al script:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/importImage.py", image_file_path, remote_ip, remote_user]
|
||||
|
||||
try:
|
||||
# Ejecutamos el script "importImage.py" (con los parámetros almacenados), y almacenamos el resultado:
|
||||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Ejecutamos el script "importImage.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso):
|
||||
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Evaluamos el resultado de la ejecución, y devolvemos una respuesta:
|
||||
if result.returncode == 0:
|
||||
if result.returncode is None:
|
||||
# Si el resultado es correcto, llamamos a la función "check_lock_local" en un hilo paralelo
|
||||
# (para que compruebe si la imagen se ha acabado de importar exitosamente):
|
||||
threading.Thread(target=check_lock_local, args=(image_file_path,)).start()
|
||||
|
||||
# Informamos que la imagen se está importando, y salimos del endpoint:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"output": "Image imported successfully"
|
||||
"output": "Importing image..."
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": result.stderr
|
||||
"error": "Image import failed"
|
||||
}), 500
|
||||
except subprocess.CalledProcessError as error:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"process exception": str(error)
|
||||
}), 500
|
||||
except Exception as error_description:
|
||||
if "exit status 2" in str(error_description):
|
||||
|
@ -540,7 +665,7 @@ def import_image():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 10 - Endpoint "Exportar una Imagen":
|
||||
# 10 - Endpoint "Exportar una Imagen" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/repo/images", methods=['PUT'])
|
||||
def export_image():
|
||||
""" Este endpoint exporta la imagen especificada como primer parámetro (y todos sus archivos asociados),
|
||||
|
@ -557,33 +682,46 @@ def export_image():
|
|||
# Obtenemos el nombre y la extensión de la imagen (y el subdirectorio de OU, si fuera el caso):
|
||||
param_dict = get_image_params(image_id, "repo")
|
||||
|
||||
# Evaluamos los parámetros obtenidos, para construir la llamada al script, o para devover un error si no se ha encontrado la imagen:
|
||||
# Evaluamos los parámetros obtenidos, para construir la ruta de la imagen, o para devover un error si no se ha encontrado la imagen:
|
||||
if param_dict:
|
||||
if 'subdir' in param_dict:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/exportImage.py", f"{param_dict['subdir']}/{param_dict['name']}.{param_dict['extension']}", remote_ip, remote_user]
|
||||
image_file_path = f"{param_dict['subdir']}/{param_dict['name']}.{param_dict['extension']}"
|
||||
else:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/exportImage.py", f"{param_dict['name']}.{param_dict['extension']}", remote_ip, remote_user]
|
||||
image_file_path = f"{param_dict['name']}.{param_dict['extension']}"
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": "Image not found"
|
||||
}), 400
|
||||
|
||||
# Construimos la llamada al script:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/exportImage.py", image_file_path, remote_ip, remote_user]
|
||||
|
||||
try:
|
||||
# Ejecutamos el script "exportImage.py" (con los parámetros almacenados), y almacenamos el resultado:
|
||||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Ejecutamos el script "exportImage.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso):
|
||||
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Evaluamos el resultado de la ejecución, y devolvemos una respuesta:
|
||||
if result.returncode == 0:
|
||||
if result.returncode is None:
|
||||
# Si el resultado es correcto, llamamos a la función "check_lock_remote" en un hilo paralelo
|
||||
# (para que compruebe si la imagen se ha acabado de exportar exitosamente):
|
||||
threading.Thread(target=check_lock_remote, args=(f"{repo_path}{image_file_path}", remote_ip, remote_user,)).start()
|
||||
|
||||
# Informamos que la imagen se está exportando, y salimos del endpoint:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"output": "Image exported successfully"
|
||||
"output": "Exporting image"
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": result.stderr
|
||||
}), 500
|
||||
except subprocess.CalledProcessError as error:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"process exception": str(error)
|
||||
}), 500
|
||||
except Exception as error_description:
|
||||
if "exit status 3" in str(error_description):
|
||||
return jsonify({
|
||||
|
@ -610,7 +748,7 @@ def export_image():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 11 - Endpoint "Crear archivos auxiliares":
|
||||
# 11 - Endpoint "Crear archivos auxiliares" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/images/torrentsum", methods=['POST'])
|
||||
def create_torrent_sum():
|
||||
""" Este endpoint crea los archivos ".size", ".sum", ".full.sum" y ".torrent" para la imagen que recibe como parámetro.
|
||||
|
@ -621,21 +759,29 @@ def create_torrent_sum():
|
|||
image_name = json_data.get("image")
|
||||
ou_subdir = json_data.get("ou_subdir")
|
||||
|
||||
# Evaluamos los parámetros obtenidos, para construir la llamada al script:
|
||||
# Evaluamos los parámetros obtenidos, para construir la ruta de la imagen (relativa a "repo_path"):
|
||||
if ou_subdir == "none":
|
||||
cmd = ['sudo', 'python3', f"{script_path}/createTorrentSum.py", image_name]
|
||||
image_file_path = image_name
|
||||
else:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/createTorrentSum.py", f"{ou_subdir}/{image_name}"]
|
||||
image_file_path = f"{ou_subdir}/{image_name}"
|
||||
|
||||
# Construimos la llamada al script:
|
||||
cmd = ['sudo', 'python3', f"{script_path}/createTorrentSum.py", image_file_path]
|
||||
|
||||
try:
|
||||
# Ejecutamos el script "createTorrentSum.py" (con los parámetros almacenados), y almacenamos el resultado:
|
||||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Ejecutamos el script "createTorrentSum.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso):
|
||||
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Evaluamos el resultado de la ejecución, y devolvemos una respuesta:
|
||||
if result.returncode == 0:
|
||||
if result.returncode is None:
|
||||
# Si el resultado es correcto, llamamos a la función "check_aux_files" en un hilo paralelo
|
||||
# (para que compruebe si se han creado todos los archivos auxiliares exitosamente):
|
||||
threading.Thread(target=check_aux_files, args=(f"{repo_path}{image_file_path}",)).start()
|
||||
|
||||
# Informamos que los archivos auxiliares se están creando, y salimos del endpoint:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"output": "Files created successfully"
|
||||
"output": "Creating auxiliar files..."
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
|
@ -663,7 +809,7 @@ def create_torrent_sum():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 12 - Endpoint "Enviar paquete Wake On Lan":
|
||||
# 12 - Endpoint "Enviar paquete Wake On Lan" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/wol", methods=['POST'])
|
||||
def send_wakeonlan():
|
||||
""" Este endpoint envía un paquete mágico Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificadac.
|
||||
|
@ -699,7 +845,7 @@ def send_wakeonlan():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 13 - Endpoint "Enviar una Imagen mediante UDPcast":
|
||||
# 13 - Endpoint "Enviar una Imagen mediante UDPcast" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/udpcast", methods=['POST'])
|
||||
def send_udpcast():
|
||||
""" Este endpoint envía mediante UDPcast la imagen que recibe como primer parámetro, con los datos de transferencia que recibe en los demás parámetros.
|
||||
|
@ -731,19 +877,28 @@ def send_udpcast():
|
|||
}), 400
|
||||
|
||||
try:
|
||||
# Ejecutamos el script "sendFileMcast.py" (con los parámetros almacenados), y almacenamos el resultado:
|
||||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Ejecutamos el script "sendFileMcast.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso):
|
||||
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Comprobamos si está corriendo el proceso correspondiente de "udp-sender" (esperando 5 segundos para darle tiempo a iniciarse):
|
||||
sleep(5)
|
||||
process_running = search_process('udp-sender', f"{param_dict['name']}.{param_dict['extension']}")
|
||||
|
||||
# Evaluamos el resultado de la ejecución, y devolvemos una respuesta:
|
||||
if result.returncode == 0: # NOTA: Devolverá "0" cuando finalize la transmisión, lo que finalizará también el proceso asociado,
|
||||
return jsonify({ # pero si ningún cliente se conecta, el proceso quedará corriendo, y el script no devolverá nada.
|
||||
"success": True, # Esto podría paliarse utilizando el parámetro "--autostart", pero creo que no será necesario.
|
||||
"output": "Image sended successfully"
|
||||
if result.returncode is None and process_running == True:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"output": "Sending image..."
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": result.stderr
|
||||
"error": "Image send failed"
|
||||
}), 500
|
||||
except subprocess.CalledProcessError as error:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"process exeption": str(error)
|
||||
}), 500
|
||||
except Exception as error_description:
|
||||
return jsonify({
|
||||
|
@ -755,7 +910,7 @@ def send_udpcast():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 14 - Endpoint "Enviar una Imagen mediante UFTP":
|
||||
# 14 - Endpoint "Enviar una Imagen mediante UFTP" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/uftp", methods=['POST'])
|
||||
def send_uftp():
|
||||
""" Este endpoint envía mediante UFTP la imagen que recibe como primer parámetro, con los datos de transferencia que recibe en los demás parámetros.
|
||||
|
@ -785,19 +940,28 @@ def send_uftp():
|
|||
}), 400
|
||||
|
||||
try:
|
||||
# Ejecutamos el script "sendFileUFTP.py" (con los parámetros almacenados), y almacenamos el resultado:
|
||||
result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
# Ejecutamos el script "sendFileUFTP.py" (con los parámetros almacenados), y almacenamos el resultado (pero sin esperar a que termine el proceso):
|
||||
result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
|
||||
|
||||
# Comprobamos si está corriendo el proceso correspondiente de "uftp" (esperando 5 segundos para darle tiempo a iniciarse):
|
||||
sleep(5)
|
||||
process_running = search_process('uftp', f"{param_dict['name']}.{param_dict['extension']}")
|
||||
|
||||
# Evaluamos el resultado de la ejecución, y devolvemos una respuesta:
|
||||
if result.returncode == 0: # NOTA: Devolverá "0" cuando finalize la transmisión, lo que finalizará también el proceso asociado,
|
||||
return jsonify({ # pero si ningún cliente se conecta, el proceso finalizará automáticamente (y tambien devolverá "0"").
|
||||
if result.returncode is None and process_running == True:
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"output": "Image sended successfully"
|
||||
"output": "Sending image..."
|
||||
}), 200
|
||||
else:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"error": result.stderr
|
||||
"error": "Image send failed"
|
||||
}), 500
|
||||
except subprocess.CalledProcessError as error:
|
||||
return jsonify({
|
||||
"success": False,
|
||||
"process exeption": str(error)
|
||||
}), 500
|
||||
except Exception as error_description:
|
||||
return jsonify({
|
||||
|
@ -809,7 +973,7 @@ def send_uftp():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 15 - Endpoint "Enviar una Imagen mediante P2P":
|
||||
# 15 - Endpoint "Enviar una Imagen mediante P2P" (ASINCRONO):
|
||||
@app.route("/ogrepository/v1/p2p", methods=['POST'])
|
||||
def send_p2p():
|
||||
""" Este endpoint inicia el tracker "bttrack" y el seeder "bittornado", en el directorio en el que esté situada la imagen que recibe como parámetro.
|
||||
|
@ -866,7 +1030,7 @@ def send_p2p():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 16 - Endpoint "Ver Estado de Transmisiones UDPcast":
|
||||
# 16 - Endpoint "Ver Estado de Transmisiones UDPcast" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/udpcast", methods=['GET'])
|
||||
def get_udpcast_info():
|
||||
""" Este endpoint devuelve información sobre los procesos de "udp-sender" activos, en formato json,
|
||||
|
@ -909,7 +1073,7 @@ def get_udpcast_info():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 17 - Endpoint "Ver Estado de Transmisiones UFTP":
|
||||
# 17 - Endpoint "Ver Estado de Transmisiones UFTP" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/uftp", methods=['GET'])
|
||||
def get_uftp_info():
|
||||
""" Este endpoint devuelve información sobre los procesos de "uftp" activos, en formato json,
|
||||
|
@ -952,7 +1116,7 @@ def get_uftp_info():
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 18 - Endpoint "Cancelar Transmisión UDPcast":
|
||||
# 18 - Endpoint "Cancelar Transmisión UDPcast" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/udpcast/images/<string:imageId>", methods=['DELETE'])
|
||||
def stop_udpcast(imageId):
|
||||
""" Este endpoint cancela la transmisión UDPcast de la imagen que recibe como parámetro, finalizando el proceso "udp-sender" asociado.
|
||||
|
@ -1014,7 +1178,7 @@ def stop_udpcast(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 19 - Endpoint "Cancelar Transmisión UFTP":
|
||||
# 19 - Endpoint "Cancelar Transmisión UFTP" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/uftp/images/<string:imageId>", methods=['DELETE'])
|
||||
def stop_uftp(imageId):
|
||||
""" Este endpoint cancela la transmisión UFTP de la imagen que recibe como parámetro, finalizando el proceso "uftp" asociado.
|
||||
|
@ -1076,7 +1240,7 @@ def stop_uftp(imageId):
|
|||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
# 20 - Endpoint "Cancelar Transmisiones P2P":
|
||||
# 20 - Endpoint "Cancelar Transmisiones P2P" (SINCRONO):
|
||||
@app.route("/ogrepository/v1/p2p", methods=['DELETE'])
|
||||
def stop_p2p():
|
||||
""" Este endpoint cancela las transmisiones P2P activas, finalizando los procesos "btlaunchmany.bittornado" (seeder) y "bttrack" (tracker).
|
||||
|
|
153
api/swagger.yaml
153
api/swagger.yaml
|
@ -1,6 +1,6 @@
|
|||
swagger: "2.0"
|
||||
info:
|
||||
title: "Ogrepository API"
|
||||
title: "OgRepository API"
|
||||
version: "1.0"
|
||||
description: |
|
||||
API de ogRepository, programada en Flask.
|
||||
|
@ -21,7 +21,7 @@ paths:
|
|||
tags:
|
||||
- "Estado de ogRepository"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La información de estado se obtuvo exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -95,7 +95,7 @@ paths:
|
|||
btlaunchmany:
|
||||
type: string
|
||||
example: "stopped"
|
||||
500:
|
||||
"500":
|
||||
description: "Error al consultar y/o devolver la información de estado."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -118,7 +118,7 @@ paths:
|
|||
tags:
|
||||
- "Imágenes de Repositorio"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La información de las imágenes se obtuvo exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -266,7 +266,7 @@ paths:
|
|||
fullsum:
|
||||
type: string
|
||||
example: "22735b9070e4a8043371b8c6ae52b90d"
|
||||
500:
|
||||
"500":
|
||||
description: "Error al consultar y/o devolver la información de las imágenes."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -287,7 +287,7 @@ paths:
|
|||
tags:
|
||||
- "Imágenes de Repositorio"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La actualización de la información del repositorio se realizó exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -298,7 +298,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Repository info updated successfully"
|
||||
500:
|
||||
"500":
|
||||
description: "Error al actualizar la información de las imágenes."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -326,7 +326,7 @@ paths:
|
|||
type: string
|
||||
description: "El ID de la imagen (corresponde al hash MD5 'fullsum' de la imagen)"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La información de la imagen se obtuvo exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -375,7 +375,7 @@ paths:
|
|||
fullsum:
|
||||
type: string
|
||||
example: "33575b9070e4a8043371b8c6ae52b80e"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -386,7 +386,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
500:
|
||||
"500":
|
||||
description: "Error al consultar y/o devolver la información de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -418,7 +418,7 @@ paths:
|
|||
type: string
|
||||
description: "Método de eliminación (puede ser 'trash' para enviar a la papelera o 'permanent' para eliminar definitivamente)"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se eliminó exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -429,7 +429,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image deleted successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -440,7 +440,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found (inexistent or deleted)"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al eliminar la imagen. Puede ocurrir debido a:
|
||||
- Un error de ejecución del script (con salida no 0).
|
||||
|
@ -454,7 +454,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la eliminación de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -481,7 +481,7 @@ paths:
|
|||
type: string
|
||||
description: "El ID de la imagen (corresponde al hash MD5 'fullsum' de la imagen)"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: >
|
||||
La imagen se ha chequeado exitosamente. El chequeo puede devolver dos resultados:
|
||||
- Si pasa la verificación de integridad.
|
||||
|
@ -495,7 +495,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image file passed the Integrity Check correctly"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -506,7 +506,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found (inexistent or deleted)"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al chequear la imagen. Puede ocurrir debido a una excepción inesperada.
|
||||
schema:
|
||||
|
@ -518,7 +518,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Generic error description for unexpected exceptions."
|
||||
200 (KO):
|
||||
"200 (KO)":
|
||||
description: "La imagen se ha chequeado correctamente, pero no ha pasado el test de integridad."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -550,7 +550,7 @@ paths:
|
|||
type: string
|
||||
example: "image_id"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se recuperó exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -561,7 +561,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image recovered successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -572,7 +572,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found (inexistent or recovered previously)"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al recuperar la imagen. Puede ocurrir debido a:
|
||||
- Un error de ejecución del script (con salida no 0).
|
||||
|
@ -586,7 +586,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la recuperación de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -613,7 +613,7 @@ paths:
|
|||
type: string
|
||||
description: "El ID de la imagen (corresponde al hash MD5 'fullsum' de la imagen en la papelera)"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se eliminó exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -624,7 +624,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image deleted successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada en la papelera."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -635,7 +635,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found at trash"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al eliminar la imagen desde la papelera. Puede ocurrir debido a:
|
||||
- Un error de ejecución del script (con salida no 0).
|
||||
|
@ -649,7 +649,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la eliminación de la imagen desde la papelera."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -694,7 +694,7 @@ paths:
|
|||
description: "Usuario para acceder al repositorio remoto"
|
||||
example: "user_name"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se ha importado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -705,7 +705,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image imported successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "Error de conexión o imagen no disponible en el servidor remoto."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -716,7 +716,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Can't connect to remote server | Remote image not found | Remote image is locked"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al importar la imagen. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -728,7 +728,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la importación de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -767,7 +767,7 @@ paths:
|
|||
description: "Usuario para acceder al repositorio remoto"
|
||||
example: "user_name"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se ha exportado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -778,7 +778,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image exported successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "Error de conexión o imagen no disponible en el servidor remoto."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -789,7 +789,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Image is locked | Can't connect to remote server | Image already exists on remote server"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al exportar la imagen. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -801,7 +801,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la exportación de la imagen."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -836,7 +836,7 @@ paths:
|
|||
description: "Subdirectorio correspondiente a la OU (o 'none' si no es el caso)"
|
||||
example: "none"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "Los archivos se han creado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -847,7 +847,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Files created successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "Error de conexión o imagen no disponible en el servidor remoto."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -858,7 +858,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Image not found | Image is locked"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al crear los archivos auxiliares. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -870,7 +870,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la creación de los archivos auxiliares."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -906,7 +906,7 @@ paths:
|
|||
description: "Dirección MAC del equipo a encender"
|
||||
example: "00:19:99:5c:bb:bb"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "El paquete Wake On Lan se ha enviado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -917,7 +917,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Wake On Lan packet sent successfully"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al enviar el paquete Wake On Lan. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -929,7 +929,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante el envío del paquete Wake On Lan."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -950,7 +950,7 @@ paths:
|
|||
tags:
|
||||
- "Transferencia de Imágenes"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La información de las transmisiones UDPcast activas se obtuvo exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -969,7 +969,7 @@ paths:
|
|||
image_name:
|
||||
type: string
|
||||
example: "Ubuntu20.img"
|
||||
400:
|
||||
"400":
|
||||
description: "No se han encontrado transmisiones UDPcast activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -980,7 +980,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "No UDPCast active transmissions"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al comprobar las transmisiones UDPcast activas, posiblemente debido a un error inesperado durante la ejecución del script.
|
||||
schema:
|
||||
|
@ -992,7 +992,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la comprobación de transmisiones UDPcast activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1046,7 +1046,7 @@ paths:
|
|||
description: "Tiempo máximo de espera en segundos"
|
||||
example: 120
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se ha enviado exitosamente mediante UDPcast."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1057,7 +1057,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image sent successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1068,7 +1068,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al enviar la imagen mediante UDPcast. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -1080,7 +1080,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante el envío de la imagen mediante UDPcast."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1101,7 +1101,7 @@ paths:
|
|||
tags:
|
||||
- "Transferencia de Imágenes"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La información de las transmisiones UFTP activas se obtuvo exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1120,7 +1120,7 @@ paths:
|
|||
image_name:
|
||||
type: string
|
||||
example: "Ubuntu20.img"
|
||||
400:
|
||||
"400":
|
||||
description: "No se han encontrado transmisiones UFTP activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1131,7 +1131,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "No UFTP active transmissions"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al comprobar las transmisiones UFTP activas, posiblemente debido a un error inesperado durante la ejecución del script.
|
||||
schema:
|
||||
|
@ -1143,7 +1143,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante la comprobación de transmisiones UFTP activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1186,7 +1186,7 @@ paths:
|
|||
description: "Velocidad de transmisión (con 'K' para Kbps, 'M' para Mbps, o 'G' para Gbps)"
|
||||
example: "1G"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se ha enviado exitosamente mediante UFTP."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1197,7 +1197,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image sent successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1208,7 +1208,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error interno al enviar la imagen mediante UFTP. Puede ocurrir debido a un problema en la ejecución del script o una excepción inesperada.
|
||||
schema:
|
||||
|
@ -1220,7 +1220,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Script execution error description."
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante el envío de la imagen mediante UFTP."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1253,7 +1253,7 @@ paths:
|
|||
type: string
|
||||
example: "image_id"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La imagen se está enviando exitosamente a través de P2P."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1264,7 +1264,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Tracker and Seeder serving image correctly"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1275,7 +1275,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Image not found"
|
||||
500:
|
||||
"500":
|
||||
description: >
|
||||
Error al intentar iniciar el tracker o el seeder para el envío P2P.
|
||||
Puede ocurrir si alguno de los procesos no se inicia correctamente o si ocurre una excepción inesperada.
|
||||
|
@ -1288,7 +1288,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Tracker or Seeder (or both) not running"
|
||||
500 (Exception):
|
||||
"500 (Exception)":
|
||||
description: "Error inesperado durante el proceso de envío P2P."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1307,7 +1307,7 @@ paths:
|
|||
tags:
|
||||
- "Transferencia de Imágenes"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "Las transmisiones P2P se han cancelado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1318,7 +1318,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "P2P transmissions canceled successfully"
|
||||
500 (Error del script):
|
||||
"500 (Error del script)":
|
||||
description: "Error en la ejecución del script durante la cancelación de las transmisiones P2P."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1329,7 +1329,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Detailed error message from script stderr output."
|
||||
500 (Excepción general):
|
||||
"500 (Excepción general)":
|
||||
description: "Excepción inesperada durante la cancelación de las transmisiones P2P."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1357,7 +1357,7 @@ paths:
|
|||
description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum' asociado)"
|
||||
example: "image_id"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La transmisión UDPcast se ha cancelado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1368,7 +1368,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image transmission canceled successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada o no hay transmisiones UDPcast activas para la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1379,7 +1379,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "No UDPCast active transmissions for specified image"
|
||||
500 (Error del script):
|
||||
"500 (Error del script)":
|
||||
description: "Error en la ejecución del script durante la cancelación de la transmisión."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1390,7 +1390,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Detailed error message from script stderr output."
|
||||
500 (Error en verificación):
|
||||
"500 (Error en verificación)":
|
||||
description: "Error inesperado al verificar las transmisiones UDPcast activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1401,7 +1401,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Unexpected error checking UDPcast transmissions"
|
||||
500 (Error en finalización):
|
||||
"500 (Error en finalización)":
|
||||
description: "Error inesperado al finalizar la transmisión UDPcast."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1412,7 +1412,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Unexpected error finalizing UDPcast transmission"
|
||||
500 (Excepción general):
|
||||
"500 (Excepción general)":
|
||||
description: "Excepción inesperada durante la cancelación de la transmisión UDPcast."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1440,7 +1440,7 @@ paths:
|
|||
description: "Identificador de la imagen (correspondiente al contenido del archivo 'full.sum' asociado)"
|
||||
example: "image_id"
|
||||
responses:
|
||||
200:
|
||||
"200":
|
||||
description: "La transmisión UFTP se ha cancelado exitosamente."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1451,7 +1451,7 @@ paths:
|
|||
output:
|
||||
type: string
|
||||
example: "Image transmission canceled successfully"
|
||||
400:
|
||||
"400":
|
||||
description: "No se ha encontrado la imagen especificada o no hay transmisiones UFTP activas para la imagen especificada."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1462,7 +1462,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "No UFTP active transmissions for specified image"
|
||||
500 (Error del script):
|
||||
"500 (Error del script)":
|
||||
description: "Error en la ejecución del script durante la cancelación de la transmisión."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1473,7 +1473,7 @@ paths:
|
|||
error:
|
||||
type: string
|
||||
example: "Detailed error message from script stderr output."
|
||||
500 (Error en verificación):
|
||||
"500 (Error en verificación)":
|
||||
description: "Error inesperado al verificar las transmisiones UFTP activas."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1484,7 +1484,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Unexpected error checking UFTP transmissions"
|
||||
500 (Error en finalización):
|
||||
"500 (Error en finalización)":
|
||||
description: "Error inesperado al finalizar la transmisión UFTP."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1495,7 +1495,7 @@ paths:
|
|||
exception:
|
||||
type: string
|
||||
example: "Unexpected error finalizing UFTP transmission"
|
||||
500 (Excepción general):
|
||||
"500 (Excepción general)":
|
||||
description: "Excepción inesperada durante la cancelación de la transmisión UFTP."
|
||||
schema:
|
||||
type: object
|
||||
|
@ -1507,4 +1507,3 @@ paths:
|
|||
type: string
|
||||
example: "General error description for unexpected exceptions"
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue