Example #1
0
def exec_search(file_name, rootdir='/', dirnames=False):
    """
    Find the filename in the rootdir tree.

    Parameters
    ----------
    file_name: str
        The filename to look for.
    rootdir: str
        The directory to start from, default is root.
    dirnames: bool
        If True, also consider directory names.

    Returns
    -------
        str: The full path of the filename if found, None otherwise.
    """
    _logger.debug('__ Looking for %s in %s', file_name, rootdir)
    result_msg(msg='Looking for %s in %s, might take a while.' % (file_name, rootdir))
    try:
        for path_name, directories, files in os.walk(rootdir):
            # _logger.debug('%s %s %s', path_name, directories, files)
            if file_name in files:
                _logger.debug('Found %s', os.path.join(rootdir, path_name, file_name))
                return os.path.join(rootdir, path_name, file_name)
            if dirnames and file_name in directories:
                _logger.debug('Found %s as directory.', os.path.join(rootdir, path_name, file_name))
                return os.path.join(rootdir, path_name, file_name)
    except Exception as e:
        _logger.error('  Error while looking for %s: %s', file_name, str(e))
        raise OciMigrateException('Error while looking for %s:' % file_name) from e
    return None
Example #2
0
    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().__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' %
                                      self._fn) from 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
        result_msg(msg='Got image %s header' % filename, result=False)
Example #3
0
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.
    """
    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

    result_msg(msg='Adjusted network configuration.', result=True)
    return network_list, network_config
Example #4
0
def show_default_kernel(kernelversion):
    """
    Show the default kernel version.
    Parameters
    ----------
    kernelversion: str
        The version of the kernel booted by default.

    Returns
    -------
        No return value.
    """
    result_msg(msg='\n  Default kernel: %s' % kernelversion, result=True)
Example #5
0
def show_fstab(fstabdata):
    """
    Show the relevant data in the fstab file.

    Parameters
    ----------
    fstabdata: list of lists, one list per fstab line.

    Returns
    -------
        No return value.
    """
    for line in fstabdata:
        result_msg(msg='%60s %20s %8s %20s %2s %2s' % (line[0], line[1], line[2], line[3], line[4], line[5]), result=True)
Example #6
0
def show_kernel_list(kernels):
    """
    Show the kernels defined in the grub config file.
    Parameters
    ----------
    kernels: list
        List of kernels defined in the grub config file.

    Returns
    -------
        No return value.
    """
    for kver in sorted(kernels):
        result_msg(msg='   %s' % kver, result=True)
Example #7
0
def print_header(head):
    """
    Display header for image data component.

    Parameters
    ----------
    head: str
        The header

    Returns
    -------
        No return value.
    """
    result_msg(msg='\n  %30s\n  %30s' % (head, '-' * 30), result=True)
Example #8
0
    def show_header(self):
        """
        Lists the header contents formatted.

        Returns
        -------
            No return value.
        """
        result_msg(msg='\n  %30s\n  %30s' %
                   ('QCOW2 file header data', '-' * 30),
                   result=False)
        for f in Qcow2Head.header2_structure:
            result_msg(msg=''.join(
                ["  %-30s" % f[2], f[1] % self.qcowhead_dict[f[2]]]),
                       result=False)
Example #9
0
    def __init__(self, filename):
        """
        Initialisation of the vmdk header analysis.

        Parameters
        ----------
        filename: str
            Full path of the vmdk image file.
        """
        super().__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) from 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) from 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
        result_msg(msg='Got image %s header' % filename, result=False)
Example #10
0
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, pause_flag='_OCI_EXEC')
    try:
        result = run_popen_cmd(cmd)['output'].decode('utf-8')
        partdata = dict()
        for devx in result.splitlines():
            if devx.startswith(devname):
                key = devx.split(':')[0].strip()
                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
Example #11
0
def show_network_data(networkdata):
    """
    Show the collected data on the network interfaces.

    Parameters
    ----------
    networkdata: dict
        Dictionary of dictionaries containing the network configuration data.

    Returns
    -------
        No return value.
    """
    for nic, nicdata in sorted(networkdata.items()):
        result_msg(msg='  %20s:' % nic, result=True)
        for k, v in sorted(nicdata.items()):
            result_msg(msg='  %30s = %s' % (k, v), result=True)
Example #12
0
def show_img_header(headerdata):
    """
    Show the header data.

    Parameters
    ----------
    headerdata: dict
        Dictionary containing data extracted from the image header; contents
        is dependent form image type.

    Returns
    -------
        No return value.
    """
    result_msg(msg='\n  %30s\n  %30s' % ('Image header:', '-'*30), result=True)
    for k, v in sorted(headerdata):
        result_msg(msg='  %30s : %s' % (k, v), result=True)
Example #13
0
    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
        }

        result_msg(msg='Image size: physical %10.2f GB, logical %10.2f GB' %
                   (img_sz['physical'], img_sz['logical']),
                   result=True)
        return img_sz
Example #14
0
def show_grub_data(grublist):
    """
    Show the relevant data in the grub config file.

    Parameters
    ----------
    grublist: list of dictionaries, 1 per boot section, containing grub
    lines as list.

    Returns
    -------
        No return value.
    """
    for entry in grublist:
        _logger.debug('%s', entry)
        for grubkey in entry:
            for grubline in entry[grubkey]:
                result_msg(msg=grubline, result=True)
            result_msg(msg='\n', result=True)
Example #15
0
def show_partition_table(table):
    """
    Show the relevant data of the partition table.

    Parameters
    ----------
    table: list of dict.
        The partition table data.

    Returns
    -------
        No return value.
    """
    result_msg(msg='  %2s %5s %16s %32s' % ('nb', 'boot', 'type', 'data'),
               result=True)
    result_msg(msg='  %2s %5s %16s %32s' %
               ('-' * 2, '-' * 5, '-' * 16, '-' * 32),
               result=True)
    for i in range(0, 4):
        if table[i]['boot']:
            bootflag = 'YES'
        else:
            bootflag = ' NO'
        result_msg(msg='  %02d %5s %16s %32s' %
                   (i, bootflag, table[i]['type'], table[i]['entry']),
                   result=True)
Example #16
0
    def __init__(self, filename):
        """
        Initialisation of the templatetype header analysis.

        Parameters
        ----------
        filename: str
            Full path of the template_type image file.
        """
        super().__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' % self._fn) from 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
        result_msg(msg='Got image %s header' % filename, result=False)
        #
        # mount the image using the nbd
        try:
            self.device_name = self.mount_img()
            _logger.debug('Image data %s', self.device_name)
            result_msg(msg='Mounted %s' % self.device_name, result=False)
            deviceinfo = self.handle_image()
        except Exception as e:
            _logger.critical('   Error %s', str(e))
            raise OciMigrateException('Failed') from e
Example #17
0
def show_partition_data(partition_dict):
    """
    Show the collected data on the partitions of the image file.

    Parameters
    ----------
    partition_dict: dict
        The data.

    Returns
    -------
        No return value
    """
    for k, v in sorted(partition_dict.items()):
        result_msg(msg='%30s :\n%s' % ('partition %s' % k, '-'*60), result=True)
        for x, y in sorted(v.items()):
            result_msg(msg='%30s : %s' % (x, y), result=True)
        result_msg(msg='\n', result=True)
    result_msg(msg='\n', result=True)
Example #18
0
    def show_header(self):
        """
        Lists the header contents formatted.

        Returns
        -------
            No return value.
        """
        result_msg(msg='\n  %30s\n  %30s   %30s' %
                   ('VMDK file header data', '-' * 30, '-' * 30),
                   result=False)
        for f in VmdkHead.header0_structure:
            result_msg(msg=''.join(
                ['  %30s : ' % f[2], f[1] % self.vmdkhead_dict[f[2]]]),
                       result=False)
        result_msg(msg='\n  %30s\n  %30s   %30s' %
                   ('VMDK file descriptor data', '-' * 30, '-' * 30),
                   result=False)
        for k in sorted(self.vmdkdesc_dict):
            result_msg(msg='  %30s : %-30s' % (k, self.vmdkdesc_dict[k]),
                       result=False)
Example #19
0
def show_parted_data(parted_dict):
    """
    Show the data collected by the parted command.

    Parameters
    ----------
    parted_dict: dict
        The data.

    Returns
    -------
        No return value.
    """
    for k, v in sorted(parted_dict.items()):
        if k == 'Partition List':
            result_msg(msg='%30s :' % k, result=True)
            for part in v:
                result_msg(msg='%30s : %s' % (' ', ' '.join(part)), result=True)
        else:
            result_msg(msg='%30s : %s' % (k, v), result=True)
    result_msg(msg='\n', result=True)
Example #20
0
def mount_imgfn(imgname):
    """
    Link vm image with an nbd device.

    Parameters
    ----------
    imgname: str
        Full path of the image file.

    Returns
    -------
        str: Device name on success, raises an exception otherwise.
    """
    #
    # create nbd devices
    _logger.debug('__ Running mount image file %s.', imgname)
    result_msg(msg='Load nbd')
    if not system_tools.create_nbd():
        raise OciMigrateException('Failed ot load nbd module')

    _logger.debug('nbd module loaded')
    #
    # find free nbd device
    result_msg(msg='Find free nbd device')
    devpath = system_tools.get_free_nbd()
    _logger.debug('Device %s is free.', devpath)
    #
    # link img with first free nbd device
    result_msg(msg='Mount image %s' % imgname, result=True)
    _, nbcols = terminal_dimension()
    try:
        mountwait = ProgressBar(nbcols, 0.2, progress_chars=['mounting image'])
        mountwait.start()
        qemucmd = ['-c', devpath, imgname]
        pause_msg(qemucmd, pause_flag='_OCI_MOUNT')
        qemunbd_ret = system_tools.exec_qemunbd(qemucmd)
        if qemunbd_ret == 0:
            time.sleep(5)
            _logger.debug('qemu-nbd %s succeeded', qemucmd)
            return devpath

        _logger.critical('\n   Failed to create nbd devices: %d', qemunbd_ret)
        raise Exception('Failed to create nbd devices: %d' % qemunbd_ret)
    except Exception as e:
        _logger.critical('\n   Something wrong with creating nbd devices: %s',
                         str(e))
        raise OciMigrateException('Unable to create nbd devices:') from e
    finally:
        if system_tools.is_thread_running(mountwait):
            mountwait.stop()
Example #21
0
def show_lvm2_data(lvm2_data):
    """
    Show the collected lvm2 data.

    Parameters
    ----------
    lvm2_data: dict
        Dictionary containing the recognised volume groups and logical volumes.

    Returns
    -------
        No return value.
    """
    for k, v in sorted(lvm2_data.items()):
        result_msg(msg='\n  Volume Group: %s:' % k, result=True)
        for t in v:
            result_msg(msg='%40s : %-30s' % (t[0], t[1]), result=True)
    result_msg(msg='\n', result=True)
Example #22
0
def show_image_data(imgobj):
    """
    Show the collected data about the image.

    Parameters
    ----------
    imgobj: object
        The data about the image.

    Returns
    -------
        No return value.
    """
    print_header('Components collected.')
    for k, _ in sorted(imgobj.image_info.items()):
        result_msg(msg='  %30s' % k, result=True)

    _logger.debug('show data')
    print('\n  %25s\n  %s' % ('Image data:', '-' * 60))
    #
    # name
    fnname = '  missing'
    print_header('Image file path.')
    if 'img_name' in imgobj.image_info:
        fnname = imgobj.image_info['img_name']
    result_msg(msg='  %30s' % fnname, result=True)
    #
    # type
    imgtype = '  missing'
    print_header('Image type.')
    if 'img_type' in imgobj.image_info:
        imgtype = imgobj.image_info['img_type']
    result_msg(msg='  %30s' % imgtype, result=True)
    #
    # size
    imgsizes = '    physical: missing data\n    logical:  missing data'
    print_header('Image size:')
    if 'img_size' in imgobj.image_info:
        imgsizes = '    physical: %8.2f GB\n      logical:  %8.2f GB' \
                   % (imgobj.image_info['img_size']['physical'],
                      imgobj.image_info['img_size']['logical'])
    result_msg(msg='%s' % imgsizes, result=True)
    #
    # header
    if 'img_header' in imgobj.image_info:
        try:
            imgobj.show_header()
        except Exception as e:
            result_msg(msg='Failed to show the image hadear: %s' % str(e),
                       result=True)
    else:
        result_msg(msg='\n  Image header data missing.', result=True)
    #
    # mbr
    mbr = '  missing'
    print_header('Master Boot Record.')
    if 'mbr' in imgobj.image_info:
        if 'hex' in imgobj.image_info['mbr']:
            mbr = imgobj.image_info['mbr']['hex']
        result_msg(msg='%s' % mbr, result=True)
        #
        # partition table
        print_header('Partiton Table.')
        parttabmissing = '  Partition table data is missing.'
        if 'partition_table' in imgobj.image_info['mbr']:
            show_partition_table(imgobj.image_info['mbr']['partition_table'])
        else:
            result_msg(msg=parttabmissing, result=True)
    #
    # parted data
    print_header('Parted data.')
    parteddata = '  Parted data is missing.'
    if 'parted' in imgobj.image_info:
        show_parted_data(imgobj.image_info['parted'])
    else:
        result_msg(msg='%s' % parteddata, result=True)
    #
    # partition data
    print_header('Partition Data.')
    partdata = '  Partition data is missing.'
    if 'partitions' in imgobj.image_info:
        show_partition_data(imgobj.image_info['partitions'])
    else:
        result_msg(msg='%s' % partdata, result=True)
    #
    # grub config data
    print_header('Grub configuration data.')
    grubdat = '  Grub configuration data is missing.'
    if 'grubdata' in imgobj.image_info:
        show_grub_data(imgobj.image_info['grubdata'])
    else:
        result_msg(msg='%s' % grubdat, result=True)
    #
    # kernel versions
    print_header('Default kernel version.')
    kerneldefdat = '   Default kernel data not found or is missing.'
    if 'kernelversion' in imgobj.image_info:
        show_default_kernel(imgobj.image_info['kernelversion'])
    else:
        result_msg(msg='%s' % kerneldefdat, result=True)
    print_header('Installed kernels.')
    kernellisdat = '   List of kernels is missing.'
    if 'kernellist' in imgobj.image_info:
        show_kernel_list(imgobj.image_info['kernellist'])
    else:
        result_msg(msg='%s' % kernellisdat, result=True)
    #
    # logical volume data
    print_header('Logical Volume data.')
    lvmdata = '  Logical Volume data is missing.'
    if 'volume_groups' in imgobj.image_info:
        if imgobj.image_info['volume_groups']:
            show_lvm2_data(imgobj.image_info['volume_groups'])
    else:
        result_msg(msg=lvmdata, result=True)
    #
    # various data:
    print_header('Various data.')
    if 'bootmnt' in imgobj.image_info:
        result_msg(msg='  %30s: %s mounted on %s' %
                   ('boot', imgobj.image_info['bootmnt'][0],
                    imgobj.image_info['bootmnt'][1]),
                   result=True)
    if 'rootmnt' in imgobj.image_info:
        result_msg(msg='  %30s: %s mounted on %s' %
                   ('root', imgobj.image_info['rootmnt'][0],
                    imgobj.image_info['rootmnt'][1]),
                   result=True)
    if 'boot_type' in imgobj.image_info:
        result_msg(msg='  %30s: %-30s' %
                   ('boot type:', imgobj.image_info['boot_type']),
                   result=True)
    #
    # fstab
    print_header('fstab data.')
    fstabmiss = '  fstab data is missing.'
    if 'fstab' in imgobj.image_info:
        show_fstab(imgobj.image_info['fstab'])
    else:
        result_msg(msg=fstabmiss, result=True)
    #
    # os release data
    print_header('Operating System information.')
    osinfomissing = '  Operation System information is missing.'
    if 'osinformation' in imgobj.image_info:
        for k in sorted(imgobj.image_info['osinformation']):
            result_msg(msg='  %35s : %-30s' %
                       (k, imgobj.image_info['osinformation'][k]),
                       result=True)
    else:
        result_msg(msg=osinfomissing, result=True)
Example #23
0
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:
        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))
            result_msg(msg='Networkmanager configuration updated.',
                       result=False)
    else:
        _logger.debug(msg='  No NetworkManager configuration present.')

    return netwmg_nics, netwmg_data
Example #24
0
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'))
                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
Example #25
0
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:
                            _ = 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'))
        result_msg(msg='systemd-networkd configuration rewritten.',
                   result=True)
    else:
        _logger.debug('No systemd-networkd configuration.')
    return sorted(sys_nics), sys_data
Example #26
0
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)
                # 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'))
            result_msg(msg='Replaced ifcfg network configuration.',
                       result=False)
        except Exception as e:
            _logger.error('  Failed to write %s/ifcfg-eth0', ifrootdir)
            error_msg('Failed to write %s: %s' % (dhcpniccfg, str(e)))
            raise OciMigrateException('Failed to write %s:' %
                                      dhcpniccfg) from e
    else:
        _logger.debug('No ifcfg definitions found.')

    return ifcfg_list, ifcfg_data
Example #27
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 isinstance(cloudcfg, dict):
                    if 'runcmd' in list(cloudcfg.keys()):
                        #
                        # runcmd present in cloud config file
                        run_cmd = cloudcfg['runcmd']
                        for yaml_key in run_cmd:
                            if isinstance(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
                _logger.error('Invalid cloud config file.')
                return False
            _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.')
            result_msg(msg='Updated OCI region.', result=False)
            return True
        _logger.debug('Failed to update oci region.')
        return False
Example #28
0
    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')
                if not bool(pkg_list):
                    _logger.debug('Package list is empty.')
                    return False
                _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
                installoutput = pkg_mgr(self.package_tool['package_install'] +
                                        [pkg])
                _logger.debug('Successfully installed pkg %s:\n%s', pkg,
                              installoutput)
                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)
            error_msg('%s' % errmsg)
            migrate_data.migrate_preparation = False
            migrate_data.migrate_non_upload_reason += '\n  %s' % errmsg
            return False
        return True
Example #29
0
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
    python_version = sys.version_info[0]
    _logger.debug('Python version is %s', python_version)
    #
    # 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:
            image_path = args.input_image.name
            result_filename = get_config_data('result_filepath') \
                              + '_' \
                              + os.path.splitext(os.path.basename(image_path))[0] \
                              + '.res'
            migrate_data.result_filename = result_filename
            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
        qemu_version_info = qemu_img_version()
        if qemu_version_info[1] < 2:
            raise OciMigrateException('Minimal version of qemu-img is 2, '
                                      '%s found.' % qemu_version_info[0])
        _logger.debug('release data ok')
        #
        # Get the nameserver definition
        if system_tools.get_nameserver():
            result_msg(msg='nameserver %s identified.' %
                       migrate_data.nameserver,
                       result=False)
            _logger.debug('Nameserver identified as %s',
                          migrate_data.nameserver)
        else:
            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
    result_msg(msg='Results are written to %s.' % migrate_data.result_filename,
               result=True)
    result_msg(msg='Input image:  %s' % image_path, result=True)
    #
    # Verify if readable.
    fn_magic = migrate_tools.get_magic_data(image_path)
    if fn_magic is None:
        exit_with_msg('*** ERROR *** An error occurred while trying to read '
                      'magic number of File %s.' % image_path)
    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', image_path, 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.
    image_clazz = supported_formats[fn_magic]
    result_msg(msg='Type of image %s identified as %s' %
               (image_path, image_clazz['name']),
               result=True)
    pause_msg('Image type is %s' % image_clazz['name'])
    #
    # Locate the class and module
    image_class_def = getattr(
        sys.modules['oci_utils.migrate.image_types.%s' %
                    supported_formats[fn_magic]['name']], image_clazz['clazz'])
    image_object = image_class_def(image_path)
    #
    # 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')
                if not vgrename_res:
                    _logger.warning('Failed to rename local volume groups.')
                    if not read_yn(
                            '\n   Failed to rename the local volume groups. '
                            'Continue on your own responsibility?',
                            waitenter=True,
                            suppose_yes=migrate_data.yes_flag):
                        exit_with_msg('Exiting.')
                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.', image_path)
        else:
            _logger.critical('   %s failed.', image_path, exc_info=False)
    except Exception as e:
        _logger.critical('   %s failed: %s', image_path, str(e))
        exit_with_msg('*** ERROR *** Problem detected during investigation of '
                      'the image %s: %s, exiting.' % (image_path, 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')
        if not vgrename_res:
            _logger.warning('Failed to restore local volume group names.')
    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:
        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.' % image_path
        else:
            prereq_passed = False
            prereq_msg += msg
        #
        if imgres:
            prereq_msg += '\n\n  %s data collection and processing succeeded.' \
                          % image_path
        else:
            prereq_passed = False
        #
        if prereq_passed:
            result_msg(msg=prereq_msg, result=True)
            if imagedata['boot_type'] == 'BIOS':
                result_msg(
                    msg=
                    '\n  Boot type is BIOS, use launch_mode PARAVIRTUALIZED (or EMULATED) at import.',
                    result=True)
            elif imagedata['boot_type'] == 'UEFI':
                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.' \
                          % image_path
            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:
        result_msg(
            'Successfully verified and processed image %s and is ready for upload.'
            % image_path)
    return 0