1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16  import os, urllib 
 17  from cPickle import load 
 18  from twisted.python import log 
 19  from twisted.persisted import styles 
 20  from twisted.internet import defer 
 21  from zope.interface import implements 
 22  from buildbot import interfaces 
 23  from buildbot.util import bbcollections 
 24  from buildbot.util.eventual import eventually 
 25  from buildbot.changes import changes 
 26  from buildbot.status import buildset, builder, buildrequest 
 29      """ 
 30      I represent the status of the buildmaster. 
 31      """ 
 32      implements(interfaces.IStatus) 
 33   
 58   
 59      @property 
 62   
 65   
 68   
 69       
 70   
 77   
 80   
 82          prefix = self.getBuildbotURL() 
 83          if not prefix: 
 84              return None 
 85          if interfaces.IStatus.providedBy(thing): 
 86              return prefix 
 87          if interfaces.ISchedulerStatus.providedBy(thing): 
 88              pass 
 89          if interfaces.IBuilderStatus.providedBy(thing): 
 90              bldr = thing 
 91              return prefix + "builders/%s" % ( 
 92                  urllib.quote(bldr.getName(), safe=''), 
 93                  ) 
 94          if interfaces.IBuildStatus.providedBy(thing): 
 95              build = thing 
 96              bldr = build.getBuilder() 
 97              return prefix + "builders/%s/builds/%d" % ( 
 98                  urllib.quote(bldr.getName(), safe=''), 
 99                  build.getNumber()) 
100          if interfaces.IBuildStepStatus.providedBy(thing): 
101              step = thing 
102              build = step.getBuild() 
103              bldr = build.getBuilder() 
104              return prefix + "builders/%s/builds/%d/steps/%s" % ( 
105                  urllib.quote(bldr.getName(), safe=''), 
106                  build.getNumber(), 
107                  urllib.quote(step.getName(), safe='')) 
108           
109           
110           
111   
112           
113          if interfaces.IStatusEvent.providedBy(thing): 
114               
115              if isinstance(thing, changes.Change): 
116                  change = thing 
117                  return "%schanges/%d" % (prefix, change.number) 
118   
119          if interfaces.IStatusLog.providedBy(thing): 
120              loog = thing 
121              step = loog.getStep() 
122              build = step.getBuild() 
123              bldr = build.getBuilder() 
124   
125              logs = step.getLogs() 
126              for i in range(len(logs)): 
127                  if loog is logs[i]: 
128                      break 
129              else: 
130                  return None 
131              return prefix + "builders/%s/builds/%d/steps/%s/logs/%s" % ( 
132                  urllib.quote(bldr.getName(), safe=''), 
133                  build.getNumber(), 
134                  urllib.quote(step.getName(), safe=''), 
135                  urllib.quote(loog.getName())) 
 136   
139   
147          d.addCallback(chdict2change) 
148          return d 
 149   
152   
164   
166          """ 
167          @rtype: L{BuilderStatus} 
168          """ 
169          return self.botmaster.builders[name].builder_status 
 170   
173   
176   
182          d.addCallback(make_status_objects) 
183          return d 
184   
185 -    def generateFinishedBuilds(self, builders=[], branches=[], 
186                                 num_builds=None, finished_before=None, 
187                                 max_search=200): 
 188   
189          def want_builder(bn): 
190              if builders: 
191                  return bn in builders 
192              return True 
 193          builder_names = [bn 
194                           for bn in self.getBuilderNames() 
195                           if want_builder(bn)] 
196   
197           
198           
199           
200          sources = [] 
201          for bn in builder_names: 
202              b = self.getBuilder(bn) 
203              g = b.generateFinishedBuilds(branches, 
204                                           finished_before=finished_before, 
205                                           max_search=max_search) 
206              sources.append(g) 
207   
208           
209          next_build = [None] * len(sources) 
210   
211          def refill(): 
212              for i,g in enumerate(sources): 
213                  if next_build[i]: 
214                       
215                      continue 
216                  if not g: 
217                       
218                      continue 
219                  try: 
220                      next_build[i] = g.next() 
221                  except StopIteration: 
222                      next_build[i] = None 
223                      sources[i] = None 
224   
225          got = 0 
226          while True: 
227              refill() 
228               
229              candidates = [(i, b, b.getTimes()[1]) 
230                            for i,b in enumerate(next_build) 
231                            if b is not None] 
232              candidates.sort(lambda x,y: cmp(x[2], y[2])) 
233              if not candidates: 
234                  return 
235   
236               
237              i, build, finshed_time = candidates[-1] 
238              next_build[i] = None 
239              got += 1 
240              yield build 
241              if num_builds is not None: 
242                  if got >= num_builds: 
243                      return 
244   
251   
252   
253       
254   
259   
261          """ 
262          @rtype: L{BuilderStatus} 
263          """ 
264          filename = os.path.join(self.basedir, basedir, "builder") 
265          log.msg("trying to load status pickle from %s" % filename) 
266          builder_status = None 
267          try: 
268              builder_status = load(open(filename, "rb")) 
269               
270               
271               
272               
273               
274               
275              versioneds = styles.versionedsToUpgrade 
276              styles.doUpgrade() 
277              if True in [ hasattr(o, 'wasUpgraded') for o in versioneds.values() ]: 
278                  log.msg("re-writing upgraded builder pickle") 
279                  builder_status.saveYourself() 
280   
281          except IOError: 
282              log.msg("no saved status pickle, creating a new one") 
283          except: 
284              log.msg("error while loading status pickle, creating a new one") 
285              log.msg("error follows:") 
286              log.err() 
287          if not builder_status: 
288              builder_status = builder.BuilderStatus(name, category) 
289              builder_status.addPointEvent(["builder", "created"]) 
290          log.msg("added builder %s in category %s" % (name, category)) 
291           
292           
293          builder_status.category = category 
294          builder_status.basedir = os.path.join(self.basedir, basedir) 
295          builder_status.name = name  
296          builder_status.status = self 
297   
298          if not os.path.isdir(builder_status.basedir): 
299              os.makedirs(builder_status.basedir) 
300          builder_status.determineNextBuildNumber() 
301   
302          builder_status.setBigState("offline") 
303          builder_status.setLogCompressionLimit(self.logCompressionLimit) 
304          builder_status.setLogCompressionMethod(self.logCompressionMethod) 
305          builder_status.setLogMaxSize(self.logMaxSize) 
306          builder_status.setLogMaxTailSize(self.logMaxTailSize) 
307   
308          for t in self.watchers: 
309              self.announceNewBuilder(t, name, builder_status) 
310   
311          return builder_status 
 312   
317   
322   
327   
332   
334          result = {} 
335           
336          result['title'] = self.getTitle() 
337          result['titleURL'] = self.getTitleURL() 
338          result['buildbotURL'] = self.getBuildbotURL() 
339           
340           
341          return result 
 342   
344          for r in requests: 
345               
346               
347              pass 
 348   
350          if brid in self._buildreq_observers: 
351              for o in self._buildreq_observers[brid]: 
352                  eventually(o, build_status) 
 353   
355          self._buildreq_observers.add(brid, observer) 
 356   
358          self._buildreq_observers.discard(brid, observer) 
 359   
361          d = defer.Deferred() 
362          self._buildset_finished_waiters.add(bsid, d) 
363          self._maybeBuildsetFinished(bsid) 
364          return d 
 365   
377          d.addCallback(do_notifies) 
378          d.addErrback(log.err, 'while notifying for buildset finishes') 
379   
381           
382          self._builder_observers.add(buildername, watcher) 
 383   
385          self._builder_observers.discard(buildername, watcher) 
 386   
395          d.addCallback(do_notifies) 
396          d.addErrback(log.err, 'while notifying buildsetSubmitted') 
397   
399          self._maybeBuildsetFinished(bsid) 
 400   
402          buildername = notif['buildername'] 
403          if buildername in self._builder_observers: 
404              brs = buildrequest.BuildRequestStatus(buildername, 
405                                                  notif['brid'], self) 
406              for observer in self._builder_observers[buildername]: 
407                  if hasattr(observer, 'requestSubmitted'): 
408                      eventually(observer.requestSubmitted, brs) 
 409