Ejemplo n.º 1
0
    def test_get_state(self):
        """Ensure get_state() can get a value from a state file."""
        temp_state = "{}/temp_sktrc".format(self.tmpdir)

        # Start with an empty state file.
        self.assertIsNone(state_file.get_state(temp_state, 'foo'))

        # Create an empty state file.
        with open(temp_state, 'w') as fileh:
            fileh.write('')

        # Test with the empty state file.
        self.assertIsNone(state_file.get_state(temp_state, 'foo'))

        # Write a normal state file.
        new_state = {
            'foo': 'bar',
            'foo2': 'bar2',
        }
        state_file.update_state(temp_state, new_state)

        # Test that we get the right data.
        self.assertEqual(state_file.get_state(temp_state, 'foo'), 'bar')
        self.assertEqual(state_file.get_state(temp_state, 'foo2'), 'bar2')

        # Try to get an option that doesn't exist.
        self.assertIsNone(state_file.get_state(temp_state, 'toot'))
Ejemplo n.º 2
0
    def test_update_state(self):
        """Ensure update_state() writes a state file."""
        temp_state = "{}/temp_sktrc".format(self.tmpdir)
        new_state = {
            'foo': 'bar',
            'foo2': 'bar2',
        }
        state_file.update_state(temp_state, new_state)

        config = ConfigParser.RawConfigParser()
        config.read(temp_state)
        self.assertEqual(config.get('state', 'foo'), 'bar')
        self.assertEqual(config.get('state', 'foo2'), 'bar2')

        # Test a write with an existing state file.
        state_file.update_state(temp_state, new_state)

        config = ConfigParser.RawConfigParser()
        config.read(temp_state)
        self.assertEqual(config.get('state', 'foo'), 'bar')
        self.assertEqual(config.get('state', 'foo2'), 'bar2')
Ejemplo n.º 3
0
def cmd_build(args):
    """
    Build the kernel with specified configuration and put it into a tarball.

    Args:
        args:    Command line arguments
    """
    global retcode
    tstamp = datetime.datetime.strftime(datetime.datetime.now(),
                                        "%Y%m%d%H%M%S")

    tgz = None
    builder = KernelBuilder(
        source_dir=args.get('workdir'),
        basecfg=args.get('baseconfig'),
        cfgtype=args.get('cfgtype'),
        extra_make_args=args.get('makeopts'),
        enable_debuginfo=args.get('enable_debuginfo'),
        rh_configs_glob=args.get('rh_configs_glob'),
        make_target=args.get('make_target'),
        localversion=args.get('localversion')
    )

    # Clean the kernel source with 'make mrproper' if requested.
    if args.get('wipe'):
        builder.clean_kernel_source()

    # Gather additional details about the build and save them to the state
    # file.
    kernel_arch = builder.build_arch
    make_opts = builder.assemble_make_options()
    state = {
        'kernel_arch': kernel_arch,
        'make_opts': ' '.join(make_opts)
    }
    update_state(args['rc'], state)

    # Write the cross compiler prefix to the state file only if the
    # environment variable is set:
    cross_compiler_prefix = builder.cross_compiler_prefix
    if cross_compiler_prefix:
        state = {'cross_compiler_prefix': cross_compiler_prefix}
        update_state(args['rc'], state)

    # Attempt to compile the kernel.
    package_path = None
    try:
        package_path = builder.compile_kernel()
    # Handle a failure if the build times out, fails, or if the build
    # artifacts can't be found.
    except (CommandTimeoutError, subprocess.CalledProcessError, ParsingError,
            IOError) as exc:
        logging.error(exc)

        # Update the state file with the path to the build log.
        state = {'buildlog': builder.buildlog}
        update_state(args['rc'], state)

        # Set the return code.
        retcode = SKT_FAIL
    # Re-raise any unexpected exceptions.
    except Exception:
        (exc, exc_type, trace) = sys.exc_info()
        raise exc, exc_type, trace

    # Get the SHA of the commit from the repo that we just compiled.
    buildhead = get_state(args['rc'], 'buildhead')

    # Handle any built tarballs.
    if package_path and package_path.endswith('tar.gz'):
        if buildhead:
            # Replace the filename with the SHA of the last commit in the repo.
            ttgz = "{}.tar.gz".format(buildhead)
        else:
            # Add a timestamp to the path if we have no commit to reference.
            ttgz = addtstamp(tgz, tstamp)

        # Rename the kernel tarball.
        shutil.move(package_path, ttgz)
        logging.info("tarball path: %s", ttgz)

        # Save our tarball path to the state file.
        state = {'tarpkg': ttgz}
        update_state(args['rc'], state)

    # Handle any RPM repositories.
    if package_path and 'rpm_repo' in package_path:
        state = {'rpm_repo': package_path}
        update_state(args['rc'], state)

    # Set a filename for the kernel config file based on the SHA of the last
    # commit in the repo.
    tconfig = '{}.config'.format(buildhead)

    try:
        # Rename the config file and save its location to our state file.
        shutil.copyfile(builder.get_cfgpath(), tconfig)
        state = {'buildconf': tconfig}
        update_state(args['rc'], state)

        # Get the kernel version string.
        tag = get_state(args['rc'], 'tag')
        krelease = builder.getrelease()

        if tag and tag != "":
            index = krelease.rfind('.')
            if '-' in krelease:
                # In case of 5.1.0-rc1.cki
                # (removes the -rc1 since that's in the tag already)
                dash = krelease.rfind('-')
                krelease = krelease[:dash] + krelease[index:]
                index = krelease.rfind('.')

            krelease = krelease[:index] + "-" + tag + krelease[index:]

        state = {'krelease': krelease}
        update_state(args['rc'], state)

    except IOError:  # Kernel config failed to build
        tconfig = ''
        logging.error('No config file to copy found!')
Ejemplo n.º 4
0
def cmd_merge(args):
    """
    Fetch a kernel repository, checkout particular references, and optionally
    apply patches from patchwork instances.

    Args:
        args:    Command line arguments
    """
    global retcode
    # Counter merge patch following:
    # idx[0]: counter of merge-ref option.
    # idx[1]: counter of patch option.
    # idx[2]: counter of pw option.
    idx = [0, 0, 0]

    # Clone the kernel tree and check out the proper ref.
    ktree = KernelTree(
        args.get('baserepo'),
        ref=args.get('ref'),
        wdir=full_path(args.get('workdir')),
        fetch_depth=args.get('fetch_depth')
    )
    bhead = ktree.checkout()

    # Gather the subject and date of the commit that is currently checked out.
    bsubject = ktree.get_commit_subject(bhead)
    commitdate = ktree.get_commit_date(bhead)

    # Update the state file with what we know so far.
    state = {
        'baserepo': args.get('baserepo'),
        'basehead': bhead,
        'basesubject': bsubject,
        'commitdate': commitdate,
        'workdir': full_path(args.get('workdir')),
        'tag': get_tag(full_path(args.get('workdir'))),
    }
    update_state(args['rc'], state)

    # Loop over what we have been asked to merge (if applicable).
    for thing_to_merge in args.get('merge_queue', []):
        try:
            if thing_to_merge[0] == 'merge_ref':
                mbranch_ref = thing_to_merge[1].split()

                # Update the state file with our merge_ref data.
                state = {
                    'mergerepo_%02d' % idx[0]: mbranch_ref[0],
                    'mergehead_%02d' % idx[0]: bhead
                }
                update_state(args['rc'], state)

                # Merge the git ref.
                (retcode, bhead) = ktree.merge_git_ref(*mbranch_ref)

                if retcode:
                    return

                # Increment the counter.
                idx[0] += 1

            else:
                # Attempt to merge a local patch.
                if thing_to_merge[0] == 'patch':
                    # Get the full path to the patch to merge.
                    patch = os.path.abspath(thing_to_merge[1])

                    # Update the state file with our local patch data.
                    state = {'localpatch_%02d' % idx[1]: patch}
                    update_state(args['rc'], state)

                    # Merge the patch.
                    ktree.merge_patch_file(patch)

                    # Increment the counter.
                    idx[1] += 1

                # Attempt to merge a patch from patchwork.
                elif thing_to_merge[0] == 'pw':
                    patch = thing_to_merge[1]

                    # Update the state file with our patchwork patch data.
                    state = {'patchwork_%02d' % idx[2]: patch}
                    update_state(args['rc'], state)

                    # Merge the patch. Retrieve the Patchwork session cookie
                    # first.
                    session_id = get_state(args['rc'],
                                           'patchwork_session_cookie')
                    ktree.merge_patchwork_patch(patch, session_id)

                    # Increment the counter.
                    idx[2] += 1

        # If the patch application failed, we should set the return code,
        # log an error, and update our state file.
        except PatchApplicationError as patch_exc:
            retcode = SKT_FAIL
            logging.error(patch_exc)

            # Update the state.
            state = {'mergelog': ktree.mergelog}
            update_state(args['rc'], state)

            return

        # If something else unexpected happened, re-raise the exception.
        except Exception:
            (exc, exc_type, trace) = sys.exc_info()
            raise exc, exc_type, trace

    # Get the SHA and subject of the repo after applying patches.
    buildhead = ktree.get_commit_hash()
    buildsubject = ktree.get_commit_subject()

    # Update the state file with the data about the current repo commit.
    state = {
        'buildhead': buildhead,
        'buildsubject': buildsubject
    }
    update_state(args['rc'], state)
Ejemplo n.º 5
0
def cmd_build(args):
    """
    Build the kernel with specified configuration and put it into a tarball.

    Args:
        args:    Command line arguments
    """
    global retcode
    tstamp = datetime.datetime.strftime(datetime.datetime.now(),
                                        "%Y%m%d%H%M%S")

    tgz = None
    builder = KernelBuilder(source_dir=args.get('workdir'),
                            basecfg=args.get('baseconfig'),
                            cfgtype=args.get('cfgtype'),
                            extra_make_args=args.get('makeopts'),
                            enable_debuginfo=args.get('enable_debuginfo'),
                            rh_configs_glob=args.get('rh_configs_glob'),
                            localversion=args.get('localversion'))

    # Clean the kernel source with 'make mrproper' if requested.
    if args.get('wipe'):
        builder.clean_kernel_source()

    # Gather additional details about the build and save them to the state
    # file.
    kernel_arch = builder.build_arch
    cross_compiler_prefix = builder.cross_compiler_prefix
    make_opts = builder.assemble_make_options()
    state = {
        'kernel_arch': kernel_arch,
        'cross_compiler_prefix': cross_compiler_prefix,
        'make_opts': make_opts
    }
    update_state(args['rc'], state)

    # Attempt to compile the kernel.
    try:
        tgz = builder.mktgz()
    # Handle a failure if the build times out, fails, or if the build
    # artifacts can't be found.
    except (CommandTimeoutError, subprocess.CalledProcessError, ParsingError,
            IOError) as exc:
        logging.error(exc)

        # Update the state file with the path to the build log.
        state = {'buildlog': builder.buildlog}
        update_state(args['rc'], state)

        # Set the return code.
        retcode = SKT_FAIL
    # Re-raise any unexpected exceptions.
    except Exception:
        (exc, exc_type, trace) = sys.exc_info()
        raise exc, exc_type, trace

    # Get the SHA of the commit from the repo that we just compiled.
    buildhead = get_state(args['rc'], 'buildhead')

    if tgz:
        if buildhead:
            # Replace the filename with the SHA of the last commit in the repo.
            ttgz = "{}.tar.gz".format(buildhead)
        else:
            # Add a timestamp to the path if we have no commit to reference.
            ttgz = addtstamp(tgz, tstamp)

        # Rename the kernel tarball.
        shutil.move(tgz, ttgz)
        logging.info("tarball path: %s", ttgz)

        # Save our tarball path to the state file.
        state = {'tarpkg': ttgz}
        update_state(args['rc'], state)

    # Set a filename for the kernel config file based on the SHA of the last
    # commit in the repo.
    tconfig = '{}.config'.format(buildhead)

    try:
        # Rename the config file and save its location to our state file.
        shutil.copyfile(builder.get_cfgpath(), tconfig)
        state = {'buildconf': tconfig}
        update_state(args['rc'], state)

        # Get the kernel version string.
        krelease = builder.getrelease()
        state = {'krelease': krelease}
        update_state(args['rc'], state)

    except IOError:  # Kernel config failed to build
        tconfig = ''
        logging.error('No config file to copy found!')