Merge lp:~jelmer/launchpad/bug499115 into lp:launchpad

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~jelmer/launchpad/bug499115
Merge into: lp:launchpad
Diff against target: 130 lines (+56/-18)
2 files modified
lib/lp/buildmaster/model/buildbase.py (+27/-18)
lib/lp/buildmaster/tests/test_buildbase.py (+29/-0)
To merge this branch: bzr merge lp:~jelmer/launchpad/bug499115
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+20465@code.launchpad.net

Commit message

This trivial change prevents the buildd master from falling over if a container directory was created but no log file uploaded.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

This is a resubmission of https://code.edge.launchpad.net/~jelmer/launchpad/bug499115/+merge/19328 with Henning's comments addressed.

I'm submitting a new merge proposal since I would like to actually target devel rather than db-devel.

Revision history for this message
Brad Crittenden (bac) wrote :

Hi Jelmer,

Thanks for the branch. I have two suggestions:

1) UPLOADLOG_FILENAME -> UPLOAD_LOG_FILENAME

2) You use try/finally for resource management in a couple of places. It might be nice to use 'with' as Barry discussed on the mailing list a few weeks ago. That's totally up to you, though.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/buildmaster/model/buildbase.py'
--- lib/lp/buildmaster/model/buildbase.py 2010-02-16 02:27:24 +0000
+++ lib/lp/buildmaster/model/buildbase.py 2010-03-05 23:33:34 +0000
@@ -3,6 +3,8 @@
33
4# pylint: disable-msg=E0211,E02134# pylint: disable-msg=E0211,E0213
55
6from __future__ import with_statement
7
6"""Common build base classes."""8"""Common build base classes."""
79
8__metaclass__ = type10__metaclass__ = type
@@ -32,6 +34,9 @@
32from lp.soyuz.model.buildqueue import BuildQueue34from lp.soyuz.model.buildqueue import BuildQueue
3335
3436
37UPLOAD_LOG_FILENAME = 'uploader.log'
38
39
35class BuildBase:40class BuildBase:
36 """A mixin class providing functionality for farm jobs that build a41 """A mixin class providing functionality for farm jobs that build a
37 package.42 package.
@@ -96,6 +101,25 @@
96 return None101 return None
97 return self._getProxiedFileURL(self.buildlog)102 return self._getProxiedFileURL(self.buildlog)
98103
104 def getUploadLogContent(self, root, leaf):
105 """Retrieve the upload log contents.
106
107 :param root: Root directory for the uploads
108 :param leaf: Leaf for this particular upload
109 :return: Contents of log file or message saying no log file was found.
110 """
111 # Retrieve log file content.
112 possible_locations = (
113 'failed', 'failed-to-move', 'rejected', 'accepted')
114 for location_dir in possible_locations:
115 log_filepath = os.path.join(root, location_dir, leaf,
116 UPLOAD_LOG_FILENAME)
117 if os.path.exists(log_filepath):
118 with open(log_filepath, 'r') as uploader_log_file:
119 return uploader_log_file.read()
120 else:
121 return 'Could not find upload log file'
122
99 @property123 @property
100 def upload_log_url(self):124 def upload_log_url(self):
101 """See `IBuildBase`."""125 """See `IBuildBase`."""
@@ -161,7 +185,7 @@
161 out_file = open(out_file_name, "wb")185 out_file = open(out_file_name, "wb")
162 copy_and_close(slave_file, out_file)186 copy_and_close(slave_file, out_file)
163187
164 uploader_logfilename = os.path.join(upload_dir, 'uploader.log')188 uploader_logfilename = os.path.join(upload_dir, UPLOAD_LOG_FILENAME)
165 uploader_command = self.getUploaderCommand(189 uploader_command = self.getUploaderCommand(
166 upload_leaf, uploader_logfilename)190 upload_leaf, uploader_logfilename)
167 logger.debug("Saving uploader log at '%s'" % uploader_logfilename)191 logger.debug("Saving uploader log at '%s'" % uploader_logfilename)
@@ -239,23 +263,8 @@
239 not self.verifySuccessfulUpload()):263 not self.verifySuccessfulUpload()):
240 logger.debug("Build %s upload failed." % self.id)264 logger.debug("Build %s upload failed." % self.id)
241 self.buildstate = BuildStatus.FAILEDTOUPLOAD265 self.buildstate = BuildStatus.FAILEDTOUPLOAD
242 # Retrieve log file content.266 uploader_log_content = self.getUploadLogContent(root,
243 possible_locations = (267 upload_leaf)
244 'failed', 'failed-to-move', 'rejected', 'accepted')
245 for location_dir in possible_locations:
246 upload_final_location = os.path.join(
247 root, location_dir, upload_leaf)
248 if os.path.exists(upload_final_location):
249 log_filepath = os.path.join(
250 upload_final_location, 'uploader.log')
251 uploader_log_file = open(log_filepath)
252 try:
253 uploader_log_content = uploader_log_file.read()
254 finally:
255 uploader_log_file.close()
256 break
257 else:
258 uploader_log_content = 'Could not find upload log file'
259 # Store the upload_log_contents in librarian so it can be268 # Store the upload_log_contents in librarian so it can be
260 # accessed by anyone with permission to see the build.269 # accessed by anyone with permission to see the build.
261 self.storeUploadLog(uploader_log_content)270 self.storeUploadLog(uploader_log_content)
262271
=== modified file 'lib/lp/buildmaster/tests/test_buildbase.py'
--- lib/lp/buildmaster/tests/test_buildbase.py 2010-02-03 16:21:57 +0000
+++ lib/lp/buildmaster/tests/test_buildbase.py 2010-03-05 23:33:34 +0000
@@ -1,6 +1,8 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4from __future__ import with_statement
5
4"""Tests for `IBuildBase`."""6"""Tests for `IBuildBase`."""
57
6__metaclass__ = type8__metaclass__ = type
@@ -45,6 +47,33 @@
4547
46 layer = DatabaseFunctionalLayer48 layer = DatabaseFunctionalLayer
4749
50 def test_getUploadLogContent_nolog(self):
51 """If there is no log file there, a string explaining that is returned.
52 """
53 self.useTempDir()
54 build_base = BuildBase()
55 self.assertEquals('Could not find upload log file',
56 build_base.getUploadLogContent(os.getcwd(), "myleaf"))
57
58 def test_getUploadLogContent_only_dir(self):
59 """If there is a directory but no log file, expect the error string,
60 not an exception."""
61 self.useTempDir()
62 os.makedirs("accepted/myleaf")
63 build_base = BuildBase()
64 self.assertEquals('Could not find upload log file',
65 build_base.getUploadLogContent(os.getcwd(), "myleaf"))
66
67 def test_getUploadLogContent_readsfile(self):
68 """If there is a log file, return its contents."""
69 self.useTempDir()
70 os.makedirs("accepted/myleaf")
71 with open('accepted/myleaf/uploader.log', 'w') as f:
72 f.write('foo')
73 build_base = BuildBase()
74 self.assertEquals('foo',
75 build_base.getUploadLogContent(os.getcwd(), "myleaf"))
76
48 def test_getUploaderCommand(self):77 def test_getUploaderCommand(self):
49 build_base = BuildBase()78 build_base = BuildBase()
50 upload_leaf = self.factory.getUniqueString('upload-leaf')79 upload_leaf = self.factory.getUniqueString('upload-leaf')