From d082bcf9160fac4fe332031475846518b9552b95 Mon Sep 17 00:00:00 2001 From: Natalia Serrano Date: Thu, 12 Dec 2024 10:54:45 +0100 Subject: [PATCH] refs #1218 add ogGrubInstallMbr() --- client/lib/engine/bin/BootLib.py | 109 ++++++++++++++++++++++- client/lib/engine/bin/UEFILib.py | 12 +-- client/shared/scripts/updateBootCache.py | 62 +++++++++++++ 3 files changed, 174 insertions(+), 9 deletions(-) create mode 100755 client/shared/scripts/updateBootCache.py diff --git a/client/lib/engine/bin/BootLib.py b/client/lib/engine/bin/BootLib.py index 3331aec..3b4e045 100644 --- a/client/lib/engine/bin/BootLib.py +++ b/client/lib/engine/bin/BootLib.py @@ -20,6 +20,7 @@ import RegistryLib import DiskLib import InventoryLib import FileLib +import UEFILib #/** # ogBoot int_ndisk int_nfilesys [ NVRAMPERM ] [str_kernel str_initrd str_krnlparams] @@ -393,6 +394,106 @@ part_letter={registered_vol} #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +#ogGrubInstallMbr ('1', '1', 'FALSE') +#ogGrubInstallMbr ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') +def ogGrubInstallMbr (disk, par, checkos='FALSE', kernelparam=''): + backupname = '.backup.og' + + #error si no es linux. + #version = InventoryLib.ogGetOsVersion (disk, par) + #if not version or 'Linux' not in version: + # SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') + # return + + firststage = DiskLib.ogDiskToDev ('1') #La primera etapa del grub se fija en el primer disco duro + secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub + if not secondstage: return + os.makedirs (f'{secondstage}/boot/grub/', exist_ok=True) + prefixsecondstage = '/boot/grubMBR' #Localizar directorio segunda etapa del grub + efioptgrub = [] + + if InventoryLib.ogIsEfiActive(): + esp = DiskLib.ogGetEsp() + efidisk, efipart = esp.split() + # Comprobamos que exista ESP y el directorio para ubuntu + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') + efisecondstage = FileSystemLib.ogMount (efidisk, efipart) + if not efisecondstage: + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_PARTITION, 'ESP') + return + efisubdir = 'grub' + if os.path.isdir (f'{efisecondstage}/EFI/{efisubdir}'): # Borramos la configuración anterior + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}') + os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') + arch = InventoryLib.ogGetArch() + efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] + + # Si Reconfigurar segunda etapa (grub.cfg) == FALSE + if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + if os.path.isdir (f'{secondstage}{prefixsecondstage}'): + shutil.rmtree (f'{secondstage}{prefixsecondstage}') + prefixsecondstage = '' # Reactivamos el grub con el grub.cfg original. + else: # SI Reconfigurar segunda etapa (grub.cfg) == TRUE + #llamada a updateBootCache para que aloje la primera fase del ogLive + subprocess.run (['scripts/updateBootCache.py'], check=True) ## nati: TODO: ver el path + + if InventoryLib.ogIsEfiActive(): + # UEFI: grubSintax necesita grub.cfg para detectar los kernels: si no existe recupero backup. + if not os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}'): + os.rename (f'{secondstage}/boot/grub/grub.cfg{backupname}', f'{secondstage}/boot/grub/grub.cfg') + else: + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + + with open ('/etc/default/grub', 'a') as fd: #Configur la sintaxis grub para evitar menus de "recovery" en el OGLive + fd.write ('GRUB_DISABLE_RECOVERY="true"\n') + fd.write ('GRUB_DISABLE_LINUX_UUID="true"\n') + + os.makedirs (f'{secondstage}{prefixsecondstage}/boot/grub/') #Preparar configuración segunda etapa: crear ubicacion + subprocess.run (['sed', '-i', 's/^set -e/#set -e/', '/etc/grub.d/00_header']) #Preparar configuración segunda etapa: crear cabecera del fichero (ingnorar errores) + # (ogLive 5.0) Si 'pkgdatadir' está vacía ponemos valor de otros ogLive + subprocess.run (['sed', '-i', '/grub-mkconfig_lib/i\pkgdatadir=${pkgdatadir:-"${datarootdir}/grub"}', '/etc/grub.d/00_header']) + out = subprocess.run (['/etc/grub.d/00_header'], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'w') as fd: + fd.write (out + '\n') + + #Preparar configuración segunda etapa: crear entrada del sistema operativo + out = subprocess.run (['grubSyntax', kernelparam], capture_output=True, text=True).stdout + with open (f'{secondstage}{prefixsecondstage}/boot/grub/grub.cfg', 'a') as fd: + fd.write (out + '\n') + + # Renombramos la configuración de grub antigua + if os.path.exists (f'{secondstage}/boot/grub/grub.cfg'): + os.rename (f'{secondstage}/boot/grub/grub.cfg', f'{secondstage}/boot/grub/grub.cfg{backupname}') + + eval = subprocess.run (['grub-install', '--force'] + efioptgrub + [f'--root-directory={secondstage}{prefixsecondstage}', firststage]).returncode + + if InventoryLib.ogIsEfiActive(): # Movemos el grubx64.efi + for b in (glob.glob (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/*')): + os.rename (f'{efisecondstage}/EFI/{efisubdir}/EFI/BOOT/{b}', f'{efisecondstage}/EFI/{efisubdir}/Boot/{b}') + shutil.rmtree (f'{efisecondstage}/EFI/{efisubdir}/EFI') + shutil.copy2 ('/usr/lib/shim/shimx64.efi.signed', f'{efisecondstage}/EFI/{efisubdir}/Boot/shimx64.efi') + # Nombre OpenGnsys para cargador + shutil.copy2 (f'{efisecondstage}/EFI/{efisubdir}/Boot/grubx64.efi', f'{efisecondstage}/EFI/{efisubdir}/Boot/ogloader.efi') + + # Creamos entrada NVRAM y la ponemos en segundo lugar + UEFILib.ogNvramAddEntry ('grub', '/EFI/grub/Boot/shimx64.efi') + grubentry = UEFILib.ogNvramList() + for l in grubentry.splitlines(): + words = l.split (maxsplit=1) + if len(words) < 2: continue + if 'grub' == words[1]: + grubentry = words[0] + neworder = UEFILib.ogNvramGetOrder() + neworder = neworder[0:1] + [grubentry] + neworder[1:] ## la ponemos en segundo lugar + UEFILib.ogNvramSetOrder (neworder) + + return eval + #/** # ogGrubInstallPartition int_disk_SECONDSTAGE int_partition_SECONDSTAGE bolean_Check_Os_installed_and_Configure_2ndStage @@ -405,9 +506,12 @@ part_letter={registered_vol} #@exception OG_ERR_FORMAT Formato incorrecto. #*/ ## +#ogGrubInstallPartition ('1', '1', 'FALSE') +#ogGrubInstallPartition ('1', '1', 'TRUE', 'nomodeset irqpoll pci=noacpi quiet splash') def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): backupname = '.backup.og' + #error si no es linux. version = InventoryLib.ogGetOsVersion (disk, par) if not version or 'Linux' not in version: SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTOS, 'no es linux') @@ -416,12 +520,12 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): firststage = DiskLib.ogDiskToDev (disk, par) #Localizar primera etapa del grub secondstage = FileSystemLib.ogMount (disk, par) #localizar disco segunda etapa del grub prefixsecondstage = '/boot/grubPARTITION' #Localizar directorio segunda etapa del grub - efioptgrub = [] # Si es EFI instalamos el grub en la ESP - #efibootdir = '' # Desde el bootdir uefi y bios buscan el grub.cfg en subdirectorios distintos. + efioptgrub = [] if InventoryLib.ogIsEfiActive(): esp = DiskLib.ogGetEsp() efidisk, efipart = esp.split() + # Comprobamos que exista ESP y el directorio para ubuntu efisecondstage = FileSystemLib.ogMount (efidisk, efipart) if not efisecondstage: FileSystemLib.ogFormat (efidisk, efipart, 'FAT32') @@ -435,7 +539,6 @@ def ogGrubInstallPartition (disk, par, checkos='FALSE', kernelparam=''): os.makedirs (f'{efisecondstage}/EFI/{efisubdir}/Boot') arch = InventoryLib.ogGetArch() efioptgrub = ['--removable', '--no-nvram', '--uefi-secure-boot', '--target', f'{arch}-efi', f'--efi-directory={efisecondstage}/EFI/{efisubdir}'] - #efibootdir = '/boot' # Si Reconfigurar segunda etapa (grub.cfg) == FALSE if 'FALSE' == checkos.upper() and (os.path.exists (f'{secondstage}/boot/grub/grub.cfg') or os.path.exists (f'{secondstage}/boot/grub/grub.cfg{backupname}')): diff --git a/client/lib/engine/bin/UEFILib.py b/client/lib/engine/bin/UEFILib.py index 1a979f6..ecab87a 100644 --- a/client/lib/engine/bin/UEFILib.py +++ b/client/lib/engine/bin/UEFILib.py @@ -210,7 +210,7 @@ def ogNvramGetNext(): # ogNvramGetOrder #@brief Muestra el orden de las entradas del gestor de arranque (NVRAM) -#@return Orden de las entradas +#@return Array, orden de las entradas #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## def ogNvramGetOrder(): @@ -309,10 +309,10 @@ def ogNvramInactiveEntry (entry): #/** # ogNvramList #@brief Lista las entradas de la NVRAN (sólo equipos UEFI) -#@return Entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] +#@return Multiline string: entradas de la NVRAM con el formato: orden etiqueta [* (si está activa) ] #@exception OG_ERR_NOTUEFI UEFI no activa. #*/ ## -def ogNvramList (): +def ogNvramList(): if not InventoryLib.ogIsEfiActive(): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') return @@ -325,7 +325,7 @@ def ogNvramList (): if re.search ('Boot[0-9]', words[0]): active = '*' if '*' in words[0] else '' num = words[0][4:8].strip ('0') or '0' - ret += '{:>4s} {} {}'.format (num, words[1], active) + ret += '{:>4s} {} {}\n'.format (num, words[1], active) return ret @@ -520,7 +520,7 @@ def ogNvramSetOrder (order): #@exception OG_ERR_NOTFOUND fichero o dispositivo no encontrado. #*/ ## #ogNvramSetTimeout ('2') -def ogNvramSetTimeout (t) { +def ogNvramSetTimeout (t): if not InventoryLib.ogIsEfiActive(): SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTUEFI, '') return @@ -528,7 +528,7 @@ def ogNvramSetTimeout (t) { try: num = int (t) ## raises ValueError if t doesn't look like a number except ValueError: - SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)' + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_FORMAT, 'ogNvramSetTimeout (timeout)') return subprocess.run (['efibootmgr', '-t', t]) diff --git a/client/shared/scripts/updateBootCache.py b/client/shared/scripts/updateBootCache.py new file mode 100755 index 0000000..854b9c9 --- /dev/null +++ b/client/shared/scripts/updateBootCache.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +import os +import shutil + +import ogGlobals +import SystemLib +import CacheLib + +#/** +# updateBootCache +#@brief acelerador arranque pxe. incorpora a la cache el initrd y el kernel. +#@param 1 +#@param ejemplo: +#@return +#@exception OG_ERR_NOTCACHE # 15 si cache no existe 15 +#@exception OG_ERR_NOTFOUND=2 # Fichero o dispositivo no encontrado. +#@note +#@todo: +#*/ ## + +oglivedir = os.environ.get ('oglivedir', 'ogLive') +ogbtftp = f'/opt/oglive/tftpboot/{oglivedir}' +ogbcache = f'{ogGlobals.OGCAC}/boot/{oglivedir}' + +#control de errores +if not os.path.isdir (ogbtftp): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTFOUND, ogbtftp) + os.exit (1) + +if not CacheLib.ogMountCache(): + SystemLib.ogRaiseError ([], ogGlobals.OG_ERR_NOTCACHE, 'CACHE') + os.exit (1) + +os.makedirs (ogbcache, exist_ok=True) + + # comparamos los del server +with open (f'{ogbtftp}/ogvmlinuz.sum', 'rb') as fd: servervmlinuz = fd.read() +with open (f'{ogbtftp}/oginitrd.img.sum', 'rb') as fd: serverinitrd = fd.read() + + #comparamos los de la cache +with open (f'{ogbcache}/ogvmlinuz.sum', 'rb') as fd: cachevmlinuz = fd.read() +with open (f'{ogbcache}/oginitrd.img.sum', 'rb') as fd: cacheinitrd = fd.read() + +print (f'MD5 on SERVER: {servervmlinuz} {serverinitrd}') +print (f'MD5 on CACHE: {cachevmlinuz} {cacheinitrd}') + +do_reboot = '0' +if cachevmlinuz != servervmlinuz: + print ('ogvmlinuz updating') + shutil.copy2 (f'{ogbtftp}/ogvmlinuz', f'{ogbcache}/ogvmlinuz') + shutil.copy2 (f'{ogbtftp}/ogvmlinuz.sum', f'{ogbcache}/ogvmlinuz.sum') + do_reboot = '1' + +if cacheinitrd != serverinitrd: + print ('oginitrd updating') + shutil.copy2 (f'{ogbtftp}/oginitrd.img', f'{ogbcache}/oginitrd.img') + shutil.copy2 (f'{ogbtftp}/oginitrd.img.sum', f'{ogbcache}/oginitrd.img.sum') + do_reboot = '1' + +print (do_reboot) +os.exit (0)