Best Python code snippet using autotest_python
boottool.py
Source:boottool.py  
...392            # index values are integrals393            value = int(value)394        entry[name] = value395    return entry396def detect_distro_type():397    '''398    Simple distro detection based on release/version files399    '''400    if os.path.exists('/etc/redhat-release'):401        return 'redhat'402    elif os.path.exists('/etc/debian_version'):403        return 'debian'404    elif os.path.exists('/etc/SuSE-release'):405        return 'suse'406    else:407        return None408class DebianBuildDeps(object):409    '''410    Checks and install grubby build dependencies on Debian (like) systems411    Tested on:412       * Debian Squeeze (6.0)413       * Ubuntu 12.04 LTS414    '''415    PKGS = ['gcc', 'make', 'libpopt-dev', 'libblkid-dev']416    def check(self):417        '''418        Checks if necessary packages are already installed419        '''420        result = True421        for p in self.PKGS:422            args = ['dpkg-query', '--show', '--showformat=${Status}', p]423            output = subprocess.Popen(args, shell=False,424                                      stdin=subprocess.PIPE,425                                      stdout=subprocess.PIPE,426                                      stderr=subprocess.PIPE,427                                      close_fds=True).stdout.read()428            if output != 'install ok installed':429                result = False430        return result431    def install(self):432        '''433        Attempt to install the build dependencies via a package manager434        '''435        if self.check():436            return True437        else:438            try:439                args = ['apt-get', 'update', '-qq']440                subprocess.call(args,441                                stdout=subprocess.PIPE,442                                stderr=subprocess.PIPE)443                args = ['apt-get', 'install', '-qq'] + self.PKGS444                subprocess.call(args,445                                stdout=subprocess.PIPE,446                                stderr=subprocess.PIPE)447            except OSError:448                pass449        return self.check()450class RPMBuildDeps(object):451    '''452    Base class for RPM based systems453    '''454    def check(self):455        '''456        Checks if necessary packages are already installed457        '''458        result = True459        for p in self.PKGS:460            args = ['rpm', '-q', '--qf=%{NAME}', p]461            output = subprocess.Popen(args, shell=False,462                                      stdin=subprocess.PIPE,463                                      stdout=subprocess.PIPE,464                                      stderr=subprocess.PIPE,465                                      close_fds=True).stdout.read()466            if not output.startswith(p):467                result = False468        return result469class SuseBuildDeps(RPMBuildDeps):470    '''471    Checks and install grubby build dependencies on SuSE (like) systems472    Tested on:473       * OpenSuSE 12.2474    '''475    PKGS = ['gcc', 'make', 'popt-devel', 'libblkid-devel']476    def install(self):477        '''478        Attempt to install the build dependencies via a package manager479        '''480        if self.check():481            return True482        else:483            try:484                args = ['zypper', '-n', '--no-cd', 'install'] + self.PKGS485                result = subprocess.call(args,486                                         stdout=subprocess.PIPE,487                                         stderr=subprocess.PIPE)488            except OSError:489                pass490        return self.check()491class RedHatBuildDeps(RPMBuildDeps):492    '''493    Checks and install grubby build dependencies on RedHat (like) systems494    Tested on:495       * Fedora 17496       * RHEL 5497       * RHEL 6498    '''499    PKGS = ['gcc', 'make']500    REDHAT_RELEASE_RE = re.compile('.*\srelease\s(\d)\.(\d)\s.*')501    def __init__(self):502        '''503        Initializes a new dep installer, taking into account RHEL version504        '''505        match = self.REDHAT_RELEASE_RE.match(open('/etc/redhat-release').read())506        if match:507            major, minor = match.groups()508            if int(major) <= 5:509                self.PKGS += ['popt', 'e2fsprogs-devel']510            else:511                self.PKGS += ['popt-devel', 'libblkid-devel']512    def install(self):513        '''514        Attempt to install the build dependencies via a package manager515        '''516        if self.check():517            return True518        else:519            try:520                args = ['yum', 'install', '-q', '-y'] + self.PKGS521                # This is an extra safety step, to install the needed header522                # in case the blkid headers package could not be detected523                args += ['/usr/include/popt.h',524                         '/usr/include/blkid/blkid.h']525                result = subprocess.call(args,526                                         stdout=subprocess.PIPE,527                                         stderr=subprocess.PIPE)528            except OSError:529                pass530        return self.check()531DISTRO_DEPS_MAPPING = {532    'debian': DebianBuildDeps,533    'redhat': RedHatBuildDeps,534    'suse': SuseBuildDeps535}536def install_grubby_if_necessary(path=None):537    '''538    Installs grubby if it's necessary on this system539    Or if the required version is not sufficient for the needs of boottool540    '''541    installed_grubby = False542    if path is None:543        if find_executable(GRUBBY_DEFAULT_USER_PATH):544            executable = GRUBBY_DEFAULT_USER_PATH545        else:546            executable = find_executable(GRUBBY_DEFAULT_SYSTEM_PATH)547    else:548        executable = find_executable(path)549    if executable is None:550        log.info('Installing grubby because it was not found on this system')551        grubby = Grubby()552        path = grubby.grubby_install()553        installed_grubby = True554    else:555        grubby = Grubby(executable)556        current_version = grubby.get_grubby_version()557        if current_version is None:558            log.error('Could not find version for grubby executable "%s"',559                      executable)560            path = grubby.grubby_install()561            installed_grubby = True562        elif current_version < GRUBBY_REQ_VERSION:563            log.info('Installing grubby because currently installed '564                     'version (%s.%s) is not recent enough',565                     current_version[0], current_version[1])566            path = grubby.grubby_install()567            installed_grubby = True568    if installed_grubby:569        grubby = Grubby(path)570        installed_version = grubby.get_grubby_version_raw()571        log.debug('Installed: %s', installed_version)572class GrubbyInstallException(Exception):573    '''574    Exception that signals failure when doing grubby installation575    '''576    pass577class Grubby(object):578    '''579    Grubby wrapper580    This class calls the grubby binary for most commands, but also581    adds some functionality that is not really suited to be included582    in int, such as boot-once.583    '''584    SUPPORTED_BOOTLOADERS = ('lilo', 'grub2', 'grub', 'extlinux', 'yaboot',585                             'elilo')586    def __init__(self, path=None, opts=None):587        self._set_path(path)588        self.bootloader = None589        self.opts = opts590        self.log = logging.getLogger(self.__class__.__name__)591        if os.environ.has_key('BOOTTOOL_DEBUG_RUN'):592            self.debug_run = True593        else:594            self.debug_run = False595        self._check_grubby_version()596        self._set_bootloader()597    def _set_path(self, path=None):598        """599        Set grubby path.600        If path is not provided, check first if there's a built grubby,601        then look for the system grubby.602        :param path: Alternate grubby path.603        """604        if path is None:605            if os.path.exists(GRUBBY_DEFAULT_USER_PATH):606                self.path = GRUBBY_DEFAULT_USER_PATH607            else:608                self.path = GRUBBY_DEFAULT_SYSTEM_PATH609        else:610            self.path = path611    #612    # The following block contain utility functions that are used to build613    # most of these class methods, such as methods for running commands614    # and preparing grubby command line switches.615    #616    def _check_grubby_version(self):617        '''618        Checks the version of grubby in use and warns if it's not good enough619        '''620        current_version = self.get_grubby_version()621        if current_version is None:622            self.log.warn('Could not detect current grubby version. It may '623                          'be that you are running an unsupported version '624                          'of grubby')625        elif current_version < GRUBBY_REQ_VERSION:626            self.log.warn('version %s.%s being used is not guaranteed to '627                          'work properly. Mininum required version is %s.%s.',628                          current_version[0], current_version[1],629                          GRUBBY_REQ_VERSION[0], GRUBBY_REQ_VERSION[1])630    def _run_get_output(self, arguments):631        '''632        Utility function that runs a command and returns command output633        '''634        if self.debug_run:635            self.log.debug('running: "%s"', ' '.join(arguments))636        result = None637        try:638            result = subprocess.Popen(arguments, shell=False,639                                      stdin=subprocess.PIPE,640                                      stdout=subprocess.PIPE,641                                      close_fds=True).stdout.read()642        except Exception:643            pass644        if result is not None:645            result = result.strip()646            if self.debug_run:647                logging.debug('previous command output: "%s"', result)648        else:649            self.log.error('_run_get_output error while running: "%s"',650                           ' '.join(arguments))651        return result652    def _run_get_output_err(self, arguments):653        '''654        Utility function that runs a command and returns command output655        '''656        if self.debug_run:657            self.log.debug('running: "%s"', ' '.join(arguments))658        result = None659        try:660            result = subprocess.Popen(arguments, shell=False,661                                      stdin=subprocess.PIPE,662                                      stdout=subprocess.PIPE,663                                      stderr=subprocess.PIPE,664                                      close_fds=True).stdout.read()665        except Exception:666            pass667        if result is not None:668            result = result.strip()669            if self.debug_run:670                logging.debug('previous command output/error: "%s"', result)671        else:672            self.log.error('_run_get_output_err error while running: "%s"',673                           ' '.join(arguments))674        return result675    def _run_get_return(self, arguments):676        '''677        Utility function that runs a command and returns status code678        '''679        if self.debug_run:680            self.log.debug('running: "%s"', ' '.join(arguments))681        result = None682        try:683            result = subprocess.call(arguments)684            if self.debug_run:685                logging.debug('previous command result: %s', result)686        except OSError:687            result = -1688            self.log.error('caught OSError, returning %s', result)689        return result690    def _set_bootloader(self, bootloader=None):691        '''692        Attempts to detect what bootloader is installed on the system693        The result of this method is used in all other calls to grubby,694        so that it acts accordingly to the bootloader detected.695        '''696        if bootloader is None:697            result = self.get_bootloader()698            if result is not None:699                self.bootloader = result700        else:701            if bootloader in self.SUPPORTED_BOOTLOADERS:702                self.bootloader = bootloader703            else:704                raise ValueError('Bootloader "%s" is not supported' %705                                 bootloader)706    def _dist_uses_grub2(self):707        if self.get_architecture().startswith('ppc64'):708            (d_name, d_version, d_id) = platform.dist()709            if d_name.lower() == 'redhat' and d_version >= 7:710                return True711            if d_name.lower() == 'suse' and d_version >= 12:712                return True713        return False714    def _run_grubby_prepare_args(self, arguments, include_bootloader=True):715        '''716        Prepares the argument list when running a grubby command717        '''718        args = []719        if self.path is None:720            self._set_path()721        args.append(self.path)722        if self.path is not None and not os.path.exists(self.path):723            self.log.error('grubby executable does not exist: "%s"', self.path)724            if not os.access(self.path, os.R_OK | os.X_OK):725                self.log.error('insufficient permissions (read and execute) '726                               'for grubby executable: "%s"', self.path)727        # If a bootloader has been detected, that is, a mode has been set,728        # it's passed as the first command line argument to grubby729        if include_bootloader and self.bootloader is not None:730            args.append('--%s' % self.bootloader)731        # Override configuration file732        if self.opts is not None and self.opts.config_file:733            args.append('--config-file=%s' % self.opts.config_file)734        elif self._dist_uses_grub2():735            args.append('--config-file=/boot/grub2/grub.cfg')736        args += arguments737        return args738    def _run_grubby_get_output(self, arguments, include_bootloader=True):739        '''740        Utility function that runs grubby with arguments and returns output741        '''742        args = self._run_grubby_prepare_args(arguments, include_bootloader)743        return self._run_get_output(args)744    def _run_grubby_get_return(self, arguments, include_bootloader=True):745        '''746        Utility function that runs grubby with and returns status code747        '''748        args = self._run_grubby_prepare_args(arguments, include_bootloader)749        return self._run_get_return(args)750    def _extract_tarball(self, tarball, directory):751        '''752        Extract tarball into the an directory753        This code assume the first (or only) entry is the main directory754        :type tarball: string755        :param tarball: tarball file path756        :type directory: string757        :param directory: directory path758        :return: path of toplevel directory as extracted from tarball759        '''760        f = tarfile.open(tarball)761        members = f.getmembers()762        topdir = members[0]763        assert topdir.isdir()764        # we can not use extractall() because it is not available on python 2.4765        for m in members:766            f.extract(m, directory)767        return os.path.join(directory, topdir.name)768    def _get_entry_indexes(self, info):769        '''770        Returns the indexes found in a get_info() output771        :type info: list of lines772        :param info: result of utility method get_info()773        :return: maximum index number774        '''775        indexes = []776        for line in self.get_info_lines():777            try:778                key, value = line.split("=")779                if key == 'index':780                    indexes.append(int(value))781            except ValueError:782                pass783        return indexes784    def _index_for_title(self, title):785        '''786        Returns the index of an entry based on the title of the entry787        :type title: string788        :param title: the title of the entry789        :return: the index of the given entry or None790        '''791        if self._is_number(title):792            return title793        info = self.get_info_lines()794        for i in self._get_entry_indexes(info):795            info = self.get_info(i)796            if info is None:797                continue798            lines = info.splitlines()799            looking_for = ('title=%s' % title,800                           'label=%s' % title)801            for line in lines:802                if line in looking_for:803                    return i804        return None805    def _info_filter(self, info, key, value=None):806        '''807        Filters info, looking for keys, optionally set with a given value808        :type info: list of lines809        :param info: result of utility method get_info()810        :type key: string811        :param key: filter based on this key812        :type value: string813        :param value: filter based on this value814        :return: value or None815        '''816        for line in info:817            if value is not None:818                looking_for = '%s=%s' % (key, value)819                if line == looking_for:820                    return line.split("=")[1]821            else:822                if line.startswith("%s=" % key):823                    return line.split("=")[1]824        return None825    def _kernel_for_title(self, title):826        '''827        Returns the kernel path for an entry based on its title828        :type title: string829        :param title: the title of the entry830        :return: the kernel path of None831        '''832        index = self._index_for_title(title)833        if index is not None:834            info = self.get_info_lines(index)835            kernel = self._info_filter(info, 'kernel')836            return kernel837        else:838            return None839    def _is_number(self, data):840        '''841        Returns true if supplied data is an int or string with digits842        '''843        if isinstance(data, int):844            return True845        elif isinstance(data, str) and data.isdigit():846            return True847        return False848    def _get_entry_selection(self, data):849        '''850        Returns a valid grubby parameter for commands such as --update-kernel851        '''852        if self._is_number(data):853            return data854        elif isinstance(data, str) and data.startswith('/'):855            # assume it's the kernel filename856            return data857        elif isinstance(data, str):858            return self._kernel_for_title(data)859        else:860            raise ValueError("Bad value for 'kernel' parameter. Expecting "861                             "either and int (index) or string (kernel or "862                             "title)")863    def _remove_duplicate_cmdline_args(self, cmdline):864        """865        Remove the duplicate entries in cmdline making sure that the first866        duplicate occurrences are the ones removed and the last one remains867        (this is in order to not change the semantics of the "console"868        parameter where the last occurrence has special meaning)869        :param cmdline: a space separate list of kernel boot parameters870            (ex. 'console=ttyS0,57600n8 nmi_watchdog=1')871        :return: a space separated list of kernel boot parameters without872            duplicates873        """874        copied = set()875        new_args = []876        for arg in reversed(cmdline.split()):877            if arg not in copied:878                new_args.insert(0, arg)879                copied.add(arg)880        return ' '.join(new_args)881    #882    # The following methods implement a form of "API" that action methods883    # can rely on. Another goal is to maintain compatibility with the current884    # client side API in autotest (client/shared/boottool.py)885    #886    def get_bootloader(self):887        '''888        Get the bootloader name that is detected on this machine889        This module performs the same action as client side boottool.py890        get_type() method, but with a better name IMHO.891        :return: name of detected bootloader892        '''893        args = [self.path, '--bootloader-probe']894        output = self._run_get_output_err(args)895        if output is None:896            return None897        if output.startswith('grubby: bad argument'):898            return None899        elif output not in self.SUPPORTED_BOOTLOADERS:900            return None901        return output902    # Alias for client side boottool.py API903    get_type = get_bootloader904    # Alias for boottool app905    bootloader_probe = get_bootloader906    def get_architecture(self):907        '''908        Get the system architecture909        This is much simpler version then the original boottool version, that910        does not attempt to filter the result of the command / system call911        that returns the archicture.912        :return: string with system archicteture, such as x86_64, ppc64, etc913        '''914        return os.uname()[4]915    # Alias for boottool app916    arch_probe = get_architecture917    def get_titles(self):918        '''919        Get the title of all boot entries.920        :return: list with titles of boot entries921        '''922        titles = []923        for line in self.get_info_lines():924            try:925                key, value = line.split("=")926                if key in ['title', 'label']:927                    titles.append(value)928            except ValueError:929                pass930        return titles931    def get_default_index(self):932        '''933        Get the default entry index.934        This module performs the same action as client side boottool.py935        get_default() method, but with a better name IMHO.936        :return: an integer with the the default entry.937        '''938        default_index = self._run_grubby_get_output(['--default-index'])939        if default_index is not None and default_index:940            default_index = int(default_index)941        return default_index942    # Alias for client side boottool.py API943    get_default = get_default_index944    # Alias for boottool app945    default = get_default_index946    def set_default_by_index(self, index):947        """948        Sets the given entry number to be the default on every next boot949        To set a default only for the next boot, use boot_once() instead.950        This module performs the same action as client side boottool.py951        set_default() method, but with a better name IMHO.952        Note: both --set-default=<kernel> and --set-default-index=<index>953        on grubby returns no error when it doesn't find the kernel or954        index. So this method will, until grubby gets fixed, always return955        success.956        :param index: entry index number to set as the default.957        """958        return self._run_grubby_get_return(['--set-default-index=%s' % index])959    # Alias for client side boottool.py API960    set_default = set_default_by_index961    def get_default_title(self):962        '''963        Get the default entry title.964        Conforms to the client side boottool.py API, but rely directly on965        grubby functionality.966        :return: a string of the default entry title.967        '''968        return self._run_grubby_get_output(['--default-title'])969    def get_entry(self, search_info):970        """971        Get a single bootloader entry information.972        NOTE: if entry is "fallback" and bootloader is grub973        use index instead of kernel title ("fallback") as fallback is974        a special option in grub975        :param search_info: can be 'default', position number or title976        :return: a dictionary of key->value where key is the type of entry977                information (ex. 'title', 'args', 'kernel', etc) and value978                is the value for that piece of information.979        """980        info = self.get_info(search_info)981        return parse_entry(info)982    def get_entries(self):983        """984        Get all entries information.985        :return: a dictionary of index -> entry where entry is a dictionary986                of entry information as described for get_entry().987        """988        raw = self.get_info()989        entries = {}990        for entry_str in re.split("index", raw):991            if len(entry_str.strip()) == 0:992                continue993            if entry_str.startswith('boot='):994                continue995            if 'non linux entry' in entry_str:996                continue997            entry = parse_entry("index" + entry_str)998            try:999                entries[entry["index"]] = entry1000            except KeyError:1001                continue1002        return entries1003    def get_info(self, entry='ALL'):1004        '''1005        Returns information on a given entry, or all of them if not specified1006        The information is returned as a set of lines, that match the output1007        of 'grubby --info=<entry>'1008        :type entry: string1009        :param entry: entry description, usually an index starting from 01010        :return: set of lines1011        '''1012        command = '--info=%s' % entry1013        info = self._run_grubby_get_output([command])1014        if info:1015            return info1016    def get_title_for_kernel(self, path):1017        """1018        Returns a title for a particular kernel.1019        :param path: path of the kernel image configured in the boot config1020        :return: if the given kernel path is found it will return a string1021                with the title for the found entry, otherwise returns None1022        """1023        entries = self.get_entries()1024        for entry in entries.itervalues():1025            if entry.get('kernel') == path:1026                return entry['title']1027        return None1028    def add_args(self, kernel, args):1029        """1030        Add cmdline arguments for the specified kernel.1031        :param kernel: can be a position number (index) or title1032        :param args: argument to be added to the current list of args1033        """1034        entry_selection = self._get_entry_selection(kernel)1035        command_arguments = ['--update-kernel=%s' % entry_selection,1036                             '--args=%s' % args]1037        self._run_grubby_get_return(command_arguments)1038    def remove_args(self, kernel, args):1039        """1040        Removes specified cmdline arguments.1041        :param kernel: can be a position number (index) or title1042        :param args: argument to be removed of the current list of args1043        """1044        entry_selection = self._get_entry_selection(kernel)1045        command_arguments = ['--update-kernel=%s' % entry_selection,1046                             '--remove-args=%s' % args]1047        self._run_grubby_get_return(command_arguments)1048    def add_kernel(self, path, title='autoserv', root=None, args=None,1049                   initrd=None, default=False, position='end'):1050        """1051        Add a kernel entry to the bootloader (or replace if one exists1052        already with the same title).1053        :param path: string path to the kernel image file1054        :param title: title of this entry in the bootloader config1055        :param root: string of the root device1056        :param args: string with cmdline args1057        :param initrd: string path to the initrd file1058        :param default: set to True to make this entry the default one1059                (default False)1060        :param position: where to insert the new entry in the bootloader1061                config file (default 'end', other valid input 'start', or1062                # of the title)1063        :param xen_hypervisor: xen hypervisor image file (valid only when1064                xen mode is enabled)1065        """1066        if title in self.get_titles():1067            self.remove_kernel(title)1068        parameters = ['--add-kernel=%s' % path, '--title=%s' % title]1069        # FIXME: grubby takes no --root parameter1070        # if root:1071        #     parameters.append('--root=%s' % root)1072        if args:1073            parameters.append('--args=%s' %1074                              self._remove_duplicate_cmdline_args(args))1075        if initrd:1076            parameters.append('--initrd=%s' % initrd)1077        if default:1078            parameters.append('--make-default')1079        # There's currently an issue with grubby '--add-to-bottom' feature.1080        # Because it uses the tail instead of the head of the list to add1081        # a new entry, when copying a default entry as a template1082        # (--copy-default), it usually copies the "recover" entries that1083        # usually go along a regular boot entry, specially on grub2.1084        #1085        # So, for now, until I fix grubby, we'll *not* respect the position1086        # (--position=end) command line option.1087        #1088        # if opts.position == 'end':1089        #     parameters.append('--add-to-bottom')1090        parameters.append("--copy-default")1091        return self._run_grubby_get_return(parameters)1092    def remove_kernel(self, kernel):1093        """1094        Removes a specific entry from the bootloader configuration.1095        :param kernel: entry position or entry title.1096        FIXME: param kernel should also take 'start' or 'end'.1097        """1098        entry_selection = self._get_entry_selection(kernel)1099        if entry_selection is None:1100            self.log.debug('remove_kernel for title "%s" did not find an '1101                           'entry. This is most probably NOT an error', kernel)1102            return 01103        command_arguments = ['--remove-kernel=%s' % entry_selection]1104        return self._run_grubby_get_return(command_arguments)1105    #1106    # The following methods are not present in the original client side1107    # boottool.py1108    #1109    def get_info_lines(self, entry='ALL'):1110        '''1111        Returns information on a given entry, or all of them if not specified1112        The information is returned as a set of lines, that match the output1113        of 'grubby --info=<entry>'1114        :type entry: string1115        :param entry: entry description, usually an index starting from 01116        :return: set of lines1117        '''1118        info = self.get_info(entry)1119        if info:1120            return info.splitlines()1121    def get_grubby_version_raw(self):1122        '''1123        Get the version of grubby that is installed on this machine as is1124        :return: string with raw output from grubby --version1125        '''1126        return self._run_grubby_get_output(['--version'], False)1127    def get_grubby_version(self):1128        '''1129        Get the version of grubby that is installed on this machine1130        :return: tuple with (major, minor) grubby version1131        '''1132        output = self.get_grubby_version_raw()1133        if output is None:1134            self.log.warn('Could not run grubby to fetch its version')1135            return None1136        match = re.match('(grubby version)?(\s)?(\d+)\.(\d+)(.*)', output)1137        if match:1138            groups = match.groups()1139            return (int(groups[2]), int(groups[3]))1140        else:1141            return None1142    def grubby_install_patch_makefile(self):1143        '''1144        Patch makefile, making CFLAGS more forgivable to older toolchains1145        '''1146        cflags_line = 'CFLAGS += $(RPM_OPT_FLAGS) -std=gnu99 -ggdb\n'1147        libs_line = 'grubby_LIBS = -lblkid -lpopt -luuid\n'1148        shutil.move('Makefile', 'Makefile.boottool.bak')1149        o = open('Makefile', 'w')1150        for l in open('Makefile.boottool.bak').readlines():1151            if l.startswith('CFLAGS += '):1152                o.write(cflags_line)1153            elif l.startswith('grubby_LIBS = -lblkid -lpopt'):1154                o.write(libs_line)1155            else:1156                o.write(l)1157        o.close()1158    def grubby_install_backup(self, path):1159        '''1160        Backs up the current grubby binary to make room the one we'll build1161        :type path: string1162        :param path: path to the binary that should be backed up1163        '''1164        backup_path = '%s.boottool.bkp' % path1165        if (os.path.exists(path) and not os.path.exists(backup_path)):1166            try:1167                shutil.move(path, backup_path)1168            except Exception:1169                self.log.warn('Failed to backup the current grubby binary')1170    def grubby_install_fetch_tarball(self, topdir):1171        '''1172        Fetches and verifies the grubby source tarball1173        '''1174        tarball_name = os.path.basename(GRUBBY_TARBALL_URI)1175        # first look in the current directory1176        try:1177            tarball = tarball_name1178            f = open(tarball)1179        except Exception:1180            try:1181                # then the autotest source directory1182                # pylint: disable=E06111183                from autotest.client.shared.settings import settings1184                top_path = settings.get_value('COMMON', 'autotest_top_path')1185                tarball = os.path.join(top_path, tarball_name)1186                f = open(tarball)1187            except Exception:1188                # then try to grab it from github1189                try:1190                    tarball = os.path.join(topdir, tarball_name)1191                    urllib.urlretrieve(GRUBBY_TARBALL_URI, tarball)1192                    f = open(tarball)1193                except Exception:1194                    return None1195        tarball_md5 = md5.md5(f.read()).hexdigest()1196        if tarball_md5 != GRUBBY_TARBALL_MD5:1197            return None1198        return tarball1199    def grubby_build(self, topdir, tarball):1200        '''1201        Attempts to build grubby from the source tarball1202        '''1203        def log_lines(lines):1204            for line in lines:1205                self.log.debug(line.strip())1206        try:1207            find_header('popt.h')1208        except ValueError:1209            self.log.debug('No popt.h header present, skipping build')1210            return False1211        tarball_name = os.path.basename(tarball)1212        srcdir = os.path.join(topdir, 'src')1213        srcdir = self._extract_tarball(tarball, srcdir)1214        os.chdir(srcdir)1215        self.grubby_install_patch_makefile()1216        result = subprocess.Popen(['make'],1217                                  stdout=subprocess.PIPE,1218                                  stderr=subprocess.PIPE)1219        if result.wait() != 0:1220            self.log.debug('Failed to build grubby during "make" step')1221            log_lines(result.stderr.read().splitlines())1222            return False1223        install_root = os.path.join(topdir, 'install_root')1224        os.environ['DESTDIR'] = install_root1225        result = subprocess.Popen(['make', 'install'],1226                                  stdout=subprocess.PIPE,1227                                  stderr=subprocess.PIPE)1228        if result.wait() != 0:1229            self.log.debug('Failed to build grubby during "make install" step')1230            log_lines(result.stderr.read().splitlines())1231            return False1232        return True1233    def grubby_install(self, path=None):1234        '''1235        Attempts to install a recent enough version of grubby1236        So far tested on:1237           * Fedora 16 x86_641238           * Debian 6 x86_641239           * SuSE 12.1 x86_641240           * RHEL 4 on ia64 (with updated python 2.4)1241           * RHEL 5 on ia641242           * RHEL 6 on ppc641243        '''1244        if path is None:1245            if os.geteuid() == 0:1246                path = GRUBBY_DEFAULT_SYSTEM_PATH1247            else:1248                path = GRUBBY_DEFAULT_USER_PATH1249        topdir = tempfile.mkdtemp()1250        deps_klass = DISTRO_DEPS_MAPPING.get(detect_distro_type(), None)1251        if deps_klass is not None:1252            deps = deps_klass()1253            if not deps.check():1254                self.log.warn('Installing distro build deps for grubby. This '1255                              'may take a while, depending on bandwidth and '1256                              'actual number of packages to install')1257                if not deps.install():1258                    self.log.error('Failed to install distro build deps for '1259                                   'grubby')1260        tarball = self.grubby_install_fetch_tarball(topdir)1261        if tarball is None:1262            raise GrubbyInstallException('Failed to fetch grubby tarball')1263        srcdir = os.path.join(topdir, 'src')1264        install_root = os.path.join(topdir, 'install_root')...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
