예제 #1
0
 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
예제 #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(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)
예제 #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.
    """
    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
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
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)
    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
예제 #7
0
    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))
예제 #8
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
        }

        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
예제 #9
0
    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
예제 #10
0
    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)
예제 #11
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))
                # 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
예제 #12
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:
                            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
예제 #13
0
    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
예제 #14
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'))
                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
예제 #15
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:
        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
예제 #16
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')
                _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
예제 #18
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