From caf1f4416159a46c4abff6f6f657c504fbc7b8f8 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Tue, 18 Feb 2025 14:17:39 +0100 Subject: [PATCH] refs #1528 add ogCreatePartitions --- client/lib/engine/bin/DiskLib.py | 173 ++++++++++++--------- client/shared/functions/ogCreatePartitions | 23 +++ 2 files changed, 124 insertions(+), 72 deletions(-) create mode 100755 client/shared/functions/ogCreatePartitions diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index 21db54a..e6bd26d 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -54,49 +54,42 @@ def parted(*args): #@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 - IODISCO = IOSIZE = CACHESIZE = EXTSTART = EXTSIZE = NVME_PREFIX = tmpsfdisk = None +def ogCreatePartitions (disk, parts): + ND = disk + DISK = ogDiskToDev (ND) + if not DISK: return None - # Si se solicita, mostrar ayuda. - if len(args) == 1 and args[0] == "help": - SystemLib.ogHelp('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', - 'ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000') - return + PTTYPE = ogGetPartitionTableType (disk) + if not PTTYPE: PTTYPE = 'MSDOS' # Por defecto para discos vacíos. - # Error si no se reciben al menos 2 parámetros. - if len(args) < 2: - SystemLib.ogRaiseError(OG_ERR_FORMAT) - return + if 'GPT' == PTTYPE: + return ogCreateGptPartitions (disk, parts) + elif 'MSDOS' != PTTYPE: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, PTTYPE) + return None - # Nº total de sectores, para evitar desbordamiento (evitar redondeo). - ND = args[0] - DISK = ogDiskToDev(ND) - if DISK is None: - return + SECTORS = ogGetLastSector (disk) - PTTYPE = ogGetPartitionTableType(ND) or "MSDOS" # Por defecto para discos vacíos. - - if PTTYPE == "GPT": - ogCreateGptPartitions(*args) - return - elif PTTYPE != "MSDOS": - SystemLib.ogRaiseError(OG_ERR_PARTITION, PTTYPE) - return - - SECTORS = ogGetLastSector(ND) - - # Se recalcula el nº de sectores del disco 1, si existe partición de caché. +# Se recalcula el nº de sectores del disco 1, si existe partición de caché. + CACHESIZE = 0 CACHEPART = CacheLib.ogFindCache() - if CACHEPART and ND == CACHEPART.split()[0]: - CACHESIZE = int(CacheLib.ogGetCacheSize()) * 2 + if CACHEPART: + cache_disk, cache_part = CACHEPART.split() + if ND == cache_disk: + CACHESIZE = int (CacheLib.ogGetCacheSize()) * 2 - # Sector de inicio (la partición 1 empieza en el sector 63). - IODISCO = ogDiskToDev(ND) - IOSIZE = subprocess.getoutput(f"fdisk -l {IODISCO} | awk '/I\\/O/ {{print $4}}'") +# 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 + 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 - if IOSIZE == "4096": + if '4096' == IOSIZE: START = 4096 SECTORS -= 8192 if CACHESIZE: @@ -108,48 +101,84 @@ def ogCreatePartitions(*args): PART = 1 - # Fichero temporal de entrada para "sfdisk" - tmpsfdisk = f"/tmp/sfdisk{os.getpid()}" - try: - with open(tmpsfdisk, 'w') as f: - f.write("unit: sectors\n\n") +# Fichero temporal de entrada para "sfdisk" + sfdisk_input = 'unit: sectors\n\n' - NVME_PREFIX = "p" if "nvme" in DISK else "" + NVME_PREFIX = 'p' if 'nvme' in DISK else '' - # Generar fichero de entrada para "sfdisk" con las particiones. - args = args[1:] # Shift - while args: - # Conservar los datos de la partición de caché. - if f"{ND} {PART}" == CACHEPART and CACHESIZE: - with open(tmpsfdisk, 'a') as f: - f.write(f"{DISK}{NVME_PREFIX}{PART} : start={SECTORS + 1}, size={CACHESIZE}, Id=ca\n") - PART += 1 - - # Leer formato de cada parámetro - Tipo:Tamaño - TYPE = args[0].split(":")[0] - SIZE = int(args[0].split(":")[1]) - - # Obtener identificador de tipo de partición válido. - ID = ogTypeToId(TYPE, "MSDOS") - with open(tmpsfdisk, 'a') as f: - f.write(f"{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n") - START += SIZE - SECTORS -= SIZE +# Generar fichero de entrada para "sfdisk" con las particiones. + 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 - args = args[1:] - # Ejecutar "sfdisk" con el fichero temporal. - subprocess.run(["sfdisk", DISK], input=open(tmpsfdisk, 'r').read(), text=True) - subprocess.run(["partprobe", DISK]) + # 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 - finally: - # Eliminar fichero temporal. - if os.path.exists(tmpsfdisk): - os.remove(tmpsfdisk) + # 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 + # Comprobar tamaño numérico y convertir en sectores de 512 B. + SIZE *= 2 + # Comprobar si la partición es extendida. + EXTSTART = EXTSIZE = 0 + if 5 == ID: + if PART > 4: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + # El inicio de la primera partición logica es el de la extendida más 4x512 + EXTSTART = START+2048 + 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 + # Generar datos para la partición. + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n' + # Error si se supera el nº total de sectores. + START += SIZE + if '4096' == IOSIZE and PART > 4: + START += 2048 + if START > SECTORS: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'{START//2} > {SECTORS//2}') + return None + PART += 1 - if CACHESIZE: - CacheLib.ogMountCache() - return 0 +# 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' + else: + sfdisk_input += f'{DISK}{NVME_PREFIX}{PART} : start=0, size=0, Id=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' + +# 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) +# Definir particiones y notificar al kernel. + print (f'about to run sfdisk: ({sfdisk_input})') + p = subprocess.run (['sfdisk', DISK], input=sfdisk_input, capture_output=True, text=True) + print (f'rc ({p.returncode}) stdout ({p.stdout}) stderr ({p.stderr})') + subprocess.run (['partprobe', DISK]) + if CACHESIZE: CacheLib.ogMountCache() + return True #/** diff --git a/client/shared/functions/ogCreatePartitions b/client/shared/functions/ogCreatePartitions new file mode 100755 index 0000000..8269a53 --- /dev/null +++ b/client/shared/functions/ogCreatePartitions @@ -0,0 +1,23 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from DiskLib import ogCreatePartitions + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...', ['ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +parser.add_argument ('disk') +parser.add_argument ('parts', nargs='+') +args = parser.parse_args() + +ret = ogCreatePartitions (args.disk, args.parts) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret)