From 588ed960984ddae77feed395d3412ec2ae212d15 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 13:41:44 +0200 Subject: [PATCH 01/18] refs #2412 rename variables, add a couple of log messages, move a check --- ogclient/interfaceAdm/Configurar.py | 38 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index f49eef8..ac94750 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -34,12 +34,12 @@ prog = os.path.basename(__name__) # # El parámetro $2 es el que aporta toda la información y el $1 se queda obsoleto # Formato de entrada: -# dis=Número de disco -# != caracter de separación +# dis=Número de disco +# != caracter de separación # # Y un numero indeterminado de cadenas del tipo siguuenteseparadas por el caracter '$': -# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación -# @= caracter de separación +# par=Número de particion*cod=Código de partición*sfi=Sistema de ficheros*tam=Tamaño de la partición*ope=Operación +# @= caracter de separación #____________________________________________________________________ # Captura de parámetros (se ignora el 1er parámetro y se eliminan espacios y tabuladores). @@ -51,12 +51,13 @@ param = sys.argv[2] tbprm = param.split ('!') pparam = tbprm[0] # General disk parameters sparam = tbprm[1] # Partitioning and formatting parameters +is_there_cache = 'CACHE' in sparam # Toma valores de disco y caché, separados por "*". # Los valores están en las variables $dis: disco, $che: existe cache (1, 0), $tch: Tamaño de la cache. -tbprm = pparam.split ('*') +pparams = pparam.split ('*') dis = tch = None -for item in tbprm: +for item in pparams: if '=' not in item: continue k, v = item.split ('=', 1) @@ -74,10 +75,10 @@ if dis is None: tbp = [] # Valores de configuración (parámetros para ogCreatePartitions) tbf = {} # Tabla de formateo -tbprm = sparam.split('%') +sparams = sparam.split('%') maxp=0 -for item in tbprm: +for item in sparams: if not item: continue ## por si nos pasan un '%' al final de todo # Leer datos de la partición, separados por "*". par = cpt = sfi = tam = None @@ -120,6 +121,18 @@ for item in tbprm: if tch is None: tch = '0' + + +cur_ptt = DiskLib.ogGetPartitionTableType (dis) +ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS' +recreate_partition_table = False +if not cur_ptt: + SystemLib.ogEcho (['session', 'log'], None, f'No partition table--will create a "{ptt}" one') + recreate_partition_table = True +if cur_ptt and ptt != cur_ptt: + SystemLib.ogEcho (['session', 'log'], None, f'Current partition table type "{cur_ptt}" is wrong for this system--will replace it for a "{ptt}" one') + recreate_partition_table = True + #____________________________________________________ # # Proceso @@ -133,19 +146,16 @@ SystemLib.ogEcho (['session', 'log'], None, f'[10] {ogGlobals.lang.MSG_HELP_ogUn FileSystemLib.ogUnmountAll (dis) CacheLib.ogUnmountCache() -# Elimina la tabla de particiones -cur_ptt = DiskLib.ogGetPartitionTableType (dis) -ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS' -if not cur_ptt or ptt != cur_ptt: +if recreate_partition_table: DiskLib.ogDeletePartitionTable (dis) SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable']) DiskLib.ogCreatePartitionTable (dis, ptt) # Inicia la cache. -if 'CACHE' in sparam: +if is_there_cache: SystemLib.ogEcho (['session', 'log'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogCreateCache}') SystemLib.ogEcho (['session', 'log'], None, f' initCache.py {tch}') - rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache.py', tch]) + rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache.py', str (tch)]) if not rc: SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'initCache.py failed') sys.exit (1) From a7f4d767f5cded8f3d4e4056fbfbc2fe4d613fac Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 13:43:33 +0200 Subject: [PATCH 02/18] refs #2412 add and improve error messages --- ogclient/lib/python3/CacheLib.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ogclient/lib/python3/CacheLib.py b/ogclient/lib/python3/CacheLib.py index 8edde91..28ad37b 100644 --- a/ogclient/lib/python3/CacheLib.py +++ b/ogclient/lib/python3/CacheLib.py @@ -37,6 +37,9 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): NVME_PREFIX = 'p' END = DiskLib.ogGetLastSector (ndsk) + if not END: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'Failed to get last sector of disk') + return None SIZE = 2 * sizecache # Inicio partición cache según el disco tenga sectores de 4k o menores IOSIZE = 0 @@ -70,7 +73,7 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): MINSIZE = 25000 MAXSIZE = END if SIZE < MINSIZE or SIZE > MAXSIZE or START < ENDPREVPART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_GENERIC, f'size ({SIZE}) < minsize ({MINSIZE}) or size > maxsize ({MAXSIZE}) or start ({START}) < endprevpart ({ENDPREVPART})') + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'size ({SIZE}) < minsize ({MINSIZE}) or size ({SIZE}) > maxsize ({MAXSIZE}) or start ({START}) < endprevpart ({ENDPREVPART})') return None # Desmontar todos los sistemas de archivos del disco. @@ -111,6 +114,9 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): # Guardamos nueva configuración en el disco. i = '\n'.join(tmp) subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True) + else: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'No hay tabla de particiones en el disco') + return False # Actualiza la tabla de particiones en el kernel. DiskLib.ogUpdatePartitionTable() return True From 9cad17e4f4b6602ebcfc2037eca59f4b3b12ce6f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 14:01:11 +0200 Subject: [PATCH 03/18] refs #2412 check partition sizes before touching the disk --- ogclient/interfaceAdm/Configurar.py | 37 +++++++++++++++++++++++++++-- ogclient/lib/python3/CacheLib.py | 37 +++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index ac94750..7934ce1 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -78,6 +78,8 @@ tbf = {} # Tabla de formateo sparams = sparam.split('%') maxp=0 +sum_tam = 0 +do_sum_tam = True for item in sparams: if not item: continue ## por si nos pasan un '%' al final de todo # Leer datos de la partición, separados por "*". @@ -94,7 +96,7 @@ for item in sparams: if 'par' == k: par = int (v) elif 'cpt' == k: cpt = v elif 'sfi' == k: sfi = v - elif 'tam' == k: tam = v + elif 'tam' == k: tam = int (v) elif 'ope' == k: ope = int (v) missing_params = [] @@ -111,6 +113,11 @@ for item in sparams: tch = tam else: tbp.append (f'{cpt}:{tam}') + if do_sum_tam: + sum_tam += tam + if 'EXTENDED' == cpt: + do_sum_tam = False ## don't sum sizes anymore + if ope: # Si se activa operación de formatear, componer datos de formateo. if cpt not in ['EMPTY', 'EXTENDED', 'LINUX-LVM', 'LVM', 'ZPOOL']: @@ -119,7 +126,10 @@ for item in sparams: if par > maxp: maxp = par if tch is None: - tch = '0' + tch = 0 + +if is_there_cache and 0 == tch: + print (f'nati ===================== is_there_cache ({is_there_cache}) tch ({tch}), this should not happen') @@ -133,6 +143,29 @@ if cur_ptt and ptt != cur_ptt: SystemLib.ogEcho (['session', 'log'], None, f'Current partition table type "{cur_ptt}" is wrong for this system--will replace it for a "{ptt}" one') recreate_partition_table = True + +## size check: check that cache fits in the space left by the previously existing partitions +if not recreate_partition_table and not CacheLib.ogCheckNewCacheSize (dis, tch): + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'nueva partición de caché no cabe en el hueco actual') + sys.exit (1) + +## size check: check that the newly defined partitions fit in the space left by the newly defined cache +disk_sectors = DiskLib.ogGetLastSector (dis) +IOSIZE = 512 ## TODO +if 512 == IOSIZE: + sum_tam_sectors = sum_tam*2 + cache_sectors = tch*2 +else: + sum_tam_sectors = (sum_tam+3)//4 ## sumamos 3 para que la división entera "redondee al alza" + cache_sectors = (tch+3)//4 +## esta comprobacion puede dejar pasar situaciones que más tarde dan error +## la ventana es bastante estrecha, y sumando aquí simplemente un 1 por 1000, ya la cerramos del todo +sum_tam_sectors = int (sum_tam_sectors * 1.001) +space_left_by_cache = disk_sectors - cache_sectors +if sum_tam_sectors > space_left_by_cache: + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'las particiones no caben en el disco') + sys.exit (1) + #____________________________________________________ # # Proceso diff --git a/ogclient/lib/python3/CacheLib.py b/ogclient/lib/python3/CacheLib.py index 28ad37b..a7bf170 100644 --- a/ogclient/lib/python3/CacheLib.py +++ b/ogclient/lib/python3/CacheLib.py @@ -364,3 +364,40 @@ def ogUnmountCache(): def initCache (*args): p = subprocess.run ([f'{ogGlobals.OGSCRIPTS}/initCache.py'] + list(args)) return not p.returncode ## negate shell return code + + +#/** +# ogCheckNewCacheSize +#@brief Comprueba si un cache de X tamaño cabe en el hueco que dejan las demás particiones +#@param Tamaño de la nueva hipotética cache +#@return Boolean, True si la nueva cache cabría, False si no +#*/ ## +def ogCheckNewCacheSize (disk, kB): + IOSIZE=512 #DiskLib.blablaIoSize (disk) + last_sector = DiskLib.ogGetLastSector (disk) + + end_of_last_partition = 0 + cachepart = ogFindCache() + if cachepart: + cache_disk, cache_part = cachepart.split() + cache_dev = DiskLib.ogDiskToDev (cache_disk, cache_part) + else: + cache_dev = None + fdisk_l_out = subprocess.run (['fdisk', '-l'], capture_output=True, text=True).stdout + for l in fdisk_l_out.splitlines(): + if not re.match ('^/dev', l): ## no empieza por /dev, nos la saltamos + continue + if cache_dev and re.match (f'^{cache_dev}', l): ## es la de cache, nos la saltamos + continue + last_sector_of_partition = int (l.split()[2]) + if last_sector_of_partition > end_of_last_partition: + end_of_last_partition = last_sector_of_partition + + if 512 == IOSIZE: + cache_sectors = kB*2 + else: ## 4096 + cache_sectors = (kB+3)//4 ## sumamos 3 para que la división entera "redondee al alza" + if end_of_last_partition + cache_sectors > last_sector: + SystemLib.ogEcho (['session', 'log'], None, f'end_of_last_partition ({end_of_last_partition}) + cache_sectors ({cache_sectors}) > last_sector ({last_sector}), check failed') + return False + return True From 0d28787318fb69d429916f0a3a0e23a9e32b0e27 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 14:07:34 +0200 Subject: [PATCH 04/18] refs #2412 fix bug with extended/logical partitions, remove useless variable, add some comments --- ogclient/lib/python3/DiskLib.py | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index 24138a7..164e5ef 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -78,10 +78,10 @@ def ogCreatePartitions (disk, parts): cache_disk, cache_part = CACHEPART.split() if int (ND) == int (cache_disk): CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 + # Sector de inicio (la partición 1 empieza en el sector 63). - IODISCO = ogDiskToDev (disk) IOSIZE = 0 - fdisk_out = subprocess.run (['fdisk', '-l', IODISCO], capture_output=True, text=True).stdout + fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout for l in fdisk_out.splitlines(): if 'I/O' not in l: continue items = l.split() @@ -103,6 +103,7 @@ def ogCreatePartitions (disk, parts): sfdisk_input = 'unit: sectors\n\n' NVME_PREFIX = 'p' if 'nvme' in DISK else '' + EXTSTART = EXTSIZE = 0 for p in parts: # Conservar los datos de la partición de caché. if f'{ND} {PART}' == CACHEPART and CACHESIZE: @@ -124,14 +125,39 @@ def ogCreatePartitions (disk, parts): if 'CACHE' == TYPE or not ID: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. + + # Comprobar tamaño numérico y convertir en sectores de 512 B. ## BUG!! qué pasa si IOSIZE==4096 SIZE *= 2 + + ## TODO ojo, no puede haber dos extendidas + # Comprobar si la partición es extendida. - EXTSTART = EXTSIZE = 0 if 5 == ID: if PART > 4: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') return None + + ## la extendida debe ser: + ## - si no estamos creando cache: /dev/sda4 + ## - si sí estamos creando cache: /dev/sda3 + ## de lo contrario, crea eg. esto: + ## Device Boot Start End Sectors Size Id Type + ## /dev/sda1 63 222444728 222444666 106,1G 82 Linux swap / Solaris + ## /dev/sda2 222444729 244889394 22444666 10,7G 5 Extended <--------- + ## /dev/sda3 244889395 251334060 6444666 3,1G 83 Linux <--------- + ## /dev/sda4 314103633 314572766 469134 229,1M ca unknown + ## /dev/sda5 222446777 224891442 2444666 1,2G 83 Linux + ## /dev/sda6 224891443 229558330 4666888 2,2G 83 Linux + ## la sda2 es extendida, y las lógicas deberían ser sda5, sda6, sda7 + ## pero esto mete una sda3 como lógica, y luego va el cache que es primaria... WTF + error_in_extended = False + if CACHEPART and PART != 3: error_in_extended = True + if not CACHEPART and PART != 4: error_in_extended = True + if PART > 4: error_in_extended = True + if error_in_extended: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'No se puede definir la partición extendida en la partición "{PART}"') + return None + # El inicio de la primera partición logica es el de la extendida más 4x512 EXTSTART = START+2048 EXTSIZE = SIZE-2048 From cf5ec4c214dd914c469dd1927ab37529e116d948 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 14:12:19 +0200 Subject: [PATCH 05/18] refs #2412 fix two more bugs with extended/logical partitions --- ogclient/lib/python3/DiskLib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index 164e5ef..ff2367f 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -109,7 +109,7 @@ def ogCreatePartitions (disk, parts): if f'{ND} {PART}' == CACHEPART and CACHESIZE: sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' PART += 1 - continue + #continue # Leer formato de cada parámetro - Tipo:Tamaño TYPE, SIZE = p.split (':') @@ -132,7 +132,7 @@ def ogCreatePartitions (disk, parts): ## TODO ojo, no puede haber dos extendidas # Comprobar si la partición es extendida. - if 5 == ID: + if '5' == ID: if PART > 4: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') return None From 36a8277aab2b9ec464037bb905316ecc3d9e4691 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 14:18:03 +0200 Subject: [PATCH 06/18] refs #2412 merge ogCreatePartitions and ogCreateGptPartitions into a single function --- ogclient/lib/python3/DiskLib.py | 167 +++++++++++--------------------- 1 file changed, 54 insertions(+), 113 deletions(-) diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index ff2367f..0510f29 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -61,12 +61,11 @@ def ogCreatePartitions (disk, parts): PTTYPE = ogGetPartitionTableType (disk) if not PTTYPE: PTTYPE = 'MSDOS' # Por defecto para discos vacíos. - - if 'GPT' == PTTYPE: - return ogCreateGptPartitions (disk, parts) - elif 'MSDOS' != PTTYPE: + if PTTYPE not in ['MSDOS', 'GPT']: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE) return None + if 'MSDOS' == PTTYPE: CACHE_ID = ogTypeToId ('CACHE', 'MSDOS') + else: CACHE_ID = ogTypeToId ('CACHE', 'GPT_GUID') # Se calcula el ultimo sector del disco (total de sectores usables) SECTORS = ogGetLastSector (disk) @@ -95,7 +94,8 @@ def ogCreatePartitions (disk, parts): if CACHESIZE: SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1 else: - START = 63 + if 'MSDOS' == PTTYPE: START = 63 + else: START = 2048 if CACHESIZE: SECTORS -= CACHESIZE @@ -105,23 +105,29 @@ def ogCreatePartitions (disk, parts): NVME_PREFIX = 'p' if 'nvme' in DISK else '' EXTSTART = EXTSIZE = 0 for p in parts: - # Conservar los datos de la partición de caché. - if f'{ND} {PART}' == CACHEPART and CACHESIZE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' - PART += 1 - #continue # Leer formato de cada parámetro - Tipo:Tamaño TYPE, SIZE = p.split (':') if TYPE is None or 'None' == TYPE: TYPE='EMPTY' + + # Obtener identificador de tipo de partición válido. + if 'GPT' == PTTYPE: + ID = ogTypeToId (TYPE, 'GPT_GUID') + else: + ID = ogTypeToId (TYPE, PTTYPE) + + # Conservar los datos de la partición de caché. + if f'{ND} {PART}' == CACHEPART and CACHESIZE: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, type={CACHE_ID}\n' + PART += 1 + #continue + try: SIZE = int (SIZE) except ValueError: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) return None - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId (TYPE, 'MSDOS') if 'CACHE' == TYPE or not ID: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) return None @@ -133,8 +139,8 @@ def ogCreatePartitions (disk, parts): # Comprobar si la partición es extendida. if '5' == ID: - if PART > 4: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + if 'GPT' == PTTYPE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED') return None ## la extendida debe ser: @@ -163,22 +169,26 @@ def ogCreatePartitions (disk, parts): EXTSIZE = SIZE-2048 # Incluir particiones lógicas dentro de la partición extendida. if 5 == PART: - if not EXTSTART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') - return None - START = EXTSTART - SECTORS = EXTSTART+EXTSIZE + if 'GPT' == PTTYPE: + pass ## sin problema, la partición 5 es simplemente una más + else: + if not EXTSTART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'PART==5 and not EXTSTART') + return None + START = EXTSTART + SECTORS = EXTSTART+EXTSIZE # Generar datos para la partición. # En el caso de que la partición sea EMPTY no se crea nada if 'EMPTY' != TYPE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, type={ID}\n' START += SIZE - # Error si se supera el nº total de sectores. - if '4096' == IOSIZE and PART > 4: + if 'MSDOS' == PTTYPE and '4096' == IOSIZE and PART > 4: START += 2048 + + # Error si se supera el nº total de sectores. if START > SECTORS: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') return None @@ -187,13 +197,14 @@ def ogCreatePartitions (disk, parts): # Si no se indican las 4 particiones primarias, definirlas como vacías, conservando la partición de caché. while PART <= 4: if f'{ND} {PART}' == CACHEPART and CACHESIZE: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, Id=ca\n' + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, type={CACHE_ID}\n' else: - sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=0\n' + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, type=0\n' PART += 1 + # Si se define partición extendida sin lógicas, crear particion 5 vacía. if 5 == PART and EXTSTART: - sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, Id=0\n' + sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, type=0\n' # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. FileSystemLib.ogUnmountAll (ND) @@ -226,94 +237,8 @@ def ogCreatePartitions (disk, parts): #@todo Definir atributos (arranque, oculta) y tamaños en MB, GB, etc. #*/ ## def ogCreateGptPartitions (disk, parts): - ND = disk - DISK = ogDiskToDev (ND) - if not DISK: return None - - # Se calcula el ultimo sector del disco (total de sectores usables) - SECTORS = ogGetLastSector (disk) - - # Se recalcula el nº de sectores del disco si existe partición de caché. - CACHESIZE = 0 - CACHEPART = CacheLib.ogFindCache() - if CACHEPART: - cache_disk, cache_part = CACHEPART.split() - if ND == cache_disk: - CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - if CACHESIZE: - SECTORS -= CACHESIZE - - # Si el disco es GPT empieza en el sector 2048 por defecto, pero podria cambiarse - ALIGN = int (subprocess.run (['sgdisk', '-D', DISK], capture_output=True, text=True).stdout) - START = ALIGN - PART = 1 - print (f'START ({START}) SECTORS ({SECTORS}) PART ({PART})') - - # Leer parámetros con definición de particionado. - DELOPTIONS = [] - OPTIONS = [] - for p in parts: - # Conservar los datos de la partición de caché. - if f'{ND} {PART}' == CACHEPART and CACHESIZE: - PART += 1 - - # Leer formato de cada parámetro - Tipo:Tamaño - TYPE, SIZE = p.split (':') - try: - SIZE = int (SIZE) - except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, SIZE) - return None - - # Error si la partición es extendida (no válida en discos GPT). - if 'EXTENDED' == TYPE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED') - return None - - # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no - PARTSIZE = ogGetPartitionSize (ND, PART) - # En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas - if PARTSIZE: - DELOPTIONS.append (f'-d{PART}') - - # Creamos la particion - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId (TYPE, 'GPT') - if 'CACHE' == TYPE or not ID: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) - return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. - SIZE *= 2 - # SIZE debe ser múltiplo de ALIGN, si no gdisk lo mueve automáticamente. - SIZE = (SIZE // ALIGN) * ALIGN - - # Generar datos para la partición. - # En el caso de que la partición sea EMPTY no se crea nada - if 'EMPTY' != TYPE: - OPTIONS += [f'-n{PART}:{START}:+{SIZE}', f'-t{PART}:{ID}'] - - START += SIZE - - # Error si se supera el nº total de sectores. - if START > SECTORS: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') - return None - - PART += 1 - - # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. - FileSystemLib.ogUnmountAll (ND) - if CACHESIZE: CacheLib.ogUnmountCache() - - # Si la tabla de particiones no es valida, volver a generarla. - ogCreatePartitionTable (ND, 'GPT') - - # Definir particiones y notificar al kernel. - p = subprocess.run (['sgdisk'] + DELOPTIONS + OPTIONS + [DISK], capture_output=True, text=True) - print (f'sgdisk rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})') - subprocess.run (['partprobe', DISK]) - if CACHESIZE: CacheLib.ogMountCache() - return not p.returncode + print ('nati in ogCreateGptPartitions(), return False') + return False #/** @@ -1303,6 +1228,22 @@ def ogSetPartitionType (disk, par, t): #ogTypeToId ('LINUX', 'MSDOS') => "83" def ogTypeToId (type, pttype='MSDOS'): data = { + 'GPT_GUID': { + ## https://en.wikipedia.org/wiki/GUID_Partition_Table?useskin=vector + 'WINDOWS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', + 'NTFS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', + 'FAT32': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', + 'FAT16': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', + 'FAT12': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', + 'WIN-RESERV': 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE', + 'LINUX-SWAP': '0657FD6D-A4AB-43C4-84E5-0933C84B4F4F', + 'LINUX': '0FC63DAF-8483-4772-8E79-3D69D8477DE4', + 'EXT2': '0FC63DAF-8483-4772-8E79-3D69D8477DE4', + 'EXT3': '0FC63DAF-8483-4772-8E79-3D69D8477DE4', + 'EXT4': '0FC63DAF-8483-4772-8E79-3D69D8477DE4', + 'CACHE': '0FC63DAF-8483-4772-8E79-3D69D8477DE4', + 'EFI': 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B', + }, 'GPT': { 'EMPTY': '0', 'WINDOWS': '0700', From 38be98d9f1d2e5eb1686f9d357254b133941138d Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Wed, 9 Jul 2025 14:56:43 +0200 Subject: [PATCH 07/18] refs #2436 add new function to obtain disk I/O size --- ogclient/interfaceAdm/Configurar.py | 5 ++- ogclient/lib/python3/CacheLib.py | 22 ++++++------ ogclient/lib/python3/DiskLib.py | 56 ++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index 7934ce1..63a4bf8 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -151,7 +151,10 @@ if not recreate_partition_table and not CacheLib.ogCheckNewCacheSize (dis, tch): ## size check: check that the newly defined partitions fit in the space left by the newly defined cache disk_sectors = DiskLib.ogGetLastSector (dis) -IOSIZE = 512 ## TODO +IOSIZE = DiskLib.ogGetIoSize (dis) +if not IOSIZE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') + sys.exit (1) if 512 == IOSIZE: sum_tam_sectors = sum_tam*2 cache_sectors = tch*2 diff --git a/ogclient/lib/python3/CacheLib.py b/ogclient/lib/python3/CacheLib.py index a7bf170..f5ca0bb 100644 --- a/ogclient/lib/python3/CacheLib.py +++ b/ogclient/lib/python3/CacheLib.py @@ -42,14 +42,10 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): return None SIZE = 2 * sizecache # Inicio partición cache según el disco tenga sectores de 4k o menores - IOSIZE = 0 - fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout - for l in fdisk_out.splitlines(): - items = l.split() - if len(items) < 4: continue - if 'I/O' == items[0]: - IOSIZE = int (items[3]) - break + IOSIZE = DiskLib.ogGetIoSize (DISK) + if not IOSIZE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') + return None START = 0 if 4096 == IOSIZE: END -= 8192 @@ -373,7 +369,13 @@ def initCache (*args): #@return Boolean, True si la nueva cache cabría, False si no #*/ ## def ogCheckNewCacheSize (disk, kB): - IOSIZE=512 #DiskLib.blablaIoSize (disk) + DISK = DiskLib.ogDiskToDev (disk) + if not DISK: return None + + IOSIZE = DiskLib.ogGetIoSize (disk) + if not IOSIZE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') + return None last_sector = DiskLib.ogGetLastSector (disk) end_of_last_partition = 0 @@ -383,7 +385,7 @@ def ogCheckNewCacheSize (disk, kB): cache_dev = DiskLib.ogDiskToDev (cache_disk, cache_part) else: cache_dev = None - fdisk_l_out = subprocess.run (['fdisk', '-l'], capture_output=True, text=True).stdout + fdisk_l_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout for l in fdisk_l_out.splitlines(): if not re.match ('^/dev', l): ## no empieza por /dev, nos la saltamos continue diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index 0510f29..dc47b89 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -38,6 +38,34 @@ def parted(*args): return "Error: 'parted' command not found" +#/** +# ogGetIoSize int_ndisk +#@brief Devuelve el tamaño de sector de un disco +#@param int_ndisk nº de orden del disco +#@return Tamaño de sector +#*/ ## +def ogGetIoSize (disk): + DISK = ogDiskToDev (disk) + if not DISK: return None + + IOSIZE = None + print (f'nati ejecutando fdisk -l') + fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout + for l in fdisk_out.splitlines(): + if 'I/O' not in l: continue + items = l.split() + if len(items) < 4: continue + IOSIZE = items[3] + print (f'nati detectado IOSIZE ({IOSIZE})') + break + + if IOSIZE is None: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Could not extract disk sector size from fdisk output') + return None + + return int (IOSIZE) + + #/** # ogCreatePartitions int_ndisk str_parttype:int_partsize ... #@brief Define el conjunto de particiones de un disco. @@ -79,21 +107,17 @@ def ogCreatePartitions (disk, parts): CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 # Sector de inicio (la partición 1 empieza en el sector 63). - IOSIZE = 0 - fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout - for l in fdisk_out.splitlines(): - if 'I/O' not in l: continue - items = l.split() - if len(items) < 4: continue - IOSIZE = items[3] - break + IOSIZE = ogGetIoSize (ND) + if not IOSIZE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') + return None - if '4096' == IOSIZE: + if 4096 == IOSIZE: START = 4096 SECTORS -= 8192 if CACHESIZE: SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1 - else: + else: ## 512 if 'MSDOS' == PTTYPE: START = 63 else: START = 2048 if CACHESIZE: @@ -120,7 +144,6 @@ def ogCreatePartitions (disk, parts): if f'{ND} {PART}' == CACHEPART and CACHESIZE: sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={SECTORS+1}, size={CACHESIZE}, type={CACHE_ID}\n' PART += 1 - #continue try: SIZE = int (SIZE) @@ -132,10 +155,9 @@ def ogCreatePartitions (disk, parts): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, TYPE) return None - # Comprobar tamaño numérico y convertir en sectores de 512 B. ## BUG!! qué pasa si IOSIZE==4096 - SIZE *= 2 - - ## TODO ojo, no puede haber dos extendidas + # Comprobar tamaño numérico y convertir en sectores + if 512 == IOSIZE: SIZE *= 2 + else: SIZE = (SIZE+3)//4 ## sumamos 3 para que la división entera "redondee al alza" # Comprobar si la partición es extendida. if '5' == ID: @@ -185,7 +207,7 @@ def ogCreatePartitions (disk, parts): START += SIZE - if 'MSDOS' == PTTYPE and '4096' == IOSIZE and PART > 4: + if 'MSDOS' == PTTYPE and 4096 == IOSIZE and PART > 4: START += 2048 # Error si se supera el nº total de sectores. @@ -809,7 +831,7 @@ def ogGetPartitionSize (disk, par): #@return Devuelve el numero paritiones del disco duro indicado #@warning Salidas de errores no determinada #@attention Requisitos: parted -#@note Notas sin especificar +#@note Notas sin especificar #*/ ## def ogGetPartitionsNumber (disk): DISK = ogDiskToDev (disk) From df36d74d7c8b0331e06836051fc3d9bf7ad94545 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 10:56:19 +0200 Subject: [PATCH 08/18] refs #2441 remove "sgdisk" call in ogCreateCache --- ogclient/lib/python3/CacheLib.py | 36 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/ogclient/lib/python3/CacheLib.py b/ogclient/lib/python3/CacheLib.py index f5ca0bb..b305184 100644 --- a/ogclient/lib/python3/CacheLib.py +++ b/ogclient/lib/python3/CacheLib.py @@ -42,7 +42,7 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): return None SIZE = 2 * sizecache # Inicio partición cache según el disco tenga sectores de 4k o menores - IOSIZE = DiskLib.ogGetIoSize (DISK) + IOSIZE = DiskLib.ogGetIoSize (ndsk) if not IOSIZE: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') return None @@ -89,30 +89,32 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): subprocess.run (['gdisk', DISK], input='2\nw\nY\n', capture_output=True, text=True) # Si existe la cache se borra previamente if ogFindCache(): ogDeleteCache() - # Capturamos el codigo de particion GPT para cache - # PATCH - Cuando es GPT, la particion con codigo CACHE (CA00) no existe y no puede crearse, se cambia por LINUX (8300) - ID = DiskLib.ogTypeToId ('LINUX', 'GPT') - subprocess.run (['sgdisk', DISK, f'-n{part}:{START}:{END}', f'-c{part}:CACHE', f'-t{part}:{ID}']) + + ID = DiskLib.ogTypeToId ('LINUX', 'GPT_GUID') + sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, type={ID}, name=CACHE' elif 'MSDOS' == get_ptt: # Si la tabla de particiones no es valida, volver a generarla. if subprocess.run (['parted', '-s', DISK, 'print']).returncode: ## if True, then parted failed subprocess.run (['fdisk', DISK], input='w\n', text=True) - # Definir particiones y notificar al kernel. + ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS') - # Salvamos la configuración de las particiones e incluimos la cache. - tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines() - tmp = [ x for x in tmp if f'{DISK}{part}' not in x ] - tmp.append (f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}') - # Ordenamos las líneas de los dispositivos - UNIT = [ x for x in tmp if 'unit' in x ][0] - tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ]) - tmp = [UNIT, ''] + tmp - # Guardamos nueva configuración en el disco. - i = '\n'.join(tmp) - subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True) + sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}' else: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'No hay tabla de particiones en el disco') return False + + # Salvamos la configuración de las particiones e incluimos la cache. + tmp = subprocess.run (['sfdisk', '--dump', DISK], capture_output=True, text=True).stdout.splitlines() + tmp = [ x for x in tmp if f'{DISK}{part}' not in x ] ## grep -v la_de_cache + tmp.append (sfdisk_line) + # Ordenamos las líneas de los dispositivos + UNIT = [ x for x in tmp if 'unit' in x ][0] + tmp = sorted ([ x for x in tmp if re.match ('^/dev', x) ]) + tmp = [UNIT, ''] + tmp + # Guardamos nueva configuración en el disco. + i = '\n'.join(tmp) + subprocess.run (['sfdisk', '--no-reread', DISK], input=i, text=True) + # Actualiza la tabla de particiones en el kernel. DiskLib.ogUpdatePartitionTable() return True From 9e7fda89446ba5482f2b57745fe56c2c43f2bfcd Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 14:44:37 +0200 Subject: [PATCH 09/18] refs #2414 fail early when requested some wrong scenarios --- ogclient/interfaceAdm/Configurar.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index 63a4bf8..b613d31 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -2,7 +2,6 @@ import os import sys -import subprocess import ogGlobals import SystemLib @@ -80,6 +79,7 @@ sparams = sparam.split('%') maxp=0 sum_tam = 0 do_sum_tam = True +cache_seen = extended_seen = False for item in sparams: if not item: continue ## por si nos pasan un '%' al final de todo # Leer datos de la partición, separados por "*". @@ -110,12 +110,20 @@ for item in sparams: # Componer datos de particionado. if 'CACHE' == cpt: + if cache_seen: + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición de cache') + sys.exit (1) + cache_seen = True tch = tam else: tbp.append (f'{cpt}:{tam}') if do_sum_tam: sum_tam += tam if 'EXTENDED' == cpt: + if extended_seen: + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición extendida') + sys.exit (1) + extended_seen = True do_sum_tam = False ## don't sum sizes anymore if ope: @@ -133,6 +141,10 @@ if is_there_cache and 0 == tch: +if not cache_seen and not tbp: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'No se ha solicitado ninguna partición') + sys.exit (1) + cur_ptt = DiskLib.ogGetPartitionTableType (dis) ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS' recreate_partition_table = False From 83c1c7763aa8c188264f27c73d74d32172e99b33 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 14:46:34 +0200 Subject: [PATCH 10/18] refs #2414 do not fail when only the cache partition is requested --- ogclient/interfaceAdm/Configurar.py | 52 +++++++++++++---------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index b613d31..fb22ca0 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -209,35 +209,31 @@ if is_there_cache: sys.exit (1) # Definir particionado. -SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}') -SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}') -res = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreatePartitions', str(dis)] + tbp) -if not res: - SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_GENERIC, f'ogCreatePartitions {dis} {' '.join (tbp)}') - sys.exit (1) -SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable']) +if tbp: + SystemLib.ogEcho (['session', 'log'], None, f'[50] {ogGlobals.lang.MSG_HELP_ogCreatePartitions}') + SystemLib.ogEcho (['session', 'log'], None, f' ogCreatePartitions {dis} {' '.join (tbp)}') + res = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogCreatePartitions', str(dis)] + tbp) + if not res: + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'ogCreatePartitions {dis} {' '.join (tbp)}') + sys.exit (1) + SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogUpdatePartitionTable']) -# Formatear particiones -SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}') retval = 0 -for p in range (1, maxp+1): - if p not in tbf: continue - if 'CACHE' == tbf[p]: - if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado. - SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache') - retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatCache']) - else: - SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}') - retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', str(dis), str(p), tbf[p]]) - if not retval: - SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}') - sys.exit (1) -# Registro de fin de ejecución +if tbf: + # Formatear particiones + SystemLib.ogEcho (['session', 'log'], None, f'[70] {ogGlobals.lang.MSG_HELP_ogFormat}') + for p in range (1, maxp+1): + if p not in tbf: continue + if 'CACHE' == tbf[p]: + if CACHESIZE == tch: # Si el tamaño es distinto ya se ha formateado. + SystemLib.ogEcho (['session', 'log'], None, ' ogFormatCache') + retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatCache']) + else: + SystemLib.ogEcho (['session', 'log'], None, f' ogFormatFs {dis} {p} {tbf[p]}') + retval = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGPYFUNCS}/ogFormatFs', str(dis), str(p), tbf[p]]) + if not retval: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_GENERIC, f'ogFormatFs {dis} {p} {tbf[p]}') + sys.exit (1) + SystemLib.ogEcho (['session', 'log'], None, f'{ogGlobals.lang.MSG_INTERFACE_END} {retval}') - -#___________________________________________________________________ -# -# Retorno -#___________________________________________________________________ - sys.exit (0) From 73721d70f73cecb86e5204a023007783e9995a2b Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 14:50:09 +0200 Subject: [PATCH 11/18] refs #2414 make initCache.py output more silent --- ogclient/lib/python3/CacheLib.py | 14 +++++++------- ogclient/scripts/initCache.py | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ogclient/lib/python3/CacheLib.py b/ogclient/lib/python3/CacheLib.py index b305184..ab0ff90 100644 --- a/ogclient/lib/python3/CacheLib.py +++ b/ogclient/lib/python3/CacheLib.py @@ -94,8 +94,8 @@ def ogCreateCache (ndsk=1, part=4, sizecache=0): sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, type={ID}, name=CACHE' elif 'MSDOS' == get_ptt: # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['parted', '-s', DISK, 'print']).returncode: ## if True, then parted failed - subprocess.run (['fdisk', DISK], input='w\n', text=True) + if subprocess.run (['parted', '-s', DISK, 'print'], capture_output=True).returncode: ## if True, then parted failed + subprocess.run (['fdisk', DISK], input='w\n', text=True, capture_output=True) ID = DiskLib.ogTypeToId ('CACHE', 'MSDOS') sfdisk_line = f'{DISK}{NVME_PREFIX}{part} : start= {START}, size= {SIZE}, Id={ID}' @@ -143,15 +143,15 @@ def ogDeleteCache(): ptt = DiskLib.ogGetPartitionTableType (ndisk) if 'GPT' == ptt: # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['sgdisk', '-p', disk]).returncode: ## if True, then sgdisk failed - subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True) + if subprocess.run (['sgdisk', '-p', disk], capture_output=True).returncode: ## if True, then sgdisk failed + subprocess.run (['gdisk', disk], input='2\nw\nY\n', text=True, capture_output=True) subprocess.run (['sgdisk', disk, f'-d{npart}']) elif 'MSDOS' == ptt: # Si la tabla de particiones no es valida, volver a generarla. - if subprocess.run (['parted', '-s', disk, 'print']).returncode: ## if True, then parted failed - subprocess.run (['fdisk', disk], input='w', text=True) + if subprocess.run (['parted', '-s', disk, 'print'], capture_output=True).returncode: ## if True, then parted failed + subprocess.run (['fdisk', disk], input='w', text=True, capture_output=True) # Eliminar la partición de caché. - subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True) + subprocess.run (['fdisk', disk], input=f'd\n{npart}\nw', text=True, capture_output=True) # Borrar etiqueta de la caché. if os.path.exists ('/dev/disk/by-label/CACHE'): os.unlink ('/dev/disk/by-label/CACHE') diff --git a/ogclient/scripts/initCache.py b/ogclient/scripts/initCache.py index f564924..6371ceb 100755 --- a/ogclient/scripts/initCache.py +++ b/ogclient/scripts/initCache.py @@ -50,6 +50,8 @@ def main (NDISK, NPART, SIZE, MOUNT): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_CACHE, 'failed to create cache') return False DiskLib.ogUpdatePartitionTable() + else: + print("[10] Partición de caché solicitada es del mismo tamaño que la existente, ignorar.") # Si caché no montada y no formateada o cambia el tamaño: formatear. cache = CacheLib.ogFindCache() From 8029d469a764846ea135a9dc1e3a181c3a954394 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 14:53:29 +0200 Subject: [PATCH 12/18] refs #2414 improve some error messages, create a windows logical partition rather than an empty one --- ogclient/lib/python3/DiskLib.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index dc47b89..4c1b781 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -156,6 +156,7 @@ def ogCreatePartitions (disk, parts): return None # Comprobar tamaño numérico y convertir en sectores + ORIG_SIZE = SIZE ## para reportar en un error if 512 == IOSIZE: SIZE *= 2 else: SIZE = (SIZE+3)//4 ## sumamos 3 para que la división entera "redondee al alza" @@ -195,7 +196,7 @@ def ogCreatePartitions (disk, parts): pass ## sin problema, la partición 5 es simplemente una más else: if not EXTSTART: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'PART==5 and not EXTSTART') + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'la partición 5 es lógica pero no hay ninguna EXTENDED definida antes') return None START = EXTSTART SECTORS = EXTSTART+EXTSIZE @@ -212,7 +213,7 @@ def ogCreatePartitions (disk, parts): # Error si se supera el nº total de sectores. if START > SECTORS: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'partición "{TYPE}:{ORIG_SIZE}" no cabe') return None PART += 1 @@ -226,7 +227,8 @@ def ogCreatePartitions (disk, parts): # Si se define partición extendida sin lógicas, crear particion 5 vacía. if 5 == PART and EXTSTART: - sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, type=0\n' + ID = ogTypeToId ('WINDOWS', PTTYPE) + sfdisk_input += f'{DISK}5 : start={EXTSTART}, SIZE={EXTSIZE}, type={ID}\n' # Desmontar los sistemas de archivos del disco antes de realizar las operaciones. FileSystemLib.ogUnmountAll (ND) From e529768257fbcb7de394bd22e83e6c1ee112cd0c Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 15:42:55 +0200 Subject: [PATCH 13/18] refs #2414 add some more checks --- ogclient/interfaceAdm/Configurar.py | 46 +++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index fb22ca0..6da2e0c 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -124,6 +124,7 @@ for item in sparams: SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición extendida') sys.exit (1) extended_seen = True + extended_is_at = par do_sum_tam = False ## don't sum sizes anymore if ope: @@ -136,17 +137,44 @@ for item in sparams: if tch is None: tch = 0 -if is_there_cache and 0 == tch: - print (f'nati ===================== is_there_cache ({is_there_cache}) tch ({tch}), this should not happen') -if not cache_seen and not tbp: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'No se ha solicitado ninguna partición') - sys.exit (1) - cur_ptt = DiskLib.ogGetPartitionTableType (dis) ptt = 'GPT' if InventoryLib.ogIsEfiActive() else 'MSDOS' + +if not cache_seen and not tbp: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'No se ha solicitado ninguna partición') + sys.exit (1) + +if 'GPT' == ptt and extended_seen: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT no se pueden usar particiones extendidas') + sys.exit (1) + +## error si nos piden más de 4 y ninguna es extendida +if 'MSDOS' == ptt and not extended_seen: + requested_partitions = len (tbp) + if cache_seen: requested_partitions += 1 + if requested_partitions > 4: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'Se han solicitado más de 4 particiones y ninguna es extendida') + sys.exit (1) + +## si no nos definen partición de cache y el disco tiene una, hay que borrarla +if not cache_seen: + c = CacheLib.ogFindCache() + if c: + cache_disk, cache_part = c.split() + if int (cache_disk) == int (dis): + CacheLib.ogUnmountCache() + CacheLib.ogDeleteCache() + +## la extendida solo puede estar en la (si hay cache) o en la 4 (si no lo hay) +if extended_seen: + extended_should_be_at = 3 if cache_seen else 4 + if extended_is_at != extended_should_be_at: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'La partición extendida no puede ser la "{extended_is_at}" sino que debe ser la "{extended_should_be_at}"') + sys.exit (1) + recreate_partition_table = False if not cur_ptt: SystemLib.ogEcho (['session', 'log'], None, f'No partition table--will create a "{ptt}" one') @@ -155,17 +183,17 @@ if cur_ptt and ptt != cur_ptt: SystemLib.ogEcho (['session', 'log'], None, f'Current partition table type "{cur_ptt}" is wrong for this system--will replace it for a "{ptt}" one') recreate_partition_table = True - ## size check: check that cache fits in the space left by the previously existing partitions if not recreate_partition_table and not CacheLib.ogCheckNewCacheSize (dis, tch): SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'nueva partición de caché no cabe en el hueco actual') + ## BUG el "hueco actual" me podría dar igual, si luego resulta que también estoy definiendo otras particiones y ya sí hay sitio para todo sys.exit (1) -## size check: check that the newly defined partitions fit in the space left by the newly defined cache +## size check: check that the newly defined partitions fit in the disk disk_sectors = DiskLib.ogGetLastSector (dis) IOSIZE = DiskLib.ogGetIoSize (dis) if not IOSIZE: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size') sys.exit (1) if 512 == IOSIZE: sum_tam_sectors = sum_tam*2 From 3d692f54a534bb864b1907390d31d49ddb3eb4bc Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 10 Jul 2025 15:44:08 +0200 Subject: [PATCH 14/18] refs #2414 add a missing partition type --- ogclient/lib/python3/DiskLib.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index 4c1b781..12b775c 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -49,14 +49,12 @@ def ogGetIoSize (disk): if not DISK: return None IOSIZE = None - print (f'nati ejecutando fdisk -l') fdisk_out = subprocess.run (['fdisk', '-l', DISK], capture_output=True, text=True).stdout for l in fdisk_out.splitlines(): if 'I/O' not in l: continue items = l.split() if len(items) < 4: continue IOSIZE = items[3] - print (f'nati detectado IOSIZE ({IOSIZE})') break if IOSIZE is None: @@ -1254,6 +1252,7 @@ def ogTypeToId (type, pttype='MSDOS'): data = { 'GPT_GUID': { ## https://en.wikipedia.org/wiki/GUID_Partition_Table?useskin=vector + 'EMPTY': '0', 'WINDOWS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', 'NTFS': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', 'FAT32': 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7', From c5db321d931e6503e0e1955584feab14f7f1875f Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 14 Jul 2025 12:17:41 +0200 Subject: [PATCH 15/18] refs #2461 remove dangling symlinks --- ogclient/scripts/bootLinux | 1 - ogclient/scripts/bootWindows | 1 - 2 files changed, 2 deletions(-) delete mode 120000 ogclient/scripts/bootLinux delete mode 120000 ogclient/scripts/bootWindows diff --git a/ogclient/scripts/bootLinux b/ogclient/scripts/bootLinux deleted file mode 120000 index d19be90..0000000 --- a/ogclient/scripts/bootLinux +++ /dev/null @@ -1 +0,0 @@ -bootOs \ No newline at end of file diff --git a/ogclient/scripts/bootWindows b/ogclient/scripts/bootWindows deleted file mode 120000 index d19be90..0000000 --- a/ogclient/scripts/bootWindows +++ /dev/null @@ -1 +0,0 @@ -bootOs \ No newline at end of file From 87b566532cfa6d457017461902825943198ee176 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 14 Jul 2025 12:20:34 +0200 Subject: [PATCH 16/18] refs #2415 check that 1st partition is the ESP in EFI systems --- ogclient/interfaceAdm/Configurar.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index 6da2e0c..7e9f6aa 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -79,7 +79,7 @@ sparams = sparam.split('%') maxp=0 sum_tam = 0 do_sum_tam = True -cache_seen = extended_seen = False +cache_seen = extended_seen = efi_seen = False for item in sparams: if not item: continue ## por si nos pasan un '%' al final de todo # Leer datos de la partición, separados por "*". @@ -109,6 +109,11 @@ for item in sparams: sys.exit (1) # Componer datos de particionado. + if 'EFI' == cpt: + if efi_seen: + SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición de ESP') + sys.exit (1) + efi_seen = True if 'CACHE' == cpt: if cache_seen: SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_FORMAT, f'se ha solicitado más de una partición de cache') @@ -148,8 +153,8 @@ if not cache_seen and not tbp: sys.exit (1) if 'GPT' == ptt and extended_seen: - SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT no se pueden usar particiones extendidas') - sys.exit (1) + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT no se pueden usar particiones extendidas') + sys.exit (1) ## error si nos piden más de 4 y ninguna es extendida if 'MSDOS' == ptt and not extended_seen: @@ -159,6 +164,15 @@ if 'MSDOS' == ptt and not extended_seen: SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'Se han solicitado más de 4 particiones y ninguna es extendida') sys.exit (1) +if efi_seen: + if 'EFI' != tbp[0].split (':')[0]: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'la partición ESP debe estar declarada en primera posición') + sys.exit (1) +else: + if 'GPT' == ptt and 1 == dis: + SystemLib.ogRaiseError (['session', 'log'], ogGlobals.OG_ERR_FORMAT, f'En GPT debe haber una partición ESP') + sys.exit (1) + ## si no nos definen partición de cache y el disco tiene una, hay que borrarla if not cache_seen: c = CacheLib.ogFindCache() From 4432b603266ea2298d2d3506e1f1dceedf1a8d94 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 14 Jul 2025 12:44:20 +0200 Subject: [PATCH 17/18] refs #2450 support two disks --- ogclient/interfaceAdm/Configurar.py | 4 ++-- ogclient/lib/python3/BootLib.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ogclient/interfaceAdm/Configurar.py b/ogclient/interfaceAdm/Configurar.py index 7e9f6aa..72f43ba 100755 --- a/ogclient/interfaceAdm/Configurar.py +++ b/ogclient/interfaceAdm/Configurar.py @@ -244,8 +244,8 @@ if recreate_partition_table: # Inicia la cache. if is_there_cache: SystemLib.ogEcho (['session', 'log'], None, f'[30] {ogGlobals.lang.MSG_HELP_ogCreateCache}') - SystemLib.ogEcho (['session', 'log'], None, f' initCache.py {tch}') - rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache.py', str (tch)]) + SystemLib.ogEcho (['session', 'log'], None, f' initCache.py {dis} {tch}') + rc = SystemLib.ogExecAndLog ('command', [f'{ogGlobals.OGSCRIPTS}/initCache.py', str (dis), str (tch)]) if not rc: SystemLib.ogRaiseError (['log', 'session'], ogGlobals.OG_ERR_CACHE, f'initCache.py failed') sys.exit (1) diff --git a/ogclient/lib/python3/BootLib.py b/ogclient/lib/python3/BootLib.py index 28c7d6e..3d3b7b9 100644 --- a/ogclient/lib/python3/BootLib.py +++ b/ogclient/lib/python3/BootLib.py @@ -195,7 +195,7 @@ def ogBoot (disk, par, nvramperm=False, params=''): winboot = os.environ.get ('winboot', '') if 'kexec' == winboot: # Modo de arranque en caliente (con kexec). - cp_cmd = f'cp {ogGlobals.OGLIB}/grub4dos/* {mntdir}' + cp_cmd = f'cp {ogGlobals.OGLIB}/grub4dos/* {mntdir}' ## shutil sucks a bit for copying both files and dirs subprocess.run (cp_cmd, shell=True) disk0 = int(disk)-1 par0 = int(par)-1 From c2d04ca39f9f84bcb59f4627212d9ca94f02f3ca Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Mon, 14 Jul 2025 13:23:03 +0200 Subject: [PATCH 18/18] refs #2432 remove unused function and debug stmts --- CHANGELOG.md | 6 ++++++ ogclient/lib/python3/DiskLib.py | 21 --------------------- ogclient/lib/python3/ProtocolLib.py | 2 -- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eb29af..7034738 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.26.0] - 2025-07-14 + +### Fixed + +- Overhaul partitioning + ## [0.25.2] - 2025-07-14 ### Fixed diff --git a/ogclient/lib/python3/DiskLib.py b/ogclient/lib/python3/DiskLib.py index 12b775c..be7366b 100644 --- a/ogclient/lib/python3/DiskLib.py +++ b/ogclient/lib/python3/DiskLib.py @@ -242,27 +242,6 @@ def ogCreatePartitions (disk, parts): return not p.returncode -#/** -# 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 (disk, parts): - print ('nati in ogCreateGptPartitions(), return False') - return False - - #/** # ogCreatePartitionTable int_ndisk [str_tabletype] #@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada. diff --git a/ogclient/lib/python3/ProtocolLib.py b/ogclient/lib/python3/ProtocolLib.py index 1b41ba8..59ce192 100644 --- a/ogclient/lib/python3/ProtocolLib.py +++ b/ogclient/lib/python3/ProtocolLib.py @@ -224,7 +224,6 @@ def ogUcastSendFile (disk=None, par=None, container=None, file=None, sess=None): return path2 = FileLib.ogGetPath (file=source) - print (f'nati path2 ({path2})') if not path2: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') return @@ -483,7 +482,6 @@ def ogMcastSendFile (disk=None, par=None, container=None, file=None, sess=None): return path2 = FileLib.ogGetPath (file=source) - print (f'nati path2 ({path2})') if not path2: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, f'device or file {dev_err} not found') return