refs #631 - Add updateTrashInfo.py

pull/1/head
Gerardo GIl Elizeire 2024-08-21 12:29:42 +02:00
parent ccd0ebd8ef
commit 99bd49d730
3 changed files with 342 additions and 46 deletions

View File

@ -20,15 +20,15 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará
### Tabla de Contenido:
1. [Obtener Información de todas las Imágenes](#obtener-información-de-todas-las-imágenes) - `GET /ogrepository/v1/images`
2. [Obtener Información de una Imagen concreta](#obtener-información-de-una-imagen-concreta) - `GET /ogrepository/v1/images/{name}`
2. [Obtener Información de una Imagen concreta](#obtener-información-de-una-imagen-concreta) - `GET /ogrepository/v1/images/get-info`
3. [Actualizar Información del Repositorio](#actualizar-información-del-repositorio) - `PUT /ogrepository/v1/images`
4. [Eliminar una Imagen](#eliminar-una-imagen) - `DELETE /ogrepository/v1/images/{name}`
5. [Recuperar una Imagen](#recuperar-una-imagen) - `POST /ogrepository/v1/images/{name}`
4. [Eliminar una Imagen](#eliminar-una-imagen) - `DELETE /ogrepository/v1/images/delete-image`
5. [Recuperar una Imagen](#recuperar-una-imagen) - `POST /ogrepository/v1/images/recover-image`
6. [Importar una Imagen](#importar-una-imagen) - `POST /ogrepository/v1/images/import-image`
7. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/images/{protocol}`
8. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/images/{protocol}`
7. [Enviar una Imagen mediante UDPcast](#enviar-una-imagen-mediante-udpcast) - `POST /ogrepository/v1/images/send-udpcast`
8. [Enviar una Imagen mediante UFTP](#enviar-una-imagen-mediante-uftp) - `POST /ogrepository/v1/images/send-uftp`
9. [Crear archivo ".torrent"](#crear-archivo-torrent) - `POST /ogrepository/v1/images/create-torrent`
10. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/images/{protocol}`
10. [Enviar una Imagen mediante P2P](#enviar-una-imagen-mediante-p2p) - `POST /ogrepository/v1/images/send-p2p`
11. [Chequear integridad de Imagen](#chequear-integridad-de-imagen) - `GET /ogrepository/v1/images/check-image`
12. [Exportar una Imagen](#exportar-una-imagen) - `POST /ogrepository/v1/images/export-image`
13. [Definir Imagen Global](#definir-imagen-global) - `PUT /ogrepository/v1/images/set-global`
@ -95,16 +95,17 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (correspondiente a la imagen especificada).
Se debe crear un script que devuelva dicha información, porque actualmente no hay ninguno.
**URL:** `/ogrepository/v1/images/{name}`
**URL:** `/ogrepository/v1/images/get-info`
**Método HTTP:** GET
**Parámetros de la URL:**
- `{name}`: Nombre de la imagen.
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/images/Windows10
curl -X GET -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img","ou_subdir":"none"}' http://example.com/ogrepository/v1/images/get-info
```
**Respuestas:**
@ -156,17 +157,18 @@ curl -X PUT -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag
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.
**URL:** `/ogrepository/v1/images/{name}`
**URL:** `/ogrepository/v1/images/delete-image`
**Método HTTP:** DELETE
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
- **method**: Método de eliminación (puede ser "trash" o "permanent").
**Ejemplo de Solicitud:**
```bash
curl -X DELETE -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ou_subdir":"none", "method":"trash"}' http://example.com/ogrepository/v1/images/Windows10.img
curl -X DELETE -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none", "method":"trash"}' http://example.com/ogrepository/v1/images/delete-image
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al eliminar la imagen.
@ -179,16 +181,17 @@ curl -X DELETE -H "Authorization: $API_KEY" -H "Content-Type: application/json"
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.
**URL:** `/ogrepository/v1/images/{name}`
**URL:** `/ogrepository/v1/images/recover-image`
**Método HTTP:** POST
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"ou_subdir":"none"}' http://example.com/ogrepository/v1/images/Windows10.img
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/recover-image
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al recuperar la imagen.
@ -207,12 +210,13 @@ Se puede intentar hacer con el script "**importimage**", que actualmente no se u
**Cuerpo de la Solicitud (JSON):**
- **user**: Usuario con el que acceder al repositorio remoto (por defecto, usuario local).
- **repo**: IP o hostname del repositorio remoto.
- **image**: Nombre de la imagen a importar.
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"user":"user_name", "repo":"192.168.56.100", "image":"Windows10"}' http://example.com/ogrepository/v1/images/import-image
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"user":"user_name", "repo":"192.168.56.100", "image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/import-image
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al importar la imagen.
@ -225,14 +229,12 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
Se enviará una imagen por Multicast, mediante la aplicación UDPcast.
Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binario "**udp-sender**", que es quien realmente realiza el envío.
**URL:** `/ogrepository/v1/images/{protocol}`
**URL:** `/ogrepository/v1/images/send-udpcast`
**Método HTTP:** POST
**Parámetros de la URL:**
- `{protocol}`: Protocolo que se utilizará para enviar la imagen (en este caso, "udpcast").
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a enviar, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
- **port**: Puerto Multicast.
- **method**: Modalidad half-duplex o full-duplex.
- **ip**: IP Multicast.
@ -243,7 +245,7 @@ Se puede hacer con el script "**sendFileMcast.py**", que a su vez llama al binar
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/images/udpcast
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none", "port":"9000", "method":"full", "ip":"239.194.17.2", "bitrate":"70M", "nclients":"20", "maxtime":"120"}' http://example.com/ogrepository/v1/images/send-udpcast
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
@ -257,14 +259,12 @@ Se enviará una imagen por Unicast o Multicast, mediante el protocolo "UFTP".
Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente los clientes ogLive destino se pongan en escucha con un daemon "UFTPD" (ejecutando el script "**listenUFTPD.py**").
**NOTA**: Los envíos mediante "UFTP" funcionan al revés que los envíos mediante "UDPcast" (con este último, primero se debe ejecutar un comando en el servidor, y luego en los clientes).
**URL:** `/ogrepository/v1/images/{protocol}`
**URL:** `/ogrepository/v1/images/send-uftp`
**Método HTTP:** POST
**Parámetros de la URL:**
- `{protocol}`: Protocolo que se utilizará para enviar la imagen (en este caso, "uftp").
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a enviar, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
- **port**: Puerto Multicast.
- **ip**: IP Unicast/Multicast.
- **bitrate**: Velocidad de transmisión (con "K" para Kbps, "M" para Mbps o "G" para Gbps).
@ -272,7 +272,7 @@ Se puede hacer con el script "**sendFileUFTP.py**", que requiere que previamente
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/images/uftp
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none", "port":"9000", "ip":"239.194.17.2", "bitrate":"1G"}' http://example.com/ogrepository/v1/images/send-uftp
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
@ -290,12 +290,13 @@ Se debe crear un script que realice dicha tarea, porque actualmente se hace medi
**Método HTTP:** POST
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a la que asociar un archivo torrent.
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/create-torrent
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/create-torrent
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al crear el archivo torrent.
@ -308,19 +309,17 @@ curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d
Se debe hacer tracking de los torrents almacenados en ogRepository, e iniciar la transferencia de la imagen especificada (además, los clientes deben disponer del torrent asociado, y añadirlo a su cliente torrent).
No tengo claro cómo se haría con los scripts existentes (que utilizan "bttrack" y "ctorrent"), pero si usáramos "opentracker" y "transmission" (como se había propuesto), se debería crear nuevos scripts.
**URL:** `/ogrepository/v1/images/{protocol}`
**URL:** `/ogrepository/v1/images/send-p2p`
**Método HTTP:** POST
**Parámetros de la URL:**
- `{protocol}`: Protocolo que se utilizará para enviar la imagen (en este caso, "p2p").
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a enviar, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/p2p
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/send-p2p
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al enviar la imagen.
@ -337,12 +336,13 @@ Para esto, entiendo que se debe crear un script que compare el contenido de los
**Método HTTP:** GET
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a chequear, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/check-image
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/check-image
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al chequear la imagen.
@ -363,12 +363,13 @@ Se debe crear un script que realice dicha tarea (o se puede intentar utilizar el
**Cuerpo de la Solicitud (JSON):**
- **repo**: IP o hostname del repositorio remoto.
- **ou**: Unidad Organizativa del repositorio remoto.
- **image**: Nombre de la imagen a exportar.
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"repo":"192.168.56.200", "ou":"OU_Ejemplo", "image":"Windows10"}' http://example.com/ogrepository/v1/images/export-image
curl -X POST -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"repo":"192.168.56.200", "ou":"OU_Ejemplo", "image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/export-image
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al exportar la imagen.
@ -387,12 +388,13 @@ Además, deberá llamarse a un script que exporte dicha imagen a los demás repo
**Método HTTP:** PUT
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a definir como global, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/set-global
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/set-global
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al definir la imagen.
@ -411,12 +413,13 @@ Este endpoint deberá ser llamado en todos los repositorios gestionados por el m
**Método HTTP:** PUT
**Cuerpo de la Solicitud (JSON):**
- **image**: Nombre completo de la imagen a definir como local, con extensión (con o sin ruta).
- **image**: Nombre de la imagen (con extensión).
- **ou_subdir**: Subdirectorio correspondiente a la OU (o "none" si no es el caso).
**Ejemplo de Solicitud:**
```bash
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img"}' http://example.com/ogrepository/v1/images/set-local
curl -X PUT -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"Windows10.img", "ou_subdir":"none"}' http://example.com/ogrepository/v1/images/set-local
```
**Respuestas:**
- **Código 500 Internal Server Error:** Ocurrió un error al definir la imagen.

View File

@ -6,8 +6,7 @@ Este script actualiza la información de las imágenes del repositorio, reflejá
añadiendo información de las imágenes nuevas, y borrando la información de las imágenes que fueron eliminadas.
La información es obtenida desde archivos "<imagen_name>.info", que originalmente eran eliminados,
pero que en esta versión son renombrados a "<imagen_name>.info.checked", obteniendo la misma funcionalidad.
En principio, debería hacer lo mismo que el script bash original (cuyo nombre es "checkrepo"), salvo por el detalle que acabamos de comentar.
Al acabar, llama al script "updateTrashInfo.py", para actualizar también la información de la papelera del repositorio.
No recibe ningún parámetro, y debería ser llamado por el propio ogRepoitory cada vez que se elimine una imagen (desde el script "deleteImage.py"),
y por ogCore u ogLive cada vez que se cree una imagen.
@ -30,6 +29,8 @@ import shutil
repo_path = '/opt/opengnsys/images'
info_file = '/opt/opengnsys/etc/repoinfo.json'
#update_trash_script = '/opt/opengnsys/py_scripts/updateTrashInfo.py'
update_trash_script = '/home/administrador/updateTrashInfo.py'
# --------------------------------------------------------------------------------------------
@ -236,6 +237,21 @@ def remove_from_json():
def update_trash_info():
""" Actualiza la información de la papelera del repositorio, ejecutando el script "updateTrashInfo.py".
Como se ve, es necesario que el script se ejecute como sudo, o dará error.
"""
try:
result = subprocess.run(['sudo', 'python3', update_trash_script], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as error:
print(f"Error Output: {error.stderr.decode()}")
sys.exit(3)
except Exception as error:
print(f"Se ha producido un error inesperado: {error}")
sys.exit(4)
# --------------------------------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------------------------------
@ -272,6 +288,9 @@ def main():
print("Removing deleted images...")
remove_from_json()
# Actualizamos la información de la papelera, ejecutando el script "updateTrashInfo.py":
print("Updating Trash Info...")
update_trash_info()
# --------------------------------------------------------------------------------------------

View File

@ -0,0 +1,274 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Este script actualiza la información de las imágenes de la papelera del repositorio, reflejándola en el archivo "/opt/opengnsys/etc/trashinfo.json",
añadiendo información de las nuevas imágenes eliminadas, y borrando la información de las imágenes que fueron restauradas (o que ya no están en la papelera).
La información es obtenida desde archivos "<imagen_name>.info.checked", cuyo nombre original era "<imagen_name>.info"
(pero que fueron renombrados al ser insertada su información en el archivo ""/opt/opengnsys/etc/repoinfo.json", antes de ser eliminadas).
No recibe ningún parámetro, y no necesita ser llamado explícitamente (porque lo llama el script "updateRepoInfo.py")".
"""
# --------------------------------------------------------------------------------------------
# IMPORTS
# --------------------------------------------------------------------------------------------
import os
import json
import subprocess
import shutil
# --------------------------------------------------------------------------------------------
# VARIABLES
# --------------------------------------------------------------------------------------------
trash_path = '/opt/opengnsys/images_trash'
info_file = '/opt/opengnsys/etc/trashinfo.json'
# --------------------------------------------------------------------------------------------
# FUNCTIONS
# --------------------------------------------------------------------------------------------
def create_empty_json():
""" Esta función crea el archivo "trashinfo.json", con la estructura básica que debe contener.
Evidentemente, solo es llamada cuando no existe el archivo.
"""
# Creamos un diccionario con la estructura básica que debe tener el archivo json:
json_data = {"directory": trash_path, "images": [], "ous": []}
# Abrimos el archivo json en modo escritura (creándolo si no existe, como es el caso),
# y le añadimos la estructura almacenada en el diccionario "json_data":
with open(info_file, 'w') as file:
json.dump(json_data, file, indent=2)
def check_files():
""" Esta función recorre el directorio de imágenes, para buscar archivos con extensiones ".img" o ".dsk".
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
que además tengan un archivo ".info.checked" asociado (siempre que este no se haya modificado antes que la propia imagen).
"""
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images_trash",
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
for root, dirs, files in os.walk(trash_path):
for file in files:
# Si la imagen actual tiene extensión ".img" o ".dsk", construimos la ruta completa ("img_path"):
if file.endswith((".img", ".dsk")):
img_path = os.path.join(root, file)
# Si existe un archivo ".lock" asociado a la imagen actual, pasamos a la siguiente:
if os.path.exists(f"{img_path}.lock"):
continue
# Comprobamos si existe un archivo ".info.checked" asociado a la imagen actual:
info_file = f"{img_path}.info.checked"
if os.path.exists(info_file):
# Si la fecha de modificación del archivo ".info.checked" es anterior a la de la imagen, lo eliminamos (porque estará desactualizado):
if os.path.getmtime(info_file) < os.path.getmtime(img_path):
os.remove(info_file)
print(f"Warning: Deleted outdated file {info_file}")
# En caso contrario, almacenamos el contenido del archivo ".info.checked" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en la variable "data":
else:
with open(info_file, 'r') as file:
data = file.read()
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
# (pasándole el nombre de la imagen, la extensión, y los datos extraídos del archivo ".info.checked"):
img_name = os.path.relpath(img_path, trash_path)
add_to_json(os.path.splitext(img_name)[0], os.path.splitext(img_name)[1][1:], data)
def check_dirs():
""" Esta función recorre el directorio de imágenes, para buscar archivos con nombre "ogimg.info".
Llama a la función "add_to_json" para que esta añada información de las imágenes no bloqueadas (sin archivo ".lock"),
que además tengan un archivo "ogimg.info" asociado (pero no que tipo de imágenes son esas).
"""
# Iteramos recursivamente todos los archivos y directorios de "/opt/opengnsys/images_trash",
# y luego iteramos todos los archivos encontrados (en una iteración anidada):
for root, dirs, files in os.walk(trash_path):
for file in files:
# Si el nombre del archivo actual es "ogimg.info", construimos su ruta completa ("info_path"), y la ruta del directorio ("img_path"):
if file == "ogimg.info":
info_path = os.path.join(root, file)
img_path = os.path.dirname(info_path)
# Si existe un archivo ".lock" asociado a la imagen actual, o si la ruta coincide con "trash_path", pasamos a la siguiente:
if img_path == trash_path or os.path.exists(f"{img_path}.lock"):
continue
# Almacenamos el contenido del archivo "ogimg.info", en la variable "lines":
with open(info_path, 'r') as file:
lines = file.readlines()
# Iteramos las lineas obtenidas, para extraer el tipo de sistema de archivos ("fstype") y el tamaño de los datos ("sizedata"),
# y con ello construimos una cadena "rsync::{fstype}:{sizedata}:" (que almacenamos en "data"):
for line in lines:
if line.startswith("# fstype"):
fstype = line.split("=")[1].strip()
elif line.startswith("# sizedata"):
sizedata = line.split("=")[1].strip()
data = f"rsync::{fstype}:{sizedata}:"
# Llamamos a la función "add_to_json", para que inserte la información de la imagen en el archivo json
# (pasándole el nombre de la imagen, el tipo "dir"", y los datos extraídos del archivo "ogimg.info"):
img_name = os.path.relpath(img_path, trash_path)
add_to_json(img_name, "dir", data)
def add_to_json(image_name, image_type, data):
""" Esta función añade al archivo "trashinfo.json" la información de las imágenes que aun no ha sido introducida en él (imágenes eliminadas recientemente, básicamente).
El procedimiento es diferente para las imágenes "normales" y para las imágenes basadas en OU.
"""
# Almacenamos el contenido de la variable "data" (del tipo "PARTCLONE:LZOP:EXTFS:8500000:Ubuntu_20") en variables separadas:
clonator, compressor, fstype, datasize, client = data.split(":")
# Si la imagen está dentro de una OU (directorio), extraemos el nombre de la OU y de la imagen:
ou_name = None
if '/' in image_name:
ou_name = os.path.dirname(image_name)
image_name = os.path.basename(image_name)
# Creamos un diccionario con los datos de la imagen, que luego insertaremos en el json:
json_data = {
"name": image_name,
"type": image_type.lower(),
"clientname": client.strip('\n'), # Eliminamos el salto de linea
"clonator": clonator.lower(),
"compressor": compressor.lower(),
"filesystem": fstype.upper(),
"datasize": int(datasize) * 1024 # Convertimos el valor a bytes (desde KB)
}
# Almacenamos el contenido del archivo "trashinfo.json" en la variable "info_data":
with open(info_file, 'r') as file:
info_data = json.load(file)
# Comprobamos si las claves "info_data" (o sea, del archivo json) son las correctas:
if set(info_data.keys()) == {"directory", "images", "ous"}:
# Actualizamos la información de las imágenes "normales" (no basadas en OU):
if ou_name is None:
img_index = next((i for i, img in enumerate(info_data["images"]) if img["name"] == image_name), None)
if img_index is not None:
# Update if image data changes
if info_data["images"][img_index] != json_data:
info_data["images"][img_index] = json_data
else:
# Append a new entry
info_data["images"].append(json_data)
# Actualizamos la información de las imágenes basadas en OU:
else:
ou_index = next((i for i, ou in enumerate(info_data["ous"]) if ou["subdir"] == ou_name), None)
if ou_index is None:
# Append a new OU entry
info_data["ous"].append({"subdir": ou_name, "images": [json_data]})
else:
img_index = next((i for i, img in enumerate(info_data["ous"][ou_index]["images"]) if img["name"] == image_name), None)
if img_index is not None:
# Update if image data changes
if info_data["ous"][ou_index]["images"][img_index] != json_data:
info_data["ous"][ou_index]["images"][img_index] = json_data
else:
# Append a new entry
info_data["ous"][ou_index]["images"].append(json_data)
# Si las claves de "info_data" no son las correctas, creamos toda la estructura:
else:
if ou_name is None:
info_data = {"directory": trash_path, "images": [json_data], "ous": []}
else:
info_data = {"directory": trash_path, "images": [], "ous": [{"subdir": ou_name, "images": [json_data]}]}
# Sobreescribimos el archivo "trashinfo.json", con el contenido de "info_data" (que estará actualizado):
with open(info_file, 'w') as file:
json.dump(info_data, file, indent=2)
def remove_from_json():
""" Esta función carga el contenido del archivo "trashinfo.json", y comprueba la existencia de las imágenes especificadas allí.
Elimina las claves correspondientes a imágenes inexistentes en la papelera, y posteriormente sobreescribe el archivo "trashinfo.json".
"""
# Almacenamos el contenido del archivo "trashinfo.json", en la variable "json_data":
with open(info_file, 'r') as file:
json_data = json.load(file)
# Iteramos las imágenes de la clave "images" de "json_data", construimos sus rutas y comprobamos su existencia
# (si no existen, las eliminamos de "json_data"):
for i, image in enumerate(json_data.get("images", [])):
img_name = image["name"]
img_type = image["type"]
if img_type != "dir":
img_name = f"{img_name}.{img_type}"
img_path = os.path.join(trash_path, img_name)
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
json_data["images"].pop(i)
# Iteramos las imágenes de la clave "ous" de "json_data", construimos sus rutas y comprobamos su existencia
# (si no existen, las eliminamos de "json_data"):
for j, ou in enumerate(json_data.get("ous", [])):
ou_name = ou["subdir"]
ou_path = os.path.join(trash_path, ou_name)
if not os.path.exists(ou_path):
json_data["ous"].pop(j)
else:
for i, image in enumerate(ou.get("images", [])):
img_name = image["name"]
img_type = image["type"]
if img_type != "dir":
img_name = f"{img_name}.{img_type}"
img_path = os.path.join(ou_path, img_name)
if not os.path.exists(img_path) and not os.path.exists(f"{img_path}.lock"):
ou["images"].pop(i)
# Sobreescribimos el archivo "trashinfo.json", con el contenido de "json_data"
# (una vez eliminadas las imágenes inexistentes):
with open(info_file, 'w') as file:
json.dump(json_data, file, indent=2)
# --------------------------------------------------------------------------------------------
# MAIN
# --------------------------------------------------------------------------------------------
def main():
"""
"""
# Comprobamos si tenemos permisos de escritura sobre el directorio que contiene el archivo "trashinfo.json"
# ("/opt/opengnsys/etc"), y en caso contrario lanzamos una excepción:
if not os.access(os.path.dirname(info_file), os.W_OK):
raise PermissionError(f"Cannot access {info_file}")
# Comprobamos si existe el archivo "trashinfo.json", y en caso contrario lo creamos:
if not os.path.exists(info_file):
print("Creating empty json file...")
create_empty_json()
# Comprobamos si tenemos permisos de escritura sobre el archivo, y en caso contrario lanzamos un error:
if not os.access(info_file, os.W_OK):
raise PermissionError(f"Cannot access {info_file}")
# Llamamos a la función "check_files", para añadir al archivo json las imágenes ".img" o ".dsk" aun no añadidas
# (que son las que tienen asociado un archivo ".info.checked"):
print("Checking file images...")
check_files()
# Llamamos a la función "check_dirs", para añadir al archivo json las imágenes aun no añadidas que tienen asociado un archivo "ogimg.info"
# (no sé qué imágenes son estas, pero de alguna forma están basadas en directorios):
print("Checking dir images...")
check_dirs()
# Llamamos a la función "remove_from_json", para eliminar del archivo json las imágenes que ya no están en la papelera:
print("Removing inexistent images...")
remove_from_json()
# --------------------------------------------------------------------------------------------
if __name__ == "__main__":
main()
# --------------------------------------------------------------------------------------------