Merge lp:~jelmer/launchpad/bug471148 into lp:launchpad/db-devel

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/bug471148
Merge into: lp:launchpad/db-devel
Diff against target: 711 lines (+423/-18)
18 files modified
database/sampledata/current-dev.sql (+5/-4)
database/sampledata/current.sql (+5/-4)
database/schema/patch-2207-35-0.sql (+8/-0)
database/schema/security.cfg (+2/-2)
lib/lp/soyuz/browser/archive.py (+1/-1)
lib/lp/soyuz/configure.zcml (+2/-1)
lib/lp/soyuz/interfaces/archive.py (+3/-0)
lib/lp/soyuz/interfaces/archivearch.py (+11/-0)
lib/lp/soyuz/interfaces/processor.py (+24/-1)
lib/lp/soyuz/model/archive.py (+35/-0)
lib/lp/soyuz/model/archivearch.py (+16/-0)
lib/lp/soyuz/model/processor.py (+12/-0)
lib/lp/soyuz/model/publishing.py (+25/-5)
lib/lp/soyuz/tests/test_archive.py (+53/-0)
lib/lp/soyuz/tests/test_archivearch.py (+57/-0)
lib/lp/soyuz/tests/test_processor.py (+32/-0)
lib/lp/soyuz/tests/test_publishing.py (+99/-0)
lib/lp/testing/factory.py (+33/-0)
To merge this branch: bzr merge lp:~jelmer/launchpad/bug471148
Reviewer Review Type Date Requested Status
Björn Tillenius (community) db Approve
Stuart Bishop (community) db Approve
Paul Hummer (community) code Approve
Review via email: mp+20142@code.launchpad.net

This proposal supersedes a proposal from 2010-02-24.

Commit message

Add restricted flag to processor families and allow them to be overriden on a per-archive basis.

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

This makes it possible for processor families to be marked restricted. Source packages in archives will only be built using these processor families if they are explicitly permitted, using an entry in ArchiveArch.

This patch also adds some infrastructure to create processor families and processors, which we use for testing.

I reran "make newsampledata" which doesn't appear to have happened in a while, so there are some updates there related to earlier branches as well.

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote : Posted in a previous version of this proposal

It looks as if this diff got polluted with extraneous changes.

Revision history for this message
Jelmer Vernooij (jelmer) wrote : Posted in a previous version of this proposal

Hi Jeroen,

On Wed, 2010-02-24 at 18:18 +0000, Jeroen T. Vermeulen wrote:
> It looks as if this diff got polluted with extraneous changes.
The sampledata doesn't appear to have been regenerated a couple of times
after some other schema changes landed, and that causes the diff to
database/sampledata/current{,-devel}.sql to be so large - the only real
change I've made to the sample data is to add a ARM processor family
that has the new restricted column set to true. Other than that, this is
a fairly simple branch against db-devel.

If you'd rather have me submit a separate branch that just runs "make
newsampledata" in db-devel so that the diff for this branch isn't
cluttered by it, please let me know.

Cheers,

Jelmer

Revision history for this message
Jelmer Vernooij (jelmer) wrote : Posted in a previous version of this proposal

Muharem has now submitted a separate branch which just updates the existing sampledata, that should make the diff for this branch a fair bit smaller.

Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote : Posted in a previous version of this proposal

Yep, it's lp:~al-maisan/launchpad/sampledata-update and it was just approved.

Revision history for this message
Paul Hummer (rockstar) wrote :

<rockstar> jelmer, is this diff up to date? Does it have a dependent branch?
<jelmer> rockstar: the bug471148 one? That's current now
<rockstar> jelmer, okay.
<jelmer> rockstar: It's a fair bit smaller now that Muharems prerequisite branch has landed.
<rockstar> jelmer, you should set the prerequisite branch on the mp anyway, because it's informational.
<jelmer> rockstar: Even if that branch has already landed?
<rockstar> jelmer, yeah, it's still a good idea to say "I based my work off of this work."
<rockstar> Not a necessity, but for history's sake.
<jelmer> rockstar: Ah, that makes sense. I'll keep that in mind for next time.
<rockstar> jelmer, your tests need comments/documentation
<rockstar> lib/lp/soyuz/tests/test_processor.py and lib/lp/soyuz/tests/test_publishing.py
<rockstar> Actually, it looks like some of the tests have docstrings, so you'll probably just need to add the docstrings to the ones that lack them.
<jelmer> ok
<rockstar> jelmer, good on you for adding factory methods for your new work.
<jelmer> rockstar: Thanks
<rockstar> jelmer, other than the missing docstrings, this looks like very good work.

review: Approve (code)
Revision history for this message
Stuart Bishop (stub) wrote :

So if there are no ArchArchive entries, the archive is build with all the non-retricted architectures.

A less generic name might be nice, but I can't think of a better term right now.

Looks fine anyway. Patch number patch-2207-35-0.sql.

review: Approve (db)
Revision history for this message
Björn Tillenius (bjornt) wrote :

I also would like to see a better name, but can't think of any right now.

review: Approve (db)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'database/sampledata/current-dev.sql'
2--- database/sampledata/current-dev.sql 2010-02-25 08:39:19 +0000
3+++ database/sampledata/current-dev.sql 2010-02-26 23:30:37 +0000
4@@ -8143,10 +8143,11 @@
5
6 ALTER TABLE processorfamily DISABLE TRIGGER ALL;
7
8-INSERT INTO processorfamily (id, name, title, description) VALUES (1, 'x86', 'Intel 386 compatible chips', 'Bring back the 8086!');
9-INSERT INTO processorfamily (id, name, title, description) VALUES (2, 'powerpc', 'PowerPC compatible systems, G3 G4 etc', 'An architecture conceived by Motorola and developed further in cooperation with IBM. Was used very successfully by Apple for their PowerMac range, until 2007.');
10-INSERT INTO processorfamily (id, name, title, description) VALUES (3, 'amd64', 'AMD64 and Intel EM64T and compatible systems', 'A 64-bit extension to the venerable x86 architecture, pioneered by AMD and later adopted by Intel as well.');
11-INSERT INTO processorfamily (id, name, title, description) VALUES (4, 'hppa', 'PA-RISC Processors', 'The HP PA-RISC and compatible processors');
12+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (1, 'x86', 'Intel 386 compatible chips', 'Bring back the 8086!', false);
13+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (2, 'powerpc', 'PowerPC compatible systems, G3 G4 etc', 'An architecture conceived by Motorola and developed further in cooperation with IBM. Was used very successfully by Apple for their PowerMac range, until 2007.', false);
14+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (3, 'amd64', 'AMD64 and Intel EM64T and compatible systems', 'A 64-bit extension to the venerable x86 architecture, pioneered by AMD and later adopted by Intel as well.', false);
15+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (4, 'hppa', 'PA-RISC Processors', 'The HP PA-RISC and compatible processors', false);
16+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (5, 'arm', 'ARM Processors', 'The ARM and compatible processors', true);
17
18
19 ALTER TABLE processorfamily ENABLE TRIGGER ALL;
20
21=== modified file 'database/sampledata/current.sql'
22--- database/sampledata/current.sql 2010-02-25 08:39:19 +0000
23+++ database/sampledata/current.sql 2010-02-26 23:30:37 +0000
24@@ -8039,10 +8039,11 @@
25
26 ALTER TABLE processorfamily DISABLE TRIGGER ALL;
27
28-INSERT INTO processorfamily (id, name, title, description) VALUES (1, 'x86', 'Intel 386 compatible chips', 'Bring back the 8086!');
29-INSERT INTO processorfamily (id, name, title, description) VALUES (2, 'powerpc', 'PowerPC compatible systems, G3 G4 etc', 'An architecture conceived by Motorola and developed further in cooperation with IBM. Was used very successfully by Apple for their PowerMac range, until 2007.');
30-INSERT INTO processorfamily (id, name, title, description) VALUES (3, 'amd64', 'AMD64 and Intel EM64T and compatible systems', 'A 64-bit extension to the venerable x86 architecture, pioneered by AMD and later adopted by Intel as well.');
31-INSERT INTO processorfamily (id, name, title, description) VALUES (4, 'hppa', 'PA-RISC Processors', 'The HP PA-RISC and compatible processors');
32+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (1, 'x86', 'Intel 386 compatible chips', 'Bring back the 8086!', false);
33+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (2, 'powerpc', 'PowerPC compatible systems, G3 G4 etc', 'An architecture conceived by Motorola and developed further in cooperation with IBM. Was used very successfully by Apple for their PowerMac range, until 2007.', false);
34+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (3, 'amd64', 'AMD64 and Intel EM64T and compatible systems', 'A 64-bit extension to the venerable x86 architecture, pioneered by AMD and later adopted by Intel as well.', false);
35+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (4, 'hppa', 'PA-RISC Processors', 'The HP PA-RISC and compatible processors', false);
36+INSERT INTO processorfamily (id, name, title, description, restricted) VALUES (5, 'arm', 'ARM Processors', 'The ARM and compatible processors', true);
37
38
39 ALTER TABLE processorfamily ENABLE TRIGGER ALL;
40
41=== added file 'database/schema/patch-2207-35-0.sql'
42--- database/schema/patch-2207-35-0.sql 1970-01-01 00:00:00 +0000
43+++ database/schema/patch-2207-35-0.sql 2010-02-26 23:30:37 +0000
44@@ -0,0 +1,8 @@
45+-- Copyright 2010 Canonical Ltd. This software is licensed under the
46+-- GNU Affero General Public License version 3 (see the file LICENSE).
47+
48+SET client_min_messages=ERROR;
49+
50+ALTER TABLE processorfamily ADD COLUMN restricted boolean DEFAULT FALSE NOT NULL;
51+
52+INSERT INTO LaunchpadDatabaseRevision VALUES (2207, 35, 0);
53
54=== modified file 'database/schema/security.cfg'
55--- database/schema/security.cfg 2010-02-22 12:44:29 +0000
56+++ database/schema/security.cfg 2010-02-26 23:30:37 +0000
57@@ -125,7 +125,7 @@
58 public.archive = SELECT, INSERT, UPDATE
59 public.archiveauthtoken = SELECT, INSERT, UPDATE
60 public.archivesubscriber = SELECT, INSERT, UPDATE
61-public.archivearch = SELECT, INSERT, UPDATE
62+public.archivearch = SELECT, INSERT, UPDATE, DELETE
63 public.archivedependency = SELECT, INSERT, DELETE
64 public.archivepermission = SELECT, INSERT, UPDATE, DELETE
65 public.authtoken = SELECT, INSERT, UPDATE, DELETE
66@@ -916,7 +916,7 @@
67 # certain processes, such as the librarian tables. This group is deprecated -
68 # access should be explicitly granted to users.
69 public.archive = SELECT, INSERT, UPDATE
70-public.archivearch = SELECT, INSERT, UPDATE
71+public.archivearch = SELECT, INSERT, UPDATE, DELETE
72 public.binarypackagerelease = SELECT, INSERT, UPDATE
73 public.binarypackagefile = SELECT, INSERT, UPDATE
74 public.binarypackagefilepublishing = SELECT, INSERT, UPDATE
75
76=== modified file 'lib/lp/soyuz/browser/archive.py'
77--- lib/lp/soyuz/browser/archive.py 2010-02-25 16:49:16 +0000
78+++ lib/lp/soyuz/browser/archive.py 2010-02-26 23:30:37 +0000
79@@ -1790,7 +1790,7 @@
80
81 field_names = ['enabled', 'private', 'require_virtualized',
82 'buildd_secret', 'authorized_size', 'relative_build_score',
83- 'external_dependencies']
84+ 'external_dependencies', 'arm_builds_allowed']
85
86 custom_widget('external_dependencies', TextAreaWidget, height=3)
87
88
89=== modified file 'lib/lp/soyuz/configure.zcml'
90--- lib/lp/soyuz/configure.zcml 2010-02-25 22:41:23 +0000
91+++ lib/lp/soyuz/configure.zcml 2010-02-26 23:30:37 +0000
92@@ -400,7 +400,8 @@
93 <require
94 permission="launchpad.Edit"
95 interface="lp.soyuz.interfaces.archive.IArchiveEdit"
96- set_attributes="description displayname publish"/>
97+ set_attributes="description displayname arm_builds_allowed
98+ publish"/>
99 <require
100 permission="launchpad.Commercial"
101 set_attributes="authorized_size buildd_secret
102
103=== modified file 'lib/lp/soyuz/interfaces/archive.py'
104--- lib/lp/soyuz/interfaces/archive.py 2010-02-25 16:49:16 +0000
105+++ lib/lp/soyuz/interfaces/archive.py 2010-02-26 23:30:37 +0000
106@@ -1090,6 +1090,9 @@
107 def disable():
108 """Disable the archive."""
109
110+ arm_builds_allowed = Bool(
111+ title=_("Allow ARM builds for this archive"))
112+
113
114 class IArchive(IArchivePublic, IArchiveAppend, IArchiveEdit, IArchiveView):
115 """Main Archive interface."""
116
117=== modified file 'lib/lp/soyuz/interfaces/archivearch.py'
118--- lib/lp/soyuz/interfaces/archivearch.py 2009-06-25 04:06:00 +0000
119+++ lib/lp/soyuz/interfaces/archivearch.py 2010-02-26 23:30:37 +0000
120@@ -62,3 +62,14 @@
121
122 :return: A (potentially empty) result set of `IArchiveArch` instances.
123 """
124+
125+ def getRestrictedfamilies(archive):
126+ """All restricted processor families, paired with `ArchiveArch`
127+ instances if associated with `archive`.
128+
129+ :return: A sequence containing a (`ProcessorFamily`, `ArchiveArch`)
130+ 2-tuple for each processor family.
131+ The second value in the tuple will be None if the given `archive`
132+ is not associated with the `ProcessorFamily` yet.
133+ """
134+
135
136=== modified file 'lib/lp/soyuz/interfaces/processor.py'
137--- lib/lp/soyuz/interfaces/processor.py 2009-06-25 04:06:00 +0000
138+++ lib/lp/soyuz/interfaces/processor.py 2010-02-26 23:30:37 +0000
139@@ -13,7 +13,10 @@
140 'IProcessorFamilySet',
141 ]
142
143+from canonical.launchpad import _
144+
145 from zope.interface import Interface, Attribute
146+from zope.schema import Bool
147
148 class IProcessor(Interface):
149 """The SQLObject Processor Interface"""
150@@ -29,11 +32,21 @@
151 name = Attribute("The Processor Family Name")
152 title = Attribute("The Processor Family Title")
153 description = Attribute("The Processor Name Description")
154-
155 processors = Attribute("The Processors in this family.")
156+ restricted = Bool(title=_("Whether this family is restricted."))
157+
158+ def addProcessor(name, title, description):
159+ """Add a new processor to this family.
160+
161+ :param name: Name of the processor
162+ :param title: Title of the processor
163+ :param description: Description of the processor
164+ :return: A `IProcessor`
165+ """
166
167 class IProcessorFamilySet(Interface):
168 """Operations related to ProcessorFamily instances."""
169+
170 def getByName(name):
171 """Return the ProcessorFamily instance with the matching name.
172
173@@ -49,3 +62,13 @@
174
175 :return: A `IProcessorFamily` instance if found, None otherwise.
176 """
177+
178+ def new(name, title, description, restricted):
179+ """Create a new processor family.
180+
181+ :param name: Name of the family.
182+ :param title: Title for the family.
183+ :param description: Extended description of the family
184+ :param restricted: Whether the processor family is restricted
185+ :return: a `IProcessorFamily`.
186+ """
187
188=== modified file 'lib/lp/soyuz/model/archive.py'
189--- lib/lp/soyuz/model/archive.py 2010-02-18 17:05:50 +0000
190+++ lib/lp/soyuz/model/archive.py 2010-02-26 23:30:37 +0000
191@@ -59,6 +59,7 @@
192 IDistributionArchive, InvalidComponent, IPPA, MAIN_ARCHIVE_PURPOSES,
193 NoSuchPPA, PocketNotFound, VersionRequiresName, default_name_by_purpose)
194 from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet
195+from lp.soyuz.interfaces.archivearch import IArchiveArchSet
196 from lp.soyuz.interfaces.archivepermission import (
197 ArchivePermissionType, IArchivePermissionSet)
198 from lp.soyuz.interfaces.archivesubscriber import (
199@@ -75,6 +76,7 @@
200 from lp.registry.interfaces.role import IHasOwner
201 from lp.soyuz.interfaces.queue import PackageUploadStatus
202 from lp.soyuz.interfaces.packagecopyrequest import IPackageCopyRequestSet
203+from lp.soyuz.interfaces.processor import IProcessorFamilySet
204 from lp.soyuz.interfaces.publishing import (
205 active_publishing_status, PackagePublishingStatus, IPublishingSet)
206 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
207@@ -182,6 +184,39 @@
208 external_dependencies = StringCol(
209 dbName='external_dependencies', notNull=False, default=None)
210
211+ def _get_arm_builds_enabled(self):
212+ """Check whether ARM builds are allowed for this archive."""
213+ archive_arch_set = getUtility(IArchiveArchSet)
214+ restricted_families = archive_arch_set.getRestrictedfamilies(self)
215+ arm = getUtility(IProcessorFamilySet).getByName('arm')
216+ for (family, archive_arch) in restricted_families:
217+ if family == arm:
218+ return (archive_arch is not None)
219+ # ARM doesn't exist or isn't restricted. Either way, there is no
220+ # need for an explicit association.
221+ return False
222+
223+ def _set_arm_builds_enabled(self, value):
224+ """Set whether ARM builds are enabled for this archive."""
225+ archive_arch_set = getUtility(IArchiveArchSet)
226+ restricted_families = archive_arch_set.getRestrictedfamilies(self)
227+ arm = getUtility(IProcessorFamilySet).getByName('arm')
228+ for (family, archive_arch) in restricted_families:
229+ if family == arm:
230+ if value:
231+ if archive_arch is not None:
232+ # ARM builds are already enabled
233+ return
234+ else:
235+ archive_arch_set.new(self, family)
236+ else:
237+ if archive_arch is not None:
238+ Store.of(self).remove(archive_arch)
239+ else:
240+ pass # ARM builds are already disabled
241+ arm_builds_allowed = property(_get_arm_builds_enabled,
242+ _set_arm_builds_enabled)
243+
244 def _init(self, *args, **kw):
245 """Provide the right interface for URL traversal."""
246 SQLBase._init(self, *args, **kw)
247
248=== modified file 'lib/lp/soyuz/model/archivearch.py'
249--- lib/lp/soyuz/model/archivearch.py 2009-06-25 04:06:00 +0000
250+++ lib/lp/soyuz/model/archivearch.py 2010-02-26 23:30:37 +0000
251@@ -9,9 +9,11 @@
252
253 from lp.soyuz.interfaces.archivearch import (
254 IArchiveArch, IArchiveArchSet)
255+from lp.soyuz.model.processor import ProcessorFamily
256 from canonical.launchpad.webapp.interfaces import (
257 IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR)
258
259+from storm.expr import Join, LeftJoin
260 from storm.locals import Int, Reference, Storm
261
262
263@@ -55,3 +57,17 @@
264 results = results.order_by(ArchiveArch.id)
265
266 return results
267+
268+ def getRestrictedfamilies(self, archive):
269+ """See `IArchiveArchSet`."""
270+ store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR)
271+ origin = (
272+ ProcessorFamily,
273+ LeftJoin(
274+ ArchiveArch,
275+ ArchiveArch.processorfamily == ProcessorFamily.id))
276+ result_set = store.using(*origin).find(
277+ (ProcessorFamily, ArchiveArch),
278+ (ProcessorFamily.restricted == True))
279+
280+ return result_set.order_by(ProcessorFamily.name)
281
282=== modified file 'lib/lp/soyuz/model/processor.py'
283--- lib/lp/soyuz/model/processor.py 2009-06-25 04:06:00 +0000
284+++ lib/lp/soyuz/model/processor.py 2010-02-26 23:30:37 +0000
285@@ -10,6 +10,7 @@
286 from zope.interface import implements
287
288 from sqlobject import StringCol, ForeignKey, SQLMultipleJoin
289+from storm.locals import Bool
290
291 from canonical.database.sqlbase import SQLBase
292
293@@ -39,6 +40,12 @@
294 description = StringCol(dbName='description', notNull=True)
295
296 processors = SQLMultipleJoin('Processor', joinColumn='family')
297+ restricted = Bool(allow_none=False, default=False)
298+
299+ def addProcessor(self, name, title, description):
300+ """See `IProcessorFamily`."""
301+ return Processor(family=self, name=name, title=title,
302+ description=description)
303
304
305 class ProcessorFamilySet:
306@@ -62,3 +69,8 @@
307 # but there is also the possibility that the user specified a name for
308 # a non-existent processor.
309 return rset.one()
310+
311+ def new(self, name, title, description, restricted=False):
312+ """See `IProcessorFamily`."""
313+ return ProcessorFamily(name=name, title=title,
314+ description=description, restricted=restricted)
315
316=== modified file 'lib/lp/soyuz/model/publishing.py'
317--- lib/lp/soyuz/model/publishing.py 2010-02-15 12:59:55 +0000
318+++ lib/lp/soyuz/model/publishing.py 2010-02-26 23:30:37 +0000
319@@ -45,14 +45,15 @@
320 LibraryFileAlias, LibraryFileContent)
321 from lp.soyuz.model.packagediff import PackageDiff
322 from lp.soyuz.interfaces.archive import ArchivePurpose
323+from lp.soyuz.interfaces.archivearch import IArchiveArchSet
324 from lp.soyuz.interfaces.component import IComponentSet
325 from lp.soyuz.interfaces.queue import PackageUploadStatus
326 from lp.soyuz.interfaces.publishing import (
327- active_publishing_status, IArchiveSafePublisher,
328- IBinaryPackageFilePublishing, IBinaryPackagePublishingHistory,
329- IPublishingEdit, IPublishingSet, ISourcePackageFilePublishing,
330- ISourcePackagePublishingHistory, PackagePublishingPriority,
331- PackagePublishingStatus, PoolFileOverwriteError)
332+ active_publishing_status, IBinaryPackageFilePublishing,
333+ IBinaryPackagePublishingHistory, IPublishingSet,
334+ ISourcePackageFilePublishing, ISourcePackagePublishingHistory,
335+ PackagePublishingPriority, PackagePublishingStatus,
336+ PoolFileOverwriteError)
337 from lp.soyuz.interfaces.build import BuildSetStatus, BuildStatus, IBuildSet
338 from lp.soyuz.scripts.changeoverride import ArchiveOverriderError
339 from canonical.launchpad.components.decoratedresultset import (
340@@ -505,6 +506,22 @@
341 the_url = self._proxied_urls((changes_lfa,), self.archive)[0]
342 return the_url
343
344+ def _getAllowedArchitectures(self, available_archs):
345+ """Filter out any restricted architectures not specifically allowed
346+ for an archive.
347+
348+ :param available_archs: Architectures to consider
349+ :return: Sequence of `IDistroArch` instances.
350+ """
351+ associated_proc_families = [
352+ archivearch.processorfamily for archivearch
353+ in getUtility(IArchiveArchSet).getByArchive(self.archive)]
354+ # Return all distroarches with unrestricted processor families or with
355+ # processor families the archive is explicitly associated with.
356+ return [distroarch for distroarch in available_archs
357+ if not distroarch.processorfamily.restricted or
358+ distroarch.processorfamily in associated_proc_families]
359+
360 def createMissingBuilds(self, architectures_available=None,
361 pas_verify=None, logger=None):
362 """See `ISourcePackagePublishingHistory`."""
363@@ -515,6 +532,9 @@
364 architectures_available = list(
365 self.distroseries.enabled_architectures)
366
367+ architectures_available = self._getAllowedArchitectures(
368+ architectures_available)
369+
370 build_architectures = determineArchitecturesToBuild(
371 self, architectures_available, self.distroseries, pas_verify)
372
373
374=== modified file 'lib/lp/soyuz/tests/test_archive.py'
375--- lib/lp/soyuz/tests/test_archive.py 2010-02-08 16:33:12 +0000
376+++ lib/lp/soyuz/tests/test_archive.py 2010-02-26 23:30:37 +0000
377@@ -19,8 +19,10 @@
378 from lp.registry.interfaces.person import IPersonSet
379 from lp.services.job.interfaces.job import JobStatus
380 from lp.soyuz.interfaces.archive import IArchiveSet, ArchivePurpose
381+from lp.soyuz.interfaces.archivearch import IArchiveArchSet
382 from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFormat
383 from lp.soyuz.interfaces.build import BuildStatus
384+from lp.soyuz.interfaces.processor import IProcessorFamilySet
385 from lp.soyuz.interfaces.publishing import PackagePublishingStatus
386 from lp.soyuz.model.build import Build
387 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
388@@ -558,5 +560,56 @@
389 self.assertEqual(1, len(pubs))
390 self.assertEqual('0.5.11~ppa1', pubs[0].source_package_version)
391
392+
393+class TestARMBuildsAllowed(TestCaseWithFactory):
394+ """Ensure that ARM builds can be allowed and disallowed correctly."""
395+
396+ layer = LaunchpadZopelessLayer
397+
398+ def setUp(self):
399+ """Setup an archive with relevant publications."""
400+ super(TestARMBuildsAllowed, self).setUp()
401+ self.publisher = SoyuzTestPublisher()
402+ self.publisher.prepareBreezyAutotest()
403+ self.archive = self.factory.makeArchive()
404+ self.archive_arch_set = getUtility(IArchiveArchSet)
405+ self.arm = getUtility(IProcessorFamilySet).getByName('arm')
406+
407+ def test_default(self):
408+ """By default, ARM builds are not allowed."""
409+ self.assertEquals(0,
410+ self.archive_arch_set.getByArchive(self.archive, self.arm).count())
411+ self.assertFalse(self.archive.arm_builds_allowed)
412+
413+ def test_get_uses_archivearch(self):
414+ """Adding an entry to ArchiveArch for ARM and an archive will
415+ enable arm_builds_allowed for that archive."""
416+ self.assertFalse(self.archive.arm_builds_allowed)
417+ self.archive_arch_set.new(self.archive, self.arm)
418+ self.assertTrue(self.archive.arm_builds_allowed)
419+
420+ def test_get_uses_arm_only(self):
421+ """Adding an entry to ArchiveArch for something other than ARM
422+ does not enable arm_builds_allowed for that archive."""
423+ self.assertFalse(self.archive.arm_builds_allowed)
424+ self.archive_arch_set.new(self.archive,
425+ getUtility(IProcessorFamilySet).getByName('amd64'))
426+ self.assertFalse(self.archive.arm_builds_allowed)
427+
428+ def test_set(self):
429+ """The property remembers its value correctly and sets ArchiveArch."""
430+ self.archive.arm_builds_allowed = True
431+ allowed_restricted_families = self.archive_arch_set.getByArchive(
432+ self.archive, self.arm)
433+ self.assertEquals(1, allowed_restricted_families.count())
434+ self.assertEquals(self.arm,
435+ allowed_restricted_families[0].processorfamily)
436+ self.assertTrue(self.archive.arm_builds_allowed)
437+ self.archive.arm_builds_allowed = False
438+ self.assertEquals(0,
439+ self.archive_arch_set.getByArchive(self.archive, self.arm).count())
440+ self.assertFalse(self.archive.arm_builds_allowed)
441+
442+
443 def test_suite():
444 return unittest.TestLoader().loadTestsFromName(__name__)
445
446=== added file 'lib/lp/soyuz/tests/test_archivearch.py'
447--- lib/lp/soyuz/tests/test_archivearch.py 1970-01-01 00:00:00 +0000
448+++ lib/lp/soyuz/tests/test_archivearch.py 2010-02-26 23:30:37 +0000
449@@ -0,0 +1,57 @@
450+# Copyright 2010 Canonical Ltd. This software is licensed under the
451+# GNU Affero General Public License version 3 (see the file LICENSE).
452+
453+"""Test ArchiveArch features."""
454+
455+import unittest
456+
457+from zope.component import getUtility
458+
459+from canonical.testing import LaunchpadZopelessLayer
460+
461+from lp.testing import TestCaseWithFactory
462+
463+from lp.registry.interfaces.person import IPersonSet
464+from lp.soyuz.interfaces.archivearch import IArchiveArchSet
465+from lp.soyuz.interfaces.processor import IProcessorFamilySet
466+
467+class TestArchiveArch(TestCaseWithFactory):
468+
469+ layer = LaunchpadZopelessLayer
470+
471+ def setUp(self):
472+ """Use `SoyuzTestPublisher` to publish some sources in archives."""
473+ super(TestArchiveArch, self).setUp()
474+
475+ self.ppa = getUtility(IPersonSet).getByName('cprov').archive
476+ pss = getUtility(IProcessorFamilySet)
477+ self.cell_proc = pss.new(
478+ 'cell-proc', 'PS cell processor', 'Screamingly faaaaaaaaaaaast',
479+ True)
480+ self.omap = pss.new(
481+ 'omap', 'Multimedia applications processor',
482+ 'Does all your sound & video', True)
483+
484+ def test_no_associations(self):
485+ """Our archive is not associated with any restricted processor
486+ families yet."""
487+ result_set = list(
488+ getUtility(IArchiveArchSet).getRestrictedfamilies(self.ppa))
489+ archivearches = [row[1] for row in result_set]
490+ self.assertTrue(all(aa is None for aa in archivearches))
491+
492+ def test_single_association(self):
493+ """Our archive is now associated with one of the restricted processor
494+ families."""
495+ getUtility(IArchiveArchSet).new(self.ppa, self.cell_proc)
496+ result_set = list(
497+ getUtility(IArchiveArchSet).getRestrictedfamilies(self.ppa))
498+ results = dict(
499+ (row[0].name, row[1] is not None) for row in result_set)
500+ self.assertEquals(
501+ { 'arm' : False, 'cell-proc' : True, 'omap' : False},
502+ results)
503+
504+
505+def test_suite():
506+ return unittest.TestLoader().loadTestsFromName(__name__)
507
508=== added file 'lib/lp/soyuz/tests/test_processor.py'
509--- lib/lp/soyuz/tests/test_processor.py 1970-01-01 00:00:00 +0000
510+++ lib/lp/soyuz/tests/test_processor.py 2010-02-26 23:30:37 +0000
511@@ -0,0 +1,32 @@
512+# Copyright 2010 Canonical Ltd. This software is licensed under the
513+# GNU Affero General Public License version 3 (see the file LICENSE).
514+
515+"""Test Processor and ProcessorFamily features."""
516+
517+from zope.component import getUtility
518+
519+from canonical.testing import LaunchpadZopelessLayer
520+
521+from lp.soyuz.interfaces.processor import (IProcessor, IProcessorFamily,
522+ IProcessorFamilySet)
523+from lp.testing import TestCaseWithFactory
524+
525+
526+class ProcessorFamilyTests(TestCaseWithFactory):
527+ """Test ProcessorFamily."""
528+
529+ layer = LaunchpadZopelessLayer
530+
531+ def test_create(self):
532+ """Test adding a new ProcessorFamily."""
533+ family = getUtility(IProcessorFamilySet).new("avr", "Atmel AVR",
534+ "The Modified Harvard architecture 8-bit RISC processors.")
535+ self.assertProvides(family, IProcessorFamily)
536+
537+ def test_add_processor(self):
538+ """Test adding a new Processor to a ProcessorFamily."""
539+ family = getUtility(IProcessorFamilySet).new("avr", "Atmel AVR",
540+ "The Modified Harvard architecture 8-bit RISC processors.")
541+ proc = family.addProcessor("avr2001", "The 2001 AVR", "Fast as light.")
542+ self.assertProvides(proc, IProcessor)
543+ self.assertEquals(family, proc.family)
544
545=== modified file 'lib/lp/soyuz/tests/test_publishing.py'
546--- lib/lp/soyuz/tests/test_publishing.py 2010-02-24 10:18:16 +0000
547+++ lib/lp/soyuz/tests/test_publishing.py 2010-02-26 23:30:37 +0000
548@@ -31,6 +31,7 @@
549 from lp.registry.interfaces.sourcepackage import SourcePackageUrgency
550 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
551 from lp.soyuz.interfaces.archive import ArchivePurpose
552+from lp.soyuz.interfaces.archivearch import IArchiveArchSet
553 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
554 from lp.soyuz.interfaces.binarypackagerelease import BinaryPackageFormat
555 from lp.soyuz.interfaces.build import BuildStatus
556@@ -861,6 +862,104 @@
557 binary, binary.distroarchseries.distroseries, 'universe')
558
559
560+class BuildRecordCreationTests(TestNativePublishingBase):
561+ """Test the creation of build records."""
562+
563+ def setUp(self):
564+ super(BuildRecordCreationTests, self).setUp()
565+ self.distro = self.factory.makeDistribution()
566+ self.distroseries = self.factory.makeDistroSeries(
567+ distribution=self.distro, name="crazy")
568+ self.archive = self.factory.makeArchive()
569+ self.avr_family = self.factory.makeProcessorFamily(
570+ name="avr", restricted=True)
571+ self.factory.makeProcessor(self.avr_family, "avr2001")
572+ self.avr_distroarch = self.factory.makeDistroArchSeries(
573+ architecturetag='avr', processorfamily=self.avr_family,
574+ distroseries=self.distroseries, supports_virtualized=True)
575+ self.sparc_family = self.factory.makeProcessorFamily(name="sparc",
576+ restricted=False)
577+ self.factory.makeProcessor(self.sparc_family, "sparc64")
578+ self.sparc_distroarch = self.factory.makeDistroArchSeries(
579+ architecturetag='sparc', processorfamily=self.sparc_family,
580+ distroseries=self.distroseries, supports_virtualized=True)
581+ self.distroseries.nominatedarchindep = self.sparc_distroarch
582+ self.addFakeChroots(self.distroseries)
583+
584+ def getPubSource(self, architecturehintlist):
585+ """Return a mock source package publishing record for the archive
586+ and architecture used in this testcase.
587+
588+ :param architecturehintlist: Architecture hint list (e.g. "i386 amd64")
589+ """
590+ return super(BuildRecordCreationTests, self).getPubSource(
591+ archive=self.archive, distroseries=self.distroseries,
592+ architecturehintlist=architecturehintlist)
593+
594+ def test__getAllowedArchitectures_restricted(self):
595+ """Test _getAllowedArchitectures doesn't return unrestricted
596+ archs.
597+
598+ For a normal archive, only unrestricted architectures should
599+ be used.
600+ """
601+ available_archs = [self.sparc_distroarch, self.avr_distroarch]
602+ pubrec = self.getPubSource(architecturehintlist='any')
603+ self.assertEquals([self.sparc_distroarch],
604+ pubrec._getAllowedArchitectures(available_archs))
605+
606+ def test__getAllowedArchitectures_restricted_override(self):
607+ """Test _getAllowedArchitectures honors overrides of restricted archs.
608+
609+ Restricted architectures should only be allowed if there is
610+ an explicit ArchiveArch association with the archive.
611+ """
612+ available_archs = [self.sparc_distroarch, self.avr_distroarch]
613+ getUtility(IArchiveArchSet).new(self.archive, self.avr_family)
614+ pubrec = self.getPubSource(architecturehintlist='any')
615+ self.assertEquals([self.sparc_distroarch, self.avr_distroarch],
616+ pubrec._getAllowedArchitectures(available_archs))
617+
618+ def test_createMissingBuilds_restricts_any(self):
619+ """createMissingBuilds() should limit builds targeted at 'any'
620+ architecture to those allowed for the archive.
621+ """
622+ pubrec = self.getPubSource(architecturehintlist='any')
623+ builds = pubrec.createMissingBuilds()
624+ self.assertEquals(1, len(builds))
625+ self.assertEquals(self.sparc_distroarch, builds[0].distroarchseries)
626+
627+ def test_createMissingBuilds_restricts_explicitlist(self):
628+ """createMissingBuilds() should limit builds targeted at a
629+ variety of architectures architecture to those allowed for the archive.
630+ """
631+ pubrec = self.getPubSource(architecturehintlist='sparc i386 avr')
632+ builds = pubrec.createMissingBuilds()
633+ self.assertEquals(1, len(builds))
634+ self.assertEquals(self.sparc_distroarch, builds[0].distroarchseries)
635+
636+ def test_createMissingBuilds_restricts_all(self):
637+ """createMissingBuilds() should limit builds targeted at 'all'
638+ architectures to the nominated independent architecture,
639+ if that is allowed for the archive.
640+ """
641+ pubrec = self.getPubSource(architecturehintlist='all')
642+ builds = pubrec.createMissingBuilds()
643+ self.assertEquals(1, len(builds))
644+ self.assertEquals(self.sparc_distroarch, builds[0].distroarchseries)
645+
646+ def test_createMissingBuilds_restrict_override(self):
647+ """createMissingBuilds() should limit builds targeted at 'any'
648+ architecture to architectures that are unrestricted or
649+ explicitly associated with the archive.
650+ """
651+ getUtility(IArchiveArchSet).new(self.archive, self.avr_family)
652+ pubrec = self.getPubSource(architecturehintlist='any')
653+ builds = pubrec.createMissingBuilds()
654+ self.assertEquals(2, len(builds))
655+ self.assertEquals(self.avr_distroarch, builds[0].distroarchseries)
656+ self.assertEquals(self.sparc_distroarch, builds[1].distroarchseries)
657+
658
659 def test_suite():
660 return unittest.TestLoader().loadTestsFromName(__name__)
661
662=== modified file 'lib/lp/testing/factory.py'
663--- lib/lp/testing/factory.py 2010-02-25 07:42:32 +0000
664+++ lib/lp/testing/factory.py 2010-02-26 23:30:37 +0000
665@@ -126,6 +126,7 @@
666 from lp.soyuz.adapters.packagelocation import PackageLocation
667 from lp.soyuz.interfaces.component import IComponentSet
668 from lp.soyuz.interfaces.packageset import IPackagesetSet
669+from lp.soyuz.interfaces.processor import IProcessorFamilySet
670 from lp.soyuz.interfaces.publishing import PackagePublishingStatus
671 from lp.soyuz.interfaces.section import ISectionSet
672 from lp.soyuz.model.buildqueue import BuildQueue
673@@ -613,6 +614,38 @@
674 productseries=productseries,
675 name=name)
676
677+ def makeProcessor(self, family, name, title=None, description=None):
678+ """Create a new processor.
679+
680+ :param family: Family of the processor
681+ :param name: Name of the processor
682+ :param title: Optional title
683+ :param description: Optional description
684+ :return: A `IProcessor`
685+ """
686+ if title is None:
687+ title = "The %s processor" % name
688+ if description is None:
689+ description = "The %s and processor and compatible processors"
690+ return family.addProcessor(name, title, description)
691+
692+ def makeProcessorFamily(self, name, title=None, description=None,
693+ restricted=False):
694+ """Create a new processor family.
695+
696+ :param name: Name of the family (e.g. x86)
697+ :param title: Optional title of the family
698+ :param description: Optional extended description
699+ :param restricted: Whether the processor family is restricted
700+ :return: A `IProcessorFamily`
701+ """
702+ if description is None:
703+ description = "Description of the %s processor family" % name
704+ if title is None:
705+ title = "%s and compatible processors." % name
706+ return getUtility(IProcessorFamilySet).new(name, title, description,
707+ restricted=restricted)
708+
709 def makeProductRelease(self, milestone=None, product=None,
710 productseries=None):
711 if milestone is None:

Subscribers

People subscribed via source and target branches

to status/vote changes: