def handler(self, mash_target, build_tag, mash_opts):
        self.logger.debug("Mashing '%s'..." % mash_target)

        build_tag = self.session.getTag(build_tag, strict=True)

        repo = self.session.getRepo(build_tag["name"])
        host = self.session.host.getHost()
        build_config = self.session.getBuildConfig(build_tag["id"],
                                                   event=repo["create_event"])
        arch = self.find_arch("noarch", host, build_config)

        # WARNING: This will bind mount the topdir inside the chroot, to write
        #          the mash output to it. Use with caution.
        #          Mock takes care of unmounting it at the end.
        bind_opts = {'dirs' : {self.options.topdir : self.options.topdir}}

        root = BuildRoot(self.session, self.options, build_tag["name"], arch,
                         self.id, repo_id=repo["id"], install_group='mash',
                         bind_opts=bind_opts)
        root.workdir = self.workdir
        self.logger.debug("Initializing buildroot")
        root.init()

        mash_cmd = ["mash"]

        if "mash_config" in mash_opts:
            mash_cmd.extend(["--config", mash_opts["mash_config"]])
        if "output_dir" in mash_opts:
            mash_cmd.extend(["--outputdir", mash_opts["output_dir"]])
        if "previous_dir" in mash_opts:
            mash_cmd.extend(["--previous", mash_opts["previous_dir"]])
        if "delta_dir" in mash_opts:
            mash_cmd.extend(["--delta", mash_opts["delta_dir"]])
        if "comps_file" in mash_opts:
            mash_cmd.extend(["--compsfile", mash_opts["comps_file"]])
        if not mash_opts["do_delta"]:
            mash_cmd.append("--no-delta")

        mash_cmd.append(mash_target)

        from datetime import datetime
        begin = datetime.now()
        rv = root.mock(["--chroot", " ".join(mash_cmd)])
        if rv:
            root.expire()
            raise koji.BuildrootError("error mashing the tree, %s"
                                      % root._mockResult(rv, logfile="mock_output.log"))
        end = datetime.now()
        self.logger.error("Mash finished in %s" % (end - begin))

        return {"brootid": root.id}
Пример #2
0
    def handler(self, root, arch, command, keep=False, packages=[], mounts=[], repo_id=None, skip_setarch=False, weight=None, upload_logs=None, new_chroot=False):
        """Create a buildroot and run a command (as root) inside of it

        Command may be a string or a list.

        Returns a message indicating success if the command was successful, and
        raises an error otherwise.  Command output will be available in
        runroot.log in the task output directory on the hub.

        skip_setarch is a rough approximation of an old hack

        the keep option is not used. keeping for compatibility for now...

        upload_logs is list of absolute paths which will be uploaded for
        archiving on hub. It always consists of /tmp/runroot.log, but can be
        used for additional logs (pungi.log, etc.)
        """
        if weight is not None:
            weight = max(weight, 0.5)
            self.session.host.setTaskWeight(self.id, weight)
        #noarch is funny
        if arch == "noarch":
            #we need a buildroot arch. Pick one that:
            #  a) this host can handle
            #  b) the build tag can support
            #  c) is canonical
            host_arches = self.session.host.getHost()['arches']
            if not host_arches:
                raise koji.BuildError("No arch list for this host")
            tag_arches = self.session.getBuildConfig(root)['arches']
            if not tag_arches:
                raise koji.BuildError("No arch list for tag: %s" % root)
            #index canonical host arches
            host_arches = dict([(koji.canonArch(a), 1) for a in host_arches.split()])
            #pick the first suitable match from tag's archlist
            for br_arch in tag_arches.split():
                br_arch = koji.canonArch(br_arch)
                if br_arch in host_arches:
                    #we're done
                    break
            else:
                #no overlap
                raise koji.BuildError("host does not match tag arches: %s (%s)" % (root, tag_arches))
        else:
            br_arch = arch
        if repo_id:
            repo_info = self.session.repoInfo(repo_id, strict=True)
            if repo_info['tag_name'] != root:
                raise koji.BuildError("build tag (%s) does not match repo tag (%s)" % (root, repo_info['tag_name']))
            if repo_info['state'] not in (koji.REPO_STATES['READY'], koji.REPO_STATES['EXPIRED']):
                raise koji.BuildError("repos in the %s state may not be used by runroot" % koji.REPO_STATES[repo_info['state']])
        else:
            repo_info = self.session.getRepo(root)
        if not repo_info:
            #wait for it
            task_id = self.session.host.subtask(method='waitrepo',
                                           arglist=[root, None, None],
                                           parent=self.id)
            repo_info = self.wait(task_id)[task_id]
        broot = BuildRoot(self.session, self.options, root, br_arch, self.id, repo_id=repo_info['id'], setup_dns=True)
        broot.workdir = self.workdir
        broot.init()
        rootdir = broot.rootdir()
        #workaround for rpm oddness
        os.system('rm -f "%s"/var/lib/rpm/__db.*' % rootdir)
        #update buildroot state (so that updateBuildRootList() will work)
        self.session.host.setBuildRootState(broot.id, 'BUILDING')
        try:
            if packages:
                #pkglog = '%s/%s' % (broot.resultdir(), 'packages.log')
                pkgcmd = ['--install'] + packages
                status = broot.mock(pkgcmd)
                self.session.host.updateBuildRootList(broot.id, broot.getPackageList())
                if not isSuccess(status):
                    raise koji.BuildrootError(parseStatus(status, pkgcmd))

            if isinstance(command, str):
                cmdstr = command
            else:
                #we were passed an arglist
                #we still have to run this through the shell (for redirection)
                #but we can preserve the list structure precisely with careful escaping
                cmdstr = ' '.join(["'%s'" % arg.replace("'", r"'\''") for arg in command])
            # A nasty hack to put command output into its own file until mock can be
            # patched to do something more reasonable than stuff everything into build.log
            cmdargs = ['/bin/sh', '-c', "{ %s; } < /dev/null 2>&1 | /usr/bin/tee /builddir/runroot.log; exit ${PIPESTATUS[0]}" % cmdstr]

            # always mount /mnt/redhat (read-only)
            # always mount /mnt/iso (read-only)
            # also need /dev bind mount
            self.do_mounts(rootdir, [self._get_path_params(x) for x in self.config['default_mounts']])
            self.do_extra_mounts(rootdir, mounts)
            mock_cmd = ['chroot']
            if new_chroot:
                mock_cmd.append('--new-chroot')
            if skip_setarch:
                #we can't really skip it, but we can set it to the current one instead of of the chroot one
                myarch = platform.uname()[5]
                mock_cmd.extend(['--arch', myarch])
            mock_cmd.append('--')
            mock_cmd.extend(cmdargs)
            rv = broot.mock(mock_cmd)
            log_paths = ['/builddir/runroot.log']
            if upload_logs is not None:
                log_paths += upload_logs
            for log_path in log_paths:
                self.uploadFile(rootdir + log_path)
        finally:
            # mock should umount its mounts, but it will not handle ours
            self.undo_mounts(rootdir, fatal=False)
            broot.expire()
        if isinstance(command, str):
            cmdlist = command.split()
        else:
            cmdlist = command
        cmdlist = [param for param in cmdlist if '=' not in param]
        if cmdlist:
            cmd = os.path.basename(cmdlist[0])
        else:
            cmd = '(none)'
        if isSuccess(rv):
            return '%s completed successfully' % cmd
        else:
            raise koji.BuildrootError(parseStatus(rv, cmd))