def get_build_cmd(self): """Return command used for building source for this distribution Substitutions are done in the command strings: $d => The distro's name $a => the target architecture $p => the package's name $v => the package's version $j => rebuildd job id """ # Strip epochs (x:) away try: index = self.package.version.index(":") args = { 'd': self.dist, 'a': self.arch, \ 'v': self.package.version[index+1:], 'p': self.package.name, \ 'j': str(self.id) } t = Template(RebuilddConfig().get('build', 'build_cmd')) return t.safe_substitute(**args) except ValueError: pass try: args = { 'd': self.dist, 'a': self.arch, \ 'v': self.package.version, 'p': self.package.name, \ 'j': str(self.id) } t = Template(RebuilddConfig().get('build', 'build_cmd')) return t.safe_substitute(**args) except TypeError, error: RebuilddLog.error("get_build_cmd has invalid format: %s" % error) return None
def add_job(self, name, version, priority, dist, mailto=None, arch=None): """Add a job""" if not arch: arch = self.cfg.arch[0] if not Dists().get_dist(dist, arch): RebuilddLog.error("Couldn't find dist/arch in the config file for %s_%s on %s/%s, don't adding it" \ % (name, version, dist, arch)) return False pkgs = Package.selectBy(name=name, version=version) if pkgs.count(): # If several packages exists, just take the first pkg = pkgs[0] else: # Maybe we found no packages, so create a brand new one! pkg = Package(name=name, version=version, priority=priority) jobs_count = Job.selectBy(package=pkg, dist=dist, arch=arch, mailto=mailto, status=JobStatus.WAIT).count() if jobs_count: RebuilddLog.error("Job already existing for %s_%s on %s/%s, don't adding it" \ % (pkg.name, pkg.version, dist, arch)) return False job = Job(package=pkg, dist=dist, arch=arch) job.status = JobStatus.WAIT job.arch = arch job.mailto = mailto log = Log(job=job) RebuilddLog.info("Added job for %s_%s on %s/%s for %s" \ % (name, version, dist, arch, mailto)) return True
def add_dep(self, dep): """Add a job dependency on another job""" for existing_dep in self.deps: if existing_dep.id == dep.id: RebuilddLog.error("Already existing dependency between job %s and job %s" % (self.id, dep.id)) return self.addJob(dep) RebuilddLog.info("Dependency added between job %s and job %s" % (self.id, dep.id))
def send_build_log(self): """When job is built, send logs by mail""" try: with open(self.logfile, "r") as build_log: log = build_log.read() except IOError, error: RebuilddLog.error("Unable to open logfile for job %d" % self.id) return False
def get_source_cmd(self, package): """Return command used for grabing source for this distribution""" try: args = { 'd': self.name, 'a': self.arch, 'v': package.version, \ 'p': package.name, 'r': package.repo } t = Template(RebuilddConfig().get('build', 'source_cmd')) return t.safe_substitute(**args) except TypeError, error: RebuilddLog.error("get_source_cmd has invalid format: %s" % error) return None
def requeue_job(self, job_id): """Requeue a failed job""" if Job.selectBy(id=job_id).count() == 0: RebuilddLog.error("There is no job related to %s that is in the job list" % job_id) return False job = Job.selectBy(id=job_id)[0] if job.status in FailedStatus: job.status = JobStatus.WAIT job.host = "" return True
def get_post_build_cmd(self, package): """Return command used after building source for this distribution""" cmd = RebuilddConfig().get('build', 'post_build_cmd') if cmd == '': return None try: args = { 'd': self.name, 'a': self.arch, \ 'v': package.version, 'p': package.name, 'r': package.repo } t = Template(cmd) return t.safe_substitute(**args) except TypeError, error: RebuilddLog.error("post_build_cmd has invalid format: %s" % error) return None
def requeue_job(self, job_id): """Requeue a failed job""" if Job.selectBy(id=job_id).count() == 0: RebuilddLog.error( "There is no job related to %s that is in the job list" % job_id) return False job = Job.selectBy(id=job_id)[0] if job.status in FailedStatus: job.status = JobStatus.WAIT job.host = "" return True
def add_deps(self, job_id, dependency_ids): if Job.selectBy(id=job_id).count() == 0: RebuilddLog.error("There is no job related to %s that is in the job list" % job_id) return False job = Job.selectBy(id=job_id)[0] deps = [] for dep in dependency_ids: if Job.selectBy(id=dep).count() == 0: RebuilddLog.error("There is no job related to %s that is in the job list" % dep) return False dep_job = Job.selectBy(id=dep)[0] deps.append(dep_job) job.add_deps(deps) return True
def add_deps(self, job_id, dependency_ids): if Job.selectBy(id=job_id).count() == 0: RebuilddLog.error( "There is no job related to %s that is in the job list" % job_id) return False job = Job.selectBy(id=job_id)[0] deps = [] for dep in dependency_ids: if Job.selectBy(id=dep).count() == 0: RebuilddLog.error( "There is no job related to %s that is in the job list" % dep) return False dep_job = Job.selectBy(id=dep)[0] deps.append(dep_job) job.add_deps(deps) return True
def get_build_cmd(self, package): """Return command used for building source for this distribution""" # Strip epochs (x:) away try: index = package.version.index(":") args = { 'd': self.name, 'a': self.arch, \ 'v': package.version[index + 1:], 'p': package.name, 'r': package.repo } t = Template(RebuilddConfig().get('build', 'build_cmd')) return t.safe_substitute(**args) except ValueError: pass try: args = { 'd': self.name, 'a': self.arch, \ 'v': package.version, 'p': package.name, 'r': package.repo } t = Template(RebuilddConfig().get('build', 'build_cmd')) return t.safe_substitute(**args) except TypeError, error: RebuilddLog.error("get_build_cmd has invalid format: %s" % error) return None
def add_job(self, name, version, priority, dist, mailto=None, arch=None): """Add a job""" if not arch: arch = self.cfg.arch[0] if not Dists().get_dist(dist, arch): RebuilddLog.error("Couldn't find dist/arch in the config file for %s_%s on %s/%s, not adding it" \ % (name, version, dist, arch)) return False pkgs = Package.selectBy(name=name, version=version) if pkgs.count(): # If several packages exists, just take the first pkg = pkgs[0] else: # Maybe we found no packages, so create a brand new one! pkg = Package(name=name, version=version, priority=priority) jobs_count = Job.selectBy(package=pkg, dist=dist, arch=arch, mailto=mailto, status=JobStatus.WAIT).count() if jobs_count: RebuilddLog.error("Job already existing for %s_%s on %s/%s, not adding it" \ % (pkg.name, pkg.version, dist, arch)) return False job = Job(package=pkg, dist=dist, arch=arch) job.status = JobStatus.WAIT job.arch = arch job.mailto = mailto log = Log(job=job) RebuilddLog.info("Added job for %s_%s on %s/%s for %s" \ % (name, version, dist, arch, mailto)) return True
def get_post_build_cmd(self): """Return command used after building source for this distribution Substitutions are done in the command strings: $d => The distro's name $a => the target architecture $p => the package's name $v => the package's version $j => rebuildd job id """ cmd = RebuilddConfig().get('build', 'post_build_cmd') if cmd == '': return None try: args = { 'd': self.dist, 'a': self.arch, \ 'v': self.package.version, 'p': self.package.name, \ 'j': str(self.id) } t = Template(cmd) return t.safe_substitute(**args) except TypeError, error: RebuilddLog.error("post_build_cmd has invalid format: %s" % error) return None
msg.set_payload(log) try: smtp = smtplib.SMTP() smtp.connect(RebuilddConfig().get('mail', 'smtp_host'), RebuilddConfig().get('mail', 'smtp_port')) smtp.sendmail(RebuilddConfig().get('mail', 'from'), [m.strip() for m in msg['To'].split(",")], msg.as_string()) except Exception, error: try: process = Popen("sendmail", shell=True, stdin=PIPE) process.communicate(input=msg.as_string()) except: RebuilddLog.error("Unable to send build log mail for job %d: %s" % (self.id, error)) return True def __str__(self): return "I: Job %s for %s_%s is status %s on %s for %s/%s" % \ (self.id, self.package.name, self.package.version, self.host, JobStatus.whatis(self.status), self.dist, self.arch) def is_allowed_to_build(self): """ Check if job is allowed to build """ for dep in Job.selectBy(id=self)[0].deps: if Job.selectBy(id=dep)[0].status != JobStatus.BUILD_OK: return False return True
state = proc.poll() self.do_quit.wait(1) if self.do_quit.isSet(): break if state != 0: with self.status_lock: self.status = failed_status break if self.do_quit.isSet(): # Kill gently the process RebuilddLog.info("Killing job %s with SIGINT" % self.id) try: os.killpg(os.getpgid(proc.pid), signal.SIGINT) except OSError, error: RebuilddLog.error("Error killing job %s: %s" % (self.id, error)) # If after 60s it's not dead, KILL HIM counter = 0 timemax = RebuilddConfig().get('build', 'kill_timeout') while proc.poll() == None and counter < timemax: time.sleep(1) counter += 1 if proc.poll() == None: RebuilddLog.error("Killing job %s timed out, killing with SIGKILL" \ % self.id) os.killpg(os.getpgid(proc.pid), signal.SIGKILL) with self.status_lock: self.status = JobStatus.WAIT_LOCKED