From 56ba4194610333430e7b6187c070f79705d12623 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Fri, 31 Jan 2025 15:54:26 +0100 Subject: [PATCH] refs #1409 add ogCreateCache, fix bugs --- client/lib/engine/bin/CacheLib.py | 112 ++++++++++++++++++++------ client/lib/engine/bin/DiskLib.py | 6 +- client/shared/functions/ogCreateCache | 36 +++++++++ client/shared/scripts/createImage.py | 1 - 4 files changed, 126 insertions(+), 29 deletions(-) create mode 100755 client/shared/functions/ogCreateCache diff --git a/client/lib/engine/bin/CacheLib.py b/client/lib/engine/bin/CacheLib.py index 19f7943..0d1a43b 100755 --- a/client/lib/engine/bin/CacheLib.py +++ b/client/lib/engine/bin/CacheLib.py @@ -23,35 +23,97 @@ import CacheLib #@warning El tamaño de caché debe estar entre 50 MB y la mitad del disco. #@warning La caché no puede solaparse con las particiones de datos. #*/ ## -def ogCreateCache(ndisk=1, npart=4, partsize=None): - """ - Define la caché local, por defecto en partición 4 del disco 1. - - :param ndisk: número de disco donde crear la caché, por defecto es 1. - :param npart: número de partición (opcional, 4 por defecto). - :param partsize: tamaño de la partición en KB. - :raises ValueError: Si el formato de los parámetros es incorrecto. - :raises RuntimeError: Si ocurre un error durante la creación de la caché. - """ +def ogCreateCache (ndsk=1, part=4, sizecache=0): + if not sizecache: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '') + return None + sizecache = int (sizecache) - if partsize is None: - raise ValueError("El tamaño de la partición debe especificarse.") + DISK = DiskLib.ogDiskToDev (ndsk) + if not DISK: return None - # Verifica si las herramientas necesarias están instaladas - required_tools = ["sfdisk", "parted", "awk", "sed"] - for tool in required_tools: - if not shutil.which(tool): - raise RuntimeError(f"La herramienta {tool} no está instalada.") + # PATCH Para discos nvme la particion debe ser p1, p2, etc...en lugar de 1,2, sino falla sfdisk + NVME_PREFIX = '' + if 'nvme' in DISK: + NVME_PREFIX = 'p' - # Preparar los comandos para crear la caché - disk = f"/dev/sd{chr(96 + ndisk)}" - size_in_sectors = partsize * 2 # Asumiendo 512B por sector + END = DiskLib.ogGetLastSector (ndsk) + 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 + START = 0 + if 4096 == IOSIZE: + END -= 8192 + START = END - SIZE + 2048 - (END-SIZE)%2048 + else: + START = END - SIZE + 1 + + ENDPREVPART = None + i = 1 + while True: + prev_part = part - i + if prev_part <= 0: break + ENDPREVPART = DiskLib.ogGetLastSector (ndsk, prev_part) + if ENDPREVPART: break + i += 1 + if not ENDPREVPART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) + return None +# Error si tamaño no está entre límites permitidos o si se solapa con la partición anterior. + MINSIZE = 25000 + MAXSIZE = END + if SIZE < MINSIZE or SIZE > MAXSIZE or START < ENDPREVPART: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, ndsk) + return None + +# Desmontar todos los sistemas de archivos del disco. + FileSystemLib.ogUnmountAll (ndsk) +# Definir particiones y notificar al kernel. +# En el caso de ser disco GPT, de momento se borra la particion y se vuelve a crear, +# por lo que se pierden los datos. + pttype = DiskLib.ogGetPartitionTableType (ndsk) + if not pttype: + pttype = 'MSDOS' + DiskLib.ogCreatePartitionTable (ndsk, pttype) + + get_ptt = DiskLib.ogGetPartitionTableType (ndsk) + if 'GPT' == get_ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['sgdisk', '-p', DISK]).returncode: + subprocess.run (['gdisk', DISK], input='2\nw\nY\n', 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}']) + elif 'MSDOS' == get_ptt: + # Si la tabla de particiones no es valida, volver a generarla. + if subprocess.run (['parted', '-s', DISK, 'print']).returncode: + 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) +# Actualiza la tabla de particiones en el kernel. + DiskLib.ogUpdatePartitionTable() - try: - # Lógica simplificada para crear la caché en la partición - subprocess.run(["parted", disk, "mkpart", "primary", str(npart), str(partsize)], check=True) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error al crear la caché: {e}") #/** diff --git a/client/lib/engine/bin/DiskLib.py b/client/lib/engine/bin/DiskLib.py index e1c3f6b..51f54b9 100755 --- a/client/lib/engine/bin/DiskLib.py +++ b/client/lib/engine/bin/DiskLib.py @@ -711,8 +711,8 @@ def ogGetLastSector (disk, par=None): for l in sgdisk_out.splitlines(): items = l.split() if len(items) < 3: continue - if par != items[0]: continue - last = items[2] + if str (par) != items[0]: continue + last = int (items[2]) break else: @@ -720,7 +720,7 @@ def ogGetLastSector (disk, par=None): for l in sgdisk_out.splitlines(): if 'last usable sector' not in l: continue items = l.split() - last = items[-1] + last = int (items[-1]) return last diff --git a/client/shared/functions/ogCreateCache b/client/shared/functions/ogCreateCache new file mode 100755 index 0000000..62a97e5 --- /dev/null +++ b/client/shared/functions/ogCreateCache @@ -0,0 +1,36 @@ +#!/usr/bin/python3 + +import sys +import argparse +from SystemLib import ogHelp +from CacheLib import ogCreateCache + +if 2 == len (sys.argv) and 'help' == sys.argv[1]: + #parser.print_help() sale en inglés aunque la locale indique otra cosa + ogHelp ('ogCreateCache', 'ogCreateCache [int_ndisk [int_npart]] int_partsize', ['ogCreateCache 10000000', 'ogCreateCache 1 10000000', 'ogCreateCache 1 4 10000000']) + sys.exit (0) + +parser = argparse.ArgumentParser (add_help=False) +if 2 == len (sys.argv): + parser.add_argument ('sizecache') +elif 3 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('sizecache') +elif 4 == len (sys.argv): + parser.add_argument ('disk') + parser.add_argument ('part') + parser.add_argument ('sizecache') + +args = parser.parse_args() + +if 2 == len (sys.argv): + ret = ogCreateCache (sizecache=args.sizecache) +elif 3 == len (sys.argv): + ret = ogCreateCache (ndsk=args.disk, sizecache=args.sizecache) +elif 4 == len (sys.argv): + ret = ogCreateCache (ndsk=int(args.disk), part=int(args.part), sizecache=int(args.sizecache)) + +if ret is not None: + if ret == True: sys.exit (0) + elif ret == False: sys.exit (1) + else: print (ret) diff --git a/client/shared/scripts/createImage.py b/client/shared/scripts/createImage.py index fb625d9..716c2b3 100755 --- a/client/shared/scripts/createImage.py +++ b/client/shared/scripts/createImage.py @@ -3,7 +3,6 @@ import os import sys import time -import tempfile import subprocess import ogGlobals