Compare commits

...

10 Commits

Author SHA1 Message Date
OpenGnSys Support Team cf9577a40e fs: call wipefs partition before formatting partition
call wipefs before formatting partition, to remove any labels and stale data.

call wipefs if formatting fails, to leave partition in consistent state.

moreover, remove unnecessary exception handling on get_partition_device().
2025-02-14 15:48:53 +01:00
OpenGnSys Support Team 6503d0ffe7 live: call wipefs if partition or format fails
wipe disk if partition or format fails to leave the disk in consistent state.
2025-02-14 15:48:13 +01:00
Alejandro Sirgo Rica 0ca16bc46c live: remove unused variable in cache_delete()
Remove unused variable delted_images in the function cache_delete()
2025-02-14 13:15:27 +01:00
Alejandro Sirgo Rica bd190f8d44 live: send refresh payload in image restore
Send the refresh payload after a completed image restore operation.

The fields sent to ogServer are not enough to update the status of
the client and the OS installed in a partition does not appear in
the database.
2025-02-13 12:40:53 +01:00
Alejandro Sirgo Rica e0ba9cc98c uefi: log efibootmgr errors as warnings
Log as warning when efibootmgr fails to update the NVRAM.

Raise an exception when the command is not available or when
there are not enough permissions to execute. Provide contextual
information in the error message.
2025-02-13 09:06:38 +01:00
Alejandro Sirgo Rica ccdcb7bfc7 uefi: add missing f-string prefix in _find_bootentry() error
Add missing f-string prefix for proper string interpolation in
the error message of _find_bootentry()
2025-02-13 09:06:25 +01:00
Alejandro Sirgo Rica 72406a7d89 live: configure OS on first disk only
Call configure_os only for first disk, any other disks are only
supported to restore data images by now.

Call os_probe only for disk 1 in refresh.
2025-02-11 11:06:29 +01:00
Alejandro Sirgo Rica 0f519ecfeb grub: move disabled boot entries at the end of boot order
The GRUB entry is always set as the second boot option, assuming
PXE is first. This is not always true, as disabled entries before
PXE IPv4 can make it the first valid but not the first defined
entry in the boot order.

Move every disabled boot entry at the end of boot order.
2025-02-05 09:42:38 +01:00
Alejandro Sirgo Rica c260534534 live: remove unneeded string formatting in image_create
Replace f-string wf'{image_path}' with the variable image_path.
2025-02-03 11:27:18 +01:00
Alejandro Sirgo Rica f67f3c598a rest: register image/update as a valid request
Accept both image/create and image/update requests from ogServer.
2025-01-31 14:31:17 +01:00
5 changed files with 67 additions and 26 deletions

View File

@ -82,8 +82,10 @@ class OgLiveOperations:
code = int(pa.parttype, base=16)
if mount_mkdir(pa.padev, target):
probe_result = os_probe(target)
part_setup['os'] = probe_result
part_setup['os'] = ''
if part_setup['disk'] == '1':
probe_result = os_probe(target)
part_setup['os'] = probe_result
total, used, free = shutil.disk_usage(target)
part_setup['used_size'] = used
@ -526,7 +528,12 @@ class OgLiveOperations:
raise OgError(f'Invalid disk number {disk}, {len(get_disks())} disks available.')
diskname = get_disks()[disk-1]
self._partition(diskname, table_type, partlist)
try:
self._partition(diskname, table_type, partlist)
except Exception as e:
ret = subprocess.run(['wipefs', '-af', f'/dev/{diskname}'])
logging.warning(f'wipefs on /dev/{diskname} after failure for consistency, reports {ret.returncode}')
raise
ret = subprocess.run(['partprobe', f'/dev/{diskname}'])
logging.info(f'first partprobe /dev/{diskname} reports {ret.returncode}')
@ -594,19 +601,14 @@ class OgLiveOperations:
extend_filesystem(disk, partition)
configure_os(disk, partition)
if disk == 1:
configure_os(disk, partition)
self.refresh(ogRest)
result = self.refresh(ogRest)
logging.info('Image restore command OK')
json_dict = {
'disk': request.getDisk(),
'partition': request.getPartition(),
'image_id': request.getId(),
'cache': self._get_cache_contents(),
}
return json_dict
return result
def image_create(self, request, ogRest):
disk = int(request.getDisk())
@ -667,7 +669,7 @@ class OgLiveOperations:
if os.access(f'/opt/opengnsys/images', os.R_OK | os.W_OK) == False:
raise OgError('Cannot access /opt/opengnsys/images in read and write mode, check permissions')
if os.access(f'{image_path}', os.R_OK) == True:
if os.access(image_path, os.R_OK) == True:
logging.info(f'image file {image_path} already exists, updating.')
if is_windows and is_uefi_supported():
@ -744,7 +746,6 @@ class OgLiveOperations:
def cache_delete(self, request, ogRest):
images = request.getImages()
deleted_images = []
logging.info(f'Request to remove files from cache')

View File

@ -343,7 +343,7 @@ class ogRest():
self.process_imagerestore(client, request)
elif ("stop" in URI):
self.process_stop(client)
elif ("image/create" in URI):
elif ("image/create" in URI or "image/update" in URI):
self.process_imagecreate(client, request)
elif ("cache/delete" in URI):
self.process_cache_delete(client, request)

View File

@ -153,13 +153,19 @@ def mkfs(fs, disk, partition, label=None):
if fs not in fsdict:
raise OgError(f'mkfs failed, unsupported target filesystem {fs}')
try:
partdev = get_partition_device(disk, partition)
except ValueError as e:
raise OgError(f'mkfs aborted: {e}') from e
partdev = get_partition_device(disk, partition)
return fsdict[fs](partdev, label)
ret = subprocess.run(['wipefs', '-af', f'{partdev}'])
if ret.returncode != 0:
logging.warning(f'wipefs on {partdev}, fails with {ret.returncode}')
err = fsdict[fs](partdev, label)
if err != 0:
ret = subprocess.run(['wipefs', '-af', f'{partdev}'])
if ret.returncode != 0:
logging.warning(f'wipefs on {partdev} for consistency, fails with {ret.returncode}')
return err
def mkfs_ext4(partdev, label=None):
err = -1

View File

@ -334,6 +334,7 @@ def get_disk_part_type(disk_num):
def _update_nvram(esp_disk, esp_part_number):
loader_path = '/EFI/grub/Boot/shimx64.efi'
bootlabel = 'grub'
egibootmgr_reorder_disabled_entries()
efibootmgr_delete_bootentry(bootlabel)
efibootmgr_create_bootentry(esp_disk, esp_part_number, loader_path, bootlabel, add_to_bootorder=False)
efibootmgr_set_entry_order(bootlabel, 1)

View File

@ -25,7 +25,7 @@ def _find_bootentry(entries, label):
if entry['description'] == label:
return entry
else:
raise OgError('Boot entry {label} not found')
raise OgError(f'Boot entry {label} not found')
def _strip_boot_prefix(entry):
@ -95,8 +95,13 @@ def efibootmgr_bootnext(description):
entry = _find_bootentry(boot_entries, description)
num = _strip_boot_prefix(entry) # efibootmgr output uses BootXXXX for each entry, remove the "Boot" prefix.
bootnext_cmd = bootnext_cmd.format(bootnum=num, efibootmgr=EFIBOOTMGR_BIN)
subprocess.run(shlex.split(bootnext_cmd), check=True,
stdout=subprocess.DEVNULL)
try:
subprocess.run(shlex.split(bootnext_cmd), check=True,
stdout=subprocess.DEVNULL)
except subprocess.CalledProcessError:
logging.warning("Failed to update BootNext. UEFI firmware might be buggy")
except OSError as e:
raise OgError(f"Unexpected error updating BootNext: {e}") from e
def efibootmgr_delete_bootentry(label):
@ -107,7 +112,12 @@ def efibootmgr_delete_bootentry(label):
if entry['description'] == label:
num = entry['name'][4:] # Remove "Boot" prefix to extract num
efibootmgr_cmd = efibootmgr_cmd.format(bootnum=num, efibootmgr=EFIBOOTMGR_BIN)
subprocess.run(shlex.split(efibootmgr_cmd), check=True)
try:
subprocess.run(shlex.split(efibootmgr_cmd), check=True)
except subprocess.CalledProcessError:
logging.warning(f"Failed to delete boot entry {label}. UEFI firmware might be buggy")
except OSError as e:
raise OgError(f"Unexpected error deleting boot entry {label}: {e}") from e
break
else:
logging.info(f'Cannot delete boot entry {label} because it was not found.')
@ -121,8 +131,10 @@ def efibootmgr_create_bootentry(disk, part, loader, label, add_to_bootorder=True
logging.info(f'{EFIBOOTMGR_BIN} command creating boot entry: {efibootmgr_cmd}')
try:
proc = subprocess.run(shlex.split(efibootmgr_cmd), check=True, text=True)
except subprocess.CalledProcessError:
logging.warning(f"Failed to add boot entry {label} to NVRAM. UEFI firmware might be buggy")
except OSError as e:
raise OgError(f'Unexpected error adding boot entry to nvram. UEFI firmware might be buggy') from e
raise OgError(f"Unexpected error adding boot entry {label}: {e}") from e
def efibootmgr_set_entry_order(label, position):
logging.info(f'Setting {label} entry to position {position} of boot order')
@ -140,8 +152,29 @@ def efibootmgr_set_entry_order(label, position):
try:
proc = subprocess.run([EFIBOOTMGR_BIN, "-o", ",".join(boot_order)], check=True, text=True)
except subprocess.CalledProcessError:
logging.warning("Failed to set boot order to NVRAM. UEFI firmware might be buggy")
except OSError as e:
raise OgError(f'Unexpected error setting boot order to NVRAM. UEFI firmware might be buggy') from e
raise OgError(f"Unexpected error updating boot order: {e}") from e
def egibootmgr_reorder_disabled_entries():
logging.info(f'Setting disabled entries at the end of boot order')
boot_info = run_efibootmgr_json(validate=False)
boot_entries = boot_info.get('vars', [])
boot_order = boot_info.get('BootOrder', [])
for entry in boot_entries:
entry_number = _strip_boot_prefix(entry)
if not entry['active'] and entry_number in boot_order:
boot_order.remove(entry_number)
boot_order.append(entry_number)
try:
proc = subprocess.run([EFIBOOTMGR_BIN, "-o", ",".join(boot_order)], check=True, text=True)
except subprocess.CalledProcessError:
logging.warning("Failed to update boot order. UEFI firmware might be buggy")
except OSError as e:
raise OgError(f"Unexpected error updating boot order: {e}") from e
def _find_efi_loader(loader_paths):
for efi_app in loader_paths: