Merge ~cjwatson/launchpad:stormify-builder into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 903b60b9ce06fb17b5222aaba0231f3fe944306b
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:stormify-builder
Merge into: launchpad:master
Diff against target: 310 lines (+85/-61)
7 files modified
lib/lp/buildmaster/doc/builder.txt (+3/-2)
lib/lp/buildmaster/manager.py (+1/-1)
lib/lp/buildmaster/model/builder.py (+74/-53)
lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py (+1/-1)
lib/lp/testing/factory.py (+3/-3)
lib/lp/testing/sampledata.py (+2/-0)
lib/lp/translations/stories/buildfarm/xx-build-summary.txt (+1/-1)
Reviewer Review Type Date Requested Status
Tom Wardill (community) Approve
Review via email: mp+395397@code.launchpad.net

Commit message

Convert Builder to Storm

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
Revision history for this message
Tom Wardill (twom) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/buildmaster/doc/builder.txt b/lib/lp/buildmaster/doc/builder.txt
2index 4290a2f..e8249ad 100644
3--- a/lib/lp/buildmaster/doc/builder.txt
4+++ b/lib/lp/buildmaster/doc/builder.txt
5@@ -14,7 +14,8 @@ packages.
6 There are several builders in the sample data. Let's examine the first.
7
8 >>> from lp.buildmaster.model.builder import Builder
9- >>> builder = Builder.get(1)
10+ >>> from lp.services.database.interfaces import IStore
11+ >>> builder = IStore(Builder).get(Builder, 1)
12
13 As expected, it implements IBuilder.
14
15@@ -65,7 +66,7 @@ And also by ID.
16 >>> print(builderset.get(100).name)
17 Traceback (most recent call last):
18 ...
19- SQLObjectNotFound: Object not found
20+ NotFoundError: 100
21
22 The 'new' method will create a new builder in the database.
23
24diff --git a/lib/lp/buildmaster/manager.py b/lib/lp/buildmaster/manager.py
25index 7bbe4aa..64fdb21 100644
26--- a/lib/lp/buildmaster/manager.py
27+++ b/lib/lp/buildmaster/manager.py
28@@ -409,7 +409,7 @@ def recover_failure(logger, vitals, builder, retry, exception):
29 # We've already tried resetting it enough times, so we have
30 # little choice but to give up.
31 logger.info("Failing builder %s.", builder.name)
32- builder.failBuilder(str(exception))
33+ builder.failBuilder(six.text_type(exception))
34 elif builder_action == True:
35 # Dirty the builder to attempt recovery. In the virtual case,
36 # the dirty idleness will cause a reset, giving us a good chance
37diff --git a/lib/lp/buildmaster/model/builder.py b/lib/lp/buildmaster/model/builder.py
38index 93326ee..5e66baf 100644
39--- a/lib/lp/buildmaster/model/builder.py
40+++ b/lib/lp/buildmaster/model/builder.py
41@@ -9,19 +9,18 @@ __all__ = [
42 'BuilderSet',
43 ]
44
45-from sqlobject import (
46- BoolCol,
47- ForeignKey,
48- IntCol,
49- SQLObjectNotFound,
50- StringCol,
51- )
52+import pytz
53 from storm.expr import (
54 Coalesce,
55 Count,
56 Sum,
57 )
58-from storm.properties import Int
59+from storm.properties import (
60+ Bool,
61+ DateTime,
62+ Int,
63+ Unicode,
64+ )
65 from storm.references import Reference
66 from storm.store import Store
67 from zope.component import getUtility
68@@ -50,14 +49,12 @@ from lp.services.database.bulk import (
69 load_related,
70 )
71 from lp.services.database.constants import UTC_NOW
72-from lp.services.database.datetimecol import UtcDateTimeCol
73 from lp.services.database.decoratedresultset import DecoratedResultSet
74-from lp.services.database.enumcol import EnumCol
75+from lp.services.database.enumcol import DBEnum
76 from lp.services.database.interfaces import (
77 ISlaveStore,
78 IStore,
79 )
80-from lp.services.database.sqlbase import SQLBase
81 from lp.services.database.stormbase import StormBase
82 from lp.services.propertycache import (
83 cachedproperty,
84@@ -71,41 +68,64 @@ from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
85
86
87 @implementer(IBuilder, IHasBuildRecords)
88-class Builder(SQLBase):
89- _table = 'Builder'
90-
91- _defaultOrder = ['id']
92-
93- url = StringCol(dbName='url', notNull=True)
94- name = StringCol(dbName='name', notNull=True)
95- title = StringCol(dbName='title', notNull=True)
96- owner = ForeignKey(
97- dbName='owner', foreignKey='Person',
98- storm_validator=validate_public_person, notNull=True)
99- _builderok = BoolCol(dbName='builderok', notNull=True)
100- failnotes = StringCol(dbName='failnotes')
101- virtualized = BoolCol(dbName='virtualized', default=True, notNull=True)
102- manual = BoolCol(dbName='manual', default=False)
103- vm_host = StringCol(dbName='vm_host')
104- active = BoolCol(dbName='active', notNull=True, default=True)
105- failure_count = IntCol(dbName='failure_count', default=0, notNull=True)
106- version = StringCol(dbName='version')
107- clean_status = EnumCol(
108+class Builder(StormBase):
109+ __storm_table__ = 'Builder'
110+ __storm_order__ = ['id']
111+
112+ id = Int(primary=True)
113+ url = Unicode(name='url', allow_none=False)
114+ name = Unicode(name='name', allow_none=False)
115+ title = Unicode(name='title', allow_none=False)
116+ owner_id = Int(
117+ name='owner', validator=validate_public_person, allow_none=False)
118+ owner = Reference(owner_id, 'Person.id')
119+ _builderok = Bool(name='builderok', allow_none=False)
120+ failnotes = Unicode(name='failnotes')
121+ virtualized = Bool(name='virtualized', default=True, allow_none=False)
122+ manual = Bool(name='manual', default=False)
123+ vm_host = Unicode(name='vm_host')
124+ active = Bool(name='active', allow_none=False, default=True)
125+ failure_count = Int(name='failure_count', default=0, allow_none=False)
126+ version = Unicode(name='version')
127+ clean_status = DBEnum(
128 enum=BuilderCleanStatus, default=BuilderCleanStatus.DIRTY)
129- vm_reset_protocol = EnumCol(enum=BuilderResetProtocol)
130- date_clean_status_changed = UtcDateTimeCol()
131+ vm_reset_protocol = DBEnum(enum=BuilderResetProtocol)
132+ date_clean_status_changed = DateTime(tzinfo=pytz.UTC)
133+
134+ def __init__(self, processors, url, name, title, owner, active=True,
135+ virtualized=True, vm_host=None, vm_reset_protocol=None,
136+ builderok=True, manual=False):
137+ super(Builder, self).__init__()
138+ # The processors cache starts out empty so that the processors
139+ # property setter doesn't issue an additional query.
140+ get_property_cache(self)._processors_cache = []
141+ self.url = url
142+ self.name = name
143+ self.title = title
144+ self.owner = owner
145+ self.active = active
146+ self.virtualized = virtualized
147+ self.vm_host = vm_host
148+ self.vm_reset_protocol = vm_reset_protocol
149+ self._builderok = builderok
150+ self.manual = manual
151+ # We have to add the new object to the store here (it might more
152+ # normally be done in BuilderSet.new), because the processors
153+ # property setter needs to link other objects to it.
154+ IStore(Builder).add(self)
155+ self.processors = processors
156
157- def _getBuilderok(self):
158+ @property
159+ def builderok(self):
160 return self._builderok
161
162- def _setBuilderok(self, value):
163+ @builderok.setter
164+ def builderok(self, value):
165 self._builderok = value
166 if value is True:
167 self.resetFailureCount()
168 self.setCleanStatus(BuilderCleanStatus.DIRTY)
169
170- builderok = property(_getBuilderok, _setBuilderok)
171-
172 def gotFailure(self):
173 """See `IBuilder`."""
174 self.failure_count += 1
175@@ -124,10 +144,12 @@ class Builder(SQLBase):
176 BuilderProcessor.processor_id == Processor.id,
177 BuilderProcessor.builder == self).order_by(Processor.name))
178
179- def _processors(self):
180+ @property
181+ def processors(self):
182 return self._processors_cache
183
184- def _set_processors(self, processors):
185+ @processors.setter
186+ def processors(self, processors):
187 existing = set(self.processors)
188 wanted = set(processors)
189 # Enable the wanted but missing.
190@@ -144,8 +166,6 @@ class Builder(SQLBase):
191 processor.id for processor in existing - wanted)).remove()
192 del get_property_cache(self)._processors_cache
193
194- processors = property(_processors, _set_processors)
195-
196 @property
197 def processor(self):
198 """See `IBuilder`."""
199@@ -218,14 +238,11 @@ class BuilderSet(object):
200 self.title = "The Launchpad build farm"
201
202 def __iter__(self):
203- return iter(Builder.select())
204+ return iter(IStore(Builder).find(Builder))
205
206 def getByName(self, name):
207 """See IBuilderSet."""
208- try:
209- return Builder.selectOneBy(name=name)
210- except SQLObjectNotFound:
211- raise NotFoundError(name)
212+ return IStore(Builder).find(Builder, name=name).one()
213
214 def __getitem__(self, name):
215 return self.getByName(name)
216@@ -234,18 +251,22 @@ class BuilderSet(object):
217 virtualized=False, vm_host=None, vm_reset_protocol=None,
218 manual=True):
219 """See IBuilderSet."""
220- return Builder(processors=processors, url=url, name=name, title=title,
221- owner=owner, active=active, virtualized=virtualized,
222- vm_host=vm_host, vm_reset_protocol=vm_reset_protocol,
223- _builderok=True, manual=manual)
224+ return Builder(
225+ processors=processors, url=url, name=name, title=title,
226+ owner=owner, active=active, virtualized=virtualized,
227+ vm_host=vm_host, vm_reset_protocol=vm_reset_protocol,
228+ builderok=True, manual=manual)
229
230 def get(self, builder_id):
231 """See IBuilderSet."""
232- return Builder.get(builder_id)
233+ builder = IStore(Builder).get(Builder, builder_id)
234+ if builder is None:
235+ raise NotFoundError(builder_id)
236+ return builder
237
238 def count(self):
239 """See IBuilderSet."""
240- return Builder.select().count()
241+ return IStore(Builder).find(Builder).count()
242
243 def preloadProcessors(self, builders):
244 """See `IBuilderSet`."""
245@@ -274,7 +295,7 @@ class BuilderSet(object):
246
247 def preload(rows):
248 self.preloadProcessors(rows)
249- load_related(Person, rows, ['ownerID'])
250+ load_related(Person, rows, ['owner_id'])
251 bqs = getUtility(IBuildQueueSet).preloadForBuilders(rows)
252 BuildQueue.preloadSpecificBuild(bqs)
253 return DecoratedResultSet(rs, pre_iter_hook=preload)
254diff --git a/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py b/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
255index b846e87..ceec2a9 100644
256--- a/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
257+++ b/lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py
258@@ -68,7 +68,7 @@ class TestSourcePackageRecipeBuildMailer(TestCaseWithFactory):
259 status=BuildStatus.FULLYBUILT, duration=timedelta(minutes=5))
260 build.updateStatus(
261 BuildStatus.FULLYBUILT,
262- builder=self.factory.makeBuilder(name='bob'))
263+ builder=self.factory.makeBuilder(name=u'bob'))
264 build.setLog(self.factory.makeLibraryFileAlias())
265 ctrl = self.makeStatusEmail(build)
266 self.assertEqual(
267diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
268index b38c7d6..685a142 100644
269--- a/lib/lp/testing/factory.py
270+++ b/lib/lp/testing/factory.py
271@@ -3016,11 +3016,11 @@ class BareLaunchpadObjectFactory(ObjectFactory):
272 if processors is None:
273 processors = [getUtility(IProcessorSet).getByName('386')]
274 if url is None:
275- url = 'http://%s:8221/' % self.getUniqueString()
276+ url = 'http://%s:8221/' % self.getUniqueUnicode()
277 if name is None:
278- name = self.getUniqueString('builder-name')
279+ name = self.getUniqueUnicode('builder-name')
280 if title is None:
281- title = self.getUniqueString('builder-title')
282+ title = self.getUniqueUnicode('builder-title')
283 if owner is None:
284 owner = self.makePerson()
285 if virtualized and vm_reset_protocol is None:
286diff --git a/lib/lp/testing/sampledata.py b/lib/lp/testing/sampledata.py
287index b314351..74d78d8 100644
288--- a/lib/lp/testing/sampledata.py
289+++ b/lib/lp/testing/sampledata.py
290@@ -7,6 +7,8 @@ If ever you use a literal in a test that refers to sample data, even if it's
291 just a small number, then you should define it as a constant here.
292 """
293
294+from __future__ import absolute_import, print_function, unicode_literals
295+
296 __metaclass__ = type
297 __all__ = [
298 'ADMIN_EMAIL',
299diff --git a/lib/lp/translations/stories/buildfarm/xx-build-summary.txt b/lib/lp/translations/stories/buildfarm/xx-build-summary.txt
300index 230b756..36c8e7b 100644
301--- a/lib/lp/translations/stories/buildfarm/xx-build-summary.txt
302+++ b/lib/lp/translations/stories/buildfarm/xx-build-summary.txt
303@@ -51,7 +51,7 @@ Create a builder working on a TranslationTemplatesBuild for a branch.
304 >>> unused = ubuntu.currentseries.nominatedarchindep.addOrUpdateChroot(
305 ... fake_chroot)
306
307- >>> builder = factory.makeBuilder(vm_host=factory.getUniqueString())
308+ >>> builder = factory.makeBuilder(vm_host=factory.getUniqueUnicode())
309 >>> _ = patch(BuilderSlave, 'makeBuilderSlave', FakeMethod(FakeSlave()))
310 >>> buildqueue.markAsBuilding(builder)
311

Subscribers

People subscribed via source and target branches

to status/vote changes: