source: client/engine/DiskLib.py @ 6482bcc

ogClonningEnginetest-python-scriptsticket-577ticket-585ticket-693ticket-700
Last change on this file since 6482bcc was 6482bcc, checked in by Antonio Emmanuel Guerrero Silva <aguerrero@…>, 9 months ago

refs #577 Library bugs resolved

  • Property mode set to 100644
File size: 43.2 KB
RevLine 
[c2925f1a]1import subprocess
2import shutil
[6482bcc]3import datetime
[c2925f1a]4import os
[6482bcc]5from DiskLib import *
6from CacheLib import *
7from FileSystemLib import *
8from SystemLib import *
9from SystemLib import OG_ERR_OUTOFLIMIT, OG_ERR_PARTITION, OG_ERR_FORMAT, OG_ERR_NOTFOUND
10
[c2925f1a]11
12def parted(*args):
13    parted_path = shutil.which("parted")
14    if parted_path:
15        try:
16            result = subprocess.run(
17                [parted_path] + list(args),
18                timeout=3,
19                capture_output=True,
20                text=True
21            )
22            return result.stdout
23        except subprocess.TimeoutExpired:
24            return "Error: Command 'parted' timed out"
25    else:
26        return "Error: 'parted' command not found"
27
28def ogCreatePartitions(*args):
29    # Variables locales
30    ND = DISK = PTTYPE = PART = SECTORS = START = SIZE = TYPE = CACHEPART = None
31    IODISCO = IOSIZE = CACHESIZE = EXTSTART = EXTSIZE = NVME_PREFIX = tmpsfdisk = None
32
33    # Si se solicita, mostrar ayuda.
34    if len(args) == 1 and args[0] == "help":
35        ogHelp('ogCreatePartitions', 'ogCreatePartitions int_ndisk str_parttype:int_partsize ...',
36               'ogCreatePartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000')
37        return
38
39    # Error si no se reciben al menos 2 parámetros.
40    if len(args) < 2:
41        ogRaiseError(OG_ERR_FORMAT)
42        return
43
44    # Nº total de sectores, para evitar desbordamiento (evitar redondeo).
45    ND = args[0]
46    DISK = ogDiskToDev(ND)
47    if DISK is None:
48        return
49
50    PTTYPE = ogGetPartitionTableType(ND) or "MSDOS"  # Por defecto para discos vacíos.
51
52    if PTTYPE == "GPT":
53        ogCreateGptPartitions(*args)
54        return
55    elif PTTYPE != "MSDOS":
56        ogRaiseError(OG_ERR_PARTITION, PTTYPE)
57        return
58
59    SECTORS = ogGetLastSector(ND)
60
61    # Se recalcula el nº de sectores del disco 1, si existe partición de caché.
62    CACHEPART = ogFindCache()
63    if CACHEPART and ND == CACHEPART.split()[0]:
64        CACHESIZE = int(ogGetCacheSize()) * 2
65
66    # Sector de inicio (la partición 1 empieza en el sector 63).
67    IODISCO = ogDiskToDev(ND)
68    IOSIZE = subprocess.getoutput(f"fdisk -l {IODISCO} | awk '/I\\/O/ {{print $4}}'")
69
70    if IOSIZE == "4096":
71        START = 4096
72        SECTORS -= 8192
73        if CACHESIZE:
74            SECTORS = SECTORS - CACHESIZE + 2048 - (SECTORS - CACHESIZE) % 2048 - 1
75    else:
76        START = 63
77        if CACHESIZE:
78            SECTORS -= CACHESIZE
79
80    PART = 1
81
82    # Fichero temporal de entrada para "sfdisk"
83    tmpsfdisk = f"/tmp/sfdisk{os.getpid()}"
84    try:
85        with open(tmpsfdisk, 'w') as f:
86            f.write("unit: sectors\n\n")
87
88        NVME_PREFIX = "p" if "nvme" in DISK else ""
89
90        # Generar fichero de entrada para "sfdisk" con las particiones.
91        args = args[1:]  # Shift
92        while args:
93            # Conservar los datos de la partición de caché.
94            if f"{ND} {PART}" == CACHEPART and CACHESIZE:
95                with open(tmpsfdisk, 'a') as f:
96                    f.write(f"{DISK}{NVME_PREFIX}{PART} : start={SECTORS + 1}, size={CACHESIZE}, Id=ca\n")
97                PART += 1
98
99            # Leer formato de cada parámetro - Tipo:Tamaño
100            TYPE = args[0].split(":")[0]
101            SIZE = int(args[0].split(":")[1])
102
103            # Obtener identificador de tipo de partición válido.
104            ID = ogTypeToId(TYPE, "MSDOS")
105            with open(tmpsfdisk, 'a') as f:
106                f.write(f"{DISK}{NVME_PREFIX}{PART} : start={START}, size={SIZE}, Id={ID}\n")
107            START += SIZE
108            SECTORS -= SIZE
109            PART += 1
110            args = args[1:]
111
112        # Ejecutar "sfdisk" con el fichero temporal.
113        subprocess.run(["sfdisk", DISK], input=open(tmpsfdisk, 'r').read(), text=True)
114        subprocess.run(["partprobe", DISK])
115
116    finally:
117        # Eliminar fichero temporal.
118        if os.path.exists(tmpsfdisk):
119            os.remove(tmpsfdisk)
120
121    if CACHESIZE:
122        ogMountCache()
123    return 0
124
125def ogCreateGptPartitions(*args):
126    # Variables locales
127    ND = DISK = PART = SECTORS = ALIGN = START = SIZE = TYPE = CACHEPART = CACHESIZE = DELOPTIONS = OPTIONS = None
128
129    # Si se solicita, mostrar ayuda.
130    if len(args) == 1 and args[0] == "help":
131        ogHelp('ogCreateGptPartitions', 'ogCreateGptPartitions int_ndisk str_parttype:int_partsize ...',
132                'ogCreateGptPartitions 1 NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000')
133        return
134
135    # Error si no se reciben menos de 2 parámetros.
136    if len(args) < 2:
137        ogRaiseError(OG_ERR_FORMAT)
138        return
139
140    # Nº total de sectores, para evitar desbordamiento (evitar redondeo).
141    ND = args[0]
142    DISK = ogDiskToDev(ND)
143    if DISK is None:
144        return
145
146    # Se calcula el ultimo sector del disco (total de sectores usables)
147    SECTORS = ogGetLastSector(ND)
148
149    # Se recalcula el nº de sectores del disco si existe partición de caché.
150    CACHEPART = ogFindCache()
151    if ND == CACHEPART.split()[0]:
152        CACHESIZE = int(ogGetCacheSize()) * 2
153    if CACHESIZE:
154        SECTORS -= CACHESIZE
155
156    # Si el disco es GPT empieza en el sector 2048  por defecto, pero podria cambiarse
157    ALIGN = subprocess.getoutput(f"sgdisk -D {DISK} 2>/dev/null")
158    START = ALIGN
159    PART = 1
160
161    # Leer parámetros con definición de particionado.
162    args = args[1:]  # Shift
163    while args:
164        # Si PART es la cache, nos la saltamos y seguimos con el siguiente numero para conservar los datos de la partición de caché.
165        if f"{ND} {PART}" == CACHEPART and CACHESIZE:
166            PART += 1
167
168        # Leer formato de cada parámetro - Tipo:Tamaño
169        TYPE = args[0].split(":")[0]
170        SIZE = int(args[0].split(":")[1])
171
172        # Error si la partición es extendida (no válida en discos GPT).
173        if TYPE == "EXTENDED":
174            ogRaiseError(OG_ERR_PARTITION, "EXTENDED")
175            return
176
177        # Comprobar si existe la particion actual, capturamos su tamaño para ver si cambio o no
178        PARTSIZE = ogGetPartitionSize(ND, PART)
179        # En sgdisk no se pueden redimensionar las particiones, es necesario borrarlas y volver a crealas
180        if PARTSIZE:
181            DELOPTIONS += f" -d{PART}"
182
183        # Creamos la particion
184        # Obtener identificador de tipo de partición válido.
185        ID = ogTypeToId(TYPE, "GPT")
186        if TYPE != "CACHE" and ID:
187            OPTIONS += f" -n{PART}:{START}:+{SIZE} -t{PART}:{ID} "
188
189        START += SIZE
190
191        # Error si se supera el nº total de sectores.
192        if START > SECTORS:
193            ogRaiseError(OG_ERR_FORMAT, f"{START//2} > {SECTORS//2}")
194            return
195
196        PART += 1
197        args = args[1:]
198
199    # Desmontar los sistemas de archivos del disco antes de realizar las operaciones.
200    ogUnmountAll(ND)
201    if CACHESIZE:
202        ogUnmountCache()
203
204    # Si la tabla de particiones no es valida, volver a generarla.
205    ogCreatePartitionTable(ND)
206
207    # Definir particiones y notificar al kernel.
208    # Borramos primero las particiones y luego creamos las nuevas
209    subprocess.run(["sgdisk"] + DELOPTIONS.split() + OPTIONS.split() + [DISK], stderr=subprocess.DEVNULL)
210    subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL)
211
212    if CACHESIZE:
213        ogMountCache()
214    return 0
215
216def ogCreatePartitionTable(*args):
217    # Variables locales
218    DISK = PTTYPE = CREATE = CREATEPTT = None
219
220    # Si se solicita, mostrar ayuda.
221    if len(args) == 1 and args[0] == "help":
222        ogHelp('ogCreatePartitionTable', 'ogCreatePartitionTable int_ndisk [str_partype]',
223               'ogCreatePartitionTable 1 GPT', 'ogCreatePartitionTable 1')
224        return
225
226    # Error si no se reciben 1 o 2 parámetros.
227    if len(args) == 1:
228        CREATEPTT = ""
229    elif len(args) == 2:
230        CREATEPTT = args[1]
231    else:
232        ogRaiseError(OG_ERR_FORMAT)
233        return
234
235    # Capturamos el tipo de tabla de particiones actual
236    DISK = ogDiskToDev(args[0])
237    if DISK is None:
238        return
239    PTTYPE = ogGetPartitionTableType(args[0]) or "MSDOS"  # Por defecto para discos vacíos.
240    CREATEPTT = CREATEPTT or PTTYPE
241
242    # Si la tabla actual y la que se indica son iguales, se comprueba si hay que regenerarla.
243    if CREATEPTT == PTTYPE:
244        if PTTYPE == "GPT":
245            try:
246                result = subprocess.run(
247                    ["sgdisk", "-p", DISK],
248                    stderr=subprocess.PIPE,
249                    stdout=subprocess.DEVNULL
250                )
251                if result.returncode != 0:
252                    CREATE = "GPT"
253            except subprocess.CalledProcessError:
254                CREATE = "GPT"
255        elif PTTYPE == "MSDOS":
256            try:
257                result = subprocess.run(
258                    ["parted", "-s", DISK, "print"],
259                    stderr=subprocess.PIPE,
260                    stdout=subprocess.DEVNULL
261                )
262                if result.returncode != 0:
263                    CREATE = "MSDOS"
264            except subprocess.CalledProcessError:
265                CREATE = "MSDOS"
266    else:
267        CREATE = CREATEPTT
268
269    # Dependiendo del valor de CREATE, creamos la tabla de particiones en cada caso.
270    if CREATE == "GPT":
271        if PTTYPE == "MSDOS":
272            subprocess.run(["sgdisk", "-go", DISK])
273        else:
274            subprocess.run(["gdisk", DISK], input="2\nw\nY\n", text=True)
275        subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL)
276    elif CREATE == "MSDOS":
277        if PTTYPE == "GPT":
278            subprocess.run(["sgdisk", "-Z", DISK])
279        subprocess.run(["fdisk", DISK], input="o\nn\np\n\n\n\nd\n\nw", text=True)
280        subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL)
281    return
282
283def ogDeletePartitionTable(*args):
284    # Variables locales
285    DISK = None
286
287    # Si se solicita, mostrar ayuda.
288    if len(args) == 1 and args[0] == "help":
289        ogHelp('ogDeletePartitionTable', 'ogDeletePartitionTable int_ndisk', 'ogDeletePartitionTable 1')
290        return
291
292    # Error si no se reciben 1 parámetros.
293    if len(args) != 1:
294        ogRaiseError(OG_ERR_FORMAT)
295        return
296
297    # Obteniendo Identificador linux del disco.
298    DISK = ogDiskToDev(args[0])
299    if DISK is None:
300        return
301
302    # Crear una tabla de particiones vacía.
303    PTTYPE = ogGetPartitionTableType(args[0])
304    if PTTYPE == "GPT":
305        subprocess.run(["sgdisk", "-o", DISK])
306    elif PTTYPE == "MSDOS":
307        subprocess.run(["fdisk", DISK], input="o\nw", text=True)
308    return
309
310def ogDevToDisk(dev):
311    # Variables locales
312    CACHEFILE = "/var/cache/disks.cfg"
313    PART = None
314    n = 1
315
316    # Si se solicita, mostrar ayuda.
317    if dev == "help":
318        ogHelp("ogDevToDisk", "ogDevToDisk path_device | LABEL=str_label | UUID=str_uuid",
319               "ogDevToDisk /dev/sda  =>  1",
320               "ogDevToDisk /dev/sda1  =>  1 1",
321               "ogDevToDisk LABEL=CACHE  =>  1 4")
322        return
323
324    # Error si no se recibe 1 parámetro.
325    if len(dev) != 1:
326        ogRaiseError(OG_ERR_FORMAT)
327        return
328
329    # Obtener dispositivo a partir de camino, etiqueta o UUID.
330    DEV = dev[0]
331    if DEV.startswith("LABEL="):
332        DEV = subprocess.getoutput(f"blkid -L {DEV[6:]}")
333    elif DEV.startswith("PARTLABEL="):
334        DEV = subprocess.getoutput(f"realpath /dev/disk/by-partlabel/{DEV[11:]} 2>/dev/null")
335    elif DEV.startswith("PARTUUID="):
336        DEV = subprocess.getoutput(f"realpath /dev/disk/by-partuuid/{DEV[10:]} 2>/dev/null")
337    elif DEV.startswith("UUID="):
338        DEV = subprocess.getoutput(f"blkid -U {DEV[5:]}")
339
340    # Error si no es fichero de bloques o directorio (para LVM).
341    if not os.path.exists(DEV):
342        ogRaiseError(OG_ERR_NOTFOUND, dev)
343        return
344
345    # Buscar en fichero de caché de discos.
346    if os.path.exists(CACHEFILE):
347        with open(CACHEFILE, 'r') as f:
348            for line in f:
349                parts = line.strip().split(':')
350                if len(parts) == 2 and parts[1] == DEV:
351                    PART = parts[0]
352                    break
353
354    if PART:
355        return PART
356
357    # Si no se encuentra, procesa todos los discos para devolver su nº de orden y de partición.
358    disks = ogDiskToDev()
359    for d in disks:
360        NVME_PREFIX = "p" if "nvme" in d else ""
361        if DEV.startswith(d):
362            return f"{n} {DEV[len(d) + len(NVME_PREFIX):]}"
363        n += 1
364
365    ogRaiseError(OG_ERR_NOTFOUND, dev)
366    return OG_ERR_NOTFOUND
367
368def ogDiskToDev(*args):
369    # Variables locales
370    CACHEFILE = "/var/cache/disks.cfg"
371    ALLDISKS = []
372    MPATH = VOLGROUPS = ZFSVOLS = DISK = PART = ZPOOL = None
373    i = 1
374
375    # Si se solicita, mostrar ayuda.
376    if len(args) == 1 and args[0] == "help":
377        ogHelp('ogDiskToDev', 'ogDiskToDev int_ndisk [int_npartition]',
378               'ogDiskToDev      =>  /dev/sda /dev/sdb',
379               'ogDiskToDev 1    =>  /dev/sda',
380               'ogDiskToDev 1 1  =>  /dev/sda1')
381        return
382
383    # Borrar fichero de caché de configuración si hay cambios en las particiones.
384    if not filecmp.cmp('/proc/partitions', '/tmp/.partitions'):
385        # Guardar copia de las particiones definidas para comprobar cambios.
386        shutil.copy2('/proc/partitions', '/tmp/.partitions')
387        os.remove(CACHEFILE)
388
389    # Si existe una correspondencia con disco/dispositivo en el caché; mostrarlo y salir.
390    with open(CACHEFILE, 'r') as f:
391        for line in f:
392            parts = line.strip().split(':')
393            if len(parts) == 2 and parts[0] == ":".join(args):
394                print(parts[1])
395                return
396
397    # Continuar para detectar nuevos dispositivos.
398    # Listar dispositivos de discos.
399    all_disks = subprocess.getoutput("lsblk -n -e 1,2 -x MAJ:MIN 2>/dev/null || lsblk -n -e 1,2").splitlines()
400    for line in all_disks:
401        parts = line.split()
402        if parts[5] == "disk":
403            ALLDISKS.append(f"/dev/{parts[0]}")
404
405    # Listar volúmenes lógicos.
406    VOLGROUPS = subprocess.getoutput("vgs -a --noheadings 2>/dev/null").splitlines()
407    VOLGROUPS = [f"/dev/{line.split()[0]}" for line in VOLGROUPS]
408
409    # Detectar caminos múltiples (ignorar mensaje si no está configurado Multipath).
410    try:
411        MPATH = subprocess.getoutput("multipath -l -v 1 2>/dev/null").splitlines()
412        MPATH = [f"/dev/mapper/{line.split()[0]}" for line in MPATH]
413        # Quitar de la lista los discos que forman parte de Multipath.
414        for line in subprocess.getoutput("multipath -ll").splitlines():
415            if line.split()[5] == "ready":
416                disk = f"/dev/{line.split()[2]}"
417                if disk in ALLDISKS:
418                    ALLDISKS.remove(disk)
419    except subprocess.CalledProcessError:
420        MPATH = []
421
422    # Detectar volúmenes ZFS.
423    ZFSVOLS = subprocess.getoutput("blkid").splitlines()
424    ZFSVOLS = [line.split(":")[0] for line in ZFSVOLS if "zfs" in line]
425
426    # Mostrar salidas segun el número de parametros.
427    if len(args) == 0:
428        print(" ".join(ALLDISKS))
429    elif len(args) == 1:
430        # Error si el parámetro no es un número positivo.
431        if not args[0].isdigit() or int(args[0]) <= 0:
432            ogRaiseError(OG_ERR_FORMAT, args[0])
433            return
434        disk = ALLDISKS[int(args[0])-1]
435        # Error si el fichero no existe.
436        if not os.path.exists(disk):
437            ogRaiseError(OG_ERR_NOTFOUND, args[0])
438            return
439        # Actualizar caché de configuración y mostrar dispositivo.
440        with open(CACHEFILE, 'a') as f:
441            f.write(f"{args[0]}:{disk}\n")
442        print(disk)
443    elif len(args) == 2:
444        # Error si los 2 parámetros no son números positivos.
445        if not args[0].isdigit() or int(args[0]) <= 0 or not args[1].isdigit() or int(args[1]) <= 0:
446            ogRaiseError(OG_ERR_FORMAT, f"{args[0]} {args[1]}")
447            return
448        disk = ALLDISKS[int(args[0])-1]
449        # Error si el fichero no existe.
450        if not os.path.exists(disk):
451            ogRaiseError(OG_ERR_NOTFOUND, args[0])
452            return
453        part = f"{disk}{args[1]}"
454        # Comprobar si es partición.
455        if os.path.exists(part):
456            # Actualizar caché de configuración y mostrar dispositivo.
457            with open(CACHEFILE, 'a') as f:
458                f.write(f"{args[0]} {args[1]}:{part}\n")
459            print(part)
460        else:
461            # Comprobar si RAID o Multipath (tener en cuenta enlace simbólico).
462            part = f"{disk}p{args[1]}"
463            if os.path.exists(part) and os.stat(part, follow_symlinks=True).st_mode[0] == "b":
464                # Actualizar caché de configuración y mostrar dispositivo.
465                with open(CACHEFILE, 'a') as f:
466                    f.write(f"{args[0]} {args[1]}:{part}\n")
467                print(part)
468            else:
469                part = ""
470                # Comprobar si volumen lógico.
471                if disk in VOLGROUPS:
472                    lvscan = subprocess.getoutput("lvscan -a 2>/dev/null").splitlines()
473                    for line in lvscan:
474                        parts = line.split("'")
475                        if parts[1].startswith(f"{disk}/") and i == int(args[1]):
476                            part = parts[1]
477                            break
478                        i += 1
479                # Comprobar si volumen ZFS que puede ser montado.
480                if disk in ZFSVOLS:
481                    subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"], stderr=subprocess.DEVNULL)
482                    zpool = subprocess.getoutput(f"blkid -s LABEL -o value {disk}")
483                    zfs_list = subprocess.getoutput(f"zfs list -Hp -o name,canmount,mountpoint -r {zpool}").splitlines()
484                    for line in zfs_list:
485                        parts = line.split()
486                        if parts[1] == "on" and parts[2] != "none":
487                            if i == int(args[1]):
488                                part = parts[0]
489                                break
490                            i += 1
491                # Salir si no se encuentra dispositivo.
492                if not part:
493                    ogRaiseError(OG_ERR_NOTFOUND, f"{args[0]} {args[1]}")
494                    return
495                # Devolver camino al dispositivo.
496                # Actualizar caché de configuración y mostrar dispositivo.
497                with open(CACHEFILE, 'a') as f:
498                    f.write(f"{args[0]} {args[1]}:{part}\n")
499                print(part)
500    else:
501        ogRaiseError(OG_ERR_FORMAT)
502        return
503
504def ogGetDiskSize(*args):
505    # Variables locales
506    DISK = SIZE = None
507
508    # Si se solicita, mostrar ayuda.
509    if len(args) == 1 and args[0] == "help":
510        ogHelp('ogGetDiskSize', 'ogGetDiskSize int_ndisk', 'ogGetDiskSize 1  => 244198584')
511        return
512
513    # Error si no se recibe 1 parámetro.
514    if len(args) != 1:
515        ogRaiseError(OG_ERR_FORMAT)
516        return
517
518    # Obtener el tamaño del disco.
519    DISK = ogDiskToDev(args[0])
520    if DISK is None:
521        return
522    SIZE = subprocess.getoutput(f"lsblk -n -b -o SIZE {DISK}")
523
524    # Mostrar salida.
525    if SIZE:
526        print(SIZE)
527    return
528
529def ogGetDiskType(*args):
530    # Variables locales
531    DEV = MAJOR = TYPE = None
532
533    # Si se solicita, mostrar ayuda.
534    if len(args) == 1 and args[0] == "help":
535        ogHelp('ogGetDiskType', 'ogGetDiskType path_device', 'ogGetDiskType /dev/sdb  =>  USB')
536        return
537
538    # Error si no se recibe 1 parámetro.
539    if len(args) != 1:
540        ogRaiseError(OG_ERR_FORMAT)
541        return
542
543    # Obtener el driver del dispositivo de bloques.
544    DEV = args[0].split("/dev/")[1]
545    MAJOR = subprocess.getoutput(f"awk -v D='{DEV}' '{{if ($4==D) print $1;}}' /proc/partitions")
546    TYPE = subprocess.getoutput(f"awk -v D={MAJOR} '/Block/ {{bl=1}} {{if ($1==D&&bl) print toupper($2)}}' /proc/devices")
547    # Devolver mnemónico del driver de dispositivo.
548    if TYPE == "SD":
549        TYPE = "DISK"
550        if subprocess.getoutput(f"udevadm info -q property {args[0]} 2>/dev/null | grep -q '^ID_BUS=usb'"):
551            TYPE = "USB"
552    elif TYPE == "BLKEXT":
553        TYPE = "NVM"
554    elif TYPE == "SR" or TYPE.startswith("IDE"):
555        TYPE = "CDROM"  # FIXME Comprobar discos IDE.
556    elif TYPE == "MD" or TYPE.startswith("CCISS"):
557        TYPE = "RAID"
558    elif TYPE == "DEVICE-MAPPER":
559        TYPE = "MAPPER"  # FIXME Comprobar LVM y RAID.
560    print(TYPE)
561    return
562
563def ogGetEsp():
564
565    for d in subprocess.getoutput("blkid -o device").split():
566        # Previene error para /dev/loop0
567        PART = ogDevToDisk([d])
568        # En discos NVMe blkid devuelve una salida del tipo:
569        #    >/dev/loop0
570        #    >/dev/nvme0n1
571        #    >/dev/nvme0n1p1
572        # al analizar la particion nvme0n1, PART solo tiene un argumento y hace que ogGetPartitionId lance un error
573        LEN = len(PART)
574        if LEN > 1:
575            if ogGetPartitionId(PART) == ogTypeToId("EFI", "GPT"):
576                return PART
577    return None
578
579def ogGetLastSector(*args):
580    # Variables locales
581    DISK = None
582    PART = None
583    LASTSECTOR = None
584
585    # Si se solicita, mostrar ayuda.
586    if len(args) == 1 and args[0] == "help":
587        ogHelp("ogGetLastSector", "ogGetLastSector int_ndisk [int_npart]",
588               "ogGetLastSector 1  =>  488392064",
589               "ogGetLastSector 1 1  =>  102400062")
590        return
591
592    # Obtener último sector.
593    if len(args) == 1:  # Para un disco.
594        DISK = ogDiskToDev(args[0])
595        if DISK is None:
596            return
597        LASTSECTOR = subprocess.getoutput(f"sgdisk -p {DISK} | awk '/last usable sector/ {{print($(NF))}}'")
598    elif len(args) == 2:  # Para una partición.
599        DISK = ogDiskToDev(args[0])
600        if DISK is None:
601            return
602        PART = ogDiskToDev(args[0], args[1])
603        if PART is None:
604            return
605        LASTSECTOR = subprocess.getoutput(f"sgdisk -p {DISK} | awk -v P='{args[1]}' '{{if ($1==P) print $3}}'")
606    else:  # Error si se reciben más parámetros.
607        ogRaiseError(OG_ERR_FORMAT)
608        return
609
610    print(LASTSECTOR)
611    return
612
613def ogGetPartitionActive(*args):
614    # Variables locales
615    DISK = None
616
617    # Si se solicita, mostrar ayuda.
618    if len(args) == 1 and args[0] == "help":
619        ogHelp('ogGetPartitionActive', 'ogGetPartitionActive int_ndisk', 'ogGetPartitionActive 1  =>  1')
620        return
621
622    # Error si no se recibe 1 parámetro.
623    if len(args) != 1:
624        ogRaiseError(OG_ERR_FORMAT)
625        return
626
627    # Comprobar que el disco existe y listar su partición activa.
628    DISK = ogDiskToDev(args[0])
629    if DISK is None:
630        return
631    output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: '$7~/boot/ {{print $1}}'")
632    print(output)
633    return
634
635def ogGetPartitionId(*args):
636    # Variables locales
637    DISK = None
638    ID = None
639
640    # Si se solicita, mostrar ayuda.
641    if len(args) == 1 and args[0] == "help":
642        ogHelp('ogGetPartitionId', 'ogGetPartitionId int_ndisk int_npartition', 'ogGetPartitionId 1 1  =>  7')
643        return
644
645    # Error si no se reciben 2 parámetros.
646    if len(args) != 2:
647        ogRaiseError(OG_ERR_FORMAT)
648        return
649
650    # Detectar y mostrar el id. de tipo de partición.
651    DISK = ogDiskToDev(args[0])
652    if DISK is None:
653        return
654    PTTYPE = ogGetPartitionTableType(args[0])
655    if PTTYPE == "GPT":
656        ID = subprocess.getoutput(f"sgdisk -p {DISK} 2>/dev/null | awk -v p={args[1]} '{{if ($1==p) print $6;}}'")
657        if ID == "8300" and f"{args[0]} {args[1]}" == ogFindCache():
658            ID = "CA00"
659    elif PTTYPE == "MSDOS":
660        ID = subprocess.getoutput(f"sfdisk --id {DISK} {args[1]} 2>/dev/null")
661    elif PTTYPE == "LVM":
662        ID = "10000"
663    elif PTTYPE == "ZPOOL":
664        ID = "10010"
665
666    print(ID)
667    return
668
669def ogGetPartitionSize(*args):
670    # Variables locales
671    PART = None
672    SIZE = None
673
674    # Si se solicita, mostrar ayuda.
675    if len(args) == 1 and args[0] == "help":
676        ogHelp('ogGetPartitionSize', 'ogGetPartitionSize int_ndisk int_npartition', 'ogGetPartitionSize 1 1  =>  10000000')
677        return
678
679    # Error si no se reciben 2 parámetros.
680    if len(args) != 2:
681        ogRaiseError(OG_ERR_FORMAT)
682        return
683
684    # Devolver tamaño de partición, del volumen lógico o del sistema de archivos (para ZFS).
685    PART = ogDiskToDev(args[0], args[1])
686    if PART is None:
687        return
688    SIZE = subprocess.getoutput(f"partx -gbo SIZE {PART} 2>/dev/null | awk '{{print int($1/1024)}}'")
689    if not SIZE:
690        SIZE = subprocess.getoutput(f"lvs --noheadings -o lv_size --units k {PART} | awk '{{printf \"%d\",$0}}'")
691    if not SIZE:
692        SIZE = ogGetFsSize(args[0], args[1])
693    print(SIZE or 0)
694    return
695
696def ogGetPartitionsNumber(*args):
697    # Variables locales
698    DISK = None
699
700    # Si se solicita, mostrar ayuda.
701    if len(args) == 1 and args[0] == "help":
702        ogHelp('ogGetPartitionsNumber', 'ogGetPartitionsNumber int_ndisk', 'ogGetPartitionsNumber 1  =>  3')
703        return
704
705    # Error si no se recibe 1 parámetro.
706    if len(args) != 1:
707        ogRaiseError(OG_ERR_FORMAT)
708        return
709
710    # Contar el número de veces que aparece el disco en su lista de particiones.
711    DISK = ogDiskToDev(args[0])
712    if DISK is None:
713        return
714    PTTYPE = ogGetPartitionTableType(args[0])
715    if PTTYPE in ["GPT", "MSDOS"]:
716        output = subprocess.getoutput(f"partx -gso NR {DISK} 2>/dev/null | awk -v p=0 '{{p=$1}} END {{print p}}'")
717    elif PTTYPE == "LVM":
718        output = subprocess.getoutput(f"lvs --noheadings {DISK} 2>/dev/null | wc -l")
719    elif PTTYPE == "ZPOOL":
720        subprocess.run(["zpool", "list"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)  # Check if zpool command exists
721        subprocess.run(["modprobe", "zfs"])  # Load zfs module if not already loaded
722        subprocess.run(["zpool", "import", "-f", "-R", "/mnt", "-N", "-a"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)  # Import all zpools
723        output = subprocess.getoutput(f"zfs list -Hp -o name,canmount,mountpoint -r $(blkid -s LABEL -o value {DISK}) | awk '$2==\"on\" && $3!=\"none\" {{c++}} END {{print c}}'")
724    else:
725        output = None
726
727    print(output)
728    return
729
730def ogGetPartitionTableType(*args):
731    # Variables locales
732    DISK = None
733    TYPE = None
734
735    # Si se solicita, mostrar ayuda.
736    if len(args) == 1 and args[0] == "help":
737        ogHelp('ogGetPartitionTableType', 'ogGetPartitionTableType int_ndisk', 'ogGetPartitionTableType 1  =>  MSDOS')
738        return
739
740    # Error si no se recibe 1 parámetro.
741    if len(args) != 1:
742        ogRaiseError(OG_ERR_FORMAT)
743        return
744
745    # Sustituye n de disco por su dispositivo.
746    DISK = ogDiskToDev(args[0])
747    if DISK is None:
748        return
749
750    # Comprobar tabla de particiones.
751    if os.path.exists(DISK):
752        output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'")
753        if not output:
754            output = subprocess.getoutput(f"parted -sm {DISK} print 2>/dev/null | awk -F: -v D={DISK} '{{ if($1 == D) print toupper($6)}}'")
755    # Comprobar si es volumen lógico.
756    if os.path.isdir(DISK) and subprocess.run(["vgs", DISK], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0:
757        output = "LVM"
758    # Comprobar si es pool de ZFS.
759    if not output or output == "UNKNOWN":
760        blkid_output = subprocess.getoutput(f"blkid -s TYPE {DISK} | grep zfs")
761        if blkid_output:
762            output = "ZPOOL"
763
764    # Mostrar salida.
765    if output:
766        print(output)
767    return
768
769def ogGetPartitionType(*args):
770    # Variables locales
771    ID = None
772    TYPE = None
773
774    # Si se solicita, mostrar ayuda.
775    if len(args) == 1 and args[0] == "help":
776        ogHelp('ogGetPartitionType', 'ogGetPartitionType int_ndisk int_npartition', 'ogGetPartitionType 1 1  =>  NTFS')
777        return
778
779    # Error si no se reciben 2 parámetros.
780    if len(args) != 2:
781        ogRaiseError(OG_ERR_FORMAT)
782        return
783
784    # Detectar id. de tipo de partición y codificar al mnemónico.
785    ID = ogGetPartitionId(args[0], args[1])
786    if ID is None:
787        return
788    TYPE = ogIdToType(ID)
789    print(TYPE)
790    return
791
792def ogHidePartition(*args):
793    # Variables locales
794    PART = None
795    TYPE = None
796    NEWTYPE = None
797
798    # Si se solicita, mostrar ayuda.
799    if len(args) == 1 and args[0] == "help":
800        ogHelp('ogHidePartition', 'ogHidePartition int_ndisk int_npartition', 'ogHidePartition 1 1')
801        return
802
803    # Error si no se reciben 2 parámetros.
804    if len(args) != 2:
805        ogRaiseError(OG_ERR_FORMAT)
806        return
807
808    # Obtener el dispositivo de la partición.
809    PART = ogDiskToDev(args[0], args[1])
810    if PART is None:
811        return
812
813    # Obtener tipo de partición.
814    TYPE = ogGetPartitionType(args[0], args[1])
815    if TYPE == "NTFS":
816        NEWTYPE = "HNTFS"
817    elif TYPE == "FAT32":
818        NEWTYPE = "HFAT32"
819    elif TYPE == "FAT16":
820        NEWTYPE = "HFAT16"
821    elif TYPE == "FAT12":
822        NEWTYPE = "HFAT12"
823    elif TYPE == "WINDOWS":
824        NEWTYPE = "WIN-RESERV"
825    else:
826        ogRaiseError(OG_ERR_PARTITION, TYPE)
827        return
828
829    # Cambiar tipo de partición.
830    ogSetPartitionType(args[0], args[1], NEWTYPE)
831    return
832
833def ogIdToType(ID):
834    # Obtener valor hexadecimal de 4 caracteres rellenado con 0 por delante.
835    ID = ID.zfill(4)
836    TYPE = None
837
838    # Asignar el tipo de partición según el ID.
839    if ID == "0000":
840        TYPE = "EMPTY"
841    elif ID == "0001":
842        TYPE = "FAT12"
843    elif ID in ["0005", "000f"]:
844        TYPE = "EXTENDED"
845    elif ID in ["0006", "000e"]:
846        TYPE = "FAT16"
847    elif ID == "0007":
848        TYPE = "NTFS"
849    elif ID in ["000b", "000c"]:
850        TYPE = "FAT32"
851    elif ID == "0011":
852        TYPE = "HFAT12"
853    elif ID == "0012":
854        TYPE = "COMPAQDIAG"
855    elif ID in ["0016", "001e"]:
856        TYPE = "HFAT16"
857    elif ID == "0017":
858        TYPE = "HNTFS"
859    elif ID in ["001b", "001c"]:
860        TYPE = "HFAT32"
861    elif ID == "0042":
862        TYPE = "WIN-DYNAMIC"
863    elif ID in ["0082", "8200"]:
864        TYPE = "LINUX-SWAP"
865    elif ID in ["0083", "8300"]:
866        TYPE = "LINUX"
867    elif ID in ["008e", "8E00"]:
868        TYPE = "LINUX-LVM"
869    elif ID in ["00a5", "a503"]:
870        TYPE = "FREEBSD"
871    elif ID == "00a6":
872        TYPE = "OPENBSD"
873    elif ID == "00a7":
874        TYPE = "CACHE"  # (compatibilidad con Brutalix)
875    elif ID in ["00af", "af00"]:
876        TYPE = "HFS"
877    elif ID in ["00be", "be00"]:
878        TYPE = "SOLARIS-BOOT"
879    elif ID in ["00bf", "bf00145"]:
880        TYPE = "SOLARIS"
881    elif ID in ["00ca", "ca00"]:
882        TYPE = "CACHE"
883    elif ID == "00da":
884        TYPE = "DATA"
885    elif ID == "00ee":
886        TYPE = "GPT"
887    elif ID in ["00ef", "ef00"]:
888        TYPE = "EFI"
889    elif ID == "00fb":
890        TYPE = "VMFS"
891    elif ID in ["00fd", "fd00"]:
892        TYPE = "LINUX-RAID"
893    elif ID == "0700":
894        TYPE = "WINDOWS"
895    elif ID == "0c01":
896        TYPE = "WIN-RESERV"
897    elif ID == "7f00":
898        TYPE = "CHROMEOS-KRN"
899    elif ID == "7f01":
900        TYPE = "CHROMEOS"
901    elif ID == "7f02":
902        TYPE = "CHROMEOS-RESERV"
903    elif ID == "8301":
904        TYPE = "LINUX-RESERV"
905    elif ID == "a500":
906        TYPE = "FREEBSD-DISK"
907    elif ID == "a501":
908        TYPE = "FREEBSD-BOOT"
909    elif ID == "a502":
910        TYPE = "FREEBSD-SWAP"
911    elif ID == "ab00":
912        TYPE = "HFS-BOOT"
913    elif ID == "af01":
914        TYPE = "HFS-RAID"
915    elif ID == "bf02":
916        TYPE = "SOLARIS-SWAP"
917    elif ID == "bf03":
918        TYPE = "SOLARIS-DISK"
919    elif ID == "ef01":
920        TYPE = "MBR"
921    elif ID == "ef02":
922        TYPE = "BIOS-BOOT"
923    elif ID == "10000":
924        TYPE = "LVM-LV"
925    elif ID == "10010":
926        TYPE = "ZFS-VOL"
927    else:
928        TYPE = "UNKNOWN"
929
930    return TYPE
931
932def ogIsDiskLocked(*args):
933    # Variables locales
934    DISK = None
935    LOCKFILE = None
936
937    # Si se solicita, mostrar ayuda.
938    if len(args) == 1 and args[0] == "help":
939        ogHelp('ogIsDiskLocked', 'ogIsDiskLocked int_ndisk', 'if ogIsDiskLocked(1): ...')
940        return
941
942    # Falso, en caso de error.
943    if len(args) != 1:
944        return False
945    DISK = ogDiskToDev(args[0], 2)
946    if DISK is None:
947        return False
948
949    # Comprobar existencia de fichero de bloqueo para el disco.
950    LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}"
951    return os.path.isfile(LOCKFILE)
952
953def ogListPartitions(*args):
954    # Variables locales
955    DISK = None
956    PART = None
957    NPARTS = None
958    TYPE = None
959    SIZE = None
960
961    # Si se solicita, mostrar ayuda.
962    if len(args) == 1 and args[0] == "help":
963        ogHelp('ogListPartitions', 'ogListPartitions int_ndisk', 'ogListPartitions 1  =>  NTFS:10000000 EXT3:5000000 LINUX-SWAP:1000000')
964        return
965
966    # Error si no se recibe 1 parámetro.
967    if len(args) != 1:
968        ogRaiseError(OG_ERR_FORMAT)
969        return
970
971    # Procesar la salida de parted.
972    DISK = ogDiskToDev(args[0])
973    if DISK is None:
974        return
975    NPARTS = ogGetPartitionsNumber(args[0])
976    for PART in range(1, NPARTS + 1):
977        TYPE = ogGetPartitionType(args[0], PART) or "EMPTY"
978        SIZE = ogGetPartitionSize(args[0], PART) or 0
979        print(f"{TYPE}:{SIZE} ", end="")
980    print()
981    return
982
983def ogListPrimaryPartitions():
984    # Variables locales
985    PTTYPE = None
986    PARTS = None
987
988    # Si se solicita, mostrar ayuda.
989    if len(args) == 1 and args[0] == "help":
990        ogHelp('ogListPrimaryPartitions', 'ogListPrimaryPartitions int_ndisk', 'ogListPrimaryPartitions 1  =>  NTFS:10000000 EXT3:5000000 EXTENDED:1000000')
991        return
992
993    PTTYPE = ogGetPartitionTableType(args[0])
994    if PTTYPE is None:
995        return
996    PARTS = ogListPartitions(*args)
997    if PARTS is None:
998        return
999
1000    if PTTYPE == "GPT":
1001        print(PARTS.rstrip(" EMPTY:0"))
1002    elif PTTYPE == "MSDOS":
1003        print(PARTS.split(" ")[0:4])
1004    return
1005
1006def ogListLogicalPartitions(*args):
1007    # Variables locales
1008    PTTYPE = None
1009    PARTS = None
1010
1011    # Si se solicita, mostrar ayuda.
1012    if len(args) == 1 and args[0] == "help":
1013        ogHelp('ogListLogicalPartitions', 'ogListLogicalPartitions int_ndisk', 'ogListLogicalPartitions 1  =>  LINUX-SWAP:999998')
1014        return
1015
1016    PTTYPE = ogGetPartitionTableType(args[0])
1017    if PTTYPE is None:
1018        return
1019    PARTS = ogListPartitions(*args)
1020    if PARTS is None:
1021        return
1022
1023    return PARTS.split(" ")[4:]
1024
1025def ogLockDisk(*args):
1026    # Variables locales
1027    DISK = None
1028    LOCKFILE = None
1029
1030    # Si se solicita, mostrar ayuda.
1031    if len(args) == 1 and args[0] == "help":
1032        ogHelp('ogLockDisk', 'ogLockDisk int_ndisk', 'ogLockDisk 1')
1033        return
1034
1035    # Error si no se recibe 1 parámetro.
1036    if len(args) != 1:
1037        ogRaiseError(OG_ERR_FORMAT)
1038        return
1039
1040    # Obtener partición.
1041    DISK = ogDiskToDev(args[0])
1042    if DISK is None:
1043        return
1044
1045    # Crear archivo de bloqueo exclusivo.
1046    LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}"
1047    open(LOCKFILE, 'a').close()
1048
1049def ogSetPartitionActive(*args):
1050    # Variables locales
1051    DISK = None
1052    PART = None
1053
1054    # Si se solicita, mostrar ayuda.
1055    if len(args) == 1 and args[0] == "help":
1056        ogHelp('ogSetPartitionActive', 'ogSetPartitionActive int_ndisk int_npartition', 'ogSetPartitionActive 1 1')
1057        return
1058
1059    # Error si no se reciben 2 parámetros.
1060    if len(args) != 2:
1061        ogRaiseError(OG_ERR_FORMAT)
1062        return
1063
1064    # Comprobar que el disco existe y activar la partición indicada.
1065    DISK = ogDiskToDev(args[0])
1066    if DISK is None:
1067        return
1068    PART = ogDiskToDev(args[0], args[1])
1069    if PART is None:
1070        return
1071    subprocess.run(["parted", "-s", DISK, "set", args[1], "boot", "on"], stderr=subprocess.DEVNULL)
1072    return
1073
1074def ogSetPartitionId(*args):
1075    # Variables locales
1076    DISK = None
1077    PART = None
1078    PTTYPE = None
1079    ID = None
1080
1081    # Si se solicita, mostrar ayuda.
1082    if len(args) == 1 and args[0] == "help":
1083        ogHelp('ogSetPartitionId', 'ogSetPartitionId int_ndisk int_npartition hex_partid', 'ogSetPartitionId 1 1 7')
1084        return
1085
1086    # Error si no se reciben 3 parámetros.
1087    if len(args) != 3:
1088        ogRaiseError(OG_ERR_FORMAT)
1089        return
1090
1091    # Sustituye nº de disco y nº partición por su dispositivo.
1092    DISK = ogDiskToDev(args[0])
1093    if DISK is None:
1094        return
1095    PART = ogDiskToDev(args[0], args[1])
1096    if PART is None:
1097        return
1098    # Error si el id. de partición no es hexadecimal.
1099    ID = args[2].upper()
1100    if not re.match("^[0-9A-F]+$", ID):
1101        ogRaiseError(OG_ERR_OUTOFLIMIT, args[2])
1102        return
1103
1104    # Elección del tipo de partición.
1105    PTTYPE = ogGetPartitionTableType(args[0])
1106    if PTTYPE == "GPT":
1107        subprocess.run(["sgdisk", f"-t{args[1]}:{ID}", DISK], stderr=subprocess.DEVNULL)
1108    elif PTTYPE == "MSDOS":
1109        subprocess.run(["sfdisk", f"--id", DISK, args[1], ID], stderr=subprocess.DEVNULL)
1110    else:
1111        ogRaiseError(OG_ERR_OUTOFLIMIT, f"{args[0]},{PTTYPE}")
1112        return
1113
1114    # MSDOS) Correcto si fdisk sin error o con error pero realiza Syncing
1115    if subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL).returncode == 0:
1116        return
1117    else:
1118        ogRaiseError(OG_ERR_PARTITION, f"{args[0]},{args[1]},{args[2]}")
1119        return
1120
1121def ogSetPartitionSize(*args):
1122    # Variables locales
1123    DISK = None
1124    PART = None
1125    SIZE = None
1126
1127    # Si se solicita, mostrar ayuda.
1128    if len(args) == 1 and args[0] == "help":
1129        ogHelp('ogSetPartitionSize', 'ogSetPartitionSize int_ndisk int_npartition int_size', 'ogSetPartitionSize 1 1 10000000')
1130        return
1131
1132    # Error si no se reciben 3 parámetros.
1133    if len(args) != 3:
1134        ogRaiseError(OG_ERR_FORMAT)
1135        return
1136
1137    # Obtener el tamaño de la partición.
1138    DISK = ogDiskToDev(args[0])
1139    if DISK is None:
1140        return
1141    PART = ogDiskToDev(args[0], args[1])
1142    if PART is None:
1143        return
1144    # Convertir tamaño en KB a sectores de 512 B.
1145    SIZE = int(args[2]) * 2
1146    # Redefinir el tamaño de la partición.
1147    subprocess.run(["sfdisk", "-f", "-uS", f"-N{args[1]}", DISK], input=f",{SIZE}", text=True, stderr=subprocess.DEVNULL)
1148    subprocess.run(["partprobe", DISK], stderr=subprocess.DEVNULL)
1149    return
1150
1151def ogSetPartitionType(*args):
1152    # Variables locales
1153    DISK = None
1154    PART = None
1155    PTTYPE = None
1156    TYPE = None
1157
1158    # Si se solicita, mostrar ayuda.
1159    if len(args) == 1 and args[0] == "help":
1160        ogHelp('ogSetPartitionType', 'ogSetPartitionType int_ndisk int_npartition str_type', 'ogSetPartitionType 1 1 NTFS')
1161        return
1162
1163    # Error si no se reciben 3 parámetros.
1164    if len(args) != 3:
1165        ogRaiseError(OG_ERR_FORMAT)
1166        return
1167
1168    # Sustituye nº de disco por su dispositivo.
1169    DISK = ogDiskToDev(args[0])
1170    if DISK is None:
1171        return
1172    PART = ogDiskToDev(args[0], args[1])
1173    if PART is None:
1174        return
1175
1176    # Elección del tipo de partición.
1177    PTTYPE = ogGetPartitionTableType(args[0])
1178    if PTTYPE is None:
1179        return
1180    TYPE = args[2]
1181    ID = ogTypeToId(TYPE, PTTYPE)
1182    if ID is None:
1183        ogRaiseError(OG_ERR_FORMAT, f"{TYPE},{PTTYPE}")
1184        return
1185
1186    ogSetPartitionId(args[0], args[1], ID)
1187    return
1188
1189def ogTypeToId(TYPE, PTTYPE="MSDOS"):
1190    # Asociar id. de partición para su mnemónico.
1191    ID = ""
1192
1193    # Elección del tipo de partición.
1194    if PTTYPE == "GPT":
1195        if TYPE == "EMPTY":
1196            ID = "0"
1197        elif TYPE in ["WINDOWS", "NTFS", "EXFAT", "FAT32", "FAT16", "FAT12", "HNTFS", "HFAT32", "HFAT16", "HFAT12"]:
1198            ID = "0700"
1199        elif TYPE == "WIN-RESERV":
1200            ID = "0C01"
1201        elif TYPE == "CHROMEOS-KRN":
1202            ID = "7F00"
1203        elif TYPE == "CHROMEOS":
1204            ID = "7F01"
1205        elif TYPE == "CHROMEOS-RESERV":
1206            ID = "7F02"
1207        elif TYPE == "LINUX-SWAP":
1208            ID = "8200"
1209        elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]:
1210            ID = "8300"
1211        elif TYPE == "LINUX-RESERV":
1212            ID = "8301"
1213        elif TYPE == "LINUX-LVM":
1214            ID = "8E00"
1215        elif TYPE == "FREEBSD-DISK":
1216            ID = "A500"
1217        elif TYPE == "FREEBSD-BOOT":
1218            ID = "A501"
1219        elif TYPE == "FREEBSD-SWAP":
1220            ID = "A502"
1221        elif TYPE == "FREEBSD":
1222            ID = "A503"
1223        elif TYPE == "HFS-BOOT":
1224            ID = "AB00"
1225        elif TYPE in ["HFS", "HFS+"]:
1226            ID = "AF00"
1227        elif TYPE == "HFS-RAID":
1228            ID = "AF01"
1229        elif TYPE == "SOLARIS-BOOT":
1230            ID = "BE00"
1231        elif TYPE == "SOLARIS":
1232            ID = "BF00"
1233        elif TYPE == "SOLARIS-SWAP":
1234            ID = "BF02"
1235        elif TYPE == "SOLARIS-DISK":
1236            ID = "BF03"
1237        elif TYPE == "CACHE":
1238            ID = "CA00"
1239        elif TYPE == "EFI":
1240            ID = "EF00"
1241        elif TYPE == "LINUX-RAID":
1242            ID = "FD00"
1243    elif PTTYPE == "MSDOS":
1244        if TYPE == "EMPTY":
1245            ID = "0"
1246        elif TYPE == "FAT12":
1247            ID = "1"
1248        elif TYPE == "EXTENDED":
1249            ID = "5"
1250        elif TYPE == "FAT16":
1251            ID = "6"
1252        elif TYPE in ["WINDOWS", "NTFS", "EXFAT"]:
1253            ID = "7"
1254        elif TYPE == "FAT32":
1255            ID = "b"
1256        elif TYPE == "HFAT12":
1257            ID = "11"
1258        elif TYPE == "HFAT16":
1259            ID = "16"
1260        elif TYPE == "HNTFS":
1261            ID = "17"
1262        elif TYPE == "HFAT32":
1263            ID = "1b"
1264        elif TYPE == "LINUX-SWAP":
1265            ID = "82"
1266        elif TYPE in ["LINUX", "EXT2", "EXT3", "EXT4", "REISERFS", "REISER4", "XFS", "JFS"]:
1267            ID = "83"
1268        elif TYPE == "LINUX-LVM":
1269            ID = "8e"
1270        elif TYPE == "FREEBSD":
1271            ID = "a5"
1272        elif TYPE == "OPENBSD":
1273            ID = "a6"
1274        elif TYPE in ["HFS", "HFS+"]:
1275            ID = "af"
1276        elif TYPE == "SOLARIS-BOOT":
1277            ID = "be"
1278        elif TYPE == "SOLARIS":
1279            ID = "bf"
1280        elif TYPE == "CACHE":
1281            ID = "ca"
1282        elif TYPE == "DATA":
1283            ID = "da"
1284        elif TYPE == "GPT":
1285            ID = "ee"
1286        elif TYPE == "EFI":
1287            ID = "ef"
1288        elif TYPE == "VMFS":
1289            ID = "fb"
1290        elif TYPE == "LINUX-RAID":
1291            ID = "fd"
1292    elif PTTYPE == "LVM":
1293        if TYPE == "LVM-LV":
1294            ID = "10000"
1295    elif PTTYPE == "ZVOL":
1296        if TYPE == "ZFS-VOL":
1297            ID = "10010"
1298
1299    return ID
1300
1301def ogUnhidePartition(*args):
1302    # Variables locales
1303    PART = None
1304    TYPE = None
1305    NEWTYPE = None
1306
1307    # Si se solicita, mostrar ayuda.
1308    if len(args) == 1 and args[0] == "help":
1309        ogHelp('ogUnhidePartition', 'ogUnhidePartition int_ndisk int_npartition', 'ogUnhidePartition 1 1')
1310        return
1311
1312    # Error si no se reciben 2 parámetros.
1313    if len(args) != 2:
1314        ogRaiseError(OG_ERR_FORMAT)
1315        return
1316
1317    PART = ogDiskToDev(args[0], args[1])
1318    if PART is None:
1319        return
1320
1321    # Obtener tipo de partición.
1322    TYPE = ogGetPartitionType(args[0], args[1])
1323    if TYPE == "HNTFS":
1324        NEWTYPE = "NTFS"
1325    elif TYPE == "HFAT32":
1326        NEWTYPE = "FAT32"
1327    elif TYPE == "HFAT16":
1328        NEWTYPE = "FAT16"
1329    elif TYPE == "HFAT12":
1330        NEWTYPE = "FAT12"
1331    elif TYPE == "WIN-RESERV":
1332        NEWTYPE = "WINDOWS"
1333    else:
1334        ogRaiseError(OG_ERR_PARTITION, TYPE)
1335        return
1336
1337    # Cambiar tipo de partición.
1338    ogSetPartitionType(args[0], args[1], NEWTYPE)
1339    return
1340
1341def ogUnlockDisk(*args):
1342    # Variables locales
1343    DISK = None
1344    LOCKFILE = None
1345
1346    # Si se solicita, mostrar ayuda.
1347    if len(args) == 1 and args[0] == "help":
1348        ogHelp('ogUnlockDisk', 'ogUnlockDisk int_ndisk', 'ogUnlockDisk 1')
1349        return
1350
1351    # Error si no se recibe 1 parámetro.
1352    if len(args) != 1:
1353        ogRaiseError(OG_ERR_FORMAT)
1354        return
1355
1356    # Obtener partición.
1357    DISK = ogDiskToDev(args[0])
1358    if DISK is None:
1359        return
1360
1361    # Borrar archivo de bloqueo exclusivo.
1362    LOCKFILE = f"/var/lock/lock{DISK.replace('/', '-')}"
1363    os.remove(LOCKFILE)
1364    return
1365
1366def ogUpdatePartitionTable():
1367    for disk in ogDiskToDev():
1368        subprocess.run(["partprobe", disk])
Note: See TracBrowser for help on using the repository browser.