~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/buildd/slave.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-03-17 20:41:13 UTC
  • mfrom: (3277.1.4 launchpad-foobar2)
  • Revision ID: pqm@pqm.ubuntu.com-20060317204113-9841a4470db3611b
[r=jamesh] Mainline soyuz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright Canonical Limited
2
 
# Author: Daniel Silverstone <daniel.silverstone@canonical.com>
 
2
# Authors: Daniel Silverstone <daniel.silverstone@canonical.com>
 
3
#      and Adam Conrad <adam.conrad@canonical.com>
3
4
 
4
5
# Buildd Slave implementation
5
6
 
168
169
    WAITING = "BuilderStatus.WAITING"
169
170
    ABORTING = "BuilderStatus.ABORTING"
170
171
    ABORTED = "BuilderStatus.ABORTED"
171
 
 
 
172
    
172
173
    UNKNOWNSUM = "BuilderStatus.UNKNOWNSUM"
173
174
    UNKNOWNBUILDER = "BuilderStatus.UNKNOWNBUILDER"
174
175
    
178
179
 
179
180
    OK = "BuildStatus.OK"
180
181
    DEPFAIL = "BuildStatus.DEPFAIL"
 
182
    GIVENBACK = "BuildStatus.GIVENBACK"
181
183
    PACKAGEFAIL = "BuildStatus.PACKAGEFAIL"
182
184
    CHROOTFAIL = "BuildStatus.CHROOTFAIL"
183
185
    BUILDERFAIL = "BuildStatus.BUILDERFAIL"
184
 
    
 
186
 
 
187
 
185
188
class BuildDSlave(object):
186
189
    """Build Daemon slave. Implementation of most needed functions
187
190
    for a Build-Slave device.
194
197
        self._cachepath = self._config.get("slave","filecache")
195
198
        self.buildstatus = BuildStatus.OK
196
199
        self.waitingfiles = {}
 
200
        self.builddependencies = ""
197
201
        self._log = None
198
202
        
199
203
        if not os.path.isdir(self._cachepath):
212
216
 
213
217
        Optionally you can provide the librarian URL and
214
218
        the build slave will fetch the file if it doesn't have it.
 
219
        Return a tuple containing: (<present>, <info>)
215
220
        """
 
221
        extra_info = 'No URL'
216
222
        if url is not None:
 
223
            extra_info = 'Cache'
217
224
            if not os.path.exists(self.cachePath(sha1sum)):
218
225
                self.log('Fetching %s by url %s' % (sha1sum, url))
219
226
                try:
220
227
                    f = urllib2.urlopen(url)
221
 
                except Exception, e:
222
 
                    self.log('Error accessing Librarian: %s' % e)
 
228
                except Exception, info:
 
229
                    extra_info = 'Error accessing Librarian: %s' % info
 
230
                    self.log(extra_info, exc_info=True)
223
231
                else:
224
232
                    of = open(self.cachePath(sha1sum), "w")
225
233
                    # Upped for great justice to 256k
229
237
                        check_sum.update(chunk)
230
238
                    of.close()
231
239
                    f.close()
 
240
                    extra_info = 'Download'
232
241
                    if check_sum.hexdigest() != sha1sum:
233
242
                        os.remove(self.cachePath(sha1sum))
234
 
                        self.log("Digests did not match, removing again!")
235
 
        return os.path.exists(self.cachePath(sha1sum))
 
243
                        extra_info = "Digests did not match, removing again!"
 
244
                    self.log(extra_info)
 
245
        return (os.path.exists(self.cachePath(sha1sum)), extra_info)
236
246
 
237
247
    def storeFile(self, content):
238
248
        """Take the provided content and store it in the file cache."""
239
249
        sha1sum = sha.sha(content).hexdigest()
240
 
        if self.ensurePresent(sha1sum):
 
250
        present, info = self.ensurePresent(sha1sum)
 
251
        if present:
241
252
            return sha1sum
242
253
        f = open(self.cachePath(sha1sum), "w")
243
254
        f.write(content)
246
257
 
247
258
    def fetchFile(self, sha1sum):
248
259
        """Fetch the file of the given sha1sum."""
249
 
        if not self.ensurePresent(sha1sum):
 
260
        present, info = self.ensurePresent(sha1sum)
 
261
        if not present:
250
262
            raise ValueError("Unknown SHA1sum %s" % sha1sum)
251
263
        f = open(self.cachePath(sha1sum), "r")
252
264
        c = f.read()
342
354
    def buildFail(self):
343
355
        """Cease building because the package failed to build."""
344
356
        if self.builderstatus != BuilderStatus.BUILDING:
345
 
            raise ValueError("Slave is not BUILDING when set to BUILDFAIL")
 
357
            raise ValueError("Slave is not BUILDING when set to PACKAGEFAIL")
346
358
        self.builderstatus = BuilderStatus.WAITING
347
359
        self.buildstatus = BuildStatus.PACKAGEFAIL
348
360
 
349
 
    def depFail(self):
 
361
    def depFail(self, dependencies):
350
362
        """Cease building due to a dependency issue."""
351
363
        if self.builderstatus != BuilderStatus.BUILDING:
352
364
            raise ValueError("Slave is not BUILDING when set to DEPFAIL")
353
365
        self.builderstatus = BuilderStatus.WAITING
354
366
        self.buildstatus = BuildStatus.DEPFAIL
 
367
        self.builddependencies = dependencies
 
368
 
 
369
    def giveBack(self):
 
370
        """Give-back package due to a transient buildd/archive issue."""
 
371
        if self.builderstatus != BuilderStatus.BUILDING:
 
372
            raise ValueError("Slave is not BUILDING when set to GIVENBACK")
 
373
        self.builderstatus = BuilderStatus.WAITING
 
374
        self.buildstatus = BuildStatus.GIVENBACK
355
375
 
356
376
    def buildComplete(self):
357
377
        """Mark the build as complete and waiting interaction from the build
431
451
        if self.slave.buildstatus in (BuildStatus.OK, BuildStatus.PACKAGEFAIL,
432
452
                                      BuildStatus.DEPFAIL):
433
453
            return (self.slave.buildstatus, self.buildid,
434
 
                    self.slave.waitingfiles)
 
454
                    self.slave.waitingfiles, self.slave.builddependencies)
435
455
        return (self.slave.buildstatus, self.buildid)
436
456
 
437
457
    def status_ABORTED(self):
466
486
        return BuilderStatus.IDLE
467
487
 
468
488
    def xmlrpc_build(self, buildid, builder, chrootsum, filemap, args):
 
489
        """Check if requested arguments are sane and initiate build procedure
 
490
 
 
491
        return a tuple containing: (<builder_status>, <info>)
 
492
 
 
493
        """
 
494
        # check requested builder
469
495
        if not builder in self._builders:
470
 
            return BuilderStatus.UNKNOWNBUILDER
471
 
        if not self.slave.ensurePresent(chrootsum):
472
 
            return BuilderStatus.UNKNOWNSUM, chrootsum
473
 
        for checksum in filemap.itervalues():
474
 
            if not self.slave.ensurePresent(checksum):
475
 
                return BuilderStatus.UNKNOWNSUM, checksum
 
496
            return (BuilderStatus.UNKNOWNBUILDER, None)
 
497
        # check requested chroot availability
 
498
        chroot_present, info = self.slave.ensurePresent(chrootsum)
 
499
        if not chroot_present:
 
500
            extra_info = """CHROOTSUM -> %s
 
501
            ***** INFO *****
 
502
            %s
 
503
            ****************
 
504
            """ % (chrootsum, info)
 
505
            return (BuilderStatus.UNKNOWNSUM, extra_info)
 
506
        # check requested files availability
 
507
        for filesum in filemap.itervalues():
 
508
            file_present, info = self.slave.ensurePresent(filesum)
 
509
            if not file_present:
 
510
                extra_info = """FILESUM -> %s
 
511
                ***** INFO *****
 
512
                %s
 
513
                ****************
 
514
                """ % (filesum, info)
 
515
                return (BuilderStatus.UNKNOWNSUM, extra_info)
 
516
        # check buildid sanity
476
517
        if buildid is None or buildid == "" or buildid == 0:
477
518
            raise ValueError(buildid)
 
519
 
478
520
        # builder is available, buildd is non empty,
479
521
        # filelist is consistent, chrootsum is available, let's initiate...
480
 
 
481
522
        self.buildid = buildid
482
 
        
483
523
        self.slave.startBuild(self._builders[builder](self.slave, buildid))
484
524
        self.slave.manager.initiate(filemap, chrootsum, args)
485
 
        return BuilderStatus.BUILDING
486
 
    
 
525
        return (BuilderStatus.BUILDING, buildid)