#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Este script convierte la imagen de OpengGnsys especificada como primer parámetro en una imagen virtual con la extensión especificada como segundo parámetro ("vdi", "vmdk", etc). La imagen virtual se exporta a la ruta "/opt/opengnsys/ogrepository/images_virtual/export/", desde donde puede ser descargada para importarla en VirtualBox, VMware, etc. Paquetes APT requeridos: "qemu" (se puede instalar con "sudo apt install qemu-utils"). "partclone" (se puede instalar con "sudo apt install partclone"). "lzop" (se puede instalar con "sudo apt install lzop"). Parámetros ------------ sys.argv[1] - Nombre completo de la imagen a convertir (sin ruta). - Ejemplo1: Ubuntu.img - Ejemplo2: Windows.img sys.argv[2] - Extensión del disco virtual destino (sin punto). - Ejemplo1: vdi - Ejemplo2: vmdk Sintaxis ---------- ./comvertIMGtoVM.py image_name virtual_extension Ejemplos --------- ./comvertIMGtoVM.py Ubuntu.img vdi ./comvertIMGtoVM.py Windows.img vmdk """ # -------------------------------------------------------------------------------------------- # IMPORTS # -------------------------------------------------------------------------------------------- import sys import os import pwd import grp import subprocess from systemd import journal # -------------------------------------------------------------------------------------------- # VARIABLES # -------------------------------------------------------------------------------------------- script_name = os.path.basename(__file__) repo_path = '/opt/opengnsys/ogrepository/images/' # No borrar la barra final vm_export_path = '/opt/opengnsys/ogrepository/images_virtual/export/' # No borrar la barra final partclone_logfile = '/opt/opengnsys/ogrepository/log/partclone.log' raw_img = '/opt/opengnsys/ogrepository/images_virtual/export/disk.raw' mount_point = "/mnt/recovery" # -------------------------------------------------------------------------------------------- # 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 virtual_extension Ejemplo1: {script_name} Ubuntu.img vdi Ejemplo2: {script_name} Windows.img vmdk """ 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 el script con más o menos de 2 parámetroa, se muestra un error y la ayuda, y se sale del script: elif len(sys.argv) != 3: print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros") show_help() sys.exit(1) def create_export_folder(): """ Crea el directorio '/opt/opengnsys/ogrepository/images_virtual/export/', y le asigna propietarios y permisos. Evidentemente, esta función solo es llamada cuando no existe el directorio. """ # Obtenemos el UID del usuario "opengnsys" y el GID del grupo "opengnsys": uid = pwd.getpwnam('opengnsys').pw_uid gid = grp.getgrnam('opengnsys').gr_gid # Creamos el directorio '/opt/opengnsys/ogrepository/images_virtual/export/': os.mkdir(vm_export_path) # Asignamos el usuario y el grupo propietarios del directorio: os.chown(vm_export_path, uid, gid) # Asignamos permisos "755" al directorio : os.chmod(vm_export_path, 0o755) def create_raw_disk(raw_size): """ Crea un disco "RAW", sobre el que luego se creará una tabla de particiones, mediante "qemu-img create". Si se ejecuta correctamente retorna "True", y si da error retorna "False". """ try: journal.send("convertIMGtoVM.py: Running command 'qemu-img create'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['qemu-img', 'create', '-f', 'raw', raw_img, raw_size], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'qemu-img create' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'qemu-img create' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def create_partition_table(partition_size): """ Crea una tabla de particiones en el disco "RAW", mediante "fdisk". Si se ejecuta correctamente retorna "True", y si da error retorna "False". """ try: journal.send("convertIMGtoVM.py: Running command 'fdisk'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Construimos el parámetro "input", que debe codificarse en bytes (con "encode"): input_data = f"o\nn\np\n1\n\n+{partition_size}\nw".encode() result = subprocess.run(['fdisk', raw_img], input=input_data, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'fdisk' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'fdisk' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def associate_loop_device(): """ Asocia el disco "RAW" a un dispositivo loopback, mediante "losetup". Si se ejecuta correctamente retorna "True", el dispositivo loopback y la partición de destino, y si da error retorna "False", "None" y "None". """ try: journal.send("convertIMGtoVM.py: Running command 'losetup'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['losetup', '-P', '--find', '--show', raw_img], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='UTF8') # Si el resultado de la ejecución es correcto, obtenemos el dispositivo loopback y la partición de destino, y los retornamos: if result.returncode == 0: # Obtenemos la partición de destino, y la imprimimos en el log, junto con el dispositivo loopback: loop_device = result.stdout.strip() dest_partition = f"{loop_device}p1" journal.send(f"convertIMGtoVM.py: Loopback device obtained: {loop_device}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") journal.send(f"convertIMGtoVM.py: Destination partition obtained: {dest_partition}", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return True, loop_device, dest_partition else: return False, None, None # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False", "None" y "None" (entrará aquí si el return code no es "0"): except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'losetup' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False, None, None except Exception as error: journal.send(f"convertIMGtoVM.py: 'losetup' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False, None, None def decompress_image(image_name_full): """ Descomprime la imagen "IMG" origen, con "lzop". Si se ejecuta correctamente retorna "True", y si da error retorna "False". """ try: journal.send("convertIMGtoVM.py: Running command 'lzop'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['lzop', '-d', f"{repo_path}{image_name_full}", '-o', f"{vm_export_path}{image_name_full}"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'lzop' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'lzop' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def restore_image(image_name_full, dest_partition): """ Restaura la imagen descomprimida en la partición de destino (que hemos obtenido con "losetup"). Si se ejecuta correctamente retorna "True", y si da error retorna "False". """ try: journal.send("convertIMGtoVM.py: Running command 'partclone.restore'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['partclone.restore', '-s', f"{vm_export_path}{image_name_full}", '-o', dest_partition, '-L', partclone_logfile], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'partclone.restore' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'partclone.restore' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def mount_partition(dest_partition): """ Crea un directorio de montaje, y monta allí la partición de destino (que hemos obtenido con "losetup"). Si se ejecuta correctamente retorna "True", y si da error retorna "False". NOTA: Los comandos "mkdir" y "mount" deben ejecutarse con "sudo", o darán error. """ try: # Creamos el directorio de montaje: subprocess.run(['sudo', 'mkdir', '-p', mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except Exception as error: journal.send(f"convertIMGtoVM.py: 'mkdir' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False try: # Montamos la partición en el directorio de montaje: journal.send("convertIMGtoVM.py: Running command 'mount'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['sudo', 'mount', dest_partition, mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'mount' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'mount' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def install_grub(loop_device): """ Instala GRUB en el dispositivo loopback. Si se ejecuta correctamente retorna "True", y si da error retorna "False". NOTA: Los comandos deben ejecutarse con "sudo", o darán error. """ try: journal.send("convertIMGtoVM.py: Installing GRUB...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Ejecutamos los comandos necesarios para instalar GRUB: subprocess.run(['sudo', 'mount', '--bind', '/dev', f"{mount_point}/dev"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'mount', '--bind', '/proc', f"{mount_point}/proc"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'mount', '--bind', '/sys', f"{mount_point}/sys"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'chroot', mount_point, 'grub-install', '--target=i386-pc', loop_device], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'chroot', mount_point, 'grub-mkconfig', '-o', '/boot/grub/grub.cfg'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Como no ha habido errores, retornamos "True": return True # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: GRUB install error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: GRUB install exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def umount_partitions(loop_device): """ Desmonta todas las particiones montadas previamente, con "umount" y "losetup". No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen. NOTA: Los comandos deben ejecutarse con "sudo", o darán error. """ try: journal.send("convertIMGtoVM.py: Umounting partitions...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Desmontamos las particiones, con "umount" y "losetup": subprocess.run(['sudo', 'umount', f"{mount_point}/dev"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'umount', f"{mount_point}/proc"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'umount', f"{mount_point}/sys"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'umount', '-l', mount_point], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) subprocess.run(['sudo', 'losetup', '-d', loop_device], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Como no ha habido errores, imprimimos un mensaje en el log: journal.send("convertIMGtoVM.py: Umount partitions OK", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Si se produce un error o una excepción lo imprimimos en el log: except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'umount' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") except Exception as error: journal.send(f"convertIMGtoVM.py: 'umount' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") def convert_image(image_name, vm_extension): """ Convierte el disco "RAW" en un disco virtual, con la extensión especificada como parámetro. Si se ejecuta correctamente retorna "True", y si da error retorna "False". """ try: journal.send("convertIMGtoVM.py: Running command 'qemu-img convert'...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") result = subprocess.run(['qemu-img', 'convert', '-f', 'raw', '-O', vm_extension, raw_img, f"{vm_export_path}{image_name}.{vm_extension}"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Evaluamos el resultado de la ejecución, retornando "True" si es correcta y "False" si no lo es: if result.returncode == 0: return True else: return False # Si se produce un error o una excepción lo imprimimos en el log, y retornamos "False": except subprocess.CalledProcessError as error: journal.send(f"convertIMGtoVM.py: 'qemu-img convert' error: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False except Exception as error: journal.send(f"convertIMGtoVM.py: 'qemu-img convert' exception: {error}", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") return False def erase_image_file(file2del): """ Borra el archivo correspondiente a la ruta "file2del". No retorna "True" o "False", porque este paso no afecta a la conversión de la imagen. """ journal.send(f"convertIMGtoVM.py: Erasing file {file2del}...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Si existe el archivo "file2del", lo borramos: if os.path.exists(file2del): os.remove(file2del) # -------------------------------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------------------------------- def main(): """ """ # Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto: check_params() # Almacenamos el nombre completo de la imagen y la extensión del disco virtual de destino (desde los parámetros), y extraemos el nombre sin extensión: image_name_full = sys.argv[1] image_name = image_name_full.split('.')[0] vm_extension = sys.argv[2].lower() # Obtenemos el tamaño de la imagen, y calculamos el tamaño a asignar al disco "RAW" y a la partición: image_size = os.path.getsize(f"{repo_path}{image_name_full}") raw_size = image_size * 6.5 # El disco "RAW" debe ser "6,5" veces más grande que la imagen partition_size = (90 * raw_size) / 100 # La partición debe tener el 90% del tamaño del disco "RAW" # Si no existe el directorio '/opt/opengnsys/ogrepository/images_virtual/export/', lo creamos: if not os.path.exists(vm_export_path): journal.send("convertIMGtoVM.py: Creating export folder...", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") create_export_folder() # Creamos el disco "RAW" (con "qemu-img create"): create_raw = create_raw_disk(f"{raw_size / 1024 / 1024 / 1024}G") if create_raw == False: journal.send("convertIMGtoVM.py: RAW disk creation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" sys.exit(2) else: journal.send("convertIMGtoVM.py: RAW disk creation OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Creamos una tabla de particiones en el disco "RAW" (con "fdisk"): create_table = create_partition_table(f"{int(partition_size / 1024 / 1024 / 1024)}G") if create_table == False: journal.send("convertIMGtoVM.py: Partition table creation failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" sys.exit(3) else: journal.send("convertIMGtoVM.py: Partition table creation OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Asociamos el disco "RAW" a un dispositivo loopback, y almacenamos este y la partición de destino assoc_loop_result, loop_device, dest_partition = associate_loop_device() if assoc_loop_result == False: journal.send("convertIMGtoVM.py: Loop device association failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" sys.exit(4) else: journal.send("convertIMGtoVM.py: Loop device association OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Descomprimimos la imagen original (con "lzop"): image_decompressed = decompress_image(image_name_full) if image_decompressed == False: journal.send("convertIMGtoVM.py: Image decompression failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" erase_image_file(f"{vm_export_path}{image_name_full}") # Como ha fallado, borramos la imagen descomprimida sys.exit(5) else: journal.send("convertIMGtoVM.py: Image decompression OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Restauramos la imagen descomprimida en la partición de destino (con "partclone.restore"): image_restored = restore_image(image_name_full, dest_partition) if image_restored == False: journal.send("convertIMGtoVM.py: Image restoration failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" erase_image_file(f"{vm_export_path}{image_name_full}") # Como ha fallado, borramos la imagen descomprimida sys.exit(6) else: journal.send("convertIMGtoVM.py: Image restoration OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(f"{vm_export_path}{image_name_full}") # Si ha ido OK también borramos la imagen descomprimida, porque ya no la necesitamos. # Montamos la partición de destino (con "mount"): partition_mounted = mount_partition(dest_partition) if partition_mounted == False: journal.send("convertIMGtoVM.py: Partition mount failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" sys.exit(7) else: journal.send("convertIMGtoVM.py: Partition mount OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Instalamos GRUB en el dispositivo loopback (con "mount" y "chroot"): grub_installed = install_grub(loop_device) if grub_installed == False: journal.send("convertIMGtoVM.py: GRUB install failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") umount_partitions(loop_device) # Como ha fallado, desmontamos todas las particiones erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" sys.exit(8) else: journal.send("convertIMGtoVM.py: GRUB install OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # Desmontamos las particiones montadas previamente (con "umount" y "losetup"): umount_partitions(loop_device) # Convertimos el disco "RAW" en un disco virtual (con "qemu-img convert"): image_conversion = convert_image(image_name, vm_extension) if image_conversion == False: journal.send("convertIMGtoVM.py: Image conversion failed", PRIORITY=journal.LOG_ERR, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") erase_image_file(raw_img) # Como ha fallado, borramos el disco "RAW" erase_image_file(f"{vm_export_path}{image_name}.{vm_extension}") # Como ha fallado, borramos la imagen virtual (por si ha creado algo) sys.exit(9) else: erase_image_file(raw_img) # Si ha funcionado OK, también borramos el disco "RAW" journal.send("convertIMGtoVM.py: Image conversion OK (ReturnCode: 0)", PRIORITY=journal.LOG_INFO, SYSLOG_IDENTIFIER="ogrepo-api_DEBUG") # -------------------------------------------------------------------------------------------- if __name__ == "__main__": main() # --------------------------------------------------------------------------------------------