refs #631 - Add 'getUDPcastInfo.py' and modify API proposal

pull/1/head
Gerardo GIl Elizeire 2024-10-04 14:03:57 +02:00
parent 73bf6b6098
commit 5bab335733
3 changed files with 138 additions and 24 deletions

View File

@ -34,16 +34,16 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará
12. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast/images/{ID_img}` 12. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/udpcast/images/{ID_img}`
13. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp/images/{ID_img}` 13. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/uftp/images/{ID_img}`
14. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/p2p/images/{ID_img}` 14. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/p2p/images/{ID_img}`
15. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}` 15. [Ver Estado de Transmisiones UDPcast](#ver-estado-de-transmisiones-udpcast) - `GET /ogrepository/v1/udpcast`
16. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p` 16. [Cancelar Transmisión UDPcast](#cancelar-transmisión-udpcast) - `DELETE /ogrepository/v1/udpcast/images/{ID_img}`
17. [Ver Estado de Transmisiones Multicast-P2P](#ver-estado-de-transmisiones-multicast-p2p) - 17. [Cancelar Transmisiones P2P](#cancelar-transmisiones-p2p) - `DELETE /ogrepository/v1/p2p`
--- ---
### Obtener Información de Estado de ogRepository ### Obtener Información de Estado de ogRepository
Se devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato JSON. Se devolverá informacion de CPU, memoria RAM, disco duro y el estado de ciertos servicios y procesos de ogRepository, en formato JSON.
Se puede utilizar el script "**getRepoStatus.py**, que hemos programado recientemente. Se puede utilizar el script "**getRepoStatus.py**, que debe ser llamado por el endpoint.
**NOTA**: En los apartados "services" y "processes" he especificado los servicios y procesos que me han parecido interesantes, pero se puede añadir o eliminar los que se desee. **NOTA**: En los apartados "services" y "processes" he especificado los servicios y procesos que me han parecido interesantes, pero se puede añadir o eliminar los que se desee.
**URL:** `/ogrepository/v1/status` **URL:** `/ogrepository/v1/status`
**Método HTTP:** GET **Método HTTP:** GET
@ -92,7 +92,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/stat
### Obtener Información de todas las Imágenes ### Obtener Información de todas las Imágenes
Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (que corresponde a todas las imágenes almacenadas en el repositorio), y en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (que corresponde a las imágenes que fueron eliminadas, que estarán en la papelera). Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (que corresponde a todas las imágenes almacenadas en el repositorio), y en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (que corresponde a las imágenes que fueron eliminadas, que estarán en la papelera).
Se puede utilizar el script "**getRepoInfo.py**, que hemos programado recientemente. Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint.
**NOTA**: La versión actual de este script requiere que se le pase "all" como primer parámetro (que correspondería al nombre de la imagen) y "none" como segundo parámetro (que corresponderia al nombre del subdirectorio correspondiente a la OU). Esta transformación de parámetros se puede realizar en el controlador PHP. **NOTA**: La versión actual de este script requiere que se le pase "all" como primer parámetro (que correspondería al nombre de la imagen) y "none" como segundo parámetro (que corresponderia al nombre del subdirectorio correspondiente a la OU). Esta transformación de parámetros se puede realizar en el controlador PHP.
**URL:** `/ogrepository/v1/images` **URL:** `/ogrepository/v1/images`
@ -198,7 +198,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
### Obtener Información de una Imagen concreta ### Obtener Información de una Imagen concreta
Se devolverá la informacion de la imagen especificada, que puede estar en el archivo "**/opt/opengnsys/etc/repoinfo.json**" o en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (en este último caso, si la imagen está en la papelera). Se devolverá la informacion de la imagen especificada, que puede estar en el archivo "**/opt/opengnsys/etc/repoinfo.json**" o en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (en este último caso, si la imagen está en la papelera).
Se puede utilizar el script "**getRepoInfo.py**, que hemos programado recientemente. Se puede utilizar el script "**getRepoInfo.py**, que debe ser llamado por el endpoint.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el subdirectorio correspondiente a la OU (o "none" si no es el caso) como segundo parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP. **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión) como primer parámetro, y el subdirectorio correspondiente a la OU (o "none" si no es el caso) como segundo parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP.
**URL:** `/ogrepository/v1/images/{ID_img}` **URL:** `/ogrepository/v1/images/{ID_img}`
@ -249,7 +249,7 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
### Actualizar Información del Repositorio ### Actualizar Información del Repositorio
Se actualizará la información de las imágenes almacenadas en el repositorio, reflejándola en el archivo "**/opt/opengnsys/etc/repoinfo.json**". Se actualizará la información de las imágenes almacenadas en el repositorio, reflejándola en el archivo "**/opt/opengnsys/etc/repoinfo.json**".
Se puede hacer con el script "**updateRepoInfo.py**", que hemos programado recientemente (y que es similar al script bash original "**checkrepo**"). Se puede hacer con el script "**updateRepoInfo.py**", que debe ser llamado por el endpoint (y que es similar al script bash original "**checkrepo**").
Este endpoint es llamado por el script "**deleteImage.py**" (para actualizar la información cada vez que se elimine una imagen), y creemos que también debe ser llamado por ogCore u ogLive cada vez que se haya creado una imagen. Este endpoint es llamado por el script "**deleteImage.py**" (para actualizar la información cada vez que se elimine una imagen), y creemos que también debe ser llamado por ogCore u ogLive cada vez que se haya creado una imagen.
**URL:** `/ogrepository/v1/images` **URL:** `/ogrepository/v1/images`
@ -289,7 +289,7 @@ curl -X POST -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/sta
### Eliminar una Imagen ### Eliminar una Imagen
Se eliminará la imagen especificada como parámetro, pudiendo eliminarla permanentemente o enviarla a la papelera. Se eliminará la imagen especificada como parámetro, pudiendo eliminarla permanentemente o enviarla a la papelera.
Se puede hacer con el script "**deleteimage.py**", que hemos programado recientemente (y que incluye la funcionalidad "papelera"), y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio. Se puede hacer con el script "**deleteimage.py**", que debe ser llamado por el endpoint (y que incluye la funcionalidad "papelera"), y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP, pero en principio habrá que especificar el método de eliminación en un json (en la URL). **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, y el parámetro opcional "-p" (para que la eliminación sea permanente). En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP, pero en principio habrá que especificar el método de eliminación en un json (en la URL).
**URL:** `/ogrepository/v1/images/{ID_img}` **URL:** `/ogrepository/v1/images/{ID_img}`
@ -312,7 +312,7 @@ curl -X DELETE -H "Authorization: $API_KEY" -H "Content-Type: application/json"
### Recuperar una Imagen ### Recuperar una Imagen
Se recuperará la imagen especificada como parámetro, desde la papelera. Se recuperará la imagen especificada como parámetro, desde la papelera.
Se puede hacer con el script "**recoverImage.py**", que hemos programado recientemente, y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio. Se puede hacer con el script "**recoverImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateRepoInfo.py**", para actualizar la información del repositorio.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP. **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP.
**URL:** `/ogrepository/v1/trash/images/{ID_img}` **URL:** `/ogrepository/v1/trash/images/{ID_img}`
@ -332,7 +332,7 @@ curl -X POST -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/tra
### Eliminar una Imagen de la Papelera ### Eliminar una Imagen de la Papelera
Se eliminará permanentemente la imagen especificada como parámetro, desde la papelera. Se eliminará permanentemente la imagen especificada como parámetro, desde la papelera.
Se puede hacer con el script "**deleteTrashImage.py**", que hemos programado recientemente, y que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera. Se puede hacer con el script "**deleteTrashImage.py**", que debe ser llamado por el endpoint, y que a su vez llama al script "**updateTrashInfo.py**", para actualizar la información de la papelera.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP. **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP.
**URL:** `/ogrepository/v1/trash/images/{ID_img}` **URL:** `/ogrepository/v1/trash/images/{ID_img}`
@ -352,7 +352,7 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/t
### Importar una Imagen ### Importar una Imagen
Se importará una imagen de un repositorio remoto al repositorio local. Se importará una imagen de un repositorio remoto al repositorio local.
Se puede hacer con el script "**importImage.py**", que hemos programado recientemente. Se puede hacer con el script "**importImage.py**", que debe ser llamado por el endpoint.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. En principio, ogCore puede acceder a estos datos a partir del ID del repositorio y del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP, pero en principio habrá que especificar el usuario remoto en un json (en la URL). **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como primer parámetro, la IP o hostname del repositorio remoto como segundo parámetro, y el usuario remoto como tercer parámetro. En principio, ogCore puede acceder a estos datos a partir del ID del repositorio y del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP, pero en principio habrá que especificar el usuario remoto en un json (en la URL).
**URL:** `/ogrepository/v1/repo/{ID_repo}/images/{ID_img}` **URL:** `/ogrepository/v1/repo/{ID_repo}/images/{ID_img}`
@ -375,7 +375,7 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
### Crear archivos auxiliares ### Crear archivos auxiliares
Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro. Se crearán los archivos ".sum", ".full.sum", ".size" y ".torrent", para la imagen especificada como parámetro.
Se puede hacer con el script "**createTorrentSum.py**", que hemos programado recientemente. Se puede hacer con el script "**createTorrentSum.py**", que debe ser llamado por el endpoint.
**URL:** `/ogrepository/v1/images/torrentsum` **URL:** `/ogrepository/v1/images/torrentsum`
**Método HTTP:** POST **Método HTTP:** POST
@ -398,7 +398,7 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
### Enviar paquete Wake On Lan ### Enviar paquete Wake On Lan
Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada. Se enviará un paquete Wake On Lan a la dirección MAC especificada, a través de la IP de broadcast especificada.
Se puede hacer con el script "**sendWakeOnLan.py**", que hemos programado recientemente. Se puede hacer con el script "**sendWakeOnLan.py**", que debe ser llamado por el endpoint.
**URL:** `/ogrepository/v1/wol` **URL:** `/ogrepository/v1/wol`
**Método HTTP:** POST **Método HTTP:** POST
@ -494,11 +494,40 @@ curl -X POST -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p2p
- **Código 400 Bad Request:** No se ha encontrado la imagen especificada. - **Código 400 Bad Request:** No se ha encontrado la imagen especificada.
- **Código 200 OK:** La imagen se ha enviado exitosamente. - **Código 200 OK:** La imagen se ha enviado exitosamente.
---
### Ver Estado de Transmisiones UDPcast
Se devolverá el pid de los procesos de transferencias UDPcast activas, y sus imágenes asociadas, en formato JSON, o un mensaje informativo si no hay procesos activos, o si se produce un error.
Se puede hacer con el script "**getUDPcastInfo.py**", que debe ser llamado por el endpoint.
**URL:** `/ogrepository/v1/udpcast`
**Método HTTP:** GET
**Ejemplo de Solicitud:**
```bash
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/udpcast
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al comprobar las transmisiones UDPcast.
- **Código 400 Bad Request:** No se han encontrado transmisiones UDPcast activas.
- **Código 200 OK:** La información de las transmisiones UDPcast activas se obtuvo exitosamente.
- **Contenido:** Información de las transmisiones UDPcast activas en formato JSON.
```json
{
"6720": {
"image": "Ubuntu20.img"
},
"6721": {
"image": "Windows10.img"
}
}
```
--- ---
### Cancelar Transmisión UDPcast ### Cancelar Transmisión UDPcast
Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen. Se cancelará la transmisión por UDPcast activa de la imagen especificada como parámetro, deteniendo el proceso "udp-sender" asociado a dicha imagen.
Se puede hacer con el script "**stopUDPcast.py**", que hemos programado recientemente. Se puede hacer con el script "**stopUDPcast.py**", que debe ser llamado por el endpoint.
**NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP. **NOTA**: La versión actual de este script requiere que se le pase el nombre de la imagen (con extensión, e incluyendo el nombre del directorio correspondiente a la OU, si fuera el caso) como único parámetro. En principio, ogCore puede acceder a estos datos a partir del ID de la imagen (que hemos quedado que será el contenido del archivo "full.sum"), y la transformación de parámetros puede realizarse en el controlador PHP.
**URL:** `/ogrepository/v1/udpcast/images/{ID_img}` **URL:** `/ogrepository/v1/udpcast/images/{ID_img}`
@ -518,7 +547,7 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/u
### Cancelar Transmisiones P2P ### Cancelar Transmisiones P2P
Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado". Se cancelarán las transmisiones P2P activas en el ogRepository al que se envíe la orden, deteniendo los procesos "bttrack" y "btlaunchmany.bittornado".
Se puede hacer con el script "**stopP2P.py**", que hemos programado recientemente. Se puede hacer con el script "**stopP2P.py**", que debe ser llamado por el endpoint.
**NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado. **NOTA**: No he encontrado la forma de detener la transmisión de una imagen concreta, ya que "bttrack" y "btlaunchmany.bittornado" hacen tracking y seed (respectivamente) de todos los torrents existentes en la raíz del directorio especificado.
**URL:** `/ogrepository/v1/p2p` **URL:** `/ogrepository/v1/p2p`
@ -533,10 +562,4 @@ curl -X DELETE -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/p
- **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones. - **Código 500 Internal Server Error:** Ocurrió un error al cancelar las transmisiones.
- **Código 200 OK:** Las transmisiones se han cancelado exitosamente. - **Código 200 OK:** Las transmisiones se han cancelado exitosamente.
---
### Ver Estado de Transmisiones Multicast-P2P
Se debe estudiar como realizar esta tarea para cada uno de los protocolos de transmisión, ya que cada uno tiene sus particularidades, y habitualmente no tienen comandos asociados para comprobar el estado de las transmisiones. Es posible que sea neceario parsear los logs de ogRepo y/o de los clientes.
**NOTA**: Seguramente deba crearse un endpoint específico para cada uno de los protocolos que se utilicen.
--- ---

View File

@ -0,0 +1,91 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Este script busca procesos activos de "udp-sender", y si encuentra alguno devuelve el pid y la imagen asociada de cada uno de ellos, en una estructura JSON.
Si no encuentra ninguno, o si se produce un error, imprime un mensaje informativo.
No recibe ningún parámetro.
En la práctica, permite comprobar las transminisones UDPcast activas, porque cuando finalizan también finaliza el proceso asociado.
"""
# --------------------------------------------------------------------------------------------
# IMPORTS
# --------------------------------------------------------------------------------------------
import subprocess
import json
# --------------------------------------------------------------------------------------------
# VARIABLES
# --------------------------------------------------------------------------------------------
repo_path = '/opt/opengnsys/images/'
# --------------------------------------------------------------------------------------------
# FUNCTIONS
# --------------------------------------------------------------------------------------------
def get_udpsender_processes():
""" Busca procesos de "udp-sender", y si los encuentra retorna el pid y la imagen asociada de cada uno de ellos, en un diccionario.
Si no encuentra ningun proceso, o si se produce un error, retorna un mensaje.
"""
try:
# Obtenemos todos los procesos, y almacenamos la salida y los errores:
result = subprocess.Popen(['ps', '-aux'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8')
out, error = result.communicate()
# Almacenamos en una lista los procesos que contengan "udp-sender":
process_list = [line for line in out.split('\n') if 'udp-sender' in line]
# Si hemos encontrado procesos de udp-sender creamos un diccionario para almacenarlos:
if process_list != []:
result_dict = {}
# Iteramos los procesos y extraemos el pid y el nombre de la imagen de cada uno,
# los almacenamos en el diccionario, y retornamos este:
for process in process_list:
pid = process.split()[1]
image = process.split(repo_path)[1]
result_dict[pid] = {'image':image}
return result_dict
# Si no hemos encontrado procesos de udp-sender retrornamos un mensaje:
else:
return "udp-sender process not found"
# Si se ha producido una excepción, retornamos un mensaje:
except Exception:
return "Unexpected error"
# --------------------------------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------------------------------
def main():
"""
"""
# Obtenemos información sobre los procesos de udp-sender:
results = get_udpsender_processes()
# Si no hay procesos activos, o si se ha producido un error, imprimimos un mensaje explicativo:
if results == "udp-sender process not found":
print("No UDPcast active transmissions")
elif results == "Unexpected error":
print("Unexpected error checking UDPcast transmissions")
# Si hay procesos activos, convertimos el diccionario de resultados a JSON, e imprimimos este:
else:
json_data = json.dumps(results, indent=4)
print(json_data)
# --------------------------------------------------------------------------------------------
if __name__ == "__main__":
main()
# --------------------------------------------------------------------------------------------

View File

@ -171,8 +171,8 @@ def main():
'--min-clients', nclients, '--min-clients', nclients,
'--max-wait', maxtime, # Esto hace que espere 120 segundos desde la conexión del primer cliente para empezar la transmisión. '--max-wait', maxtime, # Esto hace que espere 120 segundos desde la conexión del primer cliente para empezar la transmisión.
#'--autostart', '20', # Esto hace que empiece la transmisión automáticamente después de enviar 20 paquetes "hello". #'--autostart', '20', # Esto hace que empiece la transmisión automáticamente después de enviar 20 paquetes "hello".
'--file', file_path, '--log', log_file,
'--log', log_file '--file', file_path
] ]
# Imprimimos el comando con espacios (como realmente se enviará): # Imprimimos el comando con espacios (como realmente se enviará):