diff --git a/README.md b/README.md index a206438..639ee04 100644 --- a/README.md +++ b/README.md @@ -4,5 +4,6 @@ OpenGnsys Repository Manager README Este repositorio GIT contiene la estructura de datos del repositorio de datos de OpenGnsys. -- bin: binarios y scripts de gestión del repositorio. -- etc: ficheros o plantillas de configuración del repositorio. \ No newline at end of file +- bin: Binarios y scripts de gestión del repositorio. +- etc: Ficheros o plantillas de configuración del repositorio. +- py_scripts: Scripts en Python 3, algunos de los cuales son traducciones de los scripts bash situados en "bin". \ No newline at end of file diff --git a/py_scripts/sendFileMcast.py b/py_scripts/sendFileMcast.py new file mode 100644 index 0000000..72b267c --- /dev/null +++ b/py_scripts/sendFileMcast.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Este script envía mediante UDPCast la imagen recibida como primer parámetro, con los datos Multicast especificados en el segundo parámetro. +En principio, debería hacer lo mismo que el script bash original (cuyo nombre es "sendFileMcast", a secas). + + Parámetros +------------ +sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta) + - Ejemplo1: image1.img + - Ejemplo2: /opt/opengnsys/images/image1.img + +sys.argv[2] - Parámetros Multicast (en formato "Port:Duplex:IP:Mpbs:Nclients:Timeout") + - Ejemplo: 9000:full:239.194.17.2:70M:20:120 + + Sintaxis +---------- +./sendFileMcast.py image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout + + Ejemplos + --------- +./sendFileMcast.py image1.img 9000:full:239.194.17.2:70M:20:120 +./sendFileMcast.py /opt/opengnsys/images/image1.img 9000:full:239.194.17.2:70M:20:120 +""" + +# -------------------------------------------------------------------------------------------- +# IMPORTS +# -------------------------------------------------------------------------------------------- + +import os +import sys +import subprocess + + +# -------------------------------------------------------------------------------------------- +# VARIABLES +# -------------------------------------------------------------------------------------------- + +script_name = os.path.basename(__file__) +repo_path = '/opt/opengnsys/images/' +bin_path = '/opt/opengnsys/bin/' +repo_iface = subprocess.getoutput('/opt/opengnsys/bin/getRepoIface') + + +# -------------------------------------------------------------------------------------------- +# FUNCTIONS +# -------------------------------------------------------------------------------------------- + + +def show_help(): + """ Imprime la ayuda, cuando se ejecuta el script con el parámetro "help". + """ + help_text = f""" + Sintaxis: {script_name} image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout + Ejemplo1: {script_name} image1.img 9000:full-duplex:239.194.17.2:70M:20:120 + Ejemplo2: {script_name} /opt/opengnsys/images/image1.img 9000:full-duplex:239.194.17.2:70M:20:120 + """ + print(help_text) + + +def check_params(): + """ Comprueba que se haya enviado la cantidad correcta de parámetros, y en el formato correcto. + Si no es así, muestra un mensaje de error, y sale del script. + LLama a la función "show_help" cuando se ejecuta el script con el parámetro "help". + """ + # Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script: + if len(sys.argv) == 2 and sys.argv[1] == "help": + show_help() + sys.exit(0) + # Si se ejecuta la función con más o menos de 2 parámetros, se muestra un mensaje de error, y se sale del script: + elif len(sys.argv) != 3: + print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros (image_name|/image_path/image_name Port:Duplex:IP:Mpbs:Nclients:Timeout)") + sys.exit(1) + # Si en el segundo parámetro no hay 6 elementos (separados por ":"), se muestra un mensaje de error, y se sale del script: + param_list = sys.argv[2].split(':') + if len(param_list) != 6: + print(f"{script_name} Error: Datos Multicast incorrectos: \"{sys.argv[2]}\" (se debe especificar \"Port:Duplex:IP:Mpbs:Nclients:Timeout\")") + sys.exit(3) + + +def build_file_path(): + """ Construye la ruta completa al archivo a enviar + (agregando "/opt/opengnsys/images/" si no se ha especificado en el parámetro). + """ + param_path = sys.argv[1] + if not param_path.startswith(repo_path): + file_path = os.path.join(repo_path, param_path) + else: + file_path = param_path + return file_path + + +# -------------------------------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------------------------------- + + +def main(): + """ + """ + # Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto: + check_params() + + # Obtenemos la ruta completa al archivo a enviar: + file_path = build_file_path() + + # Si el fichero no es accesible, devolvermos un error, y salimos del script: + if not os.path.isfile(file_path): + print(f"{script_name} Error: Fichero \"{file_path}\" no accesible") + sys.exit(2) + + # Almacenamos los elementos del segundo parámetro en variables (su formato es "Port:Duplex:IP:Mpbs:Nclients:Timeout"): + param_list = sys.argv[2].split(':') + port, method, ip, bitrate, nclients, maxtime = param_list + + # Retocamos las variables "method" y "bitrate": + method = '--half-duplex' if 'half' in method.lower() else '--full-duplex' + bitrate = bitrate.lower() + + # Creamos la variable "cerror" (no sé que hace, pero estaba en el script original): + cerror = "8x8/128" + + # Creamos una lista con el comando a enviar (esto es requerido por la función "subprocess.run"). + # NOTA: Se desabilita el uso de mbuffer, ya que esta versión del upd-sender no la admite (ya estaba así en el script original). + mbuffer = "" # which mbuffer &> /dev/null && MBUFFER="--pipe 'mbuffer -m 20M'" + splitted_cmd = [ + os.path.join(bin_path, 'udp-sender'), + mbuffer, + '--nokbd', + '--retries-until-drop', '65', + '--portbase', port, + method, + '--interface', repo_iface, + '--mcast-data-address', ip, + '--fec', cerror, + '--max-bitrate', bitrate, + '--ttl', '16', + '--min-clients', nclients, + '--max-wait', maxtime, + '--file', file_path + ] + + # Imprimimos el comando con espacios (como realmente se enviará): + print(f"Sending command: {' '.join(splitted_cmd)}") + + # Ejecutamos el comando en el sistema, e imprimimos el resultado: + try: + result = subprocess.run(splitted_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + print(f"ReturnCode: {result.returncode}") + except subprocess.CalledProcessError as error: + print(f"ReturnCode: {error.returncode}") + print(f"Error Output: {error.stderr.decode()}") + except Exception as error: + print(f"Se ha producido un error inesperado: {error}") + + + +# -------------------------------------------------------------------------------------------- + +if __name__ == "__main__": + main() + +# -------------------------------------------------------------------------------------------- diff --git a/bin/sendFileUFTP.py b/py_scripts/sendFileUFTP.py similarity index 94% rename from bin/sendFileUFTP.py rename to py_scripts/sendFileUFTP.py index 5f18752..7fe1906 100644 --- a/bin/sendFileUFTP.py +++ b/py_scripts/sendFileUFTP.py @@ -3,7 +3,7 @@ """ Este script envía mediante UFTP la imagen recibida como primer parámetro, al puerto e IP (Multicast o Unicast) especificados en el segundo parámetro, - a la velocidad de transferencia tambíén especificada en el segundo parámetro (la sintaxis de este parámetro es "puerto:ip:bitrate"). + a la velocidad de transferencia tambíén especificada en el segundo parámetro (la sintaxis de este parámetro es "Port:IP:Bitrate"). Previamente, los clientes deben haberse puesto a escuchar en la IP Multicast correspondiente (tanto para envíos Multicast como para envíos Unicast). Paquetes APT requeridos: "uftp" @@ -14,13 +14,13 @@ sys.argv[1] - Nombre completo de la imagen a enviar (con o sin ruta) - Ejemplo1: image1.img - Ejemplo2: /opt/opengnsys/images/image1.img -sys.argv[2] - Parámetros Multicast/Unicast (en formato "puerto:ip:bitrate") +sys.argv[2] - Parámetros Multicast/Unicast (en formato "Port:IP:Bitrate") - Ejemplo1: 9000:239.194.17.2:100M - Ejemplo2: 9000:192.168.56.101:1G Sintaxis ---------- -./sendFileUFTP.py image_name|/image_path/image_name port:ip:bitrate +./sendFileUFTP.py image_name|/image_path/image_name Port:IP:Bitrate Ejemplos --------- @@ -46,7 +46,6 @@ repo_path = '/opt/opengnsys/images/' log_file = '/opt/opengnsys/images/uftp.log' - # -------------------------------------------------------------------------------------------- # FUNCTIONS # -------------------------------------------------------------------------------------------- @@ -56,7 +55,7 @@ def show_help(): """ Imprime la ayuda, cuando se ejecuta el script con el parámetro "help". """ help_text = f""" - Sintaxis: {script_name} image_name|/image_path/image_name port:ip:bitrate + Sintaxis: {script_name} image_name|/image_path/image_name Port:IP:Bitrate Ejemplo1: {script_name} image1.img 9000:239.194.17.2:100M Ejemplo2: {script_name} /opt/opengnsys/images/image1.img 9000:192.168.56.101:1G """ @@ -73,10 +72,10 @@ def check_params(): show_help() sys.exit(0) # Si se ejecuta la función con más o menos de 2 parámetros, se muestra un mensaje de error, y se sale del script: - if len(sys.argv) != 3: + elif len(sys.argv) != 3: print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros (image_name|/image_path/image_name port:ip:bitrate)") sys.exit(1) - # Si en el segundo parámetro no hay 3 elementos (separados por ":"), devolvermos un error, y salimos del script: + # Si en el segundo parámetro no hay 3 elementos (separados por ":"), se muestra un mensaje de error, y se sale del script: param_list = sys.argv[2].split(':') if len(param_list) != 3: print(f"{script_name} Error: Datos Multicast incorrectos: \"{sys.argv[2]}\" (se debe especificar \"puerto:ip:bitrate\")") @@ -129,7 +128,7 @@ def main(): print(f"{script_name} Error: Fichero \"{file_path}\" no accesible") sys.exit(2) - # Almacenamos los elementos del segundo parámetro en variables: + # Almacenamos los elementos del segundo parámetro en variables (su formato es "puerto:ip:bitrate"): param_list = sys.argv[2].split(':') port, ip, bitrate = param_list