def b20_install_cloud_agent(self): """ Install the oracle cloud agent. Returns ------- bool: True on success, False otherwise. (always True as failing to install the oracle cloud agent is not fatal. """ _logger.debug('__ Install oracle cloud agent.') if bool(migrate_data.oracle_cloud_agent_location): _logger.debug('oracle cloud agent present: %s', migrate_data.oracle_cloud_agent_location) else: _logger.debug('No oracle cloud agent package present, skipping.') return True # # get package manipulation tool. pkg_mgr = self._exec_yum \ if self.package_tool['pkg_mgr'] == 'yum' else self._exec_dnf # # install rpm oracle_cloud_agent_rpm = migrate_data.oracle_cloud_agent_location simple_rpm = oracle_cloud_agent_rpm.split('/')[-1] try: install_output = pkg_mgr( self.package_tool['package_localinstall'] + [oracle_cloud_agent_rpm]) _logger.debug('Successfully installed pkg %s:\n%s', simple_rpm, install_output) migrate_tools.result_msg(msg='Installed %s.' % simple_rpm, result=False) pause_msg('cloud agent', pause_flag='_OCI_AGENT') except Exception as e: _logger.warning('Failed to install %s: %s', simple_rpm, str(e)) return True
def __init__(self, filename): """ Initialisation of the qcow2 header analysis. Parameters ---------- filename: str Full path of the qcow2 image file. """ _logger.debug('qcow2 header size: %d bytes' % self.head_size) super(Qcow2Head, self).__init__(filename) head_size = struct.calcsize(Qcow2Head.qcowhead_fmt) try: with open(self._fn, 'rb') as f: head_bin = f.read(head_size) _logger.debug('%s header successfully read' % self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s' % (self._fn, str(e))) raise OciMigrateException('Failed to read the header of %s: %s' % (self._fn, str(e))) qcow2header = struct.unpack(Qcow2Head.qcowhead_fmt, head_bin) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.qcowhead_dict = dict( (name[2], qcow2header[i]) for i, name in enumerate(Qcow2Head.header2_structure)) self.img_header = dict() self.img_header['head'] = self.qcowhead_dict migrate_tools.result_msg(msg='Got image %s header' % filename, result=False)
def update_network_config(rootdir): """ Modify the network configuration in the image file to prevent conflicts during import. Currently ifcfg, NetworkManager, netplan, network connections systemd-networkd and interface file are scanned. Bonding and bridging are not supported for now, nor multiple ip per interface. Parameters ---------- rootdir: str Full path of image root dir. Returns ------- list: Network interfaces dict: List with dictionary representation of the network configuration files. """ migrate_tools.result_msg(msg='Adjust network configuration.', result=False) network_config = dict() network_list = list() # # Cleanup udev network device naming. if cleanup_udev(rootdir): _logger.debug('udev successfully modified.') else: _logger.debug('Failed to modify udev rules with respect to network ' 'device naming.') # # ifcfg ifcfg_nics, ifcfg_data = reconfigure_ifcfg_config(rootdir) network_list += ifcfg_nics network_config['ifcfg'] = ifcfg_data # # netplan netplan_nics, netplan_data = reconfigure_netplan(rootdir) network_list += netplan_nics network_config['netplan'] = netplan_data # # network manager nwmg_nics, nwmg_data = reconfigure_networkmanager(rootdir) network_list += nwmg_nics network_config['network_manager'] = nwmg_data # # interfaces int_list, int_data = reconfigure_interfaces(rootdir) network_list += int_list network_config['interfaces'] = int_data # # systemd netsys_nics, netsys_data = reconfigure_systemd_networkd(rootdir) network_list += netsys_nics network_config['systemd-networkd'] = netsys_data migrate_tools.result_msg(msg='Adjusted network configuration.', result=True) return network_list, network_config
def __init__(self, filename): """ Initialisation of the vmdk header analysis. Parameters ---------- filename: str Full path of the vmdk image file. """ super(VmdkHead, self).__init__(filename) _logger.debug('VMDK header size: %d bytes' % self.head_size) try: with open(self._fn, 'rb') as f: head_bin = f.read(self.head_size) _logger.debug('%s header successfully read' % self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s' % (self._fn, str(e))) raise OciMigrateException('Failed to read the header of %s: %s' % (self._fn, str(e))) vmdkheader = struct.unpack(VmdkHead.vmdkhead_fmt, head_bin) try: with open(self._fn, 'rb') as f: f.seek(512) head_descr = [ it for it in f.read(1024).decode('utf-8').splitlines() if '=' in it ] except Exception as e: _logger.critical(' Failed to read description of %s: %s' % (self._fn, str(e))) raise OciMigrateException( 'Failed to read the description of %s: %s' % (self._fn, str(e))) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.vmdkhead_dict = dict( (name[2], vmdkheader[i]) for i, name in enumerate(VmdkHead.header0_structure)) self.vmdkdesc_dict = dict( [re.sub(r'"', '', kv).split('=') for kv in head_descr]) self.img_header = dict() self.img_header['head'] = self.vmdkhead_dict self.img_header['desc'] = self.vmdkdesc_dict migrate_tools.result_msg(msg='Got image %s header' % filename, result=False)
def show_header(self): """ Lists the header contents formatted. Returns ------- No return value. """ migrate_tools.result_msg(msg='\n %30s\n %30s' % ('QCOW2 file header data', '-' * 30), result=False) for f in Qcow2Head.header2_structure: migrate_tools.result_msg(msg=''.join( [" %-30s" % f[2], f[1] % self.qcowhead_dict[f[2]]]), result=False)
def exec_sfdisk(devname): """ Collect the data about the partitions on the image file mounted on the device devname using the sfdisk utility. Parameters ---------- devname: str The device. Returns ------- dict: The partition data with sfdisk results on success, None otherwise. """ cmd = ['sfdisk', '-d', devname] _logger.debug('__ Running %s' % cmd) pause_msg(cmd) try: result = run_popen_cmd(cmd).decode('utf-8') partdata = dict() for devx in result.splitlines(): if devx.startswith(devname): key = devx.split(':')[0].strip() migrate_tools.result_msg(msg='sfdisk partition %s' % key, result=False) thispart = {'start': 0, 'size': 0, 'Id': 0, 'bootable': False} val = devx.split(':')[1].split(',') for it in val: if 'start' in it: x = it.split('=')[1] thispart['start'] = int(x) elif 'size' in it: x = it.split('=')[1] thispart['size'] = int(x) elif 'Id' in it: x = it.split('=')[1] thispart['Id'] = x.strip() elif 'bootable' in it: thispart['bootable'] = True else: _logger.debug('unrecognised item: %s' % val) partdata[key] = thispart _logger.debug(partdata) return partdata except Exception as e: _logger.error(' Failed to collect sfdisk %s partition data: %s' % (devname, str(e))) return None
def __init__(self, filename): """ Initialisation of the templatetype header analysis. Parameters ---------- filename: str Full path of the template_type image file. """ super(TemplateTypeHead, self).__init__(filename) _logger.debug('templatetype header size: %d bytes' % self.head_size) try: with open(self._fn, 'rb') as f: head_bin = f.read(self.head_size) _logger.debug('%s header successfully read' % self._fn) except Exception as e: _logger.critical(' Failed to read header of %s: %s' % (self._fn, str(e))) raise OciMigrateException('Failed to read the header of %s: %s' % (self._fn, str(e))) templatetypeheader = struct.unpack(TemplateTypeHead.templatetypehead_fmt, head_bin) self.stat = os.stat(self._fn) self.img_tag = os.path.splitext(os.path.split(self._fn)[1])[0] self.templatehead_dict = dict((name[2], templatetypeheader[i]) for i, name in enumerate(TemplateTypeHead.header2_structure)) self.img_header = dict() self.img_header['head'] = self.templatehead_dict migrate_tools.result_msg(msg='Got image %s header' % filename, result=False) # # mount the image using the nbd try: self.devicename = self.mount_img() _logger.debug('Image data %s' % self.devicename) migrate_tools.result_msg(msg='Mounted %s' % self.devicename, result=False) deviceinfo = self.handle_image() except Exception as e: _logger.critical(' Error %s' % str(e)) raise OciMigrateException(str(e))
def image_size(self): """ Get the size of the image file. Returns ------- dict: physical file size, logical file size """ img_sz = { 'physical': float(self.stat.st_size) / gigabyte, 'logical': float(self.vmdkhead_dict['capacity'] * 512) / gigabyte } migrate_tools.result_msg( msg='Image size: physical %10.2f GB, logical %10.2f GB' % (img_sz['physical'], img_sz['logical']), result=True) return img_sz
def image_size(self): """ Get the size of the image file. Returns ------- tuple: (float, float) physical file size, logical file size """ img_sz = { 'physical': float(self.stat.st_size) / gigabyte, 'logical': float(self.qcowhead_dict['size']) / gigabyte } migrate_tools.result_msg( msg='Image size: physical %10.2f GB, logical %10.2f GB' % (img_sz['physical'], img_sz['logical']), result=True) return img_sz
def show_header(self): """ Lists the header contents formatted. Returns ------- No return value. """ migrate_tools.result_msg(msg='\n %30s\n %30s %30s' % ('VMDK file header data', '-' * 30, '-' * 30), result=False) for f in VmdkHead.header0_structure: migrate_tools.result_msg(msg=''.join( [' %30s : ' % f[2], f[1] % self.vmdkhead_dict[f[2]]]), result=False) migrate_tools.result_msg( msg='\n %30s\n %30s %30s' % ('VMDK file descriptor data', '-' * 30, '-' * 30), result=False) for k in sorted(self.vmdkdesc_dict): migrate_tools.result_msg(msg=' %30s : %-30s' % (k, self.vmdkdesc_dict[k]), result=False)
def reconfigure_ifcfg_config(rootdir): """ Modify the network configuration in the image file to prevent conflicts during import. This is only for ol-type linux. Parameters ---------- rootdir: str Full path of image root dir as loopback mounted. Returns ------- list: list of nic. dict: the interfaces configuration. """ # # Rename the config files _logger.debug('__ The network ifcfg configuration.') ifcfg_list = list() ifcfg_data = dict() ifrootdir = rootdir + get_config_data('default_ifcfg') if os.path.isdir(ifrootdir): for cfgfile in glob(ifrootdir + '/ifcfg-*'): _logger.debug('Checking configfile: %s' % cfgfile) try: with open(cfgfile, 'r') as f: # nl = filter(None, [x[:x.find('#')] for x in f]) nl = [_f for _f in [x[:x.find('#')] for x in f] if _f] ifcfg = dict(dl.replace('"', '').split('=') for dl in nl) if 'DEVICE' in ifcfg: devname = ifcfg['DEVICE'] else: _logger.debug('Missing device name in %s' % cfgfile) devname = cfgfile.split('/')[-1] ifcfg_list.append(devname) ifcfg_data[devname] = ifcfg _logger.debug('Network interface: %s' % devname) except Exception as e: _logger.error( ' Problem reading network configuration file %s: ' '%s' % (cfgfile, str(e))) else: _logger.debug('No ifcfg network configuration.') # # backup for fn in glob(ifrootdir + '/ifcfg-*'): if 'ifcfg-lo' not in fn: fn_bck = system_tools.exec_rename(fn) if bool(fn_bck): _logger.debug('Network config file %s successfully ' 'renamed to %s' % (fn, fn_bck)) else: _logger.debug('Failed to backup network configuration ' 'file %s to %s.' % (fn, fn_bck)) # migrate_tools.error_msg('Failed to backup network configuration ' # 'file %s to %s.' % (fn, fn_bck)) # raise OciMigrateException('Failed to rename network config ' # 'file %s to %s' % (fn, fn_bck)) else: _logger.debug('ifcfg-lo found.') # # Generate new default network configuration. if len(ifcfg_list) > 0: nic0 = sorted(ifcfg_list)[0] dhcpniccfg = ifrootdir + '/ifcfg-%s' % nic0 _logger.debug('Replacing network config file %s' % dhcpniccfg) try: with open(dhcpniccfg, 'w') as f: f.writelines( ln.replace('_XXXX_', nic0) + '\n' for ln in get_config_data('default_ifcfg_config')) migrate_tools.result_msg( msg='Replaced ifcfg network configuration.', result=False) except Exception as e: _logger.error(' Failed to write %s/ifcfg-eth0' % ifrootdir) migrate_tools.error_msg('Failed to write %s: %s' % (dhcpniccfg, str(e))) raise OciMigrateException('Failed to write %s: %s' % (dhcpniccfg, str(e))) else: _logger.debug('No ifcfg definitions found.') return ifcfg_list, ifcfg_data
def reconfigure_systemd_networkd(rootdir): """ Parse the systemd network configuration. Parameters ---------- rootdir: str Full path of image root dir as loopback mounted. Returns ------- list: list of nic. dict: the interfaces configuration. """ _logger.debug('__ The network systemd-networkd configuration.') sys_data = dict() sys_nics = list() nw_ignore = ['container-host0', 'container-ve', 'container-vz'] for root_path in get_config_data('default_systemd'): networkd_root = rootdir + root_path if os.path.isdir(networkd_root): _logger.debug('systemd network directory exists.') systemd_files = glob(root_path + '/*.network') if len(systemd_files) > 0: for sf in sorted(systemd_files): ignore = False for ig in nw_ignore: if ig in sf: ignore = True break if not ignore: systemtd_net_config = ConfigParser() sys_data[sf] = dict() try: sv = systemtd_net_config.read(sf) if 'Match' in systemtd_net_config.sections(): ifname = systemtd_net_config.get( 'Match', 'Name') sys_nics.append(ifname) else: _logger.debug('-- No Match section in %s' % sf) # for sec in systemtd_net_config.sections(): sys_data[sf][sec] = systemtd_net_config.items( sec) _logger.debug('%s' % sys_data[sf][sec]) except Exception as e: _logger.error(' Failed to parse %s: %s' % (sf, str(e))) # # rename - backup bcknm = system_tools.exec_rename(sf) if bool(bcknm): _logger.debug( 'Network config file %s renamed to %s' % (sf, bcknm)) else: _logger.error(' Failed to rename %s' % sf) raise OciMigrateException('Failed to rename %s ' % sf) else: _logger.debug('No systemd-networkd configuration.') else: _logger.debug('%s does not exist.' % get_config_data('default_systemd')) # # write new config if len(sys_nics) > 0: nicname = sorted(sys_nics)[0] with open(rootdir + get_config_data('default_systemd_file'), 'w') as sdf: sdf.writelines( ln.replace('_XXXX_', nicname) + '\n' for ln in get_config_data('default_systemd_config')) migrate_tools.result_msg( msg='systemd-networkd configuration rewritten.', result=True) else: _logger.debug('No systemd-networkd configuration.') return sorted(sys_nics), sys_data
def b30_install_snap_packages(self): """ Add a job to the cloud-init config file to install additional packages by snap at first boot. (snapd cannot be run while in chroot during image preparation.) Returns ------- bool: True on success, False otherwise. (always True as packages to be installed via snap are not considered essential.) """ def get_ubuntu_snap_package_list(): """ Retrieve the list of packages to install from oci-migrate-config file. Returns ------- list: list of package names to install. """ _logger.debug('__ Collection list of snap packages.') try: snap_pkg_list = get_config_data( 'ubuntu_os_packages_to_install_snap') if bool(snap_pkg_list): pkg_list = '(' else: _logger.debug('snap package list is empty.') return False _logger.debug('Package list: %s', snap_pkg_list) for pkg in snap_pkg_list: pkg_list = pkg_list.__add__("'")\ .__add__(pkg)\ .__add__("'")\ .__add__(" ") pkg_list = pkg_list.__add__(')') _logger.debug('Package list: %s', pkg_list) return pkg_list except Exception as e: _logger.warning('Failed to find a list of packages: %s', str(e)) return False _logger.debug('__ Install software packages using snap.') try: # # collect packages to install packages = get_ubuntu_snap_package_list() if not bool(packages): _logger.debug('No extra packages to install.') return True # # get snapd script name ubuntu_os_snap_install_script = \ get_config_data('ubuntu_os_snap_install_script') _logger.debug('snap package install script: %s', ubuntu_os_snap_install_script) # # get, update and write the script. with open(ubuntu_os_snap_install_script, 'w') as bashf: bashf.writelines( ln.replace('_XXXX_', packages) + '\n' for ln in get_config_data('ubuntu_os_snapd_bash')) os.chmod(ubuntu_os_snap_install_script, stat.S_IRWXU) # # update cloud-init with runcmd command if migrate_tools.update_cloudconfig_runcmd( ubuntu_os_snap_install_script): _logger.debug('snap install script successfully added.') migrate_tools.result_msg(msg='snap packages install script ' 'successfully added.', result=False) else: _logger.debug('Failed to add snap install script.') except Exception as e: _logger.warning( 'Failed to install one or more packages of %s:\n%s', packages, str(e)) # # not considered as essential or fatal. return True
def reconfigure_interfaces(rootdir): """ Parse the network interfaces file. Parameters ---------- rootdir: str Full path of image root dir as loopback mounted. Returns ------- list: list of nic. dict: the interfaces configuration. """ _logger.debug('__ The network interfaces configuration.') int_data = dict() int_nics = list() root_path = rootdir + get_config_data('default_interfaces') net_ifcfg_config = root_path + '/interfaces' if os.path.isfile(net_ifcfg_config): int_data[get_config_data('default_interfaces')] = list() _logger.debug('%s file exists' % net_ifcfg_config) try: with open(net_ifcfg_config, 'r') as inf: for ln in inf: int_data[get_config_data('default_interfaces')].append(ln) if 'iface' in ln.split(): if ln.split()[1] != 'lo': int_nics.append(ln.split()[1]) else: _logger.debug('no iface in %s' % ln) except Exception as e: _logger.error(' Error occured while reading %s: %s' % (net_ifcfg_config, str(e))) # # rewrite if len(int_nics) == 0: _logger.debug('No interface definitions found in %s' % net_ifcfg_config) else: try: # # backup bck_root_path = system_tools.backup_dir(root_path) _logger.debug('Copied %s to %s' % (root_path, bck_root_path)) # # remove dir shutil.rmtree(root_path + '/interfaces.d') # # recreate interfaces config with open(net_ifcfg_config, 'w') as fi: fi.writelines( ln.replace('_XXXX_', int_nics[0]) + '\n' for ln in get_config_data('default_interfaces_config')) migrate_tools.result_msg( msg='Network interfaces file rewritten.', result=False) except Exception as e: _logger.error(' Failed to write new interfaces configuration ' 'file %s: %s' % (net_ifcfg_config, str(e))) else: _logger.debug('No network interfaces configuration.') return int_nics, int_data
def reconfigure_networkmanager(rootdir): """ Replace the networkmanager configuration with Oracle Cloud Infrastructure compatible version. Parameters ---------- rootdir: str Full path of image root dir as loopback mounted. Returns ------- list: list of nic. dict: the network manager system-connections configurations """ _logger.debug('__ The NetworkManager configuration.') netwmg_data = dict() netwmg_nics = list() network_config_dir = rootdir + get_config_data('default_nwconnections') _logger.debug('Network manager dir: %s' % network_config_dir) nw_mgr_cfg = rootdir + get_config_data('default_nwmconfig') _logger.debug('Network manager conf: %s' % nw_mgr_cfg) # # backup try: # # copy if os.path.isfile(nw_mgr_cfg): bck_nw_mgr_cfg = system_tools.exec_rename(nw_mgr_cfg) if bool(bck_nw_mgr_cfg): _logger.debug('Copied %s to %s' % (nw_mgr_cfg, bck_nw_mgr_cfg)) else: _logger.warning( 'Failed to backup network manager configuration.') else: _logger.debug('No %s found.' % nw_mgr_cfg) # if os.path.isdir(network_config_dir): bck_network_config_dir = system_tools.backup_dir( network_config_dir) _logger.debug('Copied %s to %s' % (network_config_dir, bck_network_config_dir)) else: _logger.debug('%s not found.' % network_config_dir) except Exception as e: migrate_tools.error_msg('Failed to backup the networkmanager ' 'configuration: %s' % str(e)) # # if os.path.isdir(network_config_dir): _logger.debug('NetworkManager/%s directory exists.' % network_config_dir) # # contains nwm keyfiles? nwm_files = glob(network_config_dir + '/*') if len(nwm_files) > 0: system_tools.exec_rmdir(network_config_dir) system_tools.exec_mkdir(network_config_dir) _logger.debug('%s emptied.' % network_config_dir) else: _logger.debug('No network manager keyfiles found.') # # update networkmanager configuration # TODO: write config file with configparser nwm_config_data = get_config_data('default_nwm_conf_file') with open(nw_mgr_cfg, 'w') as nwmf: nwmf.write('\n'.join(str(x) for x in nwm_config_data)) migrate_tools.result_msg( msg='Networkmanager configuration updated.', result=False) else: _logger.debug(msg=' No NetworkManager configuration present.') return netwmg_nics, netwmg_data
def a20_install_extra_pkgs(self): """ Install required and useful packages for OL-type installs, read the list of packages from oci-migrate-conf.yaml, ol_os_packages_to_install. Returns ------- bool: True on success, False otherwise. """ def get_ol_package_list(): """ Retrieve the list of packages to install from oci-migrate-config file. Returns ------- list: list of package names to install. """ _logger.debug('Collection list of packages.') try: pkg_list = get_config_data('ol_os_packages_to_install') _logger.debug('Package list: %s' % pkg_list) return pkg_list except Exception as e: _logger.warning('Failed to find a list of packages: %s' % str(e)) return False _logger.debug('__ Installing extra packages.') # # collect packages to install packages = get_ol_package_list() if not bool(packages): _logger.debug('No extra packages to install.') return True # # try: # # set current nameserver config. if system_tools.set_nameserver(): _logger.debug('Updating nameserver info succeeded.') else: _logger.error(' Failed to update nameserver info.') # # get package manipulation tool. pkg_mgr = self.exec_yum \ if self.package_tool['pkg_mgr'] == 'yum' else self.exec_dnf # # install packages for pkg in packages: # # verify if the package is available, the correct channel enabled. rpmlist = pkg_mgr(self.package_tool['package_available'] + [pkg]) pkg_present = False for lline in rpmlist.splitlines(): _logger.debug('%s' % lline) if pkg in lline: _logger.debug('The rpm %s is available.' % pkg) pkg_present = True break if not pkg_present: _logger.error(' The rpm %s is missing.' % pkg) migrate_data.migrate_preparation = False migrate_data.migrate_non_upload_reason += \ '\n The rpm package %s is missing from ' \ 'the yum repository.' % pkg return False else: installoutput = \ pkg_mgr(self.package_tool['package_install'] + [pkg]) _logger.debug('Successfully installed pkg %s:\n%s' % (pkg, installoutput)) migrate_tools.result_msg(msg='Installed %s.' % pkg, result=False) pause_msg(msg='Installed %s here, or not.' % pkg, pause_flag='_OCI_CHROOT') # # restore nameserver data if system_tools.restore_nameserver(): _logger.debug('Restoring nameserver info succeeded.') else: _logger.error(' Failed to restore nameserver info.') except Exception as e: errmsg = 'Failed to install one or more packages of ' \ '%s:\n%s' % (packages, str(e)) _logger.critical(' %s' % errmsg) migrate_tools.error_msg('%s' % errmsg) migrate_data.migrate_preparation = False migrate_data.migrate_non_upload_reason += '\n %s' % errmsg return False return True
def main(): """ Main Returns ------- int 0 on success, 1 otherwise. """ # # set locale lc_all_to_set = get_config_data('lc_all') os.environ['LC_ALL'] = "%s" % lc_all_to_set _logger.debug('Locale set to %s' % lc_all_to_set) # # python version pythonver = sys.version_info[0] _logger.debug('Python version is %s' % pythonver) # # parse the commandline args = parse_args() # # Operator needs to be root. if system_tools.is_root(): _logger.debug('User is root.') else: exit_with_msg(' *** ERROR *** You must run this program with root ' 'privileges') # # Verbose mode is False by default migrate_data.verbose_flag = args.verbose_flag _logger.debug('Verbose level set to %s' % migrate_data.verbose_flag) # # Yes flag migrate_data.yes_flag = args.yes_flag _logger.debug('Answer to yes/no questions supposed to be yes always.') # # collect and save configuration data migrate_data.oci_image_migrate_config = get_config_data('*') # try: # # input image if args.input_image: imagepath = args.input_image.name resultfilename = get_config_data('resultfilepath') + \ '_' + \ os.path.splitext(os.path.basename(imagepath))[0] \ + '.res' migrate_data.resultfilename = resultfilename migrate_tools.result_msg(msg='\n Running %s at %s\n' % ((os.path.basename(sys.argv[0]) + ' ' + ' '.join(sys.argv[1:])), time.ctime()), flags='w', result=True) else: raise OciMigrateException('Missing argument: input image path.') # # Import the 'format' modules and collect the format data supported_formats = migrate_tools.import_formats() if not bool(supported_formats): exit_with_msg(' *** ERROR *** No image format modules found') if migrate_data.verbose_flag: show_supported_formats_data(supported_formats) # # Check the utilities installed. util_list, missing_list = test_helpers() _logger.debug('%s' % util_list) if migrate_data.verbose_flag: show_utilities(util_list, missing_list) if missing_list: raise OciMigrateException('%s needs packages %s installed.\n' % (sys.argv[0], missing_list)) # # if qemu-img is used, the minimal version is 2 qemuversioninfo = qemu_img_version() if qemuversioninfo[1] < 2: raise OciMigrateException('Minimal version of qemu-img is 2, ' '%s found.' % qemuversioninfo[0]) else: _logger.debug('release data ok') # # Get the nameserver definition if system_tools.get_nameserver(): migrate_tools.result_msg(msg='nameserver %s identified.' % migrate_data.nameserver, result=False) _logger.debug('Nameserver identified as %s' % migrate_data.nameserver) else: migrate_tools.error_msg('Failed to identify nameserver, using %s, ' 'but might cause issues.' % migrate_data.nameserver) except Exception as e: _logger.error('*** ERROR *** %s\n' % str(e)) exit_with_msg(' *** ERROR *** %s\n' % str(e)) # # More on command line arguments. # # initialise output migrate_tools.result_msg(msg='Results are written to %s.' % migrate_data.resultfilename, result=True) migrate_tools.result_msg(msg='Input image: %s' % imagepath, result=True) # # Verify if readable. fn_magic = migrate_tools.get_magic_data(imagepath) if fn_magic is None: exit_with_msg('*** ERROR *** An error occured while trying to read ' 'magic number of File %s.' % imagepath) else: pause_msg('Image Magic Number: %s' % fn_magic) _logger.debug('Magic number %s successfully read' % fn_magic) # # Verify if image type is supported. _logger.debug('Magic number of %s is %s' % (imagepath, fn_magic)) if fn_magic not in supported_formats: exit_with_msg('*** ERROR *** Image type %s is not recognised.' % fn_magic) else: _logger.debug('Image type recognised.') # # Get the correct class. imageclazz = supported_formats[fn_magic] migrate_tools.result_msg(msg='Type of image %s identified as %s' % (imagepath, imageclazz['name']), result=True) pause_msg('Image type is %s' % imageclazz['name']) # # Locate the class and module imageclassdef = getattr(sys.modules['oci_utils.migrate.image_types.%s' % supported_formats[fn_magic]['name']], imageclazz['clazz']) image_object = imageclassdef(imagepath) # # Local volume groups. vgs_result = system_tools.exec_vgs_noheadings() migrate_data.local_volume_groups = \ vgs_result if bool(vgs_result) \ else [] _logger.debug('Workstation volume groups: %s' % migrate_data.local_volume_groups) # # Rename local volume groups if bool(migrate_data.local_volume_groups): rename_msg = '\n The workstation has logical volumes defined. To avoid ' \ 'duplicates, the \n logical volume groups will be temporary' \ ' renamed to a hexadecimal uuid.\n If you are sure the ' \ 'image to be uploaded does not contain logical volumes,\n' \ ' or there are no conflicting volume group names, '\ 'the rename can be skipped\n\n Keep the volume group names?' if not read_yn(rename_msg, waitenter=True, suppose_yes=migrate_data.yes_flag): if migrate_tools.verify_local_fstab(): fstab_msg = '\n The fstab file on this workstation seems to ' \ 'contain device references\n using /dev/mapper ' \ 'devices. The volume group names on this ' \ 'workstation\n will be renamed temporarily. ' \ '/dev/mapper devices referring to logical volumes\n' \ ' can create problems in this context. To avoid ' \ 'this situation\n exit now and modify the ' \ 'device specification to LABEL or UUID.\n\n Continue?' if not read_yn(fstab_msg, waitenter=True, suppose_yes=migrate_data.yes_flag): exit_with_msg('Exiting') _logger.debug('Rename local volume groups to avoid conflicts.') vgrename_res = system_tools.exec_rename_volume_groups( migrate_data.local_volume_groups, 'FORWARD') migrate_data.local_volume_group_rename = True else: _logger.debug('fstab file has no /dev/mapper devices.') else: _logger.debug('Not renaming the volume groups.') _ = system_tools.reset_vg_list(migrate_data.local_volume_groups) else: _logger.debug('No local volume groups, no conflicts.') # # Generic data collection try: imgres, imagedata = collect_image_data(image_object) if migrate_data.verbose_flag: migrate_tools.show_image_data(image_object) if imgres: _logger.debug('Image processing succeeded.') else: _logger.critical(' Image processing failed.', exc_info=False) # if imagedata: _logger.debug('%s passed.' % imagepath) else: _logger.critical(' %s failed.' % imagepath, exc_info=False) except Exception as e: _logger.critical(' %s failed: %s' % (imagepath, str(e))) exit_with_msg('*** ERROR *** Problem detected during investigation of ' 'the image %s: %s, exiting.' % (imagepath, str(e))) # # Restore volume group names. if migrate_data.local_volume_group_rename: _logger.debug('Restore local volume groups.') vgrename_res = system_tools.exec_rename_volume_groups( migrate_data.local_volume_groups, 'BACKWARD') else: _logger.debug('No local volume group names to restore.') # # passed prerequisites and changes? prereq_passed = True # # Image type specific prerequisites prereq_msg = '' sup, msg = image_object.type_specific_prereq_test() if sup: migrate_tools.result_msg(msg='%s' % msg, result=True) else: prereq_passed = False prereq_msg = msg # # Generic prerequisites verification try: gen_prereq, msg = image_object.generic_prereq_check() if gen_prereq: prereq_msg += '\n %s passed the generic preqrequisites.' % imagepath else: prereq_passed = False prereq_msg += msg # if imgres: prereq_msg += '\n\n %s data collection and processing succeeded.' \ % imagepath else: prereq_passed = False # if prereq_passed: migrate_tools.result_msg(msg=prereq_msg, result=True) if imagedata['boot_type'] == 'BIOS': migrate_tools.result_msg(msg='\n Boot type is BIOS, ' 'use launch_mode PARAVIRTUALIZED ' '(or EMULATED) at import.', result=True) elif imagedata['boot_type'] == 'UEFI': migrate_tools.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') else: prereq_msg += '\n\n %s processing failed, check the logfile ' \ 'and/or set environment variable _OCI_UTILS_DEBUG.' \ % imagepath raise OciMigrateException(prereq_msg) except Exception as e: exit_with_msg('*** ERROR *** %s' % str(e)) # # While prerequisite check did not hit a fatal issue, there might be # situations where upload should not proceed. if not migrate_data.migrate_preparation: exit_with_msg('*** ERROR *** Unable to proceed with uploading image ' 'to Oracle Cloud Infrastructure: %s' % migrate_data.migrate_non_upload_reason) else: migrate_tools.result_msg('Successfully verified and processed image %s ' 'and is ready for upload.' % imagepath) return 0
def a30_set_oci_region(): """ Add a job to cloud-init config file to complete the ociregion data at first boot. Returns ------- bool: True on success, False otherwise. """ def add_oci_region(regionscript): """ Update the default user name in the cloud.cfg file. Parameters: ---------- regionscript: str full path of the bash script. Returns: ------- bool: True on success, False otherwise. """ _logger.debug('__ Add oci region.') try: cloudconfig = get_config_data('cloudconfig_file') _logger.debug('Updating cloud.cfg file %s, adding oci region ' 'detection.' % cloudconfig) except Exception as e: _logger.error('Failed to find cloud config file ' 'location: %s.' % str(e)) return False if os.path.isfile(cloudconfig): with open(cloudconfig, 'r') as f: cloudcfg = yaml.load(f, Loader=yaml.SafeLoader) region_definition = False if type(cloudcfg) is dict: if 'runcmd' in list(cloudcfg.keys()): # # runcmd present in cloud config file run_cmd = cloudcfg['runcmd'] for yaml_key in run_cmd: if type(yaml_key) == 'list': for yamlval in yaml_key: if regionscript in yamlval: _logger.debug('%s already in ' 'cloud_init' % regionscript) region_definition = True break else: if regionscript in yaml_key: _logger.debug('%s already in ' 'cloud_init' % regionscript) region_definition = True break if not region_definition: # # the regionscript not yet defined in runcmd run_cmd.append(regionscript) else: # # runcmd not yet present in cloud config file cloudcfg['runcmd'] = [regionscript] with open(cloudconfig, 'w') as f: yaml.dump(cloudcfg, f, width=50) _logger.debug('Cloud configuration file %s successfully ' 'updated.' % cloudconfig) return True else: _logger.error('Invalid cloud config file.') else: _logger.error('Cloud config file %s does not exist.' % cloudconfig) return False _logger.debug('__ Set OCI region.') # # get the script name try: oci_region_script = get_config_data('ol_os_oci_region_script') _logger.debug('Got oci-region script name: %s' % oci_region_script) except Exception as e: _logger.warning('Failed to collect the oci_region_script ' 'path: %s' % str(e)) return False # # write the oci region script code with open(oci_region_script, 'w') as fi: fi.writelines(ln + '\n' for ln in get_config_data('ol_os_oci_region_bash')) os.chmod(oci_region_script, stat.S_IRWXU) # # update cloud-init with runcmd command if add_oci_region(oci_region_script): _logger.debug('oci region successfully added.') migrate_tools.result_msg(msg='Updated OCI region.', result=False) return True else: _logger.debug('Failed to update oci region.') return False