def handler(self, buildrootID, full=False): self.logger.debug("Saving buildroot %d [full=%s]", buildrootID, full) read_config() brinfo = self.session.getBuildroot(buildrootID) if brinfo is None: raise koji.GenericError("Nonexistent buildroot: %s" % buildrootID) host_id = self.session.host.getHost()['id'] if brinfo['host_id'] != host_id: raise koji.GenericError("Task is run on wrong builder") broot = BuildRoot(self.session, self.options, brinfo['id']) path = broot.rootdir() if full: self.logger.debug("Adding buildroot (full): %s" % path) else: path = os.path.join(path, 'builddir') self.logger.debug("Adding buildroot: %s" % path) if not os.path.exists(path): raise koji.GenericError("Buildroot directory is missing: %s" % path) tar_path = os.path.join(self.workdir, 'broot-%s.tar.gz' % buildrootID) self.logger.debug("Creating buildroot archive %s", tar_path) f = tarfile.open(tar_path, "w:gz") if sys.version_info[0] < 3: f.add(path, exclude=omit_paths2) else: f.add(path, filter=omit_paths3) f.close() self.logger.debug("Uploading %s to hub", tar_path) self.uploadFile(tar_path, volume=config['volume']) os.unlink(tar_path) self.logger.debug("Finished saving buildroot %s", buildrootID)
def handler( self, root, arch, command, keep=False, packages=[], mounts=[], repo_id=None, skip_setarch=False, weight=None, upload_logs=None, ): """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 host_arches.has_key(br_arch): # 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] if compat_mode: broot = BuildRoot(root, br_arch, self.id, repo_id=repo_info["id"]) else: broot = BuildRoot(self.session, self.options, root, br_arch, self.id, repo_id=repo_info["id"]) 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 /tmp/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 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 = ["/tmp/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)
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))