diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 55f25e2..dd0c04c 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -1,3 +1,12 @@ +#/** +#@file Disk.lib +#@brief Librería o clase Disk +#@class Disk +#@brief Funciones para gestión de discos y particiones. +#@version 1.1.1 +#@warning License: GNU GPLv3+ +#*/ + import filecmp import subprocess import shutil @@ -10,6 +19,7 @@ import SystemLib import CacheLib import FileSystemLib +# Función ficticia para lanzar parted con timeout, evitando cuelgues del programa. def parted(*args): parted_path = shutil.which("parted") if parted_path: @@ -26,6 +36,23 @@ def parted(*args): else: return "Error: 'parted' command not found" + +#/** +# ogCreatePartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco. +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de cache y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#*/ ## def ogCreatePartitions(*args): # Variables locales ND = DISK = PTTYPE = PART = SECTORS = START = SIZE = TYPE = CACHEPART = None @@ -123,6 +150,23 @@ def ogCreatePartitions(*args): CacheLib.ogMountCache() return 0 + +#/** +# ogCreateGptPartitions int_ndisk str_parttype:int_partsize ... +#@brief Define el conjunto de particiones de un disco GPT +#@param int_ndisk nº de orden del disco +#@param str_parttype mnemónico del tipo de partición +#@param int_partsize tamaño de la partición (en KB) +#@return (nada, por determinar) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o partición no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION error en partición o en tabla de particiones. +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Pueden definirse particiones vacías de tipo \c EMPTY +#@attention No puede definirse partición de caché y no se modifica si existe. +#@note Requisitos: sfdisk, parted, partprobe, awk +#@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. +#*/ ## def ogCreateGptPartitions(*args): # Variables locales ND = DISK = PART = SECTORS = ALIGN = START = SIZE = TYPE = CACHEPART = CACHESIZE = DELOPTIONS = OPTIONS = None @@ -214,6 +258,18 @@ def ogCreateGptPartitions(*args): CacheLib.ogMountCache() return 0 + +#/** +# ogCreatePartitionTable int_ndisk [str_tabletype] +#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada. +#@param int_ndisk nº de orden del disco +#@param str_tabletype tipo de tabla de particiones (opcional) +#@return (por determinar) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note tabletype: { MSDOS, GPT }, MSDOS por defecto +#@note Requisitos: fdisk, gdisk, parted +#*/ ## def ogCreatePartitionTable(*args): # Variables locales DISK = PTTYPE = CREATE = CREATEPTT = None @@ -281,6 +337,13 @@ def ogCreatePartitionTable(*args): subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) return + +#/** +# ogDeletePartitionTable ndisk +#@brief Borra la tabla de particiones del disco. +#@param int_ndisk nº de orden del disco +#@return la informacion propia del fdisk +#*/ ## def ogDeletePartitionTable(*args): # Variables locales DISK = None @@ -546,6 +609,16 @@ def ogDiskToDev (arg_disk=None, arg_part=None): return part + +#/** +# ogGetDiskSize int_ndisk +#@brief Muestra el tamaño en KB de un disco. +#@param int_ndisk nº de orden del disco +#@return int_size - Tamaño en KB del disco. +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#*/ ## def ogGetDiskSize(*args): # Variables locales DISK = SIZE = None @@ -571,6 +644,15 @@ def ogGetDiskSize(*args): print(SIZE) return + +#/** +# ogGetDiskType path_device +#@brief Muestra el tipo de disco (real, RAID, meta-disco, USB, etc.). +#@param path_device Dispositivo +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco no detectado o no es un dispositivo de bloques. +#@note Requisitos: udevadm +#*/ ## def ogGetDiskType(*args): # Variables locales DEV = MAJOR = TYPE = None @@ -629,6 +711,17 @@ def ogGetEsp(): return PART return None + +#/** +# ogGetLastSector int_ndisk [int_npart] +#@brief Devuelve el último sector usable del disco o de una partición. +#@param int_ndisk nº de orden del disco +#@param int_npart nº de orden de la partición (opcional) +#@return Último sector usable. +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponde con un dispositivo. +#@note Requisitos: sfdisk, sgdisk +#*/ ## def ogGetLastSector(*args): # Variables locales DISK = None @@ -663,27 +756,39 @@ def ogGetLastSector(*args): print(LASTSECTOR) return -def ogGetPartitionActive(*args): - # Variables locales - DISK = None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', 'ogGetPartitionActive 1 => 1') - return +#/** +# ogGetPartitionActive int_ndisk +#@brief Muestra que particion de un disco esta marcada como de activa. +#@param int_ndisk nº de orden del disco +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note Requisitos: parted +#@todo Queda definir formato para atributos (arranque, oculta, ...). +#*/ ## +def ogGetPartitionActive (disk): + DISK = ogDiskToDev (disk) + if DISK is None: return - # Error si no se recibe 1 parámetro. - if len(args) != 1: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + if 'LANG' in os.environ: + lang = os.environ['LANG'] - # Comprobar que el disco existe y listar su partición activa. - DISK = ogDiskToDev(args[0]) - if DISK is None: - return - output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: '$7~/boot/ {{print $1}}'") - print(output) - return + ret = None + os.environ['LANG'] = 'C' + lines = subprocess.run (['parted', '--script', '--machine', DISK, 'print'], capture_output=True, text=True).stdout.splitlines() + for line in lines: + parts = line.split (':') + if len (parts) < 6: continue + if 'boot' in parts[6]: + ret = parts[0] + break + + if lang is None: + del os.environ['LANG'] + else: + os.environ['LAMG'] = lang + + return ret #/** @@ -743,6 +848,16 @@ def ogGetPartitionSize (disk, par): return FileSystemLib.ogGetFsSize (disk, par) + +#/** +# ogGetPartitionsNumber int_ndisk +#@brief Detecta el numero de particiones del disco duro indicado. +#@param int_ndisk nº de orden del disco +#@return Devuelve el numero paritiones del disco duro indicado +#@warning Salidas de errores no determinada +#@attention Requisitos: parted +#@note Notas sin especificar +#*/ ## def ogGetPartitionsNumber(*args): # Variables locales DISK = None @@ -845,6 +960,17 @@ def ogGetPartitionType(*args): print(TYPE) return + +#/** +# ogHidePartition int_ndisk int_npartition +#@brief Oculta un apartición visible. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@exception OG_ERR_PARTITION tipo de partición no reconocido. +#*/ ## def ogHidePartition(*args): # Variables locales PART = None @@ -886,6 +1012,14 @@ def ogHidePartition(*args): ogSetPartitionType(args[0], args[1], NEWTYPE) return + +#/** +# ogIdToType int_idpart +#@brief Devuelve el identificador correspondiente a un tipo de partición. +#@param int_idpart identificador de tipo de partición. +#@return str_parttype mnemónico de tipo de partición. +#@exception OG_ERR_FORMAT Formato incorrecto. +#*/ ## def ogIdToType(ID): # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante. ID = ID.zfill(4) @@ -985,6 +1119,13 @@ def ogIdToType(ID): return TYPE + +# ogIsDiskLocked int_ndisk +#@brief Comprueba si un disco está bloqueado por una operación de uso exclusivo. +#@param int_ndisk nº de orden del disco +#@return Código de salida: 0 - bloqueado, 1 - sin bloquear o error. +#@note Los ficheros de bloqueo se localizan en \c /var/lock/dev, siendo \c dev el dispositivo de la partición o de su disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogIsDiskLocked(*args): # Variables locales DISK = None @@ -1006,6 +1147,18 @@ def ogIsDiskLocked(*args): LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" return os.path.isfile(LOCKFILE) + +#/** +# ogListPartitions int_ndisk +#@brief Lista las particiones definidas en un disco. +#@param int_ndisk nº de orden del disco +#@return str_parttype:int_partsize ... +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: \c parted \c awk +#@attention El nº de partición se indica por el orden de los párametros \c parttype:partsize +#@attention Las tuplas de valores están separadas por espacios. +#*/ ## def ogListPartitions(*args): # Variables locales DISK = None @@ -1036,6 +1189,13 @@ def ogListPartitions(*args): print() return + +#/** +# ogListPrimaryPartitions int_ndisk +#@brief Metafunción que lista las particiones primarias no vacías de un disco. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## def ogListPrimaryPartitions(*args): # Variables locales PTTYPE = None @@ -1059,6 +1219,13 @@ def ogListPrimaryPartitions(*args): print(PARTS.split(" ")[0:4]) return + +#/** +# ogListLogicalPartitions int_ndisk +#@brief Metafunción que lista las particiones lógicas de una tabla tipo MSDOS. +#@param int_ndisk nº de orden del disco +#@see ogListPartitions +#*/ ## def ogListLogicalPartitions(*args): # Variables locales PTTYPE = None @@ -1078,6 +1245,16 @@ def ogListLogicalPartitions(*args): return PARTS.split(" ")[4:] + +#/** +# ogLockDisk int_ndisk +#@brief Genera un fichero de bloqueo para un disco en uso exlusivo. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogLockDisk(*args): # Variables locales DISK = None @@ -1102,6 +1279,17 @@ def ogLockDisk(*args): LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}" open(LOCKFILE, 'a').close() + +#/** +# ogSetPartitionActive int_ndisk int_npartition +#@brief Establece cual es la partición activa de un disco. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@return (nada). +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@note Requisitos: parted +#*/ ## def ogSetPartitionActive(*args): # Variables locales DISK = None @@ -1127,6 +1315,20 @@ def ogSetPartitionActive(*args): subprocess.run(["parted", "-s", DISK, "set", args[1], "boot", "on"], stderr=subprocess.DEVNULL) return + +#/** +# ogSetPartitionId int_ndisk int_npartition hex_partid +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param hex_partid identificador de tipo de partición +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o partición no corresponden con un dispositivo. +#@exception OG_ERR_OUTOFLIMIT Valor no válido. +#@exception OG_ERR_PARTITION Error al cambiar el id. de partición. +#@attention Requisitos: fdisk, sgdisk +#*/ ## def ogSetPartitionId(*args): # Variables locales DISK = None @@ -1174,6 +1376,19 @@ def ogSetPartitionId(*args): SystemLib.ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}") return + +#/** +# ogSetPartitionSize int_ndisk int_npartition int_size +#@brief Muestra el tamano en KB de una particion determinada. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param int_size tamaño de la partición (en KB) +#@return (nada) +#@exception OG_ERR_FORMAT formato incorrecto. +#@exception OG_ERR_NOTFOUND disco o particion no detectado (no es un dispositivo). +#@note Requisitos: sfdisk, awk +#@todo Compruebar que el tamaño sea numérico positivo y evitar que pueda solaparse con la siguiente partición. +#*/ ## def ogSetPartitionSize(*args): # Variables locales DISK = None @@ -1204,6 +1419,16 @@ def ogSetPartitionSize(*args): subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL) return + +#/** +# ogSetPartitionType int_ndisk int_npartition str_type +#@brief Cambia el identificador de la partición. +#@param int_ndisk nº de orden del disco +#@param int_npartition nº de orden de la partición +#@param str_type mnemónico de tipo de partición +#@return (nada) +#@attention Requisitos: fdisk, sgdisk +#*/ ## def ogSetPartitionType(*args): # Variables locales DISK = None @@ -1399,6 +1624,16 @@ def ogUnhidePartition(*args): ogSetPartitionType(args[0], args[1], NEWTYPE) return + +#/** +# ogUnlockDisk int_ndisk +#@brief Elimina el fichero de bloqueo para un disco. +#@param int_ndisk nº de orden del disco +#@return (nada) +#@exception OG_ERR_FORMAT Formato incorrecto. +#@exception OG_ERR_NOTFOUND Disco o particion no corresponden con un dispositivo. +#@note El fichero de bloqueo se localiza en \c /var/lock/disk, siendo \c disk el dispositivo del disco, sustituyendo el carácter "/" por "-". +#*/ ## def ogUnlockDisk(*args): # Variables locales DISK = None @@ -1424,6 +1659,15 @@ def ogUnlockDisk(*args): os.remove(LOCKFILE) return + +#/** +# ogUpdatePartitionTable +#@brief Fuerza al kernel releer la tabla de particiones de los discos duros +#@param no requiere +#@return informacion propia de la herramienta +#@note Requisitos: \c partprobe +#@warning pendiente estructurar la funcion a opengnsys +#*/ ## def ogUpdatePartitionTable(): for disk in ogDiskToDev(): subprocess.run(["partprobe", disk])