Merge pull request 'particionador' (#89) from particionador into main
ogclient/pipeline/head This commit looks good Details
ogclient/pipeline/tag This commit looks good Details

Reviewed-on: #89
getalldisks-sort 0.26.0
Natalia Serrano 2025-07-14 13:24:59 +02:00
commit 5cf92d6367
9 changed files with 349 additions and 233 deletions

View File

@ -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

View File

@ -2,7 +2,6 @@
import os
import sys
import subprocess
import ogGlobals
import SystemLib
@ -34,12 +33,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 +50,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 +74,13 @@ 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:
sum_tam = 0
do_sum_tam = True
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 "*".
par = cpt = sfi = tam = None
@ -93,7 +96,7 @@ for item in tbprm:
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 = []
@ -106,10 +109,29 @@ for item in tbprm:
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')
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
extended_is_at = par
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']:
@ -118,7 +140,88 @@ for item in tbprm:
if par > maxp: maxp = par
if tch is None:
tch = '0'
tch = 0
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)
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()
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')
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
## 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 disk
disk_sectors = DiskLib.ogGetLastSector (dis)
IOSIZE = DiskLib.ogGetIoSize (dis)
if not IOSIZE:
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
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)
#____________________________________________________
#
@ -133,53 +236,46 @@ 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])
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)
# 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)

View File

@ -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

View File

@ -37,16 +37,15 @@ 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
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 (ndsk)
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
@ -70,7 +69,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.
@ -90,27 +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.
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')
# 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
@ -139,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')
@ -358,3 +362,46 @@ 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):
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
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', 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
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

View File

@ -38,6 +38,32 @@ 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
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
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.
@ -61,12 +87,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)
@ -78,24 +103,21 @@ 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
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 '4096' == IOSIZE:
# Sector de inicio (la partición 1 empieza en el sector 63).
IOSIZE = ogGetIoSize (ND)
if not IOSIZE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'Failed to get disk sector size')
return None
if 4096 == IOSIZE:
START = 4096
SECTORS -= 8192
if CACHESIZE:
SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1
else:
START = 63
else: ## 512
if 'MSDOS' == PTTYPE: START = 63
else: START = 2048
if CACHESIZE:
SECTORS -= CACHESIZE
@ -103,71 +125,108 @@ 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:
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
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
# Comprobar tamaño numérico y convertir en sectores de 512 B.
SIZE *= 2
# 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"
# Comprobar si la partición es extendida.
EXTSTART = EXTSIZE = 0
if 5 == ID:
if PART > 4:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, '')
if '5' == ID:
if 'GPT' == PTTYPE:
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'EXTENDED')
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
# 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, 'la partición 5 es lógica pero no hay ninguna EXTENDED definida antes')
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}')
SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, f'partición "{TYPE}:{ORIG_SIZE}" no cabe')
return None
PART += 1
# 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'
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)
@ -183,113 +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):
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
#/**
# ogCreatePartitionTable int_ndisk [str_tabletype]
#@brief Genera una tabla de particiones en caso de que no sea valida, si es valida no hace nada.
@ -858,7 +810,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)
@ -1277,6 +1229,23 @@ 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
'EMPTY': '0',
'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',

View File

@ -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

View File

@ -1 +0,0 @@
bootOs

View File

@ -1 +0,0 @@
bootOs

View File

@ -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()