source: client/engine/DiskLib.py @ f160ff2

test-python-scriptsticket-693
Last change on this file since f160ff2 was 7260bdc2, checked in by Antonio Emmanuel Guerrero Silva <aguerrero@…>, 9 months ago

refs #585 Libraries convert to Python3

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