#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Este script recupera la imagen que recibe como parámetro (y todos sus archivos asociados), moviendo los archivos a "/opt/opengnsys/ogrepository/images", desde la papelera (respetando el subdirectorio correspondiente a la OU, si fuera el caso). Llama al script "updateRepoInfo.py", para actualizar la información del repositorio. Parámetros ------------ sys.argv[1] - Nombre completo de la imagen a recuperar (con o sin ruta), pero incluyendo el subdirectorio correspondiente a la OU, si es el caso. - Ejemplo1: image1.img - Ejemplo2: /opt/opengnsys/ogrepository/images_trash/image1.img - Ejemplo3: ou_subdir/image1.img - Ejemplo4: /ou_subdir/image1.img - Ejemplo5: /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img Sintaxis ---------- ./recoverImage.py [ou_subdir/]image_name|/image_path/image_name Ejemplos --------- ./recoverImage.py image1.img ./recoverImage.py /opt/opengnsys/ogrepository/images_trash/image1.img ./recoverImage.py ou_subdir/image1.img ./recoverImage.py /ou_subdir/image1.img ./recoverImage.py /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img """ # -------------------------------------------------------------------------------------------- # IMPORTS # -------------------------------------------------------------------------------------------- import os import sys import shutil import subprocess # -------------------------------------------------------------------------------------------- # VARIABLES # -------------------------------------------------------------------------------------------- script_name = os.path.basename(__file__) repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final trash_path = '/opt/opengnsys/ogrepository/images_trash/' # No borrar la barra final update_repo_script = '/opt/opengnsys/ogrepository/bin/updateRepoInfo.py' # -------------------------------------------------------------------------------------------- # FUNCTIONS # -------------------------------------------------------------------------------------------- def show_help(): """ Imprime la ayuda, cuando se ejecuta el script con el parámetro "help". """ help_text = f""" Sintaxis: {script_name} [ou_subdir/]image_name|/image_path/image_name Ejemplo1: {script_name} image1.img Ejemplo2: {script_name} /opt/opengnsys/ogrepository/images_trash/image1.img Ejemplo3: {script_name} ou_subdir/image1.img Ejemplo4: {script_name} /ou_subdir/image1.img Ejemplo5: {script_name} /opt/opengnsys/ogrepository/images_trash/ou_subdir/image1.img """ 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 sin parámetros, se muestra un error y la ayuda, y se sale del script: if len(sys.argv) == 1: print(f"{script_name} Error: Formato incorrecto: Se debe especificar al menos 1 parámetro") show_help() sys.exit(0) # Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script: elif len(sys.argv) == 2 and sys.argv[1] == "help": show_help() sys.exit(1) # Si se ejecuta el script con más de 1 parámetro, se muestra un error y la ayuda, y se sale del script: elif len(sys.argv) > 2: print(f"{script_name} Error: Formato incorrecto: Se debe especificar 1 parámetro") show_help() sys.exit(2) def build_file_path(): """ Construye la ruta completa al archivo a recuperar (agregando "/opt/opengnsys/images_trash/" si no se ha especificado en el parámetro). """ param_path = sys.argv[1] # Si la ruta comienza con una barra, pero que no corresponde a "trash_path" # (porque corresponderá al subdirectorio de una OU), eliminamos la barra: if param_path.startswith('/') and not param_path.startswith(trash_path): param_path = param_path.lstrip('/') # Construimos la ruta completa: if not param_path.startswith(trash_path): file_path = os.path.join(trash_path, param_path) else: file_path = param_path return file_path def recover_normal_image(file_path, extensions): """ Recupera la imagen "normal" que recibe en el parámetro "file_path", y todos sus archivos asociados, moviéndolos a "/opt/opengnsys/images" (desde la papelera). """ # Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos: for ext in extensions: file_to_recover = f"{file_path}{ext}" # Si el archivo actual existe, lo movemos a "/opt/opengnsys/images" (recuperándolo desde la papelera): if os.path.exists(file_to_recover): # Si la extensión del archivo actual es ".info.checked" la renombramos a ".info" (para que lo pille "updateRepoInfo"): if ext == '.info.checked': os.rename(file_to_recover, file_to_recover.strip('.checked')) file_to_recover = file_to_recover.strip('.checked') shutil.move(file_to_recover, repo_path) def recover_ou_image(file_path, extensions): """ Recupera la imagen basada en OU que recibe en el parámetro "file_path", y todos sus archivos asociados, moviéndolos a "/opt/opengnsys/images" (desde la papelera), respetando el subdirectorio correspondiente a la OU. """ # Iteramos las extensiones de los archivos, y construimos la ruta completa de cada uno de ellos: for ext in extensions: file_to_recover = f"{file_path}{ext}" # Si el archivo actual existe, lo movemos a "/opt/opengnsys/images/ou_subdir": if os.path.exists(file_to_recover): # Si la extensión del archivo actual es ".info.checked" la renombramos a ".info" (para que lo pille "updateRepoInfo"): if ext == '.info.checked': os.rename(file_to_recover, file_to_recover.strip('.checked')) file_to_recover = file_to_recover.strip('.checked') ou_subdir = file_to_recover.split('/')[4] # Comprobamos si en "repo_path" existe un subdirectorio correspondiente a la OU (y si no existe lo creamos): if not os.path.exists(f"{repo_path}{ou_subdir}"): os.mkdir(f"{repo_path}{ou_subdir}") shutil.move(file_to_recover, f"{repo_path}{ou_subdir}") def update_repo_info(): """ Actualiza la información del repositorio, ejecutando el script "updateRepoInfo.py". Como se ve, es necesario que el script se ejecute como sudo, o dará error. """ try: result = subprocess.run(['sudo', 'python3', update_repo_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 # -------------------------------------------------------------------------------------------- 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 eliminar: file_path = build_file_path() # Creamos una lista con las extensiones de los archivos asociados a la imagen # (incluyendo ninguna extensión, que corresponde a la propia imagen): extensions = ['', '.size', '.sum', '.full.sum', '.torrent', '.info', '.info.checked'] # Evaluamos la cantidad de barras que hay en la ruta de la imagen, para diferenciar entre imágenes "normales" y basadas en OU # (y llamamos a la función correspondiente para recuperarla): if file_path.count('/') == 5: print("Recovering normal image...") recover_normal_image(file_path, extensions) elif file_path.count('/') == 6: print("Recovering OU based image...") recover_ou_image(file_path, extensions) # Actualizamos la información del repositorio, ejecutando el script "updateRepoInfo.py": print("Updating Repository Info...") update_repo_info() # -------------------------------------------------------------------------------------------- if __name__ == "__main__": main() # --------------------------------------------------------------------------------------------