Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: oci-utils
Version: 0.12.7
Version: 0.14.1
Summary: Oracle Cloud Infrastructure utilities
Home-page: http://github.com/oracle/oci-utils/
Author: Laszlo Peter
Expand Down
5 changes: 4 additions & 1 deletion buildrpm/oci-utils.spec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Name: oci-utils
Version: 0.14.0
Release: 0%{?dist}
Release: 1%{?dist}
Url: http://cloud.oracle.com/iaas
Summary: Oracle Cloud Infrastructure utilities
License: UPL
Expand Down Expand Up @@ -206,6 +206,9 @@ rm -rf %{buildroot}
/opt/oci-utils/tests/__init__*

%changelog
* Thu Aug 11 2022 Guido Tijskens <guido.tijskens@oracle.com> -- 0.14.0-1
- LINUX-12027: oci-image-migrate on ol7 unable to mount ol9 xfs filesystem

* Mon Jul 25 2022 Guido Tijskens <guido.tijskens@oracle.com> -- 0.14.0-0
- support for ipv6:
- LINUX-9259 add ipv6 support in oci-metadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def parse_args():
The command line namespace.
"""
parser = argparse.ArgumentParser(
prog='oci-image-migrate-import',
description='Utility to import a (verified and modified) on-premise '
'legacy image which was uploaded to object storage in '
'the custom images folder of the Oracle Cloud '
Expand Down
14 changes: 6 additions & 8 deletions lib/oci_utils/impl/migrate/oci_image_migrate_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def parse_args():
The command line namespace.
"""
parser = argparse.ArgumentParser(
prog='oci-image-migrate',
description='Utility to support preparation of on-premise legacy '
'images for importing in the Oracle Cloud Infrastructure.')
#
Expand Down Expand Up @@ -260,7 +261,7 @@ def verify_support():
if ostype not in ['ol', 'redhat', 'centos']:
_logger.info('OS type %s is not supported.', ostype)
return False
if majorrelease not in ['7', '8']:
if majorrelease not in ['7', '8', '9']:
_logger.info('OS %s %s is not supported', ostype, majorrelease)
return False
return True
Expand Down Expand Up @@ -487,8 +488,7 @@ def main():
prereq_msg += msg
#
if imgres:
prereq_msg += '\n\n %s data collection and processing succeeded.' \
% image_path
prereq_msg += '\n\n %s data collection and processing succeeded.' % image_path
else:
prereq_passed = False
#
Expand All @@ -501,12 +501,10 @@ def main():
result_msg(msg='\n Boot type is UEFI, use launch_mode NATIVE (or EMULATED) at import.',
result=True)
else:
raise OciMigrateException('Something wrong checking '
'the boot type')
raise OciMigrateException('Checking the boot type failed.')
else:
prereq_msg += '\n\n %s processing failed, check the logfile ' \
'and/or set environment variable _OCI_UTILS_DEBUG.' \
% image_path
prereq_msg += '\n\n %s processing failed, check the logfile and/or set environment variable ' \
'_OCI_UTILS_DEBUG.' % image_path
raise OciMigrateException(prereq_msg)
except Exception as e:
exit_with_msg('*** ERROR *** %s' % str(e))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def parse_args():
The command line namespace.
"""
parser = argparse.ArgumentParser(
prog='oci-image-migrate-upload',
description='Utility to upload on-premise legacy images to object '
'storage of the Oracle Cloud Infrastructure.')
#
Expand Down
196 changes: 145 additions & 51 deletions lib/oci_utils/migrate/imgdevice.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# oci-utils
#
# Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown
# at http://oss.oracle.com/licenses/upl.

Expand Down Expand Up @@ -30,6 +30,7 @@
from oci_utils.migrate import terminal_dimension
from oci_utils.migrate.exception import OciMigrateException
from oci_utils.migrate.migrate_tools import get_config_data
from pprint import pformat

_logger = logging.getLogger('oci-utils.imgdevice')

Expand Down Expand Up @@ -433,7 +434,8 @@ def handle_image(self):
self.update_image()
return True
except Exception as e:
_logger.critical(' Image %s handling failed: %s', self.image_info['img_name'], str(e), exc_info=True)
_logger.debug(' Image %s handling failed: %s', self.image_info['img_name'], str(e), exc_info=True)
_logger.critical('\n Image %s handling failed: %s', self.image_info['img_name'], str(e))
return False
finally:
_, nbcols = terminal_dimension()
Expand Down Expand Up @@ -958,8 +960,7 @@ def find_uuid_partition(uuid_part):
"""
part_p = 'na'
mount_p = 'na'
for partition, partdata in list(
self.image_info['partitions'].items()):
for partition, partdata in list(self.image_info['partitions'].items()):
if self.skip_partition(partdata):
_logger.debug('Skipping %s', partition)
elif 'ID_FS_UUID' in list(partdata.keys()):
Expand Down Expand Up @@ -1072,6 +1073,7 @@ def find_mapper_partition(mapper_part):
def get_grub_data(self, loopdir):
"""
Collect data related to boot and grub.

Parameters:
----------
loopdir: str
Expand Down Expand Up @@ -1107,9 +1109,39 @@ def find_grub_config_file():
_logger.debug('No grub config file in %s', grubroot)
return grub_path

def find_boot_loader_entries_dir():
"""
Verify if the directory /boot/loader/entries exists and contains files.

Returns
-------
str: the path of the boot loader entries.
"""
_logger.debug('__ Looking for /boot/loader/entries')
boot_loader_entries = os.path.join(loopdir, 'boot/loader/entries')
if os.path.exists(boot_loader_entries):
if os.listdir(boot_loader_entries):
return boot_loader_entries
return None

def find_grubenv_dir():
"""
Verify if the grubenv file exists.

Returns
-------
str: the path of the grubenv file.
"""
_logger.debug('__ Looking for /boot/grub2/grubenv')
grubenvpath = os.path.join(loopdir, 'boot/grub2/grubenv')
if os.path.exists(grubenvpath):
return grubenvpath
return None

def find_efi_boot_config():
"""
Find out if the image is using BIOS or UEFI boot.

Returns
-------
str: [BIOS|UEFI]
Expand Down Expand Up @@ -1146,57 +1178,113 @@ def find_efi_boot_config():
raise OciMigrateException('No grub config file found in %s' % self._fn)
result_msg(msg='Grub config file: %s' % grub_cfg_path, result=False)
#
# verify if a boot loader entries is present
boot_loader_entries_path = find_boot_loader_entries_dir()
grub_env_path = find_grubenv_dir()
#
# investigate boot type
self.image_info['boot_type'] = find_efi_boot_config()
result_msg(msg='Image boot type: %s' % self.image_info['boot_type'])
#
# get grub config contents
grubdata = list()
grub2 = False
grubby = True if boot_loader_entries_path else False
grubentry = dict()
grubefi = dict()
kernelversion = '0'
kernellist = list()
_logger.debug('Initialised grub structure')
try:
#
# check for grub2 data
mentry = False
with open(grub_cfg_path, 'r') as f:
for ffsline in f:
fsline = ffsline.strip()
fsline_split = re.split('[ "]', fsline)
if bool(fsline.split()):
_logger.debug('%s', fsline)
if fsline_split[0] == 'menuentry':
mentry = True
grub2 = True
if grubentry:
grubdata.append(grubentry)
grubentry = {'menuentry': [fsline]}
_logger.debug('grub line: %s', fsline)
elif fsline_split[0] == 'search':
if mentry:
grubentry['menuentry'].append(fsline)
_logger.debug('Grub line: %s', grubentry['menuentry'])

if not grubby:
try:
#
# check for grub2 data
mentry = False
with open(grub_cfg_path, 'r') as f:
for ffsline in f:
fsline = ffsline.strip()
fsline_split = re.split('[ "]', fsline)
if bool(fsline.split()):
_logger.debug('%s', fsline)
if fsline_split[0] == 'menuentry':
mentry = True
grub2 = True
if grubentry:
grubdata.append(grubentry)
grubentry = {'menuentry': [fsline]}
_logger.debug('grub line: %s', fsline)
elif fsline_split[0] == 'search':
if mentry:
grubentry['menuentry'].append(fsline)
_logger.debug('Grub line: %s', grubentry['menuentry'])
else:
_logger.debug('Not a menuentry, skipping %s', fsline)
elif fsline_split[0] == 'set':
if 'default_kernelopts' in fsline_split[1]:
grubefi = {'grubefi': [fsline]}
_logger.debug('efi line: %s', fsline)
else:
_logger.debug('Not a menuentry, skipping %s', fsline)
elif fsline_split[0] == 'set':
if 'default_kernelopts' in fsline_split[1]:
grubefi = {'grubefi': [fsline]}
_logger.debug('efi line: %s', fsline)
else:
_logger.debug('Skipping %s', fsline)
if bool(grubentry):
grubdata.append(grubentry)
if bool(grubefi):
grubdata.append(grubefi)
except Exception as e:
_logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e))
raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e
if grub2:
_logger.debug('Skipping %s', fsline)
if bool(grubentry):
grubdata.append(grubentry)
if bool(grubefi):
grubdata.append(grubefi)
except Exception as e:
_logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e))
raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e

if grubby:
_logger.debug('Found /boot/loader/entries')
result_msg(msg='Found /boot/loader/entries directory.', result=False)
#
# find all kernels defined in loader entries directory.
kernellist = system_tools.get_grubby_kernels(boot_loader_entries_path)
_logger.debug('Kernels defined in boot laoder entries: %s', kernellist)
if grub_env_path:
kernelversion = system_tools.get_grubby_default_kernel(grub_env_path)
_logger.debug('Default kernel: %s', kernelversion)
kernelopts = ''
try:
# find kernel options
with open(grub_cfg_path, 'r') as f:
for ffsline in f:
fsline = ffsline.strip()
fsline_split = re.split('[ "]', fsline)
if bool(fsline.split()):
if fsline_split[0] == 'set':
if 'kernelopts' in fsline_split[1]:
kernelopts = ' '.join(fsline_split[1:])
break
for _, _, files in os.walk(boot_loader_entries_path):
for name in files:
with open(os.path.join(boot_loader_entries_path, name), 'r') as f:
for ffsline in f:
fsline = ffsline.strip()
if len(fsline) > 0:
_logger.debug('%s', fsline)
if fsline.split()[0] == 'title':
if grubentry:
grubdata.append(grubentry)
grubentry = {'title': [fsline]}
_logger.debug('grub line: %s', fsline)
elif fsline.split()[0] == 'linux':
grubentry['title'].append(fsline)
_logger.debug('grub line: %s', grubentry['title'])
else:
_logger.debug('skipping %s', fsline)
if grubentry:
if kernelopts:
grubentry['title'].append(kernelopts)
grubdata.append(grubentry)

except Exception as e:
_logger.error(' Errors during reading %s: %s', boot_loader_entries_path, str(e))
raise OciMigrateException('Errors during reading %s:' % boot_loader_entries_path) from e

elif grub2:
_logger.debug('Found grub2 configuration file.')
result_msg(msg='Found grub2 configuration file', result=False)
result_msg(msg='Found grub2 configuration file.', result=False)
#
# find all kernels defined in grub(1) config file.
kernellist = system_tools.get_grub2_kernels(grub_cfg_path)
Expand Down Expand Up @@ -1237,6 +1325,9 @@ def find_efi_boot_config():
_logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e))
raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e

_logger.debug('grubdata:\n %s', pformat(grubdata, indent=4))
_logger.debug('kernellist\n %s', pformat(kernellist, indent=4))
_logger.debug('kernelversion\n %s', kernelversion)
return grubdata, kernelversion, kernellist

def get_os_release(self):
Expand Down Expand Up @@ -1459,23 +1550,25 @@ def generic_prereq_check(self):
msg='grub2 line ->%s<- specifies boot partition via UUID.' % le)
elif l_split[0] == 'kernel':
grub_l += 1
if len([a for a in l_split
if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0:
_logger.debug('grub line ->%s<- does not specify boot partition via '
'UUID nor LVM2.', le)
if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0:
_logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le)
grub_fail += 1
else:
result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.'
% le, result=True)
result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le,)
elif 'default_kernelopts' in l_split[1]:
grub_l += 1
if len([a for a in l_split
if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0:
if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0:
_logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le)
grub_fail += 1
else:
result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le)
elif l_split[0] == 'kernelopts=':
grub_l += 1
if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0:
_logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le)
grub_fail += 1
else:
result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.'
% le, result=True)
result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le)
else:
_logger.debug('skipping %s', l_split)
if grub_l == 0:
Expand All @@ -1486,6 +1579,7 @@ def generic_prereq_check(self):
failmsg += '\n - grub config file does not guarantee booting using UUID or LVM2.'
else:
_logger.debug('Grub config file ok.')
result_msg(msg='Grub config file ok.', result=True)
else:
passed_requirement = False
failmsg += '\n - Grub config file not found.'
Expand Down
2 changes: 2 additions & 0 deletions lib/oci_utils/migrate/migrate_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ def mount_partition(devname, mountpoint=None):
#
# mount failed, need to remove mountpoint.
_logger.critical(' Failed to mount %s, missing driver, filesystem corruption...: %s', devname, str(e))
_logger.critical(' Check file system driver and kernel version compatibility. '
'Check Known Issues in the man page and manual.')
if mountpoint is None:
if system_tools.exec_rmdir(mntpoint):
_logger.debug('%s removed', mntpoint)
Expand Down
Loading